Several changes to codec_dahdi to play nice with G723.
[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
101 static int lintospeex_new(struct ast_trans_pvt *pvt)
102 {
103         struct speex_coder_pvt *tmp = pvt->pvt;
104
105         if (!(tmp->speex = speex_encoder_init(&speex_nb_mode)))
106                 return -1;
107
108         speex_bits_init(&tmp->bits);
109         speex_bits_reset(&tmp->bits);
110         speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
111         speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
112 #ifdef _SPEEX_TYPES_H
113         if (preproc) {
114                 tmp->pp = speex_preprocess_state_init(tmp->framesize, 8000); /* XXX what is this 8000 ? */
115                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_VAD, &pp_vad);
116                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC, &pp_agc);
117                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &pp_agc_level);
118                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DENOISE, &pp_denoise);
119                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB, &pp_dereverb);
120                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &pp_dereverb_decay);
121                 speex_preprocess_ctl(tmp->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &pp_dereverb_level);
122         }
123 #endif
124         if (!abr && !vbr) {
125                 speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
126                 if (vad)
127                         speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
128         }
129         if (vbr) {
130                 speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
131                 speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
132         }
133         if (abr)
134                 speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
135         if (dtx)
136                 speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &dtx); 
137         tmp->silent_state = 0;
138
139         return 0;
140 }
141
142 static int speextolin_new(struct ast_trans_pvt *pvt)
143 {
144         struct speex_coder_pvt *tmp = pvt->pvt;
145         
146         if (!(tmp->speex = speex_decoder_init(&speex_nb_mode)))
147                 return -1;
148
149         speex_bits_init(&tmp->bits);
150         speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
151         if (enhancement)
152                 speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
153
154         return 0;
155 }
156
157 /*! \brief convert and store into outbuf */
158 static int speextolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
159 {
160         struct speex_coder_pvt *tmp = pvt->pvt;
161
162         /* Assuming there's space left, decode into the current buffer at
163            the tail location.  Read in as many frames as there are */
164         int x;
165         int res;
166         int16_t *dst = pvt->outbuf.i16;
167         /* XXX fout is a temporary buffer, may have different types */
168 #ifdef _SPEEX_TYPES_H
169         spx_int16_t fout[1024];
170 #else
171         float fout[1024];
172 #endif
173
174         if (f->datalen == 0) {  /* Native PLC interpolation */
175                 if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
176                         ast_log(LOG_WARNING, "Out of buffer space\n");
177                         return -1;
178                 }
179 #ifdef _SPEEX_TYPES_H
180                 speex_decode_int(tmp->speex, NULL, dst + pvt->samples);
181 #else
182                 speex_decode(tmp->speex, NULL, fout);
183                 for (x=0;x<tmp->framesize;x++) {
184                         dst[pvt->samples + x] = (int16_t)fout[x];
185                 }
186 #endif
187                 pvt->samples += tmp->framesize;
188                 pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
189                 return 0;
190         }
191
192         /* Read in bits */
193         speex_bits_read_from(&tmp->bits, f->data.ptr, f->datalen);
194         for (;;) {
195 #ifdef _SPEEX_TYPES_H
196                 res = speex_decode_int(tmp->speex, &tmp->bits, fout);
197 #else
198                 res = speex_decode(tmp->speex, &tmp->bits, fout);
199 #endif
200                 if (res < 0)
201                         break;
202                 if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
203                         ast_log(LOG_WARNING, "Out of buffer space\n");
204                         return -1;
205                 }
206                 for (x = 0 ; x < tmp->framesize; x++)
207                         dst[pvt->samples + x] = (int16_t)fout[x];
208                 pvt->samples += tmp->framesize;
209                 pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
210         }
211         return 0;
212 }
213
214 /*! \brief store input frame in work buffer */
215 static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
216 {
217         struct speex_coder_pvt *tmp = pvt->pvt;
218
219         /* XXX We should look at how old the rest of our stream is, and if it
220            is too old, then we should overwrite it entirely, otherwise we can
221            get artifacts of earlier talk that do not belong */
222         memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
223         pvt->samples += f->samples;
224         return 0;
225 }
226
227 /*! \brief convert work buffer and produce output frame */
228 static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
229 {
230         struct speex_coder_pvt *tmp = pvt->pvt;
231         int is_speech=1;
232         int datalen = 0;        /* output bytes */
233         int samples = 0;        /* output samples */
234
235         /* We can't work on anything less than a frame in size */
236         if (pvt->samples < tmp->framesize)
237                 return NULL;
238         speex_bits_reset(&tmp->bits);
239         while (pvt->samples >= tmp->framesize) {
240 #ifdef _SPEEX_TYPES_H
241                 /* Preprocess audio */
242                 if (preproc)
243                         is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL);
244                 /* Encode a frame of data */
245                 if (is_speech) {
246                         /* If DTX enabled speex_encode returns 0 during silence */
247                         is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx;
248                 } else {
249                         /* 5 zeros interpreted by Speex as silence (submode 0) */
250                         speex_bits_pack(&tmp->bits, 0, 5);
251                 }
252 #else
253                 {
254                         float fbuf[1024];
255                         int x;
256                         /* Convert to floating point */
257                         for (x = 0; x < tmp->framesize; x++)
258                                 fbuf[x] = tmp->buf[samples + x];
259                         /* Encode a frame of data */
260                         is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
261                 }
262 #endif
263                 samples += tmp->framesize;
264                 pvt->samples -= tmp->framesize;
265         }
266
267         /* Move the data at the end of the buffer to the front */
268         if (pvt->samples)
269                 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
270
271         /* Use AST_FRAME_CNG to signify the start of any silence period */
272         if (is_speech) {
273                 tmp->silent_state = 0;
274         } else {
275                 if (tmp->silent_state) {
276                         return NULL;
277                 } else {
278                         tmp->silent_state = 1;
279                         speex_bits_reset(&tmp->bits);
280                         memset(&pvt->f, 0, sizeof(pvt->f));
281                         pvt->f.frametype = AST_FRAME_CNG;
282                         pvt->f.samples = samples;
283                         /* XXX what now ? format etc... */
284                 }
285         }
286
287         /* Terminate bit stream */
288         speex_bits_pack(&tmp->bits, 15, 5);
289         datalen = speex_bits_write(&tmp->bits, pvt->outbuf.c, pvt->t->buf_size);
290         return ast_trans_frameout(pvt, datalen, samples);
291 }
292
293 static void speextolin_destroy(struct ast_trans_pvt *arg)
294 {
295         struct speex_coder_pvt *pvt = arg->pvt;
296
297         speex_decoder_destroy(pvt->speex);
298         speex_bits_destroy(&pvt->bits);
299 }
300
301 static void lintospeex_destroy(struct ast_trans_pvt *arg)
302 {
303         struct speex_coder_pvt *pvt = arg->pvt;
304 #ifdef _SPEEX_TYPES_H
305         if (preproc)
306                 speex_preprocess_state_destroy(pvt->pp);
307 #endif
308         speex_encoder_destroy(pvt->speex);
309         speex_bits_destroy(&pvt->bits);
310 }
311
312 static struct ast_translator speextolin = {
313         .name = "speextolin", 
314         .srcfmt = AST_FORMAT_SPEEX,
315         .dstfmt =  AST_FORMAT_SLINEAR,
316         .newpvt = speextolin_new,
317         .framein = speextolin_framein,
318         .destroy = speextolin_destroy,
319         .sample = speex_sample,
320         .desc_size = sizeof(struct speex_coder_pvt),
321         .buffer_samples = BUFFER_SAMPLES,
322         .buf_size = BUFFER_SAMPLES * 2,
323         .native_plc = 1,
324 };
325
326 static struct ast_translator lintospeex = {
327         .name = "lintospeex", 
328         .srcfmt = AST_FORMAT_SLINEAR,
329         .dstfmt = AST_FORMAT_SPEEX,
330         .newpvt = lintospeex_new,
331         .framein = lintospeex_framein,
332         .frameout = lintospeex_frameout,
333         .destroy = lintospeex_destroy,
334         .sample = slin8_sample,
335         .desc_size = sizeof(struct speex_coder_pvt),
336         .buffer_samples = BUFFER_SAMPLES,
337         .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
338 };
339
340 static int parse_config(int reload) 
341 {
342         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
343         struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
344         struct ast_variable *var;
345         int res;
346         float res_f;
347
348         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
349                 return 0;
350
351         for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) {
352                 if (!strcasecmp(var->name, "quality")) {
353                         res = abs(atoi(var->value));
354                         if (res > -1 && res < 11) {
355                                 ast_verb(3, "CODEC SPEEX: Setting Quality to %d\n",res);
356                                 quality = res;
357                         } else 
358                                 ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
359                 } else if (!strcasecmp(var->name, "complexity")) {
360                         res = abs(atoi(var->value));
361                         if (res > -1 && res < 11) {
362                                 ast_verb(3, "CODEC SPEEX: Setting Complexity to %d\n",res);
363                                 complexity = res;
364                         } else 
365                                 ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
366                 } else if (!strcasecmp(var->name, "vbr_quality")) {
367                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
368                                 ast_verb(3, "CODEC SPEEX: Setting VBR Quality to %f\n",res_f);
369                                 vbr_quality = res_f;
370                         } else
371                                 ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
372                 } else if (!strcasecmp(var->name, "abr_quality")) {
373                         ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
374                 } else if (!strcasecmp(var->name, "enhancement")) {
375                         enhancement = ast_true(var->value) ? 1 : 0;
376                         ast_verb(3, "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
377                 } else if (!strcasecmp(var->name, "vbr")) {
378                         vbr = ast_true(var->value) ? 1 : 0;
379                         ast_verb(3, "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
380                 } else if (!strcasecmp(var->name, "abr")) {
381                         res = abs(atoi(var->value));
382                         if (res >= 0) {
383                                         if (res > 0)
384                                         ast_verb(3, "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
385                                         else
386                                         ast_verb(3, "CODEC SPEEX: Disabling ABR\n");
387                                 abr = res;
388                         } else 
389                                 ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
390                 } else if (!strcasecmp(var->name, "vad")) {
391                         vad = ast_true(var->value) ? 1 : 0;
392                         ast_verb(3, "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
393                 } else if (!strcasecmp(var->name, "dtx")) {
394                         dtx = ast_true(var->value) ? 1 : 0;
395                         ast_verb(3, "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
396                 } else if (!strcasecmp(var->name, "preprocess")) {
397                         preproc = ast_true(var->value) ? 1 : 0;
398                         ast_verb(3, "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
399                 } else if (!strcasecmp(var->name, "pp_vad")) {
400                         pp_vad = ast_true(var->value) ? 1 : 0;
401                         ast_verb(3, "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
402                 } else if (!strcasecmp(var->name, "pp_agc")) {
403                         pp_agc = ast_true(var->value) ? 1 : 0;
404                         ast_verb(3, "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
405                 } else if (!strcasecmp(var->name, "pp_agc_level")) {
406                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
407                                 ast_verb(3, "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
408                                 pp_agc_level = res_f;
409                         } else
410                                 ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
411                 } else if (!strcasecmp(var->name, "pp_denoise")) {
412                         pp_denoise = ast_true(var->value) ? 1 : 0;
413                         ast_verb(3, "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
414                 } else if (!strcasecmp(var->name, "pp_dereverb")) {
415                         pp_dereverb = ast_true(var->value) ? 1 : 0;
416                         ast_verb(3, "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
417                 } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
418                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
419                                 ast_verb(3, "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
420                                 pp_dereverb_decay = res_f;
421                         } else
422                                 ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
423                 } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
424                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
425                                 ast_verb(3, "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
426                                 pp_dereverb_level = res_f;
427                         } else
428                                 ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
429                 }
430         }
431         ast_config_destroy(cfg);
432         return 0;
433 }
434
435 static int reload(void) 
436 {
437         if (parse_config(1))
438                 return AST_MODULE_LOAD_DECLINE;
439         return AST_MODULE_LOAD_SUCCESS;
440 }
441
442 static int unload_module(void)
443 {
444         int res;
445
446         res = ast_unregister_translator(&lintospeex);
447         res |= ast_unregister_translator(&speextolin);
448
449         return res;
450 }
451
452 static int load_module(void)
453 {
454         int res;
455
456         if (parse_config(0))
457                 return AST_MODULE_LOAD_DECLINE;
458         res=ast_register_translator(&speextolin);
459         if (!res) 
460                 res=ast_register_translator(&lintospeex);
461         else
462                 ast_unregister_translator(&speextolin);
463         if (res)
464                 return AST_MODULE_LOAD_FAILURE;
465         return AST_MODULE_LOAD_SUCCESS;
466 }
467
468 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Speex Coder/Decoder",
469                 .load = load_module,
470                 .unload = unload_module,
471                 .reload = reload,
472                );