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