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