2 * Asterisk -- A telephony toolkit for Linux.
4 * Translate between signed linear and Internet Low Bitrate Codec
6 * The iLBC code is from The IETF code base and is copyright GlobalSound, AB
8 * Copyright (C) 1999, Mark Spencer
10 * Mark Spencer <markster@linux-support.net>
12 * This program is free software, distributed under the terms of
13 * the GNU General Public License
16 #include <asterisk/lock.h>
17 #include <asterisk/translate.h>
18 #include <asterisk/module.h>
19 #include <asterisk/logger.h>
20 #include <asterisk/channel.h>
25 #include <netinet/in.h>
29 #include "ilbc/iLBC_encode.h"
30 #include "ilbc/iLBC_decode.h"
32 /* Sample frame data */
33 #include "slin_ilbc_ex.h"
34 #include "ilbc_slin_ex.h"
36 #define USE_ILBC_ENHANCER 0
38 static ast_mutex_t localuser_lock = AST_MUTEX_INITIALIZER;
39 static int localusecnt=0;
41 static char *tdesc = "iLBC/PCM16 (signed linear) Codec Translator";
43 struct ast_translator_pvt {
47 /* Space to build offset */
48 char offset[AST_FRIENDLY_OFFSET];
49 /* Buffer for our outgoing frame */
51 /* Enough to store a full second */
56 #define ilbc_coder_pvt ast_translator_pvt
58 static struct ast_translator_pvt *lintoilbc_new(void)
60 struct ilbc_coder_pvt *tmp;
61 tmp = malloc(sizeof(struct ilbc_coder_pvt));
63 /* Shut valgrind up */
64 memset(&tmp->enc, 0, sizeof(tmp->enc));
65 initEncode(&tmp->enc);
72 static struct ast_translator_pvt *ilbctolin_new(void)
74 struct ilbc_coder_pvt *tmp;
75 tmp = malloc(sizeof(struct ilbc_coder_pvt));
77 /* Shut valgrind up */
78 memset(&tmp->dec, 0, sizeof(tmp->dec));
79 initDecode(&tmp->dec, USE_ILBC_ENHANCER);
86 static struct ast_frame *lintoilbc_sample(void)
88 static struct ast_frame f;
89 f.frametype = AST_FRAME_VOICE;
90 f.subclass = AST_FORMAT_SLINEAR;
91 f.datalen = sizeof(slin_ilbc_ex);
93 f.samples = sizeof(slin_ilbc_ex)/2;
96 f.src = __PRETTY_FUNCTION__;
97 f.data = slin_ilbc_ex;
101 static struct ast_frame *ilbctolin_sample(void)
103 static struct ast_frame f;
104 f.frametype = AST_FRAME_VOICE;
105 f.subclass = AST_FORMAT_ILBC;
106 f.datalen = sizeof(ilbc_slin_ex);
107 /* All frames are 30 ms long */
111 f.src = __PRETTY_FUNCTION__;
112 f.data = ilbc_slin_ex;
116 static struct ast_frame *ilbctolin_frameout(struct ast_translator_pvt *tmp)
120 /* Signed linear is no particular frame size, so just send whatever
121 we have in the buffer in one lump sum */
122 tmp->f.frametype = AST_FRAME_VOICE;
123 tmp->f.subclass = AST_FORMAT_SLINEAR;
124 tmp->f.datalen = tmp->tail * 2;
126 tmp->f.samples = tmp->tail;
128 tmp->f.offset = AST_FRIENDLY_OFFSET;
129 tmp->f.src = __PRETTY_FUNCTION__;
130 tmp->f.data = tmp->buf;
131 /* Reset tail pointer */
137 static int ilbctolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
139 /* Assuming there's space left, decode into the current buffer at
140 the tail location. Read in as many frames as there are */
144 if (f->datalen % 50) {
145 ast_log(LOG_WARNING, "Huh? An ilbc frame that isn't a multiple of 50 bytes long from %s (%d)?\n", f->src, f->datalen);
149 for (x=0;x<f->datalen;x+=50) {
150 if (tmp->tail + 240 < sizeof(tmp->buf)/2) {
151 iLBC_decode(tmpf, f->data + x, &tmp->dec, 1);
153 tmp->buf[tmp->tail + i] = tmpf[i];
156 ast_log(LOG_WARNING, "Out of buffer space\n");
163 static int lintoilbc_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
165 /* Just add the frames to our stream */
166 /* XXX We should look at how old the rest of our stream is, and if it
167 is too old, then we should overwrite it entirely, otherwise we can
168 get artifacts of earlier talk that do not belong */
169 if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
170 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
171 tmp->tail += f->datalen/2;
173 ast_log(LOG_WARNING, "Out of buffer space\n");
179 static struct ast_frame *lintoilbc_frameout(struct ast_translator_pvt *tmp)
183 /* We can't work on anything less than a frame in size */
186 tmp->f.frametype = AST_FRAME_VOICE;
187 tmp->f.subclass = AST_FORMAT_ILBC;
189 tmp->f.offset = AST_FRIENDLY_OFFSET;
190 tmp->f.src = __PRETTY_FUNCTION__;
191 tmp->f.data = tmp->outbuf;
192 while(tmp->tail >= 240) {
193 if ((x+1) * 50 >= sizeof(tmp->outbuf)) {
194 ast_log(LOG_WARNING, "Out of buffer space\n");
198 tmpf[i] = tmp->buf[i];
199 /* Encode a frame of data */
200 iLBC_encode(((unsigned char *)(tmp->outbuf)) + (x * 50), tmpf, &tmp->enc);
201 /* Assume 8000 Hz -- 20 ms */
203 /* Move the data at the end of the buffer to the front */
205 memmove(tmp->buf, tmp->buf + 240, tmp->tail * 2);
208 tmp->f.datalen = x * 50;
209 tmp->f.samples = x * 240;
214 fd = open("ilbc.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
215 write(fd, tmp->f.data, tmp->f.datalen);
223 static void ilbc_destroy_stuff(struct ast_translator_pvt *pvt)
229 static struct ast_translator ilbctolin =
231 AST_FORMAT_ILBC, AST_FORMAT_SLINEAR,
239 static struct ast_translator lintoilbc =
241 AST_FORMAT_SLINEAR, AST_FORMAT_ILBC,
249 int unload_module(void)
252 ast_mutex_lock(&localuser_lock);
253 res = ast_unregister_translator(&lintoilbc);
255 res = ast_unregister_translator(&ilbctolin);
258 ast_mutex_unlock(&localuser_lock);
262 int load_module(void)
265 res=ast_register_translator(&ilbctolin);
267 res=ast_register_translator(&lintoilbc);
269 ast_unregister_translator(&ilbctolin);
273 char *description(void)
281 STANDARD_USECOUNT(res);
287 return ASTERISK_GPL_KEY;