fix compiler warnings
[asterisk/asterisk.git] / codecs / codec_lpc10.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  * The lpc10 code is from a library used by nautilus, modified to be a bit
9  * nicer to the compiler.
10  * See http://www.arl.wustl.edu/~jaf/ 
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22
23 /*! \file
24  *
25  * \brief Translate between signed linear and LPC10 (Linear Predictor Code)
26  *
27  */
28
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <netinet/in.h>
33 #include <string.h>
34 #include <stdio.h>
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include "asterisk/lock.h"
41 #include "asterisk/translate.h"
42 #include "asterisk/config.h"
43 #include "asterisk/options.h"
44 #include "asterisk/module.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/channel.h"
47
48 #include "lpc10/lpc10.h"
49
50 /* Sample frame data */
51 #include "slin_lpc10_ex.h"
52 #include "lpc10_slin_ex.h"
53
54 /* We use a very strange format here...  I have no idea why...  The frames are 180
55    samples long, which isn't even an even number of milliseconds...  Not only that
56    but we hvae to waste two bits of each frame to keep them ending on a byte boundary
57    because the frames are 54 bits long */
58
59 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
60
61 AST_MUTEX_DEFINE_STATIC(localuser_lock);
62 static int localusecnt=0;
63
64 static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder";
65
66 static int useplc = 0;
67
68 struct ast_translator_pvt {
69         union {
70                 struct lpc10_encoder_state *enc;
71                 struct lpc10_decoder_state *dec;
72         } lpc10;
73         struct ast_frame f;
74         /* Space to build offset */
75         char offset[AST_FRIENDLY_OFFSET];
76         /* Buffer for our outgoing frame */
77         short outbuf[8000];
78         /* Enough to store a full second */
79         short buf[8000];
80         int tail;
81         int longer;
82         plc_state_t plc; /* god only knows why I bothered to implement PLC for LPC10 :) */
83 };
84
85 #define lpc10_coder_pvt ast_translator_pvt
86
87 static struct ast_translator_pvt *lpc10_enc_new(void)
88 {
89         struct lpc10_coder_pvt *tmp;
90         tmp = malloc(sizeof(struct lpc10_coder_pvt));
91         if (tmp) {
92                 if (!(tmp->lpc10.enc = create_lpc10_encoder_state())) {
93                         free(tmp);
94                         tmp = NULL;
95                 }
96                 tmp->tail = 0;
97                 tmp->longer = 0;
98                 localusecnt++;
99         }
100         return tmp;
101 }
102
103 static struct ast_translator_pvt *lpc10_dec_new(void)
104 {
105         struct lpc10_coder_pvt *tmp;
106         tmp = malloc(sizeof(struct lpc10_coder_pvt));
107         if (tmp) {
108                 if (!(tmp->lpc10.dec = create_lpc10_decoder_state())) {
109                         free(tmp);
110                         tmp = NULL;
111                 }
112                 tmp->tail = 0;
113                 tmp->longer = 0;
114                 plc_init(&tmp->plc);
115                 localusecnt++;
116         }
117         return tmp;
118 }
119 static struct ast_frame *lintolpc10_sample(void)
120 {
121         static struct ast_frame f;
122         f.frametype = AST_FRAME_VOICE;
123         f.subclass = AST_FORMAT_SLINEAR;
124         f.datalen = sizeof(slin_lpc10_ex);
125         /* Assume 8000 Hz */
126         f.samples = LPC10_SAMPLES_PER_FRAME;
127         f.mallocd = 0;
128         f.offset = 0;
129         f.src = __PRETTY_FUNCTION__;
130         f.data = slin_lpc10_ex;
131         return &f;
132 }
133
134 static struct ast_frame *lpc10tolin_sample(void)
135 {
136         static struct ast_frame f;
137         f.frametype = AST_FRAME_VOICE;
138         f.subclass = AST_FORMAT_LPC10;
139         f.datalen = sizeof(lpc10_slin_ex);
140         /* All frames are 22 ms long (maybe a little more -- why did he choose
141            LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
142         f.samples = LPC10_SAMPLES_PER_FRAME;
143         f.mallocd = 0;
144         f.offset = 0;
145         f.src = __PRETTY_FUNCTION__;
146         f.data = lpc10_slin_ex;
147         return &f;
148 }
149
150 static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp)
151 {
152         if (!tmp->tail)
153                 return NULL;
154         /* Signed linear is no particular frame size, so just send whatever
155            we have in the buffer in one lump sum */
156         tmp->f.frametype = AST_FRAME_VOICE;
157         tmp->f.subclass = AST_FORMAT_SLINEAR;
158         tmp->f.datalen = tmp->tail * 2;
159         /* Assume 8000 Hz */
160         tmp->f.samples = tmp->tail;
161         tmp->f.mallocd = 0;
162         tmp->f.offset = AST_FRIENDLY_OFFSET;
163         tmp->f.src = __PRETTY_FUNCTION__;
164         tmp->f.data = tmp->buf;
165         /* Reset tail pointer */
166         tmp->tail = 0;
167
168 #if 0
169         /* Save a sample frame */
170         { static int samplefr = 0;
171         if (samplefr == 80) {
172                 int fd;
173                 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
174                 write(fd, tmp->f.data, tmp->f.datalen);
175                 close(fd);
176         }               
177         samplefr++;
178         }
179 #endif
180         return &tmp->f; 
181 }
182
183 static void extract_bits(INT32 *bits, unsigned char *c)
184 {
185         int x;
186         for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
187                 if (*c & (0x80 >> (x & 7)))
188                         bits[x] = 1;
189                 else
190                         bits[x] = 0;
191                 if ((x & 7) == 7)
192                         c++;
193         }
194 }
195
196 static void build_bits(unsigned char *c, INT32 *bits)
197 {
198         unsigned char mask=0x80;
199         int x;
200         *c = 0;
201         for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
202                 if (bits[x])
203                         *c |= mask;
204                 mask = mask >> 1;
205                 if ((x % 8)==7) {
206                         c++;
207                         *c = 0;
208                         mask = 0x80;
209                 }
210         }
211 }
212
213 static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
214 {
215         /* Assuming there's space left, decode into the current buffer at
216            the tail location */
217         int x;
218         int len=0;
219         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
220         short *sd;
221         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
222
223         if(f->datalen == 0) { /* perform PLC with nominal framesize of LPC10_SAMPLES_PER_FRAME */
224               if((tmp->tail + LPC10_SAMPLES_PER_FRAME) > sizeof(tmp->buf)/2) {
225                   ast_log(LOG_WARNING, "Out of buffer space\n");
226                   return -1;
227               }
228               if(useplc) {
229                   plc_fillin(&tmp->plc, tmp->buf+tmp->tail, LPC10_SAMPLES_PER_FRAME);
230                   tmp->tail += LPC10_SAMPLES_PER_FRAME;
231               }
232               return 0;
233         }
234
235         while(len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
236                 if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
237                         sd = tmp->buf + tmp->tail;
238                         extract_bits(bits, f->data + len);
239                         if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
240                                 ast_log(LOG_WARNING, "Invalid lpc10 data\n");
241                                 return -1;
242                         }
243                         for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
244                                 /* Convert to a real between -1.0 and 1.0 */
245                                 sd[x] = 32768.0 * tmpbuf[x];
246                         }
247
248                         if(useplc) plc_rx(&tmp->plc, tmp->buf + tmp->tail, LPC10_SAMPLES_PER_FRAME);
249                         
250                         tmp->tail+=LPC10_SAMPLES_PER_FRAME;
251                 } else {
252                         ast_log(LOG_WARNING, "Out of buffer space\n");
253                         return -1;
254                 }
255                 len += LPC10_BYTES_IN_COMPRESSED_FRAME;
256         }
257         if (len != f->datalen) 
258                 printf("Decoded %d, expected %d\n", len, f->datalen);
259         return 0;
260 }
261
262 static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
263 {
264         /* Just add the frames to our stream */
265         /* XXX We should look at how old the rest of our stream is, and if it
266            is too old, then we should overwrite it entirely, otherwise we can
267            get artifacts of earlier talk that do not belong */
268         if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
269                 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
270                 tmp->tail += f->datalen/2;
271         } else {
272                 ast_log(LOG_WARNING, "Out of buffer space\n");
273                 return -1;
274         }
275         return 0;
276 }
277
278 static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
279 {
280         int x;
281         int consumed = 0;
282         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
283         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
284         /* We can't work on anything less than a frame in size */
285         if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
286                 return NULL;
287         /* Start with an empty frame */
288         tmp->f.samples = 0;
289         tmp->f.datalen = 0;
290         tmp->f.frametype = AST_FRAME_VOICE;
291         tmp->f.subclass = AST_FORMAT_LPC10;
292         while(tmp->tail >=  LPC10_SAMPLES_PER_FRAME) {
293                 if (tmp->f.datalen + LPC10_BYTES_IN_COMPRESSED_FRAME > sizeof(tmp->outbuf)) {
294                         ast_log(LOG_WARNING, "Out of buffer space\n");
295                         return NULL;
296                 }
297                 /* Encode a frame of data */
298                 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
299                         tmpbuf[x] = (float)tmp->buf[x+consumed] / 32768.0;
300                 }
301                 lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
302                 build_bits(((unsigned char *)tmp->outbuf) + tmp->f.datalen, bits);
303                 tmp->f.datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
304                 tmp->f.samples += LPC10_SAMPLES_PER_FRAME;
305                 /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
306                    important for IAX use */
307                 tmp->longer = 1 - tmp->longer;
308 #if 0   /* what the heck was this for? */
309                 ((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
310 #endif          
311                 tmp->tail -= LPC10_SAMPLES_PER_FRAME;
312                 consumed += LPC10_SAMPLES_PER_FRAME;
313         }
314         tmp->f.mallocd = 0;
315         tmp->f.offset = AST_FRIENDLY_OFFSET;
316         tmp->f.src = __PRETTY_FUNCTION__;
317         tmp->f.data = tmp->outbuf;
318         /* Move the data at the end of the buffer to the front */
319         if (tmp->tail)
320                 memmove(tmp->buf, tmp->buf + consumed, tmp->tail * 2);
321 #if 0
322         /* Save a sample frame */
323         { static int samplefr = 0;
324         if (samplefr == 0) {
325                 int fd;
326                 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
327                 write(fd, tmp->f.data, tmp->f.datalen);
328                 close(fd);
329         }               
330         samplefr++;
331         }
332 #endif
333         return &tmp->f; 
334 }
335
336 static void lpc10_destroy(struct ast_translator_pvt *pvt)
337 {
338         /* Enc and DEC are both just allocated, so they can be freed */
339         free(pvt->lpc10.enc);
340         free(pvt);
341         localusecnt--;
342 }
343
344 static struct ast_translator lpc10tolin =
345         { "lpc10tolin", 
346            AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
347            lpc10_dec_new,
348            lpc10tolin_framein,
349            lpc10tolin_frameout,
350            lpc10_destroy,
351            lpc10tolin_sample
352            };
353
354 static struct ast_translator lintolpc10 =
355         { "lintolpc10", 
356            AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
357            lpc10_enc_new,
358            lintolpc10_framein,
359            lintolpc10_frameout,
360            lpc10_destroy,
361            lintolpc10_sample
362            };
363
364 static void parse_config(void)
365 {
366         struct ast_config *cfg;
367         struct ast_variable *var;
368         if ((cfg = ast_config_load("codecs.conf"))) {
369                 if ((var = ast_variable_browse(cfg, "plc"))) {
370                         while (var) {
371                                if (!strcasecmp(var->name, "genericplc")) {
372                                        useplc = ast_true(var->value) ? 1 : 0;
373                                        if (option_verbose > 2)
374                                                ast_verbose(VERBOSE_PREFIX_3 "codec_lpc10: %susing generic PLC\n", useplc ? "" : "not ");
375                                }
376                                var = var->next;
377                         }
378                 }
379                 ast_config_destroy(cfg);
380         }
381 }
382
383 int reload(void)
384 {
385         parse_config();
386         return 0;
387 }
388
389
390 int unload_module(void)
391 {
392         int res;
393         ast_mutex_lock(&localuser_lock);
394         res = ast_unregister_translator(&lintolpc10);
395         if (!res)
396                 res = ast_unregister_translator(&lpc10tolin);
397         if (localusecnt)
398                 res = -1;
399         ast_mutex_unlock(&localuser_lock);
400         return res;
401 }
402
403 int load_module(void)
404 {
405         int res;
406         parse_config();
407         res=ast_register_translator(&lpc10tolin);
408         if (!res) 
409                 res=ast_register_translator(&lintolpc10);
410         else
411                 ast_unregister_translator(&lpc10tolin);
412         return res;
413 }
414
415 char *description(void)
416 {
417         return tdesc;
418 }
419
420 int usecount(void)
421 {
422         int res;
423         STANDARD_USECOUNT(res);
424         return res;
425 }
426
427 char *key()
428 {
429         return ASTERISK_GPL_KEY;
430 }