Version 0.1.8 from FTP
[asterisk/asterisk.git] / codecs / codec_g723_1.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Translate between signed linear and G.723.1
5  *
6  * The G.723.1 code is not included in the Asterisk distribution because
7  * it is covered with patents, and in spite of statements to the contrary,
8  * the "technology" is extremely expensive to license.
9  * 
10  * Copyright (C) 1999, Mark Spencer
11  *
12  * Mark Spencer <markster@linux-support.net>
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License
16  */
17
18 #define TYPE_SILENCE     0x2
19 #define TYPE_HIGH        0x0
20 #define TYPE_LOW         0x1
21 #define TYPE_MASK        0x3
22
23 #include <asterisk/translate.h>
24 #include <asterisk/module.h>
25 #include <asterisk/logger.h>
26 #include <asterisk/channel.h>
27 #include <pthread.h>
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 #ifdef ANNEX_B
36 #include "g723.1b/typedef2.h"
37 #include "g723.1b/cst2.h"
38 #include "g723.1b/coder2.h"
39 #include "g723.1b/decod2.h"
40 #include "g723.1b/deccng2.h"
41 #include "g723.1b/codcng2.h"
42 #include "g723.1b/vad2.h"
43 #else
44 #include "g723.1/typedef.h"
45 #include "g723.1/cst_lbc.h"
46 #include "g723.1/coder.h"
47 #include "g723.1/decod.h"
48 #include "g723.1/dec_cng.h"
49 #include "g723.1/cod_cng.h"
50 #include "g723.1/vad.h"
51 #endif
52
53 /* Sample frame data */
54 #include "slin_g723_ex.h"
55 #include "g723_slin_ex.h"
56
57 static pthread_mutex_t localuser_lock = PTHREAD_MUTEX_INITIALIZER;
58 static int localusecnt=0;
59
60 #ifdef ANNEX_B
61 static char *tdesc = "Annex B (floating point) G.723.1/PCM16 Codec Translator";
62 #else
63 static char *tdesc = "Annex A (fixed point) G.723.1/PCM16 Codec Translator";
64 #endif
65
66 /* Globals */
67 Flag UsePf = True;
68 Flag UseHp = True;
69 Flag UseVx = True;
70
71 enum Crate WrkRate = Rate63;
72
73 struct g723_encoder_pvt {
74         struct cod_state cod;
75         struct ast_frame f;
76         /* Space to build offset */
77         char offset[AST_FRIENDLY_OFFSET];
78         /* Buffer for our outgoing frame */
79         char outbuf[8000];
80         /* Enough to store a full second */
81         short buf[8000];
82         int tail;
83 };
84
85 struct g723_decoder_pvt {
86         struct dec_state dec;
87         struct ast_frame f;
88         /* Space to build offset */
89         char offset[AST_FRIENDLY_OFFSET];
90         /* Enough to store a full second */
91         short buf[8000];
92         int tail;
93 };
94
95 static struct ast_translator_pvt *g723tolin_new()
96 {
97         struct g723_decoder_pvt *tmp;
98         tmp = malloc(sizeof(struct g723_decoder_pvt));
99         if (tmp) {
100                 Init_Decod(&tmp->dec);
101             Init_Dec_Cng(&tmp->dec);
102                 tmp->tail = 0;
103                 localusecnt++;
104                 ast_update_use_count();
105         }
106         return (struct ast_translator_pvt *)tmp;
107 }
108
109 static struct ast_frame *lintog723_sample()
110 {
111         static struct ast_frame f;
112         f.frametype = AST_FRAME_VOICE;
113         f.subclass = AST_FORMAT_SLINEAR;
114         f.datalen = sizeof(slin_g723_ex);
115         /* Assume 8000 Hz */
116         f.timelen = sizeof(slin_g723_ex)/16;
117         f.mallocd = 0;
118         f.offset = 0;
119         f.src = __PRETTY_FUNCTION__;
120         f.data = slin_g723_ex;
121         return &f;
122 }
123
124 static struct ast_frame *g723tolin_sample()
125 {
126         static struct ast_frame f;
127         f.frametype = AST_FRAME_VOICE;
128         f.subclass = AST_FORMAT_G723_1;
129         f.datalen = sizeof(g723_slin_ex);
130         /* All frames are 30 ms long */
131         f.timelen = 30;
132         f.mallocd = 0;
133         f.offset = 0;
134         f.src = __PRETTY_FUNCTION__;
135         f.data = g723_slin_ex;
136         return &f;
137 }
138
139 static struct ast_translator_pvt *lintog723_new()
140 {
141         struct g723_encoder_pvt *tmp;
142         tmp = malloc(sizeof(struct g723_encoder_pvt));
143         if (tmp) {
144                 Init_Coder(&tmp->cod);
145             /* Init Comfort Noise Functions */
146                  if( UseVx ) {
147                         Init_Vad(&tmp->cod);
148                 Init_Cod_Cng(&tmp->cod);
149          }
150                 localusecnt++;
151                 ast_update_use_count();
152                 tmp->tail = 0;
153         }
154         return (struct ast_translator_pvt *)tmp;
155 }
156
157 static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
158 {
159         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
160         if (!tmp->tail)
161                 return NULL;
162         /* Signed linear is no particular frame size, so just send whatever
163            we have in the buffer in one lump sum */
164         tmp->f.frametype = AST_FRAME_VOICE;
165         tmp->f.subclass = AST_FORMAT_SLINEAR;
166         tmp->f.datalen = tmp->tail * 2;
167         /* Assume 8000 Hz */
168         tmp->f.timelen = tmp->tail / 8;
169         tmp->f.mallocd = 0;
170         tmp->f.offset = AST_FRIENDLY_OFFSET;
171         tmp->f.src = __PRETTY_FUNCTION__;
172         tmp->f.data = tmp->buf;
173         /* Reset tail pointer */
174         tmp->tail = 0;
175
176 #if 0
177         /* Save the frames */
178         { 
179                 static int fd2 = -1;
180                 if (fd2 == -1) {
181                         fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
182                 }
183                 write(fd2, tmp->f.data, tmp->f.datalen);
184         }               
185 #endif
186         return &tmp->f; 
187 }
188
189 static int g723_len(unsigned char buf)
190 {
191         switch(buf & TYPE_MASK) {
192         case TYPE_MASK:
193         case TYPE_SILENCE:
194                 return 4;
195                 break;
196         case TYPE_HIGH:
197                 return 24;
198                 break;
199         case TYPE_LOW:
200                 return 20;
201                 break;
202         default:
203                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", buf & TYPE_MASK);
204         }
205         return -1;
206 }
207
208 static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
209 {
210         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
211         int len = 0;
212         int res;
213 #ifdef  ANNEX_B
214         FLOAT tmpdata[Frame];
215         int x;
216 #endif
217         while(len < f->datalen) {
218                 /* Assuming there's space left, decode into the current buffer at
219                    the tail location */
220                 res = g723_len(((unsigned char *)f->data + len)[0]);
221                 if (res < 0) {
222                         ast_log(LOG_WARNING, "Invalid data\n");
223                         return -1;
224                 }
225                 if (res + len > f->datalen) {
226                         ast_log(LOG_WARNING, "Measured length exceeds frame length\n");
227                         return -1;
228                 }
229                 if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
230 #ifdef ANNEX_B
231                         Decod(&tmp->dec, tmpdata, f->data + len, 0);
232                         for (x=0;x<Frame;x++)
233                                 (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]); 
234 #else
235                         Decod(&tmp->dec, tmp->buf + tmp->tail, f->data + len, 0);
236 #endif
237                         tmp->tail+=Frame;
238                 } else {
239                         ast_log(LOG_WARNING, "Out of buffer space\n");
240                         return -1;
241                 }
242                 len += res;
243         }
244         return 0;
245 }
246
247 static int lintog723_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
248 {
249         /* Just add the frames to our stream */
250         /* XXX We should look at how old the rest of our stream is, and if it
251            is too old, then we should overwrite it entirely, otherwise we can
252            get artifacts of earlier talk that do not belong */
253         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
254         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
255                 memcpy(&tmp->buf[tmp->tail], f->data, f->datalen);
256                 tmp->tail += f->datalen/2;
257         } else {
258                 ast_log(LOG_WARNING, "Out of buffer space\n");
259                 return -1;
260         }
261         return 0;
262 }
263
264 static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
265 {
266         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
267 #ifdef ANNEX_B
268         int x;
269         FLOAT tmpdata[Frame];
270 #endif
271         int cnt=0;
272         /* We can't work on anything less than a frame in size */
273         if (tmp->tail < Frame)
274                 return NULL;
275         tmp->f.frametype = AST_FRAME_VOICE;
276         tmp->f.subclass = AST_FORMAT_G723_1;
277         tmp->f.offset = AST_FRIENDLY_OFFSET;
278         tmp->f.src = __PRETTY_FUNCTION__;
279         tmp->f.timelen = 0;
280         tmp->f.mallocd = 0;
281         while(tmp->tail >= Frame) {
282                 /* Encode a frame of data */
283                 if (cnt + 24 >= sizeof(tmp->outbuf)) {
284                         ast_log(LOG_WARNING, "Out of buffer space\n");
285                         return NULL;
286                 }
287 #ifdef ANNEX_B
288                 for (x=0;x<Frame;x++)
289                         tmpdata[x] = tmp->buf[x];
290                 Coder(&tmp->cod, tmpdata, tmp->outbuf + cnt);
291 #else
292                 Coder(&tmp->cod, tmp->buf, tmp->outbuf + cnt);
293 #endif
294                 /* Assume 8000 Hz */
295                 tmp->f.timelen += 30;
296                 cnt += g723_len(tmp->outbuf[0]);
297                 tmp->tail -= Frame;
298                 /* Move the data at the end of the buffer to the front */
299                 if (tmp->tail)
300                         memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
301         }
302         tmp->f.datalen = cnt;
303         tmp->f.data = tmp->outbuf;
304 #if 0
305         /* Save to a g723 sample output file... */
306         { 
307                 static int fd = -1;
308                 int delay = htonl(30);
309                 short size;
310                 if (fd < 0)
311                         fd = open("trans.g723", O_WRONLY | O_CREAT | O_TRUNC, 0644);
312                 if (fd < 0)
313                         ast_log(LOG_WARNING, "Unable to create demo\n");
314                 write(fd, &delay, 4);
315                 size = htons(tmp->f.datalen);
316                 write(fd, &size, 2);
317                 write(fd, tmp->f.data, tmp->f.datalen);
318         }
319 #endif
320         return &tmp->f; 
321 }
322
323 static void g723_destroy(struct ast_translator_pvt *pvt)
324 {
325         free(pvt);
326         localusecnt--;
327         ast_update_use_count();
328 }
329
330 static struct ast_translator g723tolin =
331 #ifdef ANNEX_B
332         { "g723tolinb", 
333 #else
334         { "g723tolin", 
335 #endif
336            AST_FORMAT_G723_1, AST_FORMAT_SLINEAR,
337            g723tolin_new,
338            g723tolin_framein,
339            g723tolin_frameout,
340            g723_destroy,
341            g723tolin_sample
342            };
343
344 static struct ast_translator lintog723 =
345 #ifdef ANNEX_B
346         { "lintog723b", 
347 #else
348         { "lintog723", 
349 #endif
350            AST_FORMAT_SLINEAR, AST_FORMAT_G723_1,
351            lintog723_new,
352            lintog723_framein,
353            lintog723_frameout,
354            g723_destroy,
355            lintog723_sample
356            };
357
358 int unload_module(void)
359 {
360         int res;
361         ast_pthread_mutex_lock(&localuser_lock);
362         res = ast_unregister_translator(&lintog723);
363         if (!res)
364                 res = ast_unregister_translator(&g723tolin);
365         if (localusecnt)
366                 res = -1;
367         ast_pthread_mutex_unlock(&localuser_lock);
368         return res;
369 }
370
371 int load_module(void)
372 {
373         int res;
374         res=ast_register_translator(&g723tolin);
375         if (!res) 
376                 res=ast_register_translator(&lintog723);
377         else
378                 ast_unregister_translator(&g723tolin);
379         return res;
380 }
381
382 char *description(void)
383 {
384         return tdesc;
385 }
386
387 int usecount(void)
388 {
389         int res;
390         STANDARD_USECOUNT(res);
391         return res;
392 }
393
394 char *key()
395 {
396         return ASTERISK_GPL_KEY;
397 }