add support for Zaptel transcoders
[asterisk/asterisk.git] / codecs / codec_speex.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief Translate between signed linear and Speex (Open Codec)
23  *
24  * http://www.speex.org
25  * \note This work was motivated by Jeremy McNamara 
26  * hacked to be configurable by anthm and bkw 9/28/2004
27  * \ingroup codecs
28  */
29
30 /*** MODULEINFO
31         <depend>libspeex</depend>
32  ***/
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include <fcntl.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <netinet/in.h>
42 #include <string.h>
43 #include <stdio.h>
44 #include <speex/speex.h>
45
46 /* We require a post 1.1.8 version of Speex to enable preprocessing
47    and better type handling */   
48 #ifdef _SPEEX_TYPES_H
49 #include <speex/speex_preprocess.h>
50 #endif
51
52 #include "asterisk/lock.h"
53 #include "asterisk/translate.h"
54 #include "asterisk/module.h"
55 #include "asterisk/config.h"
56 #include "asterisk/options.h"
57 #include "asterisk/logger.h"
58 #include "asterisk/channel.h"
59 #include "asterisk/utils.h"
60
61 /* Sample frame data */
62 #include "slin_speex_ex.h"
63 #include "speex_slin_ex.h"
64
65 /* codec variables */
66 static int quality = 3;
67 static int complexity = 2;
68 static int enhancement = 0;
69 static int vad = 0;
70 static int vbr = 0;
71 static float vbr_quality = 4;
72 static int abr = 0;
73 static int dtx = 0;     /* set to 1 to enable silence detection */
74
75 static int preproc = 0;
76 static int pp_vad = 0;
77 static int pp_agc = 0;
78 static float pp_agc_level = 8000; /* XXX what is this 8000 ? */
79 static int pp_denoise = 0;
80 static int pp_dereverb = 0;
81 static float pp_dereverb_decay = 0.4;
82 static float pp_dereverb_level = 0.3;
83
84 #define TYPE_SILENCE     0x2
85 #define TYPE_HIGH        0x0
86 #define TYPE_LOW         0x1
87 #define TYPE_MASK        0x3
88
89 #define BUFFER_SAMPLES  8000
90 #define SPEEX_SAMPLES   160
91
92 struct speex_coder_pvt {
93         void *speex;
94         SpeexBits bits;
95         int framesize;
96         int silent_state;
97 #ifdef _SPEEX_TYPES_H
98         SpeexPreprocessState *pp;
99         spx_int16_t buf[BUFFER_SAMPLES];
100 #else
101         int16_t buf[BUFFER_SAMPLES];    /* input, waiting to be compressed */
102 #endif
103 };
104
105
106 static void *lintospeex_new(struct ast_trans_pvt *pvt)
107 {
108         struct speex_coder_pvt *tmp = pvt->pvt;
109
110         if (!(tmp->speex = speex_encoder_init(&speex_nb_mode)))
111                 return NULL;
112
113         speex_bits_init(&tmp->bits);
114         speex_bits_reset(&tmp->bits);
115         speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
116         ast_log(LOG_WARNING, "speex framesize is %d\n", tmp->framesize);
117         speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
118 #ifdef _SPEEX_TYPES_H
119         if (preproc) {
120                 tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000); /* XXX what is this 8000 ? */
121                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
122                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
123                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
124                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
125                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
126                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
127                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
128         }
129 #endif
130         if (!abr && !vbr) {
131                 speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
132                 if (vad)
133                         speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
134         }
135         if (vbr) {
136                 speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
137                 speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
138         }
139         if (abr)
140                 speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
141         if (dtx)
142                 speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx); 
143         tmp->silent_state = 0;
144
145         return tmp;
146 }
147
148 static void *speextolin_new(struct ast_trans_pvt *pvt)
149 {
150         struct speex_coder_pvt *tmp = pvt->pvt;
151         
152         if (!(tmp->speex = speex_decoder_init(&speex_nb_mode)))
153                 return NULL;
154         speex_bits_init(&tmp->bits);
155         speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
156         if (enhancement)
157                 speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
158         return tmp;
159 }
160
161 static struct ast_frame *lintospeex_sample(void)
162 {
163         static struct ast_frame f;
164         f.frametype = AST_FRAME_VOICE;
165         f.subclass = AST_FORMAT_SLINEAR;
166         f.datalen = sizeof(slin_speex_ex);
167         /* Assume 8000 Hz */
168         f.samples = sizeof(slin_speex_ex)/2;
169         f.mallocd = 0;
170         f.offset = 0;
171         f.src = __PRETTY_FUNCTION__;
172         f.data = slin_speex_ex;
173         return &f;
174 }
175
176 static struct ast_frame *speextolin_sample(void)
177 {
178         static struct ast_frame f;
179         f.frametype = AST_FRAME_VOICE;
180         f.subclass = AST_FORMAT_SPEEX;
181         f.datalen = sizeof(speex_slin_ex);
182         /* All frames are 20 ms long */
183         f.samples = SPEEX_SAMPLES;
184         f.mallocd = 0;
185         f.offset = 0;
186         f.src = __PRETTY_FUNCTION__;
187         f.data = speex_slin_ex;
188         return &f;
189 }
190
191 /*! \brief convert and store into outbuf */
192 static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
193 {
194         struct speex_coder_pvt *tmp = pvt->pvt;
195
196         /* Assuming there's space left, decode into the current buffer at
197            the tail location.  Read in as many frames as there are */
198         int x;
199         int res;
200         int16_t *dst = (int16_t *)pvt->outbuf;
201         /* XXX fout is a temporary buffer, may have different types */
202 #ifdef _SPEEX_TYPES_H
203         spx_int16_t fout[1024];
204 #else
205         float fout[1024];
206 #endif
207
208         if (f->datalen == 0) {  /* Native PLC interpolation */
209                 if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
210                         ast_log(LOG_WARNING, "Out of buffer space\n");
211                         return -1;
212                 }
213 #ifdef _SPEEX_TYPES_H
214                 speex_decode_int(tmp->speex, NULL, dst + pvt->samples);
215 #else
216                 speex_decode(tmp->speex, NULL, fout);
217                 for (x=0;x<tmp->framesize;x++) {
218                         dst[pvt->samples + x] = (int16_t)fout[x];
219                 }
220 #endif
221                 pvt->samples += tmp->framesize;
222                 return 0;
223         }
224
225         /* Read in bits */
226         speex_bits_read_from(&tmp->bits, f->data, f->datalen);
227         for (;;) {
228 #ifdef _SPEEX_TYPES_H
229                 res = speex_decode_int(tmp->speex, &tmp->bits, fout);
230 #else
231                 res = speex_decode(tmp->speex, &tmp->bits, fout);
232 #endif
233                 if (res < 0)
234                         break;
235                 if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
236                         ast_log(LOG_WARNING, "Out of buffer space\n");
237                         return -1;
238                 }
239                 for (x = 0 ; x < tmp->framesize; x++)
240                         dst[pvt->samples + x] = (int16_t)fout[x];
241                 pvt->samples += tmp->framesize;
242                 pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
243         }
244         return 0;
245 }
246
247 /*! \brief store input frame in work buffer */
248 static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
249 {
250         struct speex_coder_pvt *tmp = pvt->pvt;
251
252         /* XXX We should look at how old the rest of our stream is, and if it
253            is too old, then we should overwrite it entirely, otherwise we can
254            get artifacts of earlier talk that do not belong */
255         memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
256         pvt->samples += f->samples;
257         return 0;
258 }
259
260 /*! \brief convert work buffer and produce output frame */
261 static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
262 {
263         struct speex_coder_pvt *tmp = pvt->pvt;
264         int is_speech=1;
265         int datalen = 0;        /* output bytes */
266         int samples = 0;        /* output samples */
267
268         /* We can't work on anything less than a frame in size */
269         if (pvt->samples < tmp->framesize)
270                 return NULL;
271         speex_bits_reset(&tmp->bits);
272         while (pvt->samples >= tmp->framesize) {
273 #ifdef _SPEEX_TYPES_H
274                 /* Preprocess audio */
275                 if (preproc)
276                         is_speech = speex_preprocess(tmp->pp, tmp->buf, NULL);
277                 /* Encode a frame of data */
278                 if (is_speech) {
279                         /* If DTX enabled speex_encode returns 0 during silence */
280                         is_speech = speex_encode_int(tmp->speex, tmp->buf, &tmp->bits) || !dtx;
281                 } else {
282                         /* 5 zeros interpreted by Speex as silence (submode 0) */
283                         speex_bits_pack(&tmp->bits, 0, 5);
284                 }
285 #else
286                 {
287                         float fbuf[1024];
288                         int x;
289                         /* Convert to floating point */
290                         for (x = 0; x < tmp->framesize; x++)
291                                 fbuf[x] = tmp->buf[x];
292                         /* Encode a frame of data */
293                         is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
294                 }
295 #endif
296                 samples += tmp->framesize;
297                 pvt->samples -= tmp->framesize;
298                 /* Move the data at the end of the buffer to the front */
299                 if (pvt->samples)
300                         memmove(tmp->buf, tmp->buf + tmp->framesize, pvt->samples * 2);
301         }
302
303         /* Use AST_FRAME_CNG to signify the start of any silence period */
304         if (is_speech) {
305                 tmp->silent_state = 0;
306         } else {
307                 if (tmp->silent_state) {
308                         return NULL;
309                 } else {
310                         tmp->silent_state = 1;
311                         speex_bits_reset(&tmp->bits);
312                         memset(&pvt->f, 0, sizeof(pvt->f));
313                         pvt->f.frametype = AST_FRAME_CNG;
314                         pvt->f.samples = samples;
315                         /* XXX what now ? format etc... */
316                 }
317         }
318
319         /* Terminate bit stream */
320         speex_bits_pack(&tmp->bits, 15, 5);
321         datalen = speex_bits_write(&tmp->bits, pvt->outbuf, pvt->t->buf_size);
322         return ast_trans_frameout(pvt, datalen, samples);
323 }
324
325 static void speextolin_destroy(struct ast_trans_pvt *arg)
326 {
327         struct speex_coder_pvt *pvt = arg->pvt;
328
329         speex_decoder_destroy(pvt->speex);
330         speex_bits_destroy(&pvt->bits);
331 }
332
333 static void lintospeex_destroy(struct ast_trans_pvt *arg)
334 {
335         struct speex_coder_pvt *pvt = arg->pvt;
336 #ifdef _SPEEX_TYPES_H
337         if (preproc)
338                 speex_preprocess_state_destroy(pvt->pp);
339 #endif
340         speex_encoder_destroy(pvt->speex);
341         speex_bits_destroy(&pvt->bits);
342 }
343
344 static struct ast_translator speextolin = {
345         .name = "speextolin", 
346         .srcfmt = AST_FORMAT_SPEEX,
347         .dstfmt =  AST_FORMAT_SLINEAR,
348         .newpvt = speextolin_new,
349         .framein = speextolin_framein,
350         .destroy = speextolin_destroy,
351         .sample = speextolin_sample,
352         .desc_size = sizeof(struct speex_coder_pvt),
353         .buffer_samples = BUFFER_SAMPLES,
354         .buf_size = BUFFER_SAMPLES * 2,
355 };
356
357 static struct ast_translator lintospeex = {
358         .name = "lintospeex", 
359         .srcfmt = AST_FORMAT_SLINEAR,
360         .dstfmt = AST_FORMAT_SPEEX,
361         .newpvt = lintospeex_new,
362         .framein = lintospeex_framein,
363         .frameout = lintospeex_frameout,
364         .destroy = lintospeex_destroy,
365         .sample = lintospeex_sample,
366         .desc_size = sizeof(struct speex_coder_pvt),
367         .buffer_samples = BUFFER_SAMPLES,
368         .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
369 };
370
371 static void parse_config(void) 
372 {
373         struct ast_config *cfg = ast_config_load("codecs.conf");
374         struct ast_variable *var;
375         int res;
376         float res_f;
377
378         if (cfg == NULL)
379                 return;
380
381         for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) {
382                 if (!strcasecmp(var->name, "quality")) {
383                         res = abs(atoi(var->value));
384                         if (res > -1 && res < 11) {
385                                 if (option_verbose > 2)
386                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res);
387                                 quality = res;
388                         } else 
389                                 ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
390                 } else if (!strcasecmp(var->name, "complexity")) {
391                         res = abs(atoi(var->value));
392                         if (res > -1 && res < 11) {
393                                 if (option_verbose > 2)
394                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res);
395                                 complexity = res;
396                         } else 
397                                 ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
398                 } else if (!strcasecmp(var->name, "vbr_quality")) {
399                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
400                                 if (option_verbose > 2)
401                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
402                                 vbr_quality = res_f;
403                         } else
404                                 ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
405                 } else if (!strcasecmp(var->name, "abr_quality")) {
406                         ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
407                 } else if (!strcasecmp(var->name, "enhancement")) {
408                         enhancement = ast_true(var->value) ? 1 : 0;
409                         if (option_verbose > 2)
410                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
411                 } else if (!strcasecmp(var->name, "vbr")) {
412                         vbr = ast_true(var->value) ? 1 : 0;
413                         if (option_verbose > 2)
414                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
415                 } else if (!strcasecmp(var->name, "abr")) {
416                         res = abs(atoi(var->value));
417                         if (res >= 0) {
418                                 if (option_verbose > 2) {
419                                         if (res > 0)
420                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
421                                         else
422                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n");
423                                 }
424                                 abr = res;
425                         } else 
426                                 ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
427                 } else if (!strcasecmp(var->name, "vad")) {
428                         vad = ast_true(var->value) ? 1 : 0;
429                         if (option_verbose > 2)
430                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
431                 } else if (!strcasecmp(var->name, "dtx")) {
432                         dtx = ast_true(var->value) ? 1 : 0;
433                         if (option_verbose > 2)
434                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
435                 } else if (!strcasecmp(var->name, "preprocess")) {
436                         preproc = ast_true(var->value) ? 1 : 0;
437                         if (option_verbose > 2)
438                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
439                 } else if (!strcasecmp(var->name, "pp_vad")) {
440                         pp_vad = ast_true(var->value) ? 1 : 0;
441                         if (option_verbose > 2)
442                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
443                 } else if (!strcasecmp(var->name, "pp_agc")) {
444                         pp_agc = ast_true(var->value) ? 1 : 0;
445                         if (option_verbose > 2)
446                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
447                 } else if (!strcasecmp(var->name, "pp_agc_level")) {
448                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
449                                 if (option_verbose > 2)
450                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
451                                 pp_agc_level = res_f;
452                         } else
453                                 ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
454                 } else if (!strcasecmp(var->name, "pp_denoise")) {
455                         pp_denoise = ast_true(var->value) ? 1 : 0;
456                         if (option_verbose > 2)
457                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
458                 } else if (!strcasecmp(var->name, "pp_dereverb")) {
459                         pp_dereverb = ast_true(var->value) ? 1 : 0;
460                         if (option_verbose > 2)
461                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
462                 } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
463                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
464                                 if (option_verbose > 2)
465                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
466                                 pp_dereverb_decay = res_f;
467                         } else
468                                 ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
469                 } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
470                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
471                                 if (option_verbose > 2)
472                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
473                                 pp_dereverb_level = res_f;
474                         } else
475                                 ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
476                 }
477         }
478         ast_config_destroy(cfg);
479 }
480
481 static int reload(void *mod) 
482 {
483         /*
484          * XXX reloading while there are active sessions is
485          * somewhat silly because the old state presumably
486          * wouldn't work anymore...
487          * maybe we shuld do a standard hangup localusers ?
488          */
489         ast_mutex_lock(&__mod_desc->lock);
490         parse_config();
491         ast_mutex_lock(&__mod_desc->lock);
492         return 0;
493 }
494
495 static int unload_module(void *mod)
496 {
497         int res;
498         res = ast_unregister_translator(&lintospeex);
499         res |= ast_unregister_translator(&speextolin);
500         return res;
501 }
502
503 static int load_module(void *mod)
504 {
505         int res;
506         parse_config();
507         res=ast_register_translator(&speextolin, mod);
508         if (!res) 
509                 res=ast_register_translator(&lintospeex, mod);
510         else
511                 ast_unregister_translator(&speextolin);
512         return res;
513 }
514
515 static const char *description(void)
516 {
517         return "Speex/PCM16 (signed linear) Codec Translator";
518 }
519
520 static const char *key(void)
521 {
522         return ASTERISK_GPL_KEY;
523 }
524
525 STD_MOD(MOD_1, reload, NULL, NULL);
526