c08de587967e59b437df13bcc18fbe5c8c51ee76
[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                 pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
227                 return 0;
228         }
229
230         /* Read in bits */
231         speex_bits_read_from(&tmp->bits, f->data, f->datalen);
232         for (;;) {
233 #ifdef _SPEEX_TYPES_H
234                 res = speex_decode_int(tmp->speex, &tmp->bits, fout);
235 #else
236                 res = speex_decode(tmp->speex, &tmp->bits, fout);
237 #endif
238                 if (res < 0)
239                         break;
240                 if (pvt->samples + tmp->framesize > BUFFER_SAMPLES) {
241                         ast_log(LOG_WARNING, "Out of buffer space\n");
242                         return -1;
243                 }
244                 for (x = 0 ; x < tmp->framesize; x++)
245                         dst[pvt->samples + x] = (int16_t)fout[x];
246                 pvt->samples += tmp->framesize;
247                 pvt->datalen += 2 * tmp->framesize; /* 2 bytes/sample */
248         }
249         return 0;
250 }
251
252 /*! \brief store input frame in work buffer */
253 static int lintospeex_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
254 {
255         struct speex_coder_pvt *tmp = pvt->pvt;
256
257         /* XXX We should look at how old the rest of our stream is, and if it
258            is too old, then we should overwrite it entirely, otherwise we can
259            get artifacts of earlier talk that do not belong */
260         memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
261         pvt->samples += f->samples;
262         return 0;
263 }
264
265 /*! \brief convert work buffer and produce output frame */
266 static struct ast_frame *lintospeex_frameout(struct ast_trans_pvt *pvt)
267 {
268         struct speex_coder_pvt *tmp = pvt->pvt;
269         int is_speech=1;
270         int datalen = 0;        /* output bytes */
271         int samples = 0;        /* output samples */
272
273         /* We can't work on anything less than a frame in size */
274         if (pvt->samples < tmp->framesize)
275                 return NULL;
276         speex_bits_reset(&tmp->bits);
277         while (pvt->samples >= tmp->framesize) {
278 #ifdef _SPEEX_TYPES_H
279                 /* Preprocess audio */
280                 if (preproc)
281                         is_speech = speex_preprocess(tmp->pp, tmp->buf + samples, NULL);
282                 /* Encode a frame of data */
283                 if (is_speech) {
284                         /* If DTX enabled speex_encode returns 0 during silence */
285                         is_speech = speex_encode_int(tmp->speex, tmp->buf + samples, &tmp->bits) || !dtx;
286                 } else {
287                         /* 5 zeros interpreted by Speex as silence (submode 0) */
288                         speex_bits_pack(&tmp->bits, 0, 5);
289                 }
290 #else
291                 {
292                         float fbuf[1024];
293                         int x;
294                         /* Convert to floating point */
295                         for (x = 0; x < tmp->framesize; x++)
296                                 fbuf[x] = tmp->buf[samples + x];
297                         /* Encode a frame of data */
298                         is_speech = speex_encode(tmp->speex, fbuf, &tmp->bits) || !dtx;
299                 }
300 #endif
301                 samples += tmp->framesize;
302                 pvt->samples -= tmp->framesize;
303         }
304
305         /* Move the data at the end of the buffer to the front */
306         if (pvt->samples)
307                 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
308
309         /* Use AST_FRAME_CNG to signify the start of any silence period */
310         if (is_speech) {
311                 tmp->silent_state = 0;
312         } else {
313                 if (tmp->silent_state) {
314                         return NULL;
315                 } else {
316                         tmp->silent_state = 1;
317                         speex_bits_reset(&tmp->bits);
318                         memset(&pvt->f, 0, sizeof(pvt->f));
319                         pvt->f.frametype = AST_FRAME_CNG;
320                         pvt->f.samples = samples;
321                         /* XXX what now ? format etc... */
322                 }
323         }
324
325         /* Terminate bit stream */
326         speex_bits_pack(&tmp->bits, 15, 5);
327         datalen = speex_bits_write(&tmp->bits, pvt->outbuf, pvt->t->buf_size);
328         return ast_trans_frameout(pvt, datalen, samples);
329 }
330
331 static void speextolin_destroy(struct ast_trans_pvt *arg)
332 {
333         struct speex_coder_pvt *pvt = arg->pvt;
334
335         speex_decoder_destroy(pvt->speex);
336         speex_bits_destroy(&pvt->bits);
337 }
338
339 static void lintospeex_destroy(struct ast_trans_pvt *arg)
340 {
341         struct speex_coder_pvt *pvt = arg->pvt;
342 #ifdef _SPEEX_TYPES_H
343         if (preproc)
344                 speex_preprocess_state_destroy(pvt->pp);
345 #endif
346         speex_encoder_destroy(pvt->speex);
347         speex_bits_destroy(&pvt->bits);
348 }
349
350 static struct ast_translator speextolin = {
351         .name = "speextolin", 
352         .srcfmt = AST_FORMAT_SPEEX,
353         .dstfmt =  AST_FORMAT_SLINEAR,
354         .newpvt = speextolin_new,
355         .framein = speextolin_framein,
356         .destroy = speextolin_destroy,
357         .sample = speextolin_sample,
358         .desc_size = sizeof(struct speex_coder_pvt),
359         .buffer_samples = BUFFER_SAMPLES,
360         .buf_size = BUFFER_SAMPLES * 2,
361 };
362
363 static struct ast_translator lintospeex = {
364         .name = "lintospeex", 
365         .srcfmt = AST_FORMAT_SLINEAR,
366         .dstfmt = AST_FORMAT_SPEEX,
367         .newpvt = lintospeex_new,
368         .framein = lintospeex_framein,
369         .frameout = lintospeex_frameout,
370         .destroy = lintospeex_destroy,
371         .sample = lintospeex_sample,
372         .desc_size = sizeof(struct speex_coder_pvt),
373         .buffer_samples = BUFFER_SAMPLES,
374         .buf_size = BUFFER_SAMPLES * 2, /* XXX maybe a lot less ? */
375 };
376
377 static void parse_config(void) 
378 {
379         struct ast_config *cfg = ast_config_load("codecs.conf");
380         struct ast_variable *var;
381         int res;
382         float res_f;
383
384         if (cfg == NULL)
385                 return;
386
387         for (var = ast_variable_browse(cfg, "speex"); var; var = var->next) {
388                 if (!strcasecmp(var->name, "quality")) {
389                         res = abs(atoi(var->value));
390                         if (res > -1 && res < 11) {
391                                 if (option_verbose > 2)
392                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res);
393                                 quality = res;
394                         } else 
395                                 ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
396                 } else if (!strcasecmp(var->name, "complexity")) {
397                         res = abs(atoi(var->value));
398                         if (res > -1 && res < 11) {
399                                 if (option_verbose > 2)
400                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res);
401                                 complexity = res;
402                         } else 
403                                 ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
404                 } else if (!strcasecmp(var->name, "vbr_quality")) {
405                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0 && res_f <= 10) {
406                                 if (option_verbose > 2)
407                                         ast_verbose(VERBOSE_PREFIX_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                         if (option_verbose > 2)
416                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
417                 } else if (!strcasecmp(var->name, "vbr")) {
418                         vbr = ast_true(var->value) ? 1 : 0;
419                         if (option_verbose > 2)
420                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
421                 } else if (!strcasecmp(var->name, "abr")) {
422                         res = abs(atoi(var->value));
423                         if (res >= 0) {
424                                 if (option_verbose > 2) {
425                                         if (res > 0)
426                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
427                                         else
428                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n");
429                                 }
430                                 abr = res;
431                         } else 
432                                 ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
433                 } else if (!strcasecmp(var->name, "vad")) {
434                         vad = ast_true(var->value) ? 1 : 0;
435                         if (option_verbose > 2)
436                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vad ? "on" : "off");
437                 } else if (!strcasecmp(var->name, "dtx")) {
438                         dtx = ast_true(var->value) ? 1 : 0;
439                         if (option_verbose > 2)
440                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
441                 } else if (!strcasecmp(var->name, "preprocess")) {
442                         preproc = ast_true(var->value) ? 1 : 0;
443                         if (option_verbose > 2)
444                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessing. [%s]\n",preproc ? "on" : "off");
445                 } else if (!strcasecmp(var->name, "pp_vad")) {
446                         pp_vad = ast_true(var->value) ? 1 : 0;
447                         if (option_verbose > 2)
448                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor VAD. [%s]\n",pp_vad ? "on" : "off");
449                 } else if (!strcasecmp(var->name, "pp_agc")) {
450                         pp_agc = ast_true(var->value) ? 1 : 0;
451                         if (option_verbose > 2)
452                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor AGC. [%s]\n",pp_agc ? "on" : "off");
453                 } else if (!strcasecmp(var->name, "pp_agc_level")) {
454                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
455                                 if (option_verbose > 2)
456                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor AGC Level to %f\n",res_f);
457                                 pp_agc_level = res_f;
458                         } else
459                                 ast_log(LOG_ERROR,"Error! Preprocessor AGC Level must be >= 0\n");
460                 } else if (!strcasecmp(var->name, "pp_denoise")) {
461                         pp_denoise = ast_true(var->value) ? 1 : 0;
462                         if (option_verbose > 2)
463                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Denoise. [%s]\n",pp_denoise ? "on" : "off");
464                 } else if (!strcasecmp(var->name, "pp_dereverb")) {
465                         pp_dereverb = ast_true(var->value) ? 1 : 0;
466                         if (option_verbose > 2)
467                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Preprocessor Dereverb. [%s]\n",pp_dereverb ? "on" : "off");
468                 } else if (!strcasecmp(var->name, "pp_dereverb_decay")) {
469                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
470                                 if (option_verbose > 2)
471                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Decay to %f\n",res_f);
472                                 pp_dereverb_decay = res_f;
473                         } else
474                                 ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Decay must be >= 0\n");
475                 } else if (!strcasecmp(var->name, "pp_dereverb_level")) {
476                         if (sscanf(var->value, "%f", &res_f) == 1 && res_f >= 0) {
477                                 if (option_verbose > 2)
478                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting preprocessor Dereverb Level to %f\n",res_f);
479                                 pp_dereverb_level = res_f;
480                         } else
481                                 ast_log(LOG_ERROR,"Error! Preprocessor Dereverb Level must be >= 0\n");
482                 }
483         }
484         ast_config_destroy(cfg);
485 }
486
487 static int reload(void) 
488 {
489         parse_config();
490
491         return 0;
492 }
493
494 static int unload_module(void)
495 {
496         int res;
497
498         res = ast_unregister_translator(&lintospeex);
499         res |= ast_unregister_translator(&speextolin);
500
501         return res;
502 }
503
504 static int load_module(void)
505 {
506         int res;
507
508         parse_config();
509         res=ast_register_translator(&speextolin);
510         if (!res) 
511                 res=ast_register_translator(&lintospeex);
512         else
513                 ast_unregister_translator(&speextolin);
514
515         return res;
516 }
517
518 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Speex Coder/Decoder",
519                 .load = load_module,
520                 .unload = unload_module,
521                 .reload = reload,
522                );