Version 0.1.2 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[LPC10_SAMPLES_PER_FRAME];
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         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
201         short *sd;
202         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
203         if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
204                 sd = tmp->buf + tmp->tail;
205                 extract_bits(bits, f->data);
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         return 0;
221 }
222
223 static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
224 {
225         /* Just add the frames to our stream */
226         /* XXX We should look at how old the rest of our stream is, and if it
227            is too old, then we should overwrite it entirely, otherwise we can
228            get artifacts of earlier talk that do not belong */
229         if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
230                 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
231                 tmp->tail += f->datalen/2;
232         } else {
233                 ast_log(LOG_WARNING, "Out of buffer space\n");
234                 return -1;
235         }
236         return 0;
237 }
238
239 static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
240 {
241         int x;
242         float tmpbuf[LPC10_SAMPLES_PER_FRAME];
243         INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
244         /* We can't work on anything less than a frame in size */
245         if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
246                 return NULL;
247         /* Encode a frame of data */
248         for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
249                 tmpbuf[x] = (float)tmp->buf[x] / 32768.0;
250         }
251         lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
252         build_bits((unsigned char *)tmp->outbuf, bits);
253         tmp->f.frametype = AST_FRAME_VOICE;
254         tmp->f.subclass = AST_FORMAT_LPC10;
255         tmp->f.datalen = LPC10_BYTES_IN_COMPRESSED_FRAME;
256         tmp->f.timelen = 22;
257         /* We alternate between 22 and 23 ms to simulate 22.5 ms */
258         tmp->f.timelen += tmp->longer;
259         /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
260            important for IAX use */
261         tmp->longer = 1 - tmp->longer;
262         tmp->f.mallocd = 0;
263         tmp->f.offset = AST_FRIENDLY_OFFSET;
264         tmp->f.src = __PRETTY_FUNCTION__;
265         tmp->f.data = tmp->outbuf;
266         ((char *)(tmp->f.data))[LPC10_BYTES_IN_COMPRESSED_FRAME - 1] |= tmp->longer;
267         tmp->tail -= LPC10_SAMPLES_PER_FRAME;
268         /* Move the data at the end of the buffer to the front */
269         if (tmp->tail)
270                 memmove(tmp->buf, tmp->buf + LPC10_SAMPLES_PER_FRAME, tmp->tail * 2);
271 #if 0
272         /* Save a sample frame */
273         { static int samplefr = 0;
274         if (samplefr == 0) {
275                 int fd;
276                 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
277                 write(fd, tmp->f.data, tmp->f.datalen);
278                 close(fd);
279         }               
280         samplefr++;
281         }
282 #endif
283         return &tmp->f; 
284 }
285
286 static void lpc10_destroy(struct ast_translator_pvt *pvt)
287 {
288         /* Enc and DEC are both just allocated, so they can be freed */
289         free(pvt->lpc10.enc);
290         free(pvt);
291         localusecnt--;
292 }
293
294 static struct ast_translator lpc10tolin =
295         { "lpc10tolin", 
296            AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
297            lpc10_dec_new,
298            lpc10tolin_framein,
299            lpc10tolin_frameout,
300            lpc10_destroy,
301            lpc10tolin_sample
302            };
303
304 static struct ast_translator lintolpc10 =
305         { "lintolpc10", 
306            AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
307            lpc10_enc_new,
308            lintolpc10_framein,
309            lintolpc10_frameout,
310            lpc10_destroy,
311            lintolpc10_sample
312            };
313
314 int unload_module(void)
315 {
316         int res;
317         pthread_mutex_lock(&localuser_lock);
318         res = ast_unregister_translator(&lintolpc10);
319         if (!res)
320                 res = ast_unregister_translator(&lpc10tolin);
321         if (localusecnt)
322                 res = -1;
323         pthread_mutex_unlock(&localuser_lock);
324         return res;
325 }
326
327 int load_module(void)
328 {
329         int res;
330         res=ast_register_translator(&lpc10tolin);
331         if (!res) 
332                 res=ast_register_translator(&lintolpc10);
333         else
334                 ast_unregister_translator(&lpc10tolin);
335         return res;
336 }
337
338 char *description(void)
339 {
340         return tdesc;
341 }
342
343 int usecount(void)
344 {
345         int res;
346         STANDARD_USECOUNT(res);
347         return res;
348 }