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 - 2005 Digium,inc
13 * Mark Spencer <markster@digium.com>
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License
20 #include "asterisk/lock.h"
21 #include "asterisk/translate.h"
22 #include "asterisk/config.h"
23 #include "asterisk/options.h"
24 #include "asterisk/module.h"
25 #include "asterisk/logger.h"
26 #include "asterisk/channel.h"
30 #include <netinet/in.h>
34 #include "lpc10/lpc10.h"
36 /* Sample frame data */
37 #include "slin_lpc10_ex.h"
38 #include "lpc10_slin_ex.h"
40 /* We use a very strange format here... I have no idea why... The frames are 180
41 samples long, which isn't even an even number of milliseconds... Not only that
42 but we hvae to waste two bits of each frame to keep them ending on a byte boundary
43 because the frames are 54 bits long */
45 #define LPC10_BYTES_IN_COMPRESSED_FRAME (LPC10_BITS_IN_COMPRESSED_FRAME + 7)/8
47 AST_MUTEX_DEFINE_STATIC(localuser_lock);
48 static int localusecnt=0;
50 static char *tdesc = "LPC10 2.4kbps (signed linear) Voice Coder";
52 static int useplc = 0;
54 struct ast_translator_pvt {
56 struct lpc10_encoder_state *enc;
57 struct lpc10_decoder_state *dec;
60 /* Space to build offset */
61 char offset[AST_FRIENDLY_OFFSET];
62 /* Buffer for our outgoing frame */
64 /* Enough to store a full second */
68 plc_state_t plc; /* god only knows why I bothered to implement PLC for LPC10 :) */
71 #define lpc10_coder_pvt ast_translator_pvt
73 static struct ast_translator_pvt *lpc10_enc_new(void)
75 struct lpc10_coder_pvt *tmp;
76 tmp = malloc(sizeof(struct lpc10_coder_pvt));
78 if (!(tmp->lpc10.enc = create_lpc10_encoder_state())) {
89 static struct ast_translator_pvt *lpc10_dec_new(void)
91 struct lpc10_coder_pvt *tmp;
92 tmp = malloc(sizeof(struct lpc10_coder_pvt));
94 if (!(tmp->lpc10.dec = create_lpc10_decoder_state())) {
105 static struct ast_frame *lintolpc10_sample(void)
107 static struct ast_frame f;
108 f.frametype = AST_FRAME_VOICE;
109 f.subclass = AST_FORMAT_SLINEAR;
110 f.datalen = sizeof(slin_lpc10_ex);
112 f.samples = LPC10_SAMPLES_PER_FRAME;
115 f.src = __PRETTY_FUNCTION__;
116 f.data = slin_lpc10_ex;
120 static struct ast_frame *lpc10tolin_sample(void)
122 static struct ast_frame f;
123 f.frametype = AST_FRAME_VOICE;
124 f.subclass = AST_FORMAT_LPC10;
125 f.datalen = sizeof(lpc10_slin_ex);
126 /* All frames are 22 ms long (maybe a little more -- why did he choose
127 LPC10_SAMPLES_PER_FRAME sample frames anyway?? */
128 f.samples = LPC10_SAMPLES_PER_FRAME;
131 f.src = __PRETTY_FUNCTION__;
132 f.data = lpc10_slin_ex;
136 static struct ast_frame *lpc10tolin_frameout(struct ast_translator_pvt *tmp)
140 /* Signed linear is no particular frame size, so just send whatever
141 we have in the buffer in one lump sum */
142 tmp->f.frametype = AST_FRAME_VOICE;
143 tmp->f.subclass = AST_FORMAT_SLINEAR;
144 tmp->f.datalen = tmp->tail * 2;
146 tmp->f.samples = tmp->tail;
148 tmp->f.offset = AST_FRIENDLY_OFFSET;
149 tmp->f.src = __PRETTY_FUNCTION__;
150 tmp->f.data = tmp->buf;
151 /* Reset tail pointer */
155 /* Save a sample frame */
156 { static int samplefr = 0;
157 if (samplefr == 80) {
159 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
160 write(fd, tmp->f.data, tmp->f.datalen);
169 static void extract_bits(INT32 *bits, unsigned char *c)
172 for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
173 if (*c & (0x80 >> (x & 7)))
182 static void build_bits(unsigned char *c, INT32 *bits)
184 unsigned char mask=0x80;
187 for (x=0;x<LPC10_BITS_IN_COMPRESSED_FRAME;x++) {
199 static int lpc10tolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
201 /* Assuming there's space left, decode into the current buffer at
205 float tmpbuf[LPC10_SAMPLES_PER_FRAME];
207 INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
209 if(f->datalen == 0) { /* perform PLC with nominal framesize of LPC10_SAMPLES_PER_FRAME */
210 if((tmp->tail + LPC10_SAMPLES_PER_FRAME) > sizeof(tmp->buf)/2) {
211 ast_log(LOG_WARNING, "Out of buffer space\n");
215 plc_fillin(&tmp->plc, tmp->buf+tmp->tail, LPC10_SAMPLES_PER_FRAME);
216 tmp->tail += LPC10_SAMPLES_PER_FRAME;
221 while(len + LPC10_BYTES_IN_COMPRESSED_FRAME <= f->datalen) {
222 if (tmp->tail + LPC10_SAMPLES_PER_FRAME < sizeof(tmp->buf)/2) {
223 sd = tmp->buf + tmp->tail;
224 extract_bits(bits, f->data + len);
225 if (lpc10_decode(bits, tmpbuf, tmp->lpc10.dec)) {
226 ast_log(LOG_WARNING, "Invalid lpc10 data\n");
229 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
230 /* Convert to a real between -1.0 and 1.0 */
231 sd[x] = 32768.0 * tmpbuf[x];
234 if(useplc) plc_rx(&tmp->plc, tmp->buf + tmp->tail, LPC10_SAMPLES_PER_FRAME);
236 tmp->tail+=LPC10_SAMPLES_PER_FRAME;
238 ast_log(LOG_WARNING, "Out of buffer space\n");
241 len += LPC10_BYTES_IN_COMPRESSED_FRAME;
243 if (len != f->datalen)
244 printf("Decoded %d, expected %d\n", len, f->datalen);
248 static int lintolpc10_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
250 /* Just add the frames to our stream */
251 /* XXX We should look at how old the rest of our stream is, and if it
252 is too old, then we should overwrite it entirely, otherwise we can
253 get artifacts of earlier talk that do not belong */
254 if (tmp->tail + f->datalen < sizeof(tmp->buf) / 2) {
255 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
256 tmp->tail += f->datalen/2;
258 ast_log(LOG_WARNING, "Out of buffer space\n");
264 static struct ast_frame *lintolpc10_frameout(struct ast_translator_pvt *tmp)
268 float tmpbuf[LPC10_SAMPLES_PER_FRAME];
269 INT32 bits[LPC10_BITS_IN_COMPRESSED_FRAME];
270 /* We can't work on anything less than a frame in size */
271 if (tmp->tail < LPC10_SAMPLES_PER_FRAME)
273 /* Start with an empty frame */
276 tmp->f.frametype = AST_FRAME_VOICE;
277 tmp->f.subclass = AST_FORMAT_LPC10;
278 while(tmp->tail >= LPC10_SAMPLES_PER_FRAME) {
279 if (tmp->f.datalen + LPC10_BYTES_IN_COMPRESSED_FRAME > sizeof(tmp->outbuf)) {
280 ast_log(LOG_WARNING, "Out of buffer space\n");
283 /* Encode a frame of data */
284 for (x=0;x<LPC10_SAMPLES_PER_FRAME;x++) {
285 tmpbuf[x] = (float)tmp->buf[x+consumed] / 32768.0;
287 lpc10_encode(tmpbuf, bits, tmp->lpc10.enc);
288 build_bits(((unsigned char *)tmp->outbuf) + tmp->f.datalen, bits);
289 tmp->f.datalen += LPC10_BYTES_IN_COMPRESSED_FRAME;
290 tmp->f.samples += LPC10_SAMPLES_PER_FRAME;
291 /* Use one of the two left over bits to record if this is a 22 or 23 ms frame...
292 important for IAX use */
293 tmp->longer = 1 - tmp->longer;
294 #if 0 /* what the heck was this for? */
295 ((char *)(tmp->f.data))[consumed - 1] |= tmp->longer;
297 tmp->tail -= LPC10_SAMPLES_PER_FRAME;
298 consumed += LPC10_SAMPLES_PER_FRAME;
301 tmp->f.offset = AST_FRIENDLY_OFFSET;
302 tmp->f.src = __PRETTY_FUNCTION__;
303 tmp->f.data = tmp->outbuf;
304 /* Move the data at the end of the buffer to the front */
306 memmove(tmp->buf, tmp->buf + consumed, tmp->tail * 2);
308 /* Save a sample frame */
309 { static int samplefr = 0;
312 fd = open("lpc10.example", O_WRONLY | O_CREAT, 0644);
313 write(fd, tmp->f.data, tmp->f.datalen);
322 static void lpc10_destroy(struct ast_translator_pvt *pvt)
324 /* Enc and DEC are both just allocated, so they can be freed */
325 free(pvt->lpc10.enc);
330 static struct ast_translator lpc10tolin =
332 AST_FORMAT_LPC10, AST_FORMAT_SLINEAR,
340 static struct ast_translator lintolpc10 =
342 AST_FORMAT_SLINEAR, AST_FORMAT_LPC10,
350 static void parse_config(void)
352 struct ast_config *cfg;
353 struct ast_variable *var;
354 if ((cfg = ast_config_load("codecs.conf"))) {
355 if ((var = ast_variable_browse(cfg, "plc"))) {
357 if (!strcasecmp(var->name, "genericplc")) {
358 useplc = ast_true(var->value) ? 1 : 0;
359 if (option_verbose > 2)
360 ast_verbose(VERBOSE_PREFIX_3 "codec_lpc10: %susing generic PLC\n", useplc ? "" : "not ");
365 ast_config_destroy(cfg);
376 int unload_module(void)
379 ast_mutex_lock(&localuser_lock);
380 res = ast_unregister_translator(&lintolpc10);
382 res = ast_unregister_translator(&lpc10tolin);
385 ast_mutex_unlock(&localuser_lock);
389 int load_module(void)
393 res=ast_register_translator(&lpc10tolin);
395 res=ast_register_translator(&lintolpc10);
397 ast_unregister_translator(&lpc10tolin);
401 char *description(void)
409 STANDARD_USECOUNT(res);
415 return ASTERISK_GPL_KEY;