Version 0.1.3 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 <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 a sample frame */
177         { static int samplefr = 0;
178         if (samplefr == 80) {
179                 int fd;
180                 fd = open("g723.example", O_WRONLY | O_CREAT | O_TRUNC, 0644);
181                 write(fd, tmp->f.data, tmp->f.datalen);
182                 close(fd);
183         }               
184         samplefr++;
185         }
186 #endif
187         return &tmp->f; 
188 }
189
190 static int g723tolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
191 {
192         struct g723_decoder_pvt *tmp = (struct g723_decoder_pvt *)pvt;
193 #ifdef  ANNEX_B
194         FLOAT tmpdata[Frame];
195         int x;
196 #endif
197         /* Assuming there's space left, decode into the current buffer at
198            the tail location */
199         if (tmp->tail + Frame < sizeof(tmp->buf)/2) {   
200 #ifdef ANNEX_B
201                 Decod(&tmp->dec, tmpdata, f->data, 0);
202                 for (x=0;x<Frame;x++)
203                         (tmp->buf + tmp->tail)[x] = (short)tmpdata[x]; 
204 #else
205                 Decod(&tmp->dec, tmp->buf + tmp->tail, f->data, 0);
206 #endif
207                 tmp->tail+=Frame;
208         } else {
209                 ast_log(LOG_WARNING, "Out of buffer space\n");
210                 return -1;
211         }
212         return 0;
213 }
214
215 static int lintog723_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
216 {
217         /* Just add the frames to our stream */
218         /* XXX We should look at how old the rest of our stream is, and if it
219            is too old, then we should overwrite it entirely, otherwise we can
220            get artifacts of earlier talk that do not belong */
221         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
222         if (tmp->tail + f->datalen/2 < sizeof(tmp->buf) / 2) {
223                 memcpy(&tmp->buf[tmp->tail], f->data, f->datalen);
224                 tmp->tail += f->datalen/2;
225         } else {
226                 ast_log(LOG_WARNING, "Out of buffer space\n");
227                 return -1;
228         }
229         return 0;
230 }
231
232 static struct ast_frame *lintog723_frameout(struct ast_translator_pvt *pvt)
233 {
234         struct g723_encoder_pvt *tmp = (struct g723_encoder_pvt *)pvt;
235 #ifdef ANNEX_B
236         int x;
237         FLOAT tmpdata[Frame];
238 #endif
239         /* We can't work on anything less than a frame in size */
240         if (tmp->tail < Frame)
241                 return NULL;
242         /* Encode a frame of data */
243 #ifdef ANNEX_B
244         for (x=0;x<Frame;x++)
245                 tmpdata[x] = tmp->buf[x];
246         Coder(&tmp->cod, tmpdata, tmp->outbuf);
247 #else
248         Coder(&tmp->cod, tmp->buf, tmp->outbuf);
249 #endif
250         tmp->f.frametype = AST_FRAME_VOICE;
251         tmp->f.subclass = AST_FORMAT_G723_1;
252         /* Assume 8000 Hz */
253         tmp->f.timelen = 30;
254         tmp->f.mallocd = 0;
255         tmp->f.offset = AST_FRIENDLY_OFFSET;
256         tmp->f.src = __PRETTY_FUNCTION__;
257         tmp->f.data = tmp->outbuf;
258         switch(tmp->outbuf[0] & TYPE_MASK) {
259         case TYPE_MASK:
260         case TYPE_SILENCE:
261                 tmp->f.datalen = 4;
262                 break;
263         case TYPE_HIGH:
264                 tmp->f.datalen = 24;
265                 break;
266         case TYPE_LOW:
267                 tmp->f.datalen = 20;
268                 break;
269         default:
270                 ast_log(LOG_WARNING, "Badly encoded frame (%d)\n", tmp->outbuf[0] & TYPE_MASK);
271         }
272         tmp->tail -= Frame;
273         /* Move the data at the end of the buffer to the front */
274         if (tmp->tail)
275                 memmove(tmp->buf, tmp->buf + Frame, tmp->tail * 2);
276 #if 0
277         /* Save to a g723 sample output file... */
278         { 
279                 static int fd = -1;
280                 int delay = htonl(30);
281                 short size;
282                 if (fd < 0)
283                         fd = open("trans.g723", O_WRONLY | O_CREAT | O_TRUNC, 0644);
284                 if (fd < 0)
285                         ast_log(LOG_WARNING, "Unable to create demo\n");
286                 write(fd, &delay, 4);
287                 size = htons(tmp->f.datalen);
288                 write(fd, &size, 2);
289                 write(fd, tmp->f.data, tmp->f.datalen);
290         }
291 #endif
292         return &tmp->f; 
293 }
294
295 static void g723_destroy(struct ast_translator_pvt *pvt)
296 {
297         free(pvt);
298         localusecnt--;
299         ast_update_use_count();
300 }
301
302 static struct ast_translator g723tolin =
303 #ifdef ANNEX_B
304         { "g723tolinb", 
305 #else
306         { "g723tolin", 
307 #endif
308            AST_FORMAT_G723_1, AST_FORMAT_SLINEAR,
309            g723tolin_new,
310            g723tolin_framein,
311            g723tolin_frameout,
312            g723_destroy,
313            g723tolin_sample
314            };
315
316 static struct ast_translator lintog723 =
317 #ifdef ANNEX_B
318         { "lintog723b", 
319 #else
320         { "lintog723", 
321 #endif
322            AST_FORMAT_SLINEAR, AST_FORMAT_G723_1,
323            lintog723_new,
324            lintog723_framein,
325            lintog723_frameout,
326            g723_destroy,
327            lintog723_sample
328            };
329
330 int unload_module(void)
331 {
332         int res;
333         pthread_mutex_lock(&localuser_lock);
334         res = ast_unregister_translator(&lintog723);
335         if (!res)
336                 res = ast_unregister_translator(&g723tolin);
337         if (localusecnt)
338                 res = -1;
339         pthread_mutex_unlock(&localuser_lock);
340         return res;
341 }
342
343 int load_module(void)
344 {
345         int res;
346         res=ast_register_translator(&g723tolin);
347         if (!res) 
348                 res=ast_register_translator(&lintog723);
349         else
350                 ast_unregister_translator(&g723tolin);
351         return res;
352 }
353
354 char *description(void)
355 {
356         return tdesc;
357 }
358
359 int usecount(void)
360 {
361         int res;
362         STANDARD_USECOUNT(res);
363         return res;
364 }