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