72dcd90133dcd8bcf97a1731ee07405e9f43addf
[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 <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                 localusecnt++;
103                 ast_update_use_count();
104         }
105         return (struct ast_translator_pvt *)tmp;
106 }
107
108 static struct ast_frame *lintog723_sample()
109 {
110         static struct ast_frame f;
111         f.frametype = AST_FRAME_VOICE;
112         f.subclass = AST_FORMAT_SLINEAR;
113         f.datalen = sizeof(slin_g723_ex);
114         /* Assume 8000 Hz */
115         f.timelen = sizeof(slin_g723_ex)/16;
116         f.mallocd = 0;
117         f.offset = 0;
118         f.src = __PRETTY_FUNCTION__;
119         f.data = slin_g723_ex;
120         return &f;
121 }
122
123 static struct ast_frame *g723tolin_sample()
124 {
125         static struct ast_frame f;
126         f.frametype = AST_FRAME_VOICE;
127         f.subclass = AST_FORMAT_G723_1;
128         f.datalen = sizeof(g723_slin_ex);
129         /* All frames are 30 ms long */
130         f.timelen = 30;
131         f.mallocd = 0;
132         f.offset = 0;
133         f.src = __PRETTY_FUNCTION__;
134         f.data = g723_slin_ex;
135         return &f;
136 }
137
138 static struct ast_translator_pvt *lintog723_new()
139 {
140         struct g723_encoder_pvt *tmp;
141         tmp = malloc(sizeof(struct g723_encoder_pvt));
142         if (tmp) {
143                 Init_Coder(&tmp->cod);
144             /* Init Comfort Noise Functions */
145                  if( UseVx ) {
146                         Init_Vad(&tmp->cod);
147                 Init_Cod_Cng(&tmp->cod);
148          }
149                 localusecnt++;
150                 ast_update_use_count();
151                 tmp->tail = 0;
152         }
153         return (struct ast_translator_pvt *)tmp;
154 }
155
156 static struct ast_frame *g723tolin_frameout(struct ast_translator_pvt *pvt)
157 {
158         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
159         if (!tmp->tail)
160                 return NULL;
161         /* Signed linear is no particular frame size, so just send whatever
162            we have in the buffer in one lump sum */
163         tmp->f.frametype = AST_FRAME_VOICE;
164         tmp->f.subclass = AST_FORMAT_SLINEAR;
165         tmp->f.datalen = tmp->tail * 2;
166         /* Assume 8000 Hz */
167         tmp->f.timelen = tmp->tail / 8;
168         tmp->f.mallocd = 0;
169         tmp->f.offset = AST_FRIENDLY_OFFSET;
170         tmp->f.src = __PRETTY_FUNCTION__;
171         tmp->f.data = tmp->buf;
172         /* Reset tail pointer */
173         tmp->tail = 0;
174
175 #if 0
176         /* Save the frames */
177         { 
178                 static int fd2 = -1;
179                 if (fd2 == -1) {
180                         fd2 = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
181                 }
182                 write(fd2, tmp->f.data, tmp->f.datalen);
183         }               
184 #endif
185         return &tmp->f; 
186 }
187
188 static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
189 {
190         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
191 #ifdef  ANNEX_B
192         FLOAT tmpdata[Frame];
193         int x;
194 #endif
195         /* Assuming there's space left, decode into the current buffer at
196            the tail location */
197         if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
198 #ifdef ANNEX_B
199                 Decod(&tmp->dec, tmpdata, f->data, 0);
200                 for (x=0;x<Frame;x++)
201                         (tmp->buf + tmp->tail)[x] = (short)(tmpdata[x]); 
202 #else
203                 Decod(&tmp->dec, tmp->buf + tmp->tail, f->data, 0);
204 #endif
205                 tmp->tail+=Frame;
206         } else {
207                 ast_log(LOG_WARNING, "Out of buffer space\n");
208                 return -1;
209         }
210         return 0;
211 }
212
213 static int lintog723_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
214 {
215         /* Just add the frames to our stream */
216         /* XXX We should look at how old the rest of our stream is, and if it
217            is too old, then we should overwrite it entirely, otherwise we can
218            get artifacts of earlier talk that do not belong */
219         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
220         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
221                 memcpy(&tmp->buf[tmp->tail], f->data, f->datalen);
222                 tmp->tail += f->datalen/2;
223         } else {
224                 ast_log(LOG_WARNING, "Out of buffer space\n");
225                 return -1;
226         }
227         return 0;
228 }
229
230 static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
231 {
232         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
233 #ifdef ANNEX_B
234         int x;
235         FLOAT tmpdata[Frame];
236 #endif
237         /* We can't work on anything less than a frame in size */
238         if (tmp->tail < Frame)
239                 return NULL;
240         /* Encode a frame of data */
241 #ifdef ANNEX_B
242         for (x=0;x<Frame;x++)
243                 tmpdata[x] = tmp->buf[x];
244         Coder(&tmp->cod, tmpdata, tmp->outbuf);
245 #else
246         Coder(&tmp->cod, tmp->buf, tmp->outbuf);
247 #endif
248         tmp->f.frametype = AST_FRAME_VOICE;
249         tmp->f.subclass = AST_FORMAT_G723_1;
250         /* Assume 8000 Hz */
251         tmp->f.timelen = 30;
252         tmp->f.mallocd = 0;
253         tmp->f.offset = AST_FRIENDLY_OFFSET;
254         tmp->f.src = __PRETTY_FUNCTION__;
255         tmp->f.data = tmp->outbuf;
256         switch(tmp->outbuf[0] & TYPE_MASK) {
257         case TYPE_MASK:
258         case TYPE_SILENCE:
259                 tmp->f.datalen = 4;
260                 break;
261         case TYPE_HIGH:
262                 tmp->f.datalen = 24;
263                 break;
264         case TYPE_LOW:
265                 tmp->f.datalen = 20;
266                 break;
267         default:
268                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", tmp->outbuf[0] & TYPE_MASK);
269         }
270         tmp->tail -= Frame;
271         /* Move the data at the end of the buffer to the front */
272         if (tmp->tail)
273                 memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
274 #if 0
275         /* Save to a g723 sample output file... */
276         { 
277                 static int fd = -1;
278                 int delay = htonl(30);
279                 short size;
280                 if (fd < 0)
281                         fd = open("trans.g723", O_WRONLY | O_CREAT | O_TRUNC, 0644);
282                 if (fd < 0)
283                         ast_log(LOG_WARNING, "Unable to create demo\n");
284                 write(fd, &delay, 4);
285                 size = htons(tmp->f.datalen);
286                 write(fd, &size, 2);
287                 write(fd, tmp->f.data, tmp->f.datalen);
288         }
289 #endif
290         return &tmp->f; 
291 }
292
293 static void g723_destroy(struct ast_translator_pvt *pvt)
294 {
295         free(pvt);
296         localusecnt--;
297         ast_update_use_count();
298 }
299
300 static struct ast_translator g723tolin =
301 #ifdef ANNEX_B
302         { "g723tolinb", 
303 #else
304         { "g723tolin", 
305 #endif
306            AST_FORMAT_G723_1, AST_FORMAT_SLINEAR,
307            g723tolin_new,
308            g723tolin_framein,
309            g723tolin_frameout,
310            g723_destroy,
311            g723tolin_sample
312            };
313
314 static struct ast_translator lintog723 =
315 #ifdef ANNEX_B
316         { "lintog723b", 
317 #else
318         { "lintog723", 
319 #endif
320            AST_FORMAT_SLINEAR, AST_FORMAT_G723_1,
321            lintog723_new,
322            lintog723_framein,
323            lintog723_frameout,
324            g723_destroy,
325            lintog723_sample
326            };
327
328 int unload_module(void)
329 {
330         int res;
331         pthread_mutex_lock(&localuser_lock);
332         res = ast_unregister_translator(&lintog723);
333         if (!res)
334                 res = ast_unregister_translator(&g723tolin);
335         if (localusecnt)
336                 res = -1;
337         pthread_mutex_unlock(&localuser_lock);
338         return res;
339 }
340
341 int load_module(void)
342 {
343         int res;
344         res=ast_register_translator(&g723tolin);
345         if (!res) 
346                 res=ast_register_translator(&lintog723);
347         else
348                 ast_unregister_translator(&g723tolin);
349         return res;
350 }
351
352 char *description(void)
353 {
354         return tdesc;
355 }
356
357 int usecount(void)
358 {
359         int res;
360         STANDARD_USECOUNT(res);
361         return res;
362 }