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