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