2 * Asterisk -- A telephony toolkit for Linux.
4 * Translate between signed linear and LPC10 (Linear Predictor Code)
6 * The lpc10 code is from a library used by nautilus, modified to be a bit
7 * nicer to the compiler.
9 * See http://www.arl.wustl.edu/~jaf/
11 * Copyright (C) 1999, Mark Spencer
13 * Mark Spencer <markster@linux-support.net>
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License
20 #include <asterisk/translate.h>
21 #include <asterisk/module.h>
22 #include <asterisk/logger.h>
27 #include <netinet/in.h>
31 #include "lpc10/lpc10.h"
33 /* Sample frame data */
34 #include "slin_lpc10_ex.h"
35 #include "lpc10_slin_ex.h"
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 */
42 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
44 static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
45 static int localusecnt=0;
47 static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder";
49 struct ast_translator_pvt {
51 struct lpc10_encoder_state *enc;
52 struct lpc10_decoder_state *dec;
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 */
65 #define lpc10_coder_pvt ast_translator_pvt
67 static struct ast_translator_pvt *lpc10_enc_new()
69 struct lpc10_coder_pvt *tmp;
70 tmp = malloc(sizeof(struct lpc10_coder_pvt));
72 if (!(tmp->lpc10.enc = create_lpc10_encoder_state())) {
83 static struct ast_translator_pvt *lpc10_dec_new()
85 struct lpc10_coder_pvt *tmp;
86 tmp = malloc(sizeof(struct lpc10_coder_pvt));
88 if (!(tmp->lpc10.dec = create_lpc10_decoder_state())) {
98 static struct ast_frame *lintolpc10_sample()
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);
106 f.timelen = LPC10_SAMPLES_PER_FRAME/8;
111 f.src = __PRETTY_FUNCTION__;
112 f.data = slin_lpc10_ex;
116 static struct ast_frame *lpc10tolin_sample()
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;
127 f.src = __PRETTY_FUNCTION__;
128 f.data = lpc10_slin_ex;
132 static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp)
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;
142 tmp->f.timelen = tmp->tail / 8;
144 tmp->f.offset = AST_FRIENDLY_OFFSET;
145 tmp->f.src = __PRETTY_FUNCTION__;
146 tmp->f.data = tmp->buf;
147 /* Reset tail pointer */
151 /* Save a sample frame */
152 { static int samplefr = 0;
153 if (samplefr == 80) {
155 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
156 write(fd, tmp->f.data, tmp->f.datalen);
165 static void extract_bits(INT32 *bits, unsigned char *c)
168 for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
169 if (*c & (0x80 >> (x & 7)))
178 static void build_bits(unsigned char *c, INT32 *bits)
180 unsigned char mask=0x80;
183 for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
195 static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
197 /* Assuming there's space left, decode into the current buffer at
200 float tmpbuf[LPC10_SAMPLES_PER_FRAME];
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");
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];
215 tmp->tail+=LPC10_SAMPLES_PER_FRAME;
217 ast_log(LOG_WARNING, "Out of buffer space\n");
223 static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
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;
233 ast_log(LOG_WARNING, "Out of buffer space\n");
239 static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
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)
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;
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;
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;
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 */
270 memmove(tmp->buf, tmp->buf + LPC10_SAMPLES_PER_FRAME, tmp->tail * 2);
272 /* Save a sample frame */
273 { static int samplefr = 0;
276 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
277 write(fd, tmp->f.data, tmp->f.datalen);
286 static void lpc10_destroy(struct ast_translator_pvt *pvt)
288 /* Enc and DEC are both just allocated, so they can be freed */
289 free(pvt->lpc10.enc);
294 static struct ast_translator lpc10tolin =
296 AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
304 static struct ast_translator lintolpc10 =
306 AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
314 int unload_module(void)
317 pthread_mutex_lock(&localuser_lock);
318 res = ast_unregister_translator(&lintolpc10);
320 res = ast_unregister_translator(&lpc10tolin);
323 pthread_mutex_unlock(&localuser_lock);
327 int load_module(void)
330 res=ast_register_translator(&lpc10tolin);
332 res=ast_register_translator(&lintolpc10);
334 ast_unregister_translator(&lpc10tolin);
338 char *description(void)
346 STANDARD_USECOUNT(res);