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