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