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