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