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