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