Add PLC and jitter buffer and iax2 meta trunk with timestamps (bug #2532, #3400)
[asterisk/asterisk.git] / codecs / codec_speex.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Translate between signed linear and Speex (Open Codec)
5  *
6  * Copyright (C) 2002, Digium
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  *
13  * This work was motivated by Jeremy McNamara 
14  * hacked to be configurable by anthm and bkw 9/28/2004
15  */
16
17 static int quality = 8;
18 static int complexity = 2;
19 static int enhancement = 0;
20 static int vad = 0;
21 static int vbr = 0;
22 static int vbr_quality = 0;
23 static int abr = 0;
24 static int dtx = 0;
25
26 #define TYPE_SILENCE     0x2
27 #define TYPE_HIGH        0x0
28 #define TYPE_LOW         0x1
29 #define TYPE_MASK        0x3
30
31 #include <asterisk/lock.h>
32 #include <asterisk/translate.h>
33 #include <asterisk/module.h>
34 #include <asterisk/config.h>
35 #include <asterisk/options.h>
36 #include <asterisk/logger.h>
37 #include <asterisk/channel.h>
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
45 #include <speex.h>
46
47 /* Sample frame data */
48 #include "slin_speex_ex.h"
49 #include "speex_slin_ex.h"
50
51 AST_MUTEX_DEFINE_STATIC(localuser_lock);
52 static int localusecnt=0;
53
54 static char *tdesc = "Speex/PCM16 (signed linear) Codec Translator";
55
56 struct ast_translator_pvt {
57         void *speex;
58         struct ast_frame f;
59         SpeexBits bits;
60         int framesize;
61         /* Space to build offset */
62         char offset[AST_FRIENDLY_OFFSET];
63         /* Buffer for our outgoing frame */
64         short outbuf[8000];
65         /* Enough to store a full second */
66         short buf[8000];
67         int tail;
68 };
69
70 #define speex_coder_pvt ast_translator_pvt
71
72 static struct ast_translator_pvt *lintospeex_new(void)
73 {
74         struct speex_coder_pvt *tmp;
75         tmp = malloc(sizeof(struct speex_coder_pvt));
76         if (tmp) {
77                 if (!(tmp->speex = speex_encoder_init(&speex_nb_mode))) {
78                         free(tmp);
79                         tmp = NULL;
80                 } else {
81                         speex_bits_init(&tmp->bits);
82                         speex_bits_reset(&tmp->bits);
83                         speex_encoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
84                         speex_encoder_ctl(tmp->speex, SPEEX_SET_COMPLEXITY, &complexity);
85
86                         if(!abr && !vbr) {
87                                 speex_encoder_ctl(tmp->speex, SPEEX_SET_QUALITY, &quality);
88                                 if (vad)
89                                         speex_encoder_ctl(tmp->speex, SPEEX_SET_VAD, &vad);
90                                 if (dtx)
91                                         speex_encoder_ctl(tmp->speex, SPEEX_SET_DTX, &vad);
92                         }
93                         if (vbr) {
94                                 speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR, &vbr);
95                                 speex_encoder_ctl(tmp->speex, SPEEX_SET_VBR_QUALITY, &vbr_quality);
96                         }
97                         if (abr) {
98                                 speex_encoder_ctl(tmp->speex, SPEEX_SET_ABR, &abr);
99                         }
100                         tmp->tail = 0;
101                 }
102                 localusecnt++;
103         }
104         return tmp;
105 }
106
107 static struct ast_translator_pvt *speextolin_new(void)
108 {
109         struct speex_coder_pvt *tmp;
110         tmp = malloc(sizeof(struct speex_coder_pvt));
111         if (tmp) {
112                 if (!(tmp->speex = speex_decoder_init(&speex_nb_mode))) {
113                         free(tmp);
114                         tmp = NULL;
115                 } else {
116                         speex_bits_init(&tmp->bits);
117                         speex_decoder_ctl(tmp->speex, SPEEX_GET_FRAME_SIZE, &tmp->framesize);
118                         if (enhancement)
119                                 speex_decoder_ctl(tmp->speex, SPEEX_SET_ENH, &enhancement);
120                         tmp->tail = 0;
121                 }
122                 localusecnt++;
123         }
124         return tmp;
125 }
126
127 static struct ast_frame *lintospeex_sample(void)
128 {
129         static struct ast_frame f;
130         f.frametype = AST_FRAME_VOICE;
131         f.subclass = AST_FORMAT_SLINEAR;
132         f.datalen = sizeof(slin_speex_ex);
133         /* Assume 8000 Hz */
134         f.samples = sizeof(slin_speex_ex)/2;
135         f.mallocd = 0;
136         f.offset = 0;
137         f.src = __PRETTY_FUNCTION__;
138         f.data = slin_speex_ex;
139         return &f;
140 }
141
142 static struct ast_frame *speextolin_sample(void)
143 {
144         static struct ast_frame f;
145         f.frametype = AST_FRAME_VOICE;
146         f.subclass = AST_FORMAT_SPEEX;
147         f.datalen = sizeof(speex_slin_ex);
148         /* All frames are 20 ms long */
149         f.samples = 160;
150         f.mallocd = 0;
151         f.offset = 0;
152         f.src = __PRETTY_FUNCTION__;
153         f.data = speex_slin_ex;
154         return &f;
155 }
156
157 static struct ast_frame *speextolin_frameout(struct ast_translator_pvt *tmp)
158 {
159         if (!tmp->tail)
160                 return NULL;
161         /* Signed linear is no particular frame size, so just send whatever
162            we have in the buffer in one lump sum */
163         tmp->f.frametype = AST_FRAME_VOICE;
164         tmp->f.subclass = AST_FORMAT_SLINEAR;
165         tmp->f.datalen = tmp->tail * 2;
166         /* Assume 8000 Hz */
167         tmp->f.samples = tmp->tail;
168         tmp->f.mallocd = 0;
169         tmp->f.offset = AST_FRIENDLY_OFFSET;
170         tmp->f.src = __PRETTY_FUNCTION__;
171         tmp->f.data = tmp->buf;
172         /* Reset tail pointer */
173         tmp->tail = 0;
174         return &tmp->f; 
175 }
176
177 static int speextolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
178 {
179         /* Assuming there's space left, decode into the current buffer at
180            the tail location.  Read in as many frames as there are */
181         int x;
182         int res;
183         float fout[1024];
184
185         if(f->datalen == 0) {  /* Native PLC interpolation */
186                 if(tmp->tail + tmp->framesize > sizeof(tmp->buf) / 2) {
187                         ast_log(LOG_WARNING, "Out of buffer space\n");
188                         return -1;
189                 }
190                 speex_decode(tmp->speex, NULL, fout);
191                 for (x=0;x<tmp->framesize;x++) {
192                         tmp->buf[tmp->tail + x] = fout[x];
193                 }
194                 tmp->tail += tmp->framesize;
195                 return 0;
196         }
197
198
199         /* Read in bits */
200         speex_bits_read_from(&tmp->bits, f->data, f->datalen);
201         for(;;) {
202                 res = speex_decode(tmp->speex, &tmp->bits, fout);
203                 if (res < 0)
204                         break;
205                 if (tmp->tail + tmp->framesize < sizeof(tmp->buf) / 2) {
206                         for (x=0;x<tmp->framesize;x++) {
207                                 tmp->buf[tmp->tail + x] = fout[x];
208                         }
209                         tmp->tail += tmp->framesize;
210                 } else {
211                         ast_log(LOG_WARNING, "Out of buffer space\n");
212                         return -1;
213                 }
214                 
215         }
216         return 0;
217 }
218
219 static int lintospeex_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
220 {
221         /* Just add the frames to our stream */
222         /* XXX We should look at how old the rest of our stream is, and if it
223            is too old, then we should overwrite it entirely, otherwise we can
224            get artifacts of earlier talk that do not belong */
225         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
226                 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
227                 tmp->tail += f->datalen/2;
228         } else {
229                 ast_log(LOG_WARNING, "Out of buffer space\n");
230                 return -1;
231         }
232         return 0;
233 }
234
235 static struct ast_frame *lintospeex_frameout(struct ast_translator_pvt *tmp)
236 {
237         float fbuf[1024];
238         int len;
239         int y=0,x;
240         /* We can't work on anything less than a frame in size */
241         if (tmp->tail < tmp->framesize)
242                 return NULL;
243         tmp->f.frametype = AST_FRAME_VOICE;
244         tmp->f.subclass = AST_FORMAT_SPEEX;
245         tmp->f.mallocd = 0;
246         tmp->f.offset = AST_FRIENDLY_OFFSET;
247         tmp->f.src = __PRETTY_FUNCTION__;
248         tmp->f.data = tmp->outbuf;
249         speex_bits_reset(&tmp->bits);
250         while(tmp->tail >= tmp->framesize) {
251                 /* Convert to floating point */
252                 for (x=0;x<tmp->framesize;x++)
253                         fbuf[x] = tmp->buf[x];
254                 /* Encode a frame of data */
255                 speex_encode(tmp->speex, fbuf, &tmp->bits);
256                 /* Assume 8000 Hz -- 20 ms */
257                 tmp->tail -= tmp->framesize;
258                 /* Move the data at the end of the buffer to the front */
259                 if (tmp->tail)
260                         memmove(tmp->buf, tmp->buf + tmp->framesize, tmp->tail * 2);
261                 y++;
262         }
263         /* Terminate bit stream */
264         speex_bits_pack(&tmp->bits, 15, 5);
265         len = speex_bits_write(&tmp->bits, (char *)tmp->outbuf, sizeof(tmp->outbuf));
266         tmp->f.datalen = len;
267         tmp->f.samples = y * 160;
268 #if 0
269         {
270                 static int fd = -1;
271                 if (fd  < 0) {
272                         fd = open("speex.raw", O_WRONLY|O_TRUNC|O_CREAT);
273                         if (fd > -1) {
274                                 write(fd, tmp->f.data, tmp->f.datalen);
275                                 close(fd);
276                         }
277                 }
278         }
279 #endif  
280         return &tmp->f; 
281 }
282
283 static void speextolin_destroy(struct ast_translator_pvt *pvt)
284 {
285         speex_decoder_destroy(pvt->speex);
286         speex_bits_destroy(&pvt->bits);
287         free(pvt);
288         localusecnt--;
289 }
290
291 static void lintospeex_destroy(struct ast_translator_pvt *pvt)
292 {
293         speex_encoder_destroy(pvt->speex);
294         speex_bits_destroy(&pvt->bits);
295         free(pvt);
296         localusecnt--;
297 }
298
299 static struct ast_translator speextolin =
300         { "speextolin", 
301            AST_FORMAT_SPEEX, AST_FORMAT_SLINEAR,
302            speextolin_new,
303            speextolin_framein,
304            speextolin_frameout,
305            speextolin_destroy,
306            speextolin_sample
307            };
308
309 static struct ast_translator lintospeex =
310         { "lintospeex", 
311            AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX,
312            lintospeex_new,
313            lintospeex_framein,
314            lintospeex_frameout,
315            lintospeex_destroy,
316            lintospeex_sample
317         };
318
319
320 static void parse_config(void) 
321 {
322         struct ast_config *cfg;
323         struct ast_variable *var;
324         int res;
325
326         if ((cfg = ast_config_load("codecs.conf"))) {
327                 if ((var = ast_variable_browse(cfg, "speex"))) {
328                         while (var) {
329                                 if (!strcasecmp(var->name, "quality")) {
330                                         res = abs(atoi(var->value));
331                                         if (res > -1 && res < 11) {
332                                                 if (option_verbose > 2)
333                                                         ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Quality to %d\n",res);
334                                                 ast_mutex_lock(&localuser_lock);
335                                                 quality = res;
336                                                 ast_mutex_unlock(&localuser_lock);
337                                         } else 
338                                                 ast_log(LOG_ERROR,"Error Quality must be 0-10\n");
339                                 } else if (!strcasecmp(var->name, "complexity")) {
340                                         res = abs(atoi(var->value));
341                                         if (option_verbose > 2)
342                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting Complexity to %d\n",res);
343                                         if (res > -1 && res < 11) {
344                                                 ast_mutex_lock(&localuser_lock);
345                                                 complexity = res;
346                                                 ast_mutex_unlock(&localuser_lock);
347                                         } else 
348                                                 ast_log(LOG_ERROR,"Error! Complexity must be 0-10\n");
349                                 } else if (!strcasecmp(var->name, "vbr_quality")) {
350                                         res = abs(atoi(var->value));
351                                         if (option_verbose > 2)
352                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting VBR Quality to %d\n",res);
353                                         if (res > -1 && res < 11) {
354                                                 ast_mutex_lock(&localuser_lock);
355                                                 vbr_quality = res;
356                                                 ast_mutex_unlock(&localuser_lock);
357                                         } else 
358                                                 ast_log(LOG_ERROR,"Error! VBR Quality must be 0-10\n");
359                                 } else if (!strcasecmp(var->name, "abr_quality")) {
360                                         ast_log(LOG_ERROR,"Error! ABR Quality setting obsolete, set ABR to desired bitrate\n");
361                                 } else if (!strcasecmp(var->name, "enhancement")) {
362                                         ast_mutex_lock(&localuser_lock);
363                                         enhancement = ast_true(var->value) ? 1 : 0;
364                                         if (option_verbose > 2)
365                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Perceptual Enhancement Mode. [%s]\n",enhancement ? "on" : "off");
366                                         ast_mutex_unlock(&localuser_lock);
367                                 } else if (!strcasecmp(var->name, "vbr")) {
368                                         ast_mutex_lock(&localuser_lock);
369                                         vbr = ast_true(var->value) ? 1 : 0;
370                                         if (option_verbose > 2)
371                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VBR Mode. [%s]\n",vbr ? "on" : "off");
372                                         ast_mutex_unlock(&localuser_lock);
373                                 } else if (!strcasecmp(var->name, "abr")) {
374                                         res = abs(atoi(var->value));
375                                         if (option_verbose > 2) {
376                                               if(res > 0)
377                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Setting ABR target bitrate to %d\n",res);
378                                               else
379                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: Disabling ABR\n");
380                                         }
381                                         if (res >= 0) {
382                                                 ast_mutex_lock(&localuser_lock);
383                                                 abr = res;
384                                                 ast_mutex_unlock(&localuser_lock);
385                                         } else 
386                                                 ast_log(LOG_ERROR,"Error! ABR target bitrate must be >= 0\n");
387                                 } else if (!strcasecmp(var->name, "vad")) {
388                                         ast_mutex_lock(&localuser_lock);
389                                         vad = ast_true(var->value) ? 1 : 0;
390                                         if (option_verbose > 2)
391                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: VAD Mode. [%s]\n",vbr ? "on" : "off");
392                                         ast_mutex_unlock(&localuser_lock);
393                                 } else if (!strcasecmp(var->name, "dtx")) {
394                                         ast_mutex_lock(&localuser_lock);
395                                         dtx = ast_true(var->value) ? 1 : 0;
396                                         if (option_verbose > 2)
397                                                 ast_verbose(VERBOSE_PREFIX_3 "CODEC SPEEX: DTX Mode. [%s]\n",dtx ? "on" : "off");
398                                         ast_mutex_unlock(&localuser_lock);
399                                 }
400                                 var = var->next;
401                         }
402                 }
403         }
404 }
405
406 int reload(void) 
407 {
408         parse_config();
409         return 0;
410 }
411
412 int unload_module(void)
413 {
414         int res;
415         ast_mutex_lock(&localuser_lock);
416         res = ast_unregister_translator(&lintospeex);
417         if (!res)
418                 res = ast_unregister_translator(&speextolin);
419         if (localusecnt)
420                 res = -1;
421         ast_mutex_unlock(&localuser_lock);
422         return res;
423 }
424
425 int load_module(void)
426 {
427         int res;
428         parse_config();
429         res=ast_register_translator(&speextolin);
430         if (!res) 
431                 res=ast_register_translator(&lintospeex);
432         else
433                 ast_unregister_translator(&speextolin);
434         return res;
435 }
436
437 char *description(void)
438 {
439         return tdesc;
440 }
441
442 int usecount(void)
443 {
444         int res;
445         STANDARD_USECOUNT(res);
446         return res;
447 }
448
449 char *key()
450 {
451         return ASTERISK_GPL_KEY;
452 }