formatting and doxygen fixes (issue #6300)
[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  * \brief 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  * \brief 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  * \brief 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 *ulawtolin_new(void)
97 {
98         struct ulaw_decoder_pvt *tmp;
99         tmp = malloc(sizeof(struct ulaw_decoder_pvt));
100         if (tmp) {
101                 memset(tmp, 0, sizeof(*tmp));
102                 tmp->tail = 0;
103                 plc_init(&tmp->plc);
104                 localusecnt++;
105                 ast_update_use_count();
106         }
107         return (struct ast_translator_pvt *)tmp;
108 }
109
110 /*!
111  * \brief LinToulaw_New
112  *  Create a new instance of ulaw_encoder_pvt.
113  *
114  * Results:
115  *  Returns a pointer to the new instance.
116  *
117  * Side effects:
118  *  None.
119  */
120
121 static struct ast_translator_pvt *lintoulaw_new(void)
122 {
123         struct ulaw_encoder_pvt *tmp;
124         tmp = malloc(sizeof(struct ulaw_encoder_pvt));
125         if (tmp) {
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 ulawToLin_FrameIn
136  *  Fill an input buffer with packed 4-bit ulaw 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 ulawtolin_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
147 {
148         struct ulaw_decoder_pvt *tmp = (struct ulaw_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_MULAW(b[x]);
173
174         if(useplc)
175                 plc_rx(&tmp->plc, tmp->outbuf+tmp->tail, f->datalen);
176
177         tmp->tail += f->datalen;
178         return 0;
179 }
180
181 /*!
182  * \brief ulawToLin_FrameOut
183  *  Convert 4-bit ulaw 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 *ulawtolin_frameout(struct ast_translator_pvt *pvt)
194 {
195         struct ulaw_decoder_pvt *tmp = (struct ulaw_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 LinToulaw_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 lintoulaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
224 {
225         struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
226         int x;
227         short *s;
228         if (tmp->tail + f->datalen / 2 >= sizeof(tmp->outbuf)) {
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_LIN2MU(s[x]);
235         tmp->tail += f->datalen/2;
236         return 0;
237 }
238
239 /*!
240  * \brief LinToulaw_FrameOut
241  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
242  *  of 4-bit ulaw 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 *lintoulaw_frameout(struct ast_translator_pvt *pvt)
252 {
253         struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
254   
255         if (tmp->tail) {
256                 tmp->f.frametype = AST_FRAME_VOICE;
257                 tmp->f.subclass = AST_FORMAT_ULAW;
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
267                 return NULL;
268 }
269
270
271 /*!
272  * \brief ulawToLin_Sample
273  */
274
275 static struct ast_frame *ulawtolin_sample(void)
276 {
277         static struct ast_frame f;
278         f.frametype = AST_FRAME_VOICE;
279         f.subclass = AST_FORMAT_ULAW;
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 LinToulaw_Sample
291  */
292
293 static struct ast_frame *lintoulaw_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 ulaw_Destroy
310  *  Destroys a private workspace.
311  *
312  * Results:
313  *  It's gone!
314  *
315  * Side effects:
316  *  None.
317  */
318
319 static void ulaw_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 ulawToLin.
328  */
329
330 static struct ast_translator ulawtolin = {
331         "ulawtolin",
332         AST_FORMAT_ULAW,
333         AST_FORMAT_SLINEAR,
334         ulawtolin_new,
335         ulawtolin_framein,
336         ulawtolin_frameout,
337         ulaw_destroy,
338         /* NULL */
339         ulawtolin_sample
340 };
341
342 /*!
343  * \brief The complete translator for LinToulaw.
344  */
345
346 static struct ast_translator lintoulaw = {
347         "lintoulaw",
348         AST_FORMAT_SLINEAR,
349         AST_FORMAT_ULAW,
350         lintoulaw_new,
351         lintoulaw_framein,
352         lintoulaw_frameout,
353         ulaw_destroy,
354         /* NULL */
355         lintoulaw_sample
356 };
357
358 static void parse_config(void)
359 {
360         struct ast_config *cfg;
361         struct ast_variable *var;
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_ulaw: %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(&lintoulaw);
388         if (!res)
389                 res = ast_unregister_translator(&ulawtolin);
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(&ulawtolin);
401         if (!res)
402                 res = ast_register_translator(&lintoulaw);
403         else
404                 ast_unregister_translator(&ulawtolin);
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 }