38332019c6d7554148ecde2884af7c677a67d067
[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 #include "asterisk/utils.h"
46
47 #define BUFFER_SIZE   8096      /* size for the translation buffers */
48
49 AST_MUTEX_DEFINE_STATIC(localuser_lock);
50 static int localusecnt = 0;
51
52 static char *tdesc = "Mu-law Coder/Decoder";
53
54 static int useplc = 0;
55
56 /* Sample frame data */
57
58 #include "slin_ulaw_ex.h"
59 #include "ulaw_slin_ex.h"
60
61 /*!
62  * \brief Private workspace for translating signed linear signals to ulaw.
63  */
64
65 struct ulaw_encoder_pvt
66 {
67         struct ast_frame f;
68         char offset[AST_FRIENDLY_OFFSET];   /*!< Space to build offset */
69         unsigned char outbuf[BUFFER_SIZE];  /*!< Encoded ulaw, two nibbles to a word */
70         int tail;
71 };
72
73 /*!
74  * \brief Private workspace for translating ulaw signals to signed linear.
75  */
76
77 struct ulaw_decoder_pvt
78 {
79         struct ast_frame f;
80         char offset[AST_FRIENDLY_OFFSET];       /* Space to build offset */
81         short outbuf[BUFFER_SIZE];              /* Decoded signed linear values */
82         int tail;
83         plc_state_t plc;
84 };
85
86 /*!
87  * \brief ulawToLin_New
88  *  Create a new instance of ulaw_decoder_pvt.
89  *
90  * Results:
91  *  Returns a pointer to the new instance.
92  *
93  * Side effects:
94  *  None.
95  */
96
97 static struct ast_translator_pvt *ulawtolin_new(void)
98 {
99         struct ulaw_decoder_pvt *tmp;
100
101         if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
102                 tmp->tail = 0;
103                 plc_init(&tmp->plc);
104                 localusecnt++;
105                 ast_update_use_count();
106         }
107
108         return (struct ast_translator_pvt *)tmp;
109 }
110
111 /*!
112  * \brief 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 *lintoulaw_new(void)
123 {
124         struct ulaw_encoder_pvt *tmp;
125         
126         if ((tmp = ast_calloc(1, sizeof(*tmp)))) {
127                 localusecnt++;
128                 ast_update_use_count();
129                 tmp->tail = 0;
130         }
131
132         return (struct ast_translator_pvt *)tmp;
133 }
134
135 /*!
136  * \brief ulawToLin_FrameIn
137  *  Fill an input buffer with packed 4-bit ulaw values if there is room
138  *  left.
139  *
140  * Results:
141  *  Foo
142  *
143  * Side effects:
144  *  tmp->tail is the number of packed values in the buffer.
145  */
146
147 static int ulawtolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
148 {
149         struct ulaw_decoder_pvt *tmp = (struct ulaw_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_MULAW(b[x]);
174
175         if(useplc)
176                 plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
177
178         tmp->tail += f->datalen;
179         return 0;
180 }
181
182 /*!
183  * \brief ulawToLin_FrameOut
184  *  Convert 4-bit ulaw encoded signals to 16-bit signed linear.
185  *
186  * Results:
187  *  Converted signals are placed in tmp->f.data, tmp->f.datalen
188  *  and tmp->f.samples are calculated.
189  *
190  * Side effects:
191  *  None.
192  */
193
194 static struct ast_frame *ulawtolin_frameout(struct ast_translator_pvt *pvt)
195 {
196         struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *)pvt;
197
198         if (!tmp->tail)
199                 return NULL;
200
201         tmp->f.frametype = AST_FRAME_VOICE;
202         tmp->f.subclass = AST_FORMAT_SLINEAR;
203         tmp->f.datalen = tmp->tail * 2;
204         tmp->f.samples = tmp->tail;
205         tmp->f.mallocd = 0;
206         tmp->f.offset = AST_FRIENDLY_OFFSET;
207         tmp->f.src = __PRETTY_FUNCTION__;
208         tmp->f.data = tmp->outbuf;
209         tmp->tail = 0;
210         return &tmp->f;
211 }
212
213 /*!
214  * \brief LinToulaw_FrameIn
215  *  Fill an input buffer with 16-bit signed linear PCM values.
216  *
217  * Results:
218  *  None.
219  *
220  * Side effects:
221  *  tmp->tail is number of signal values in the input buffer.
222  */
223
224 static int lintoulaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
225 {
226         struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
227         int x;
228         short *s;
229         if (tmp->tail + f->datalen / 2 >= sizeof(tmp->outbuf)) {
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_LIN2MU(s[x]);
236         tmp->tail += f->datalen/2;
237         return 0;
238 }
239
240 /*!
241  * \brief LinToulaw_FrameOut
242  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
243  *  of 4-bit ulaw 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 *lintoulaw_frameout(struct ast_translator_pvt *pvt)
253 {
254         struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
255   
256         if (tmp->tail) {
257                 tmp->f.frametype = AST_FRAME_VOICE;
258                 tmp->f.subclass = AST_FORMAT_ULAW;
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
268                 return NULL;
269 }
270
271
272 /*!
273  * \brief ulawToLin_Sample
274  */
275
276 static struct ast_frame *ulawtolin_sample(void)
277 {
278         static struct ast_frame f;
279         f.frametype = AST_FRAME_VOICE;
280         f.subclass = AST_FORMAT_ULAW;
281         f.datalen = sizeof(ulaw_slin_ex);
282         f.samples = sizeof(ulaw_slin_ex);
283         f.mallocd = 0;
284         f.offset = 0;
285         f.src = __PRETTY_FUNCTION__;
286         f.data = ulaw_slin_ex;
287         return &f;
288 }
289
290 /*!
291  * \brief LinToulaw_Sample
292  */
293
294 static struct ast_frame *lintoulaw_sample(void)
295 {
296         static struct ast_frame f;
297         f.frametype = AST_FRAME_VOICE;
298         f.subclass = AST_FORMAT_SLINEAR;
299         f.datalen = sizeof(slin_ulaw_ex);
300         /* Assume 8000 Hz */
301         f.samples = sizeof(slin_ulaw_ex) / 2;
302         f.mallocd = 0;
303         f.offset = 0;
304         f.src = __PRETTY_FUNCTION__;
305         f.data = slin_ulaw_ex;
306         return &f;
307 }
308
309 /*!
310  * \brief ulaw_Destroy
311  *  Destroys a private workspace.
312  *
313  * Results:
314  *  It's gone!
315  *
316  * Side effects:
317  *  None.
318  */
319
320 static void ulaw_destroy(struct ast_translator_pvt *pvt)
321 {
322         free(pvt);
323         localusecnt--;
324         ast_update_use_count();
325 }
326
327 /*!
328  * \brief The complete translator for ulawToLin.
329  */
330
331 static struct ast_translator ulawtolin = {
332         "ulawtolin",
333         AST_FORMAT_ULAW,
334         AST_FORMAT_SLINEAR,
335         ulawtolin_new,
336         ulawtolin_framein,
337         ulawtolin_frameout,
338         ulaw_destroy,
339         /* NULL */
340         ulawtolin_sample
341 };
342
343 /*!
344  * \brief The complete translator for LinToulaw.
345  */
346
347 static struct ast_translator lintoulaw = {
348         "lintoulaw",
349         AST_FORMAT_SLINEAR,
350         AST_FORMAT_ULAW,
351         lintoulaw_new,
352         lintoulaw_framein,
353         lintoulaw_frameout,
354         ulaw_destroy,
355         /* NULL */
356         lintoulaw_sample
357 };
358
359 static void parse_config(void)
360 {
361         struct ast_config *cfg;
362         struct ast_variable *var;
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_ulaw: %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(&lintoulaw);
389         if (!res)
390                 res = ast_unregister_translator(&ulawtolin);
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(&ulawtolin);
402         if (!res)
403                 res = ast_register_translator(&lintoulaw);
404         else
405                 ast_unregister_translator(&ulawtolin);
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 }