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