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