merge rizzo's codec module rework (very similar to the format module rework)
[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  * \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
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include "asterisk/lock.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/config.h"
44 #include "asterisk/options.h"
45 #include "asterisk/module.h"
46 #include "asterisk/logger.h"
47 #include "asterisk/channel.h"
48 #include "asterisk/utils.h"
49
50 #include "lpc10/lpc10.h"
51
52 /* Sample frame data */
53 #include "slin_lpc10_ex.h"
54 #include "lpc10_slin_ex.h"
55
56 /* We use a very strange format here...  I have no idea why...  The frames are 180
57    samples long, which isn't even an even number of milliseconds...  Not only that
58    but we hvae to waste two bits of each frame to keep them ending on a byte boundary
59    because the frames are 54 bits long */
60
61 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
62
63 #define BUFFER_SAMPLES  8000
64
65 struct lpc10_coder_pvt {
66         union {
67                 struct lpc10_encoder_state *enc;
68                 struct lpc10_decoder_state *dec;
69         } lpc10;
70         /* Enough to store a full second */
71         short buf[BUFFER_SAMPLES];
72         int longer;
73 };
74
75 static void *lpc10_enc_new(struct ast_trans_pvt *pvt)
76 {
77         struct lpc10_coder_pvt *tmp = pvt->pvt;
78
79         if (!(tmp->lpc10.enc = create_lpc10_encoder_state()))
80                 return NULL;
81         return tmp;
82 }
83
84 static void *lpc10_dec_new(struct ast_trans_pvt *pvt)
85 {
86         struct lpc10_coder_pvt *tmp = pvt->pvt;
87
88         if (!(tmp->lpc10.dec = create_lpc10_decoder_state()))
89                 return NULL;
90         return tmp;
91 }
92
93 static struct ast_frame *lintolpc10_sample(void)
94 {
95         static struct ast_frame f;
96         f.frametype = AST_FRAME_VOICE;
97         f.subclass = AST_FORMAT_SLINEAR;
98         f.datalen = sizeof(slin_lpc10_ex);
99         /* Assume 8000 Hz */
100         f.samples = LPC10_SAMPLES_PER_FRAME;
101         f.mallocd = 0;
102         f.offset = 0;
103         f.src = __PRETTY_FUNCTION__;
104         f.data = slin_lpc10_ex;
105         return &f;
106 }
107
108 static struct ast_frame *lpc10tolin_sample(void)
109 {
110         static struct ast_frame f;
111         f.frametype = AST_FRAME_VOICE;
112         f.subclass = AST_FORMAT_LPC10;
113         f.datalen = sizeof(lpc10_slin_ex);
114         /* All frames are 22 ms long (maybe a little more -- why did he choose
115            LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
116         f.samples = LPC10_SAMPLES_PER_FRAME;
117         f.mallocd = 0;
118         f.offset = 0;
119         f.src = __PRETTY_FUNCTION__;
120         f.data = lpc10_slin_ex;
121         return &f;
122 }
123
124 static void extract_bits(INT32 *bits, unsigned char *c)
125 {
126         int x;
127         for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
128                 if (*c & (0x80 >> (x & 7)))
129                         bits[x] = 1;
130                 else
131                         bits[x] = 0;
132                 if ((x & 7) == 7)
133                         c++;
134         }
135 }
136
137 /* XXX note lpc10_encode() produces one bit per word in bits[] */
138 static void build_bits(unsigned char *c, INT32 *bits)
139 {
140         unsigned char mask=0x80;
141         int x;
142         *c = 0;
143         for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
144                 if (bits[x])
145                         *c |= mask;
146                 mask = mask >> 1;
147                 if ((x % 8)==7) {
148                         c++;
149                         *c = 0;
150                         mask = 0x80;
151                 }
152         }
153 }
154
155 static int lpc10tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
156 {
157         struct lpc10_coder_pvt *tmp = pvt->pvt;
158         int16_t *dst = (int16_t *)pvt->outbuf;
159         int len = 0;
160
161         while (len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
162                 int x;
163                 float tmpbuf[LPC10_SAMPLES_PER_FRAME];
164                 INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME]; /* XXX see note */
165                 if (pvt->samples + LPC10_SAMPLES_PER_FRAME > BUFFER_SAMPLES) {
166                         ast_log(LOG_WARNING, "Out of buffer space\n");
167                         return -1;
168                 }
169                 extract_bits(bits, f->data + len);
170                 if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
171                         ast_log(LOG_WARNING, "Invalid lpc10 data\n");
172                         return -1;
173                 }
174                 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
175                         /* Convert to a short between -1.0 and 1.0 */
176                         dst[pvt->samples + x] = (int16_t)(32768.0 * tmpbuf[x]);
177                 }
178
179                 pvt->samples += LPC10_SAMPLES_PER_FRAME;
180                 pvt->datalen += 2*LPC10_SAMPLES_PER_FRAME;
181                 len += LPC10_BYTES_IN_COMPRESSED_FRAME;
182         }
183         if (len != f->datalen) 
184                 printf("Decoded %d, expected %d\n", len, f->datalen);
185         return 0;
186 }
187
188 static int lintolpc10_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
189 {
190         struct lpc10_coder_pvt *tmp = pvt->pvt;
191
192         /* Just add the frames to our stream */
193         if (pvt->samples + f->samples > BUFFER_SAMPLES) {
194                 ast_log(LOG_WARNING, "Out of buffer space\n");
195                 return -1;
196         }
197         memcpy(tmp->buf + pvt->samples, f->data, f->datalen);
198         pvt->samples += f->samples;
199         return 0;
200 }
201
202 static struct ast_frame *lintolpc10_frameout(struct ast_trans_pvt *pvt)
203 {
204         struct lpc10_coder_pvt *tmp = pvt->pvt;
205         int x;
206         int datalen = 0;        /* output frame */
207         int samples = 0;        /* output samples */
208         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
209         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];     /* XXX what ??? */
210         /* We can't work on anything less than a frame in size */
211         if (pvt->samples < LPC10_SAMPLES_PER_FRAME)
212                 return NULL;
213         while (pvt->samples >=  LPC10_SAMPLES_PER_FRAME) {
214                 /* Encode a frame of data */
215                 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++)
216                         tmpbuf[x] = (float)tmp->buf[x + samples] / 32768.0;
217                 lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
218                 build_bits(pvt->outbuf + datalen, bits);
219                 datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
220                 samples += LPC10_SAMPLES_PER_FRAME;
221                 pvt->samples -= LPC10_SAMPLES_PER_FRAME;
222                 /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
223                    important for IAX use */
224                 tmp->longer = 1 - tmp->longer;
225 #if 0   /* what the heck was this for? */
226                 ((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
227 #endif          
228         }
229         /* Move the data at the end of the buffer to the front */
230         if (pvt->samples)
231                 memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
232         return ast_trans_frameout(pvt, datalen, samples);
233 }
234
235
236 static void lpc10_destroy(struct ast_trans_pvt *arg)
237 {
238         struct lpc10_coder_pvt *pvt = arg->pvt;
239         /* Enc and DEC are both just allocated, so they can be freed */
240         free(pvt->lpc10.enc);
241 }
242
243 static struct ast_module_lock me = { .usecnt = -1 };
244
245 static struct ast_translator lpc10tolin = {
246         .name = "lpc10tolin", 
247         .srcfmt = AST_FORMAT_LPC10,
248         .dstfmt = AST_FORMAT_SLINEAR,
249         .newpvt = lpc10_dec_new,
250         .framein = lpc10tolin_framein,
251         .destroy = lpc10_destroy,
252         .sample = lpc10tolin_sample,
253         .lockp = &me,
254         .desc_size = sizeof(struct lpc10_coder_pvt),
255         .buffer_samples = BUFFER_SAMPLES,
256         .plc_samples = LPC10_SAMPLES_PER_FRAME,
257         .buf_size = BUFFER_SAMPLES * 2,
258 };
259
260 static struct ast_translator lintolpc10 = {
261         .name = "lintolpc10", 
262         .srcfmt = AST_FORMAT_SLINEAR,
263         .dstfmt = AST_FORMAT_LPC10,
264         .newpvt = lpc10_enc_new,
265         .framein = lintolpc10_framein,
266         .frameout = lintolpc10_frameout,
267         .destroy = lpc10_destroy,
268         .sample = lintolpc10_sample,
269         .lockp = &me,
270         .desc_size = sizeof(struct lpc10_coder_pvt),
271         .buffer_samples = BUFFER_SAMPLES,
272         .buf_size = LPC10_BYTES_IN_COMPRESSED_FRAME * (1 + BUFFER_SAMPLES / LPC10_SAMPLES_PER_FRAME),
273 };
274
275 static void parse_config(void)
276 {
277         struct ast_variable *var;
278         struct ast_config *cfg = ast_config_load("codecs.conf");
279         if (!cfg)
280                 return;
281         for (var = ast_variable_browse(cfg, "plc"); var; var = var->next) {
282                if (!strcasecmp(var->name, "genericplc")) {
283                         lpc10tolin.useplc = ast_true(var->value) ? 1 : 0;
284                         if (option_verbose > 2)
285                                ast_verbose(VERBOSE_PREFIX_3 "codec_lpc10: %susing generic PLC\n",
286                                         lpc10tolin.useplc ? "" : "not ");
287                 }
288         }
289         ast_config_destroy(cfg);
290 }
291
292 int reload(void)
293 {
294         parse_config();
295         return 0;
296 }
297
298
299 int unload_module(void)
300 {
301         int res;
302         ast_mutex_lock(&me.lock);
303         res = ast_unregister_translator(&lintolpc10);
304         if (!res)
305                 res = ast_unregister_translator(&lpc10tolin);
306         if (me.usecnt)
307                 res = -1;
308         ast_mutex_unlock(&me.lock);
309         return res;
310 }
311
312 int load_module(void)
313 {
314         int res;
315         parse_config();
316         res=ast_register_translator(&lpc10tolin);
317         if (!res) 
318                 res=ast_register_translator(&lintolpc10);
319         else
320                 ast_unregister_translator(&lpc10tolin);
321         return res;
322 }
323
324 char *description(void)
325 {
326         return "LPC10 2.4kbps (signed linear) Voice Coder";
327 }
328
329 int usecount(void)
330 {
331         return me.usecnt;
332 }
333
334 char *key()
335 {
336         return ASTERISK_GPL_KEY;
337 }