update copyright headers for 2005
[asterisk/asterisk.git] / codecs / codec_ilbc.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Translate between signed linear and Internet Low Bitrate Codec
5  *
6  * The iLBC code is from The IETF code base and is copyright The Internet Society (2004)
7  * 
8  * Copyright (C) 1999 - 2005, Digium, Inc.
9  *
10  * Mark Spencer <markster@digium.com>
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License
14  */
15
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>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <netinet/in.h>
25 #include <string.h>
26 #include <stdio.h>
27
28 #include "ilbc/iLBC_encode.h"
29 #include "ilbc/iLBC_decode.h"
30
31 /* Sample frame data */
32 #include "slin_ilbc_ex.h"
33 #include "ilbc_slin_ex.h"
34
35 #define USE_ILBC_ENHANCER       0
36 #define ILBC_MS                         30
37 /* #define ILBC_MS                      20 */
38
39 AST_MUTEX_DEFINE_STATIC(localuser_lock);
40 static int localusecnt=0;
41
42 static char *tdesc = "iLBC/PCM16 (signed linear) Codec Translator";
43
44 struct ast_translator_pvt {
45         iLBC_Enc_Inst_t enc;
46         iLBC_Dec_Inst_t dec;
47         struct ast_frame f;
48         /* Space to build offset */
49         char offset[AST_FRIENDLY_OFFSET];
50         /* Buffer for our outgoing frame */
51         short outbuf[8000];
52         /* Enough to store a full second */
53         short buf[8000];
54         int tail;
55 };
56
57 #define ilbc_coder_pvt ast_translator_pvt
58
59 static struct ast_translator_pvt *lintoilbc_new(void)
60 {
61         struct ilbc_coder_pvt *tmp;
62         tmp = malloc(sizeof(struct ilbc_coder_pvt));
63         if (tmp) {
64                 /* Shut valgrind up */
65                 memset(&tmp->enc, 0, sizeof(tmp->enc));
66                 initEncode(&tmp->enc, ILBC_MS);
67                 tmp->tail = 0;
68                 localusecnt++;
69         }
70         return tmp;
71 }
72
73 static struct ast_translator_pvt *ilbctolin_new(void)
74 {
75         struct ilbc_coder_pvt *tmp;
76         tmp = malloc(sizeof(struct ilbc_coder_pvt));
77         if (tmp) {
78                 /* Shut valgrind up */
79                 memset(&tmp->dec, 0, sizeof(tmp->dec));
80                 initDecode(&tmp->dec, ILBC_MS, USE_ILBC_ENHANCER);
81                 tmp->tail = 0;
82                 localusecnt++;
83         }
84         return tmp;
85 }
86
87 static struct ast_frame *lintoilbc_sample(void)
88 {
89         static struct ast_frame f;
90         f.frametype = AST_FRAME_VOICE;
91         f.subclass = AST_FORMAT_SLINEAR;
92         f.datalen = sizeof(slin_ilbc_ex);
93         /* Assume 8000 Hz */
94         f.samples = sizeof(slin_ilbc_ex)/2;
95         f.mallocd = 0;
96         f.offset = 0;
97         f.src = __PRETTY_FUNCTION__;
98         f.data = slin_ilbc_ex;
99         return &f;
100 }
101
102 static struct ast_frame *ilbctolin_sample(void)
103 {
104         static struct ast_frame f;
105         f.frametype = AST_FRAME_VOICE;
106         f.subclass = AST_FORMAT_ILBC;
107         f.datalen = sizeof(ilbc_slin_ex);
108         /* All frames are 30 ms long */
109         f.samples = 240;
110         f.mallocd = 0;
111         f.offset = 0;
112         f.src = __PRETTY_FUNCTION__;
113         f.data = ilbc_slin_ex;
114         return &f;
115 }
116
117 static struct ast_frame *ilbctolin_frameout(struct ast_translator_pvt *tmp)
118 {
119         if (!tmp->tail)
120                 return NULL;
121         /* Signed linear is no particular frame size, so just send whatever
122            we have in the buffer in one lump sum */
123         tmp->f.frametype = AST_FRAME_VOICE;
124         tmp->f.subclass = AST_FORMAT_SLINEAR;
125         tmp->f.datalen = tmp->tail * 2;
126         /* Assume 8000 Hz */
127         tmp->f.samples = tmp->tail;
128         tmp->f.mallocd = 0;
129         tmp->f.offset = AST_FRIENDLY_OFFSET;
130         tmp->f.src = __PRETTY_FUNCTION__;
131         tmp->f.data = tmp->buf;
132         /* Reset tail pointer */
133         tmp->tail = 0;
134
135         return &tmp->f; 
136 }
137
138 static int ilbctolin_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
139 {
140         /* Assuming there's space left, decode into the current buffer at
141            the tail location.  Read in as many frames as there are */
142         int x,i;
143         float tmpf[240];
144         
145         if (f->datalen % 50) {
146                 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);
147                 return -1;
148         }
149         
150         for (x=0;x<f->datalen;x+=50) {
151                 if (tmp->tail + 240 < sizeof(tmp->buf)/2) {     
152                         iLBC_decode(tmpf, f->data + x, &tmp->dec, 1);
153                         for (i=0;i<240;i++)
154                                 tmp->buf[tmp->tail + i] = tmpf[i];
155                         tmp->tail+=240;
156                 } else {
157                         ast_log(LOG_WARNING, "Out of buffer space\n");
158                         return -1;
159                 }               
160         }
161         return 0;
162 }
163
164 static int lintoilbc_framein(struct ast_translator_pvt *tmp, struct ast_frame *f)
165 {
166         /* Just add the frames to our stream */
167         /* XXX We should look at how old the rest of our stream is, and if it
168            is too old, then we should overwrite it entirely, otherwise we can
169            get artifacts of earlier talk that do not belong */
170         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
171                 memcpy((tmp->buf + tmp->tail), f->data, f->datalen);
172                 tmp->tail += f->datalen/2;
173         } else {
174                 ast_log(LOG_WARNING, "Out of buffer space\n");
175                 return -1;
176         }
177         return 0;
178 }
179
180 static struct ast_frame *lintoilbc_frameout(struct ast_translator_pvt *tmp)
181 {
182         int x=0,i;
183         float tmpf[240];
184         /* We can't work on anything less than a frame in size */
185         if (tmp->tail < 240)
186                 return NULL;
187         tmp->f.frametype = AST_FRAME_VOICE;
188         tmp->f.subclass = AST_FORMAT_ILBC;
189         tmp->f.mallocd = 0;
190         tmp->f.offset = AST_FRIENDLY_OFFSET;
191         tmp->f.src = __PRETTY_FUNCTION__;
192         tmp->f.data = tmp->outbuf;
193         while(tmp->tail >= 240) {
194                 if ((x+1) * 50 >= sizeof(tmp->outbuf)) {
195                         ast_log(LOG_WARNING, "Out of buffer space\n");
196                         break;
197                 }
198                 for (i=0;i<240;i++)
199                         tmpf[i] = tmp->buf[i];
200                 /* Encode a frame of data */
201                 iLBC_encode(((unsigned char *)(tmp->outbuf)) + (x * 50), tmpf, &tmp->enc);
202                 /* Assume 8000 Hz -- 20 ms */
203                 tmp->tail -= 240;
204                 /* Move the data at the end of the buffer to the front */
205                 if (tmp->tail)
206                         memmove(tmp->buf, tmp->buf + 240, tmp->tail * 2);
207                 x++;
208         }
209         tmp->f.datalen = x * 50;
210         tmp->f.samples = x * 240;
211 #if 0
212         {
213                 static int fd = -1;
214                 if (fd == -1) {
215                         fd = open("ilbc.out", O_CREAT|O_TRUNC|O_WRONLY, 0666);
216                         write(fd, tmp->f.data, tmp->f.datalen);
217                         close(fd);
218                 }
219         }
220 #endif  
221         return &tmp->f; 
222 }
223
224 static void ilbc_destroy_stuff(struct ast_translator_pvt *pvt)
225 {
226         free(pvt);
227         localusecnt--;
228 }
229
230 static struct ast_translator ilbctolin =
231         { "ilbctolin", 
232            AST_FORMAT_ILBC, AST_FORMAT_SLINEAR,
233            ilbctolin_new,
234            ilbctolin_framein,
235            ilbctolin_frameout,
236            ilbc_destroy_stuff,
237            ilbctolin_sample
238            };
239
240 static struct ast_translator lintoilbc =
241         { "lintoilbc", 
242            AST_FORMAT_SLINEAR, AST_FORMAT_ILBC,
243            lintoilbc_new,
244            lintoilbc_framein,
245            lintoilbc_frameout,
246            ilbc_destroy_stuff,
247            lintoilbc_sample
248            };
249
250 int unload_module(void)
251 {
252         int res;
253         ast_mutex_lock(&localuser_lock);
254         res = ast_unregister_translator(&lintoilbc);
255         if (!res)
256                 res = ast_unregister_translator(&ilbctolin);
257         if (localusecnt)
258                 res = -1;
259         ast_mutex_unlock(&localuser_lock);
260         return res;
261 }
262
263 int load_module(void)
264 {
265         int res;
266         res=ast_register_translator(&ilbctolin);
267         if (!res) 
268                 res=ast_register_translator(&lintoilbc);
269         else
270                 ast_unregister_translator(&ilbctolin);
271         return res;
272 }
273
274 char *description(void)
275 {
276         return tdesc;
277 }
278
279 int usecount(void)
280 {
281         int res;
282         STANDARD_USECOUNT(res);
283         return res;
284 }
285
286 char *key()
287 {
288         return ASTERISK_GPL_KEY;
289 }