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