bd1bdea72de022c17071d3733e559d8f8d934f10
[asterisk/asterisk.git] / codecs / codec_alaw.c
1 /* codec_alaw.c - translate between signed linear and alaw
2  * 
3  * Asterisk -- A telephony toolkit for Linux.
4  *
5  * Copyright (c) 2001 Linux Support Services, Inc.  All rights reserved.
6  *
7  * Mark Spencer <markster@linux-support.net
8  *
9  * This program is free software, distributed under the terms of
10  * the GNU General Public License
11  */
12
13 #include "asterisk/lock.h"
14 #include "asterisk/logger.h"
15 #include "asterisk/module.h"
16 #include "asterisk/config.h"
17 #include "asterisk/options.h"
18 #include "asterisk/translate.h"
19 #include "asterisk/channel.h"
20 #include "asterisk/alaw.h"
21 #include <fcntl.h>
22 #include <netinet/in.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #define BUFFER_SIZE   8096      /* size for the translation buffers */
29
30 AST_MUTEX_DEFINE_STATIC(localuser_lock);
31 static int localusecnt = 0;
32
33 static char *tdesc = "A-law Coder/Decoder";
34
35 static int useplc = 0;
36
37 /* Sample frame data (Mu data is okay) */
38
39 #include "slin_ulaw_ex.h"
40 #include "ulaw_slin_ex.h"
41
42 /*
43  * Private workspace for translating signed linear signals to alaw.
44  */
45
46 struct alaw_encoder_pvt
47 {
48   struct ast_frame f;
49   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
50   unsigned char outbuf[BUFFER_SIZE];  /* Encoded alaw, two nibbles to a word */
51   int tail;
52 };
53
54 /*
55  * Private workspace for translating alaw signals to signed linear.
56  */
57
58 struct alaw_decoder_pvt
59 {
60   struct ast_frame f;
61   char offset[AST_FRIENDLY_OFFSET];     /* Space to build offset */
62   short outbuf[BUFFER_SIZE];    /* Decoded signed linear values */
63   int tail;
64   plc_state_t plc;
65 };
66
67 /*
68  * alawToLin_New
69  *  Create a new instance of alaw_decoder_pvt.
70  *
71  * Results:
72  *  Returns a pointer to the new instance.
73  *
74  * Side effects:
75  *  None.
76  */
77
78 static struct ast_translator_pvt *
79 alawtolin_new (void)
80 {
81   struct alaw_decoder_pvt *tmp;
82   tmp = malloc (sizeof (struct alaw_decoder_pvt));
83   if (tmp)
84     {
85           memset(tmp, 0, sizeof(*tmp));
86       tmp->tail = 0;
87       plc_init(&tmp->plc);
88       localusecnt++;
89       ast_update_use_count ();
90     }
91   return (struct ast_translator_pvt *) tmp;
92 }
93
94 /*
95  * LinToalaw_New
96  *  Create a new instance of alaw_encoder_pvt.
97  *
98  * Results:
99  *  Returns a pointer to the new instance.
100  *
101  * Side effects:
102  *  None.
103  */
104
105 static struct ast_translator_pvt *
106 lintoalaw_new (void)
107 {
108   struct alaw_encoder_pvt *tmp;
109   tmp = malloc (sizeof (struct alaw_encoder_pvt));
110   if (tmp)
111     {
112           memset(tmp, 0, sizeof(*tmp));
113       localusecnt++;
114       ast_update_use_count ();
115       tmp->tail = 0;
116     }
117   return (struct ast_translator_pvt *) tmp;
118 }
119
120 /*
121  * alawToLin_FrameIn
122  *  Fill an input buffer with packed 4-bit alaw values if there is room
123  *  left.
124  *
125  * Results:
126  *  Foo
127  *
128  * Side effects:
129  *  tmp->tail is the number of packed values in the buffer.
130  */
131
132 static int
133 alawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
134 {
135   struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
136   int x;
137   unsigned char *b;
138
139   if(f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
140         if((tmp->tail + 160)  * 2 > sizeof(tmp->outbuf)) {
141             ast_log(LOG_WARNING, "Out of buffer space\n");
142             return -1;
143         }
144         if(useplc) {
145             plc_fillin(&tmp->plc, tmp->outbuf+tmp->tail, 160);
146             tmp->tail += 160;
147         }
148         return 0;
149   }
150
151   if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
152         ast_log(LOG_WARNING, "Out of buffer space\n");
153         return -1;
154   }
155
156   /* Reset ssindex and signal to frame's specified values */
157   b = f->data;
158   for (x=0;x<f->datalen;x++)
159         tmp->outbuf[tmp->tail + x] = AST_ALAW(b[x]);
160
161   if(useplc) plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
162
163   tmp->tail += f->datalen;
164   return 0;
165 }
166
167 /*
168  * alawToLin_FrameOut
169  *  Convert 4-bit alaw encoded signals to 16-bit signed linear.
170  *
171  * Results:
172  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
173  *  and tmp->f.samples are calculated.
174  *
175  * Side effects:
176  *  None.
177  */
178
179 static struct ast_frame *
180 alawtolin_frameout (struct ast_translator_pvt *pvt)
181 {
182   struct alaw_decoder_pvt *tmp = (struct alaw_decoder_pvt *) pvt;
183
184   if (!tmp->tail)
185     return NULL;
186
187   tmp->f.frametype = AST_FRAME_VOICE;
188   tmp->f.subclass = AST_FORMAT_SLINEAR;
189   tmp->f.datalen = tmp->tail *2;
190   tmp->f.samples = tmp->tail;
191   tmp->f.mallocd = 0;
192   tmp->f.offset = AST_FRIENDLY_OFFSET;
193   tmp->f.src = __PRETTY_FUNCTION__;
194   tmp->f.data = tmp->outbuf;
195   tmp->tail = 0;
196   return &tmp->f;
197 }
198
199 /*
200  * LinToalaw_FrameIn
201  *  Fill an input buffer with 16-bit signed linear PCM values.
202  *
203  * Results:
204  *  None.
205  *
206  * Side effects:
207  *  tmp->tail is number of signal values in the input buffer.
208  */
209
210 static int
211 lintoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
212 {
213   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
214   int x;
215   short *s;
216   if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
217     {
218       ast_log (LOG_WARNING, "Out of buffer space\n");
219       return -1;
220     }
221   s = f->data;
222   for (x=0;x<f->datalen/2;x++) 
223         tmp->outbuf[x+tmp->tail] = AST_LIN2A(s[x]);
224   tmp->tail += f->datalen/2;
225   return 0;
226 }
227
228 /*
229  * LinToalaw_FrameOut
230  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
231  *  of 4-bit alaw packed two to a byte (Big Endian).
232  *
233  * Results:
234  *  Foo
235  *
236  * Side effects:
237  *  Leftover inbuf data gets packed, tail gets updated.
238  */
239
240 static struct ast_frame *
241 lintoalaw_frameout (struct ast_translator_pvt *pvt)
242 {
243   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
244   
245   if (tmp->tail) {
246           tmp->f.frametype = AST_FRAME_VOICE;
247           tmp->f.subclass = AST_FORMAT_ALAW;
248           tmp->f.samples = tmp->tail;
249           tmp->f.mallocd = 0;
250           tmp->f.offset = AST_FRIENDLY_OFFSET;
251           tmp->f.src = __PRETTY_FUNCTION__;
252           tmp->f.data = tmp->outbuf;
253           tmp->f.datalen = tmp->tail;
254           tmp->tail = 0;
255           return &tmp->f;
256    } else return NULL;
257 }
258
259
260 /*
261  * alawToLin_Sample
262  */
263
264 static struct ast_frame *
265 alawtolin_sample (void)
266 {
267   static struct ast_frame f;
268   f.frametype = AST_FRAME_VOICE;
269   f.subclass = AST_FORMAT_ALAW;
270   f.datalen = sizeof (ulaw_slin_ex);
271   f.samples = sizeof(ulaw_slin_ex);
272   f.mallocd = 0;
273   f.offset = 0;
274   f.src = __PRETTY_FUNCTION__;
275   f.data = ulaw_slin_ex;
276   return &f;
277 }
278
279 /*
280  * LinToalaw_Sample
281  */
282
283 static struct ast_frame *
284 lintoalaw_sample (void)
285 {
286   static struct ast_frame f;
287   f.frametype = AST_FRAME_VOICE;
288   f.subclass = AST_FORMAT_SLINEAR;
289   f.datalen = sizeof (slin_ulaw_ex);
290   /* Assume 8000 Hz */
291   f.samples = sizeof (slin_ulaw_ex) / 2;
292   f.mallocd = 0;
293   f.offset = 0;
294   f.src = __PRETTY_FUNCTION__;
295   f.data = slin_ulaw_ex;
296   return &f;
297 }
298
299 /*
300  * alaw_Destroy
301  *  Destroys a private workspace.
302  *
303  * Results:
304  *  It's gone!
305  *
306  * Side effects:
307  *  None.
308  */
309
310 static void
311 alaw_destroy (struct ast_translator_pvt *pvt)
312 {
313   free (pvt);
314   localusecnt--;
315   ast_update_use_count ();
316 }
317
318 /*
319  * The complete translator for alawToLin.
320  */
321
322 static struct ast_translator alawtolin = {
323   "alawtolin",
324   AST_FORMAT_ALAW,
325   AST_FORMAT_SLINEAR,
326   alawtolin_new,
327   alawtolin_framein,
328   alawtolin_frameout,
329   alaw_destroy,
330   /* NULL */
331   alawtolin_sample
332 };
333
334 /*
335  * The complete translator for LinToalaw.
336  */
337
338 static struct ast_translator lintoalaw = {
339   "lintoalaw",
340   AST_FORMAT_SLINEAR,
341   AST_FORMAT_ALAW,
342   lintoalaw_new,
343   lintoalaw_framein,
344   lintoalaw_frameout,
345   alaw_destroy,
346   /* NULL */
347   lintoalaw_sample
348 };
349
350 static void 
351 parse_config(void)
352 {
353   struct ast_config *cfg;
354   struct ast_variable *var;
355
356   if ((cfg = ast_config_load("codecs.conf"))) {
357     if ((var = ast_variable_browse(cfg, "plc"))) {
358       while (var) {
359        if (!strcasecmp(var->name, "genericplc")) {
360          useplc = ast_true(var->value) ? 1 : 0;
361          if (option_verbose > 2)
362            ast_verbose(VERBOSE_PREFIX_3 "codec_alaw: %susing generic PLC\n", useplc ? "" : "not ");
363        }
364        var = var->next;
365       }
366     }
367     ast_config_destroy(cfg);
368   }
369 }
370
371 int
372 reload(void)
373 {
374   parse_config();
375   return 0;
376 }
377
378 int
379 unload_module (void)
380 {
381   int res;
382   ast_mutex_lock (&localuser_lock);
383   res = ast_unregister_translator (&lintoalaw);
384   if (!res)
385     res = ast_unregister_translator (&alawtolin);
386   if (localusecnt)
387     res = -1;
388   ast_mutex_unlock (&localuser_lock);
389   return res;
390 }
391
392 int
393 load_module (void)
394 {
395   int res;
396   parse_config();
397   res = ast_register_translator (&alawtolin);
398   if (!res)
399     res = ast_register_translator (&lintoalaw);
400   else
401     ast_unregister_translator (&alawtolin);
402   return res;
403 }
404
405 /*
406  * Return a description of this module.
407  */
408
409 char *
410 description (void)
411 {
412   return tdesc;
413 }
414
415 int
416 usecount (void)
417 {
418   int res;
419   STANDARD_USECOUNT (res);
420   return res;
421 }
422
423 char *
424 key ()
425 {
426   return ASTERISK_GPL_KEY;
427 }