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