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