Remove pthread.h from source. We should be using asterisk/lock.h everywhere instead...
[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 <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 AST_MUTEX_DEFINE_STATIC(localuser_lock);
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(void)
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(void)
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(void)
100 {
101         static struct ast_frame f;
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.samples = LPC10_SAMPLES_PER_FRAME;
107         f.mallocd = 0;
108         f.offset = 0;
109         f.src = __PRETTY_FUNCTION__;
110         f.data = slin_lpc10_ex;
111         return &f;
112 }
113
114 static struct ast_frame *lpc10tolin_sample(void)
115 {
116         static struct ast_frame f;
117         f.frametype = AST_FRAME_VOICE;
118         f.subclass = AST_FORMAT_LPC10;
119         f.datalen = sizeof(lpc10_slin_ex);
120         /* All frames are 22 ms long (maybe a little more -- why did he choose
121            LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
122         f.samples = LPC10_SAMPLES_PER_FRAME;
123         f.mallocd = 0;
124         f.offset = 0;
125         f.src = __PRETTY_FUNCTION__;
126         f.data = lpc10_slin_ex;
127         return &f;
128 }
129
130 static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp)
131 {
132         if (!tmp->tail)
133                 return NULL;
134         /* Signed linear is no particular frame size, so just send whatever
135            we have in the buffer in one lump sum */
136         tmp->f.frametype = AST_FRAME_VOICE;
137         tmp->f.subclass = AST_FORMAT_SLINEAR;
138         tmp->f.datalen = tmp->tail * 2;
139         /* Assume 8000 Hz */
140         tmp->f.samples = tmp->tail;
141         tmp->f.mallocd = 0;
142         tmp->f.offset = AST_FRIENDLY_OFFSET;
143         tmp->f.src = __PRETTY_FUNCTION__;
144         tmp->f.data = tmp->buf;
145         /* Reset tail pointer */
146         tmp->tail = 0;
147
148 #if 0
149         /* Save a sample frame */
150         { static int samplefr = 0;
151         if (samplefr == 80) {
152                 int fd;
153                 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
154                 write(fd, tmp->f.data, tmp->f.datalen);
155                 close(fd);
156         }               
157         samplefr++;
158         }
159 #endif
160         return &tmp->f; 
161 }
162
163 static void extract_bits(INT32 *bits, unsigned char *c)
164 {
165         int x;
166         for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
167                 if (*c & (0x80 >> (x & 7)))
168                         bits[x] = 1;
169                 else
170                         bits[x] = 0;
171                 if ((x & 7) == 7)
172                         c++;
173         }
174 }
175
176 static void build_bits(unsigned char *c, INT32 *bits)
177 {
178         unsigned char mask=0x80;
179         int x;
180         *c = 0;
181         for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
182                 if (bits[x])
183                         *c |= mask;
184                 mask = mask >> 1;
185                 if ((x % 8)==7) {
186                         c++;
187                         *c = 0;
188                         mask = 0x80;
189                 }
190         }
191 }
192
193 static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
194 {
195         /* Assuming there's space left, decode into the current buffer at
196            the tail location */
197         int x;
198         int len=0;
199         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
200         short *sd;
201         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
202         while(len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
203                 if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
204                         sd = tmp->buf + tmp->tail;
205                         extract_bits(bits, f->data + len);
206                         if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
207                                 ast_log(LOG_WARNING, "Invalid lpc10 data\n");
208                                 return -1;
209                         }
210                         for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
211                                 /* Convert to a real between -1.0 and 1.0 */
212                                 sd[x] = 32768.0 * tmpbuf[x];
213                         }
214                         
215                         tmp->tail+=LPC10_SAMPLES_PER_FRAME;
216                 } else {
217                         ast_log(LOG_WARNING, "Out of buffer space\n");
218                         return -1;
219                 }
220                 len += LPC10_BYTES_IN_COMPRESSED_FRAME;
221         }
222         if (len != f->datalen) 
223                 printf("Decoded %d, expected %d\n", len, f->datalen);
224         return 0;
225 }
226
227 static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
228 {
229         /* Just add the frames to our stream */
230         /* XXX We should look at how old the rest of our stream is, and if it
231            is too old, then we should overwrite it entirely, otherwise we can
232            get artifacts of earlier talk that do not belong */
233         if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
234                 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
235                 tmp->tail += f->datalen/2;
236         } else {
237                 ast_log(LOG_WARNING, "Out of buffer space\n");
238                 return -1;
239         }
240         return 0;
241 }
242
243 static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
244 {
245         int x;
246         int consumed = 0;
247         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
248         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
249         /* We can't work on anything less than a frame in size */
250         if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
251                 return NULL;
252         /* Start with an empty frame */
253         tmp->f.samples = 0;
254         tmp->f.datalen = 0;
255         tmp->f.frametype = AST_FRAME_VOICE;
256         tmp->f.subclass = AST_FORMAT_LPC10;
257         while(tmp->tail >=  LPC10_SAMPLES_PER_FRAME) {
258                 if (tmp->f.datalen + LPC10_BYTES_IN_COMPRESSED_FRAME > sizeof(tmp->outbuf)) {
259                         ast_log(LOG_WARNING, "Out of buffer space\n");
260                         return NULL;
261                 }
262                 /* Encode a frame of data */
263                 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
264                         tmpbuf[x] = (float)tmp->buf[x+consumed] / 32768.0;
265                 }
266                 lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
267                 build_bits(((unsigned char *)tmp->outbuf) + tmp->f.datalen, bits);
268                 tmp->f.datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
269                 tmp->f.samples += LPC10_SAMPLES_PER_FRAME;
270                 /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
271                    important for IAX use */
272                 tmp->longer = 1 - tmp->longer;
273 #if 0   /* what the heck was this for? */
274                 ((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
275 #endif          
276                 tmp->tail -= LPC10_SAMPLES_PER_FRAME;
277                 consumed += LPC10_SAMPLES_PER_FRAME;
278         }
279         tmp->f.mallocd = 0;
280         tmp->f.offset = AST_FRIENDLY_OFFSET;
281         tmp->f.src = __PRETTY_FUNCTION__;
282         tmp->f.data = tmp->outbuf;
283         /* Move the data at the end of the buffer to the front */
284         if (tmp->tail)
285                 memmove(tmp->buf, tmp->buf + consumed, tmp->tail * 2);
286 #if 0
287         /* Save a sample frame */
288         { static int samplefr = 0;
289         if (samplefr == 0) {
290                 int fd;
291                 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
292                 write(fd, tmp->f.data, tmp->f.datalen);
293                 close(fd);
294         }               
295         samplefr++;
296         }
297 #endif
298         return &tmp->f; 
299 }
300
301 static void lpc10_destroy(struct ast_translator_pvt *pvt)
302 {
303         /* Enc and DEC are both just allocated, so they can be freed */
304         free(pvt->lpc10.enc);
305         free(pvt);
306         localusecnt--;
307 }
308
309 static struct ast_translator lpc10tolin =
310         { "lpc10tolin", 
311            AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
312            lpc10_dec_new,
313            lpc10tolin_framein,
314            lpc10tolin_frameout,
315            lpc10_destroy,
316            lpc10tolin_sample
317            };
318
319 static struct ast_translator lintolpc10 =
320         { "lintolpc10", 
321            AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
322            lpc10_enc_new,
323            lintolpc10_framein,
324            lintolpc10_frameout,
325            lpc10_destroy,
326            lintolpc10_sample
327            };
328
329 int unload_module(void)
330 {
331         int res;
332         ast_mutex_lock(&localuser_lock);
333         res = ast_unregister_translator(&lintolpc10);
334         if (!res)
335                 res = ast_unregister_translator(&lpc10tolin);
336         if (localusecnt)
337                 res = -1;
338         ast_mutex_unlock(&localuser_lock);
339         return res;
340 }
341
342 int load_module(void)
343 {
344         int res;
345         res=ast_register_translator(&lpc10tolin);
346         if (!res) 
347                 res=ast_register_translator(&lintolpc10);
348         else
349                 ast_unregister_translator(&lpc10tolin);
350         return res;
351 }
352
353 char *description(void)
354 {
355         return tdesc;
356 }
357
358 int usecount(void)
359 {
360         int res;
361         STANDARD_USECOUNT(res);
362         return res;
363 }
364
365 char *key()
366 {
367         return ASTERISK_GPL_KEY;
368 }