1 /* codec_ulaw.c - translate between signed linear and ulaw
3 * Asterisk -- A telephony toolkit for Linux.
5 * Copyright (c) 2001 Linux Support Services, Inc. All rights reserved.
7 * Mark Spencer <markster@linux-support.net
9 * This program is free software, distributed under the terms of
10 * the GNU General Public License
13 #include <asterisk/lock.h>
14 #include <asterisk/logger.h>
15 #include <asterisk/module.h>
16 #include <asterisk/translate.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/ulaw.h>
20 #include <netinet/in.h>
27 #define BUFFER_SIZE 8096 /* size for the translation buffers */
29 AST_MUTEX_DEFINE_STATIC(localuser_lock);
30 static int localusecnt = 0;
32 static char *tdesc = "Mu-law Coder/Decoder";
34 /* Sample frame data */
36 #include "slin_ulaw_ex.h"
37 #include "ulaw_slin_ex.h"
40 * Private workspace for translating signed linear signals to ulaw.
43 struct ulaw_encoder_pvt
46 char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
47 unsigned char outbuf[BUFFER_SIZE]; /* Encoded ulaw, two nibbles to a word */
52 * Private workspace for translating ulaw signals to signed linear.
55 struct ulaw_decoder_pvt
58 char offset[AST_FRIENDLY_OFFSET]; /* Space to build offset */
59 short outbuf[BUFFER_SIZE]; /* Decoded signed linear values */
65 * Create a new instance of ulaw_decoder_pvt.
68 * Returns a pointer to the new instance.
74 static struct ast_translator_pvt *
77 struct ulaw_decoder_pvt *tmp;
78 tmp = malloc (sizeof (struct ulaw_decoder_pvt));
81 memset(tmp, 0, sizeof(*tmp));
84 ast_update_use_count ();
86 return (struct ast_translator_pvt *) tmp;
91 * Create a new instance of ulaw_encoder_pvt.
94 * Returns a pointer to the new instance.
100 static struct ast_translator_pvt *
103 struct ulaw_encoder_pvt *tmp;
104 tmp = malloc (sizeof (struct ulaw_encoder_pvt));
107 memset(tmp, 0, sizeof(*tmp));
109 ast_update_use_count ();
112 return (struct ast_translator_pvt *) tmp;
117 * Fill an input buffer with packed 4-bit ulaw values if there is room
124 * tmp->tail is the number of packed values in the buffer.
128 ulawtolin_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
130 struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
134 if ((tmp->tail + f->datalen) * 2 > sizeof(tmp->outbuf)) {
135 ast_log(LOG_WARNING, "Out of buffer space\n");
139 /* Reset ssindex and signal to frame's specified values */
141 for (x=0;x<f->datalen;x++)
142 tmp->outbuf[tmp->tail + x] = AST_MULAW(b[x]);
144 tmp->tail += f->datalen;
150 * Convert 4-bit ulaw encoded signals to 16-bit signed linear.
153 * Converted signals are placed in tmp->f.data, tmp->f.datalen
154 * and tmp->f.samples are calculated.
160 static struct ast_frame *
161 ulawtolin_frameout (struct ast_translator_pvt *pvt)
163 struct ulaw_decoder_pvt *tmp = (struct ulaw_decoder_pvt *) pvt;
168 tmp->f.frametype = AST_FRAME_VOICE;
169 tmp->f.subclass = AST_FORMAT_SLINEAR;
170 tmp->f.datalen = tmp->tail *2;
171 tmp->f.samples = tmp->tail;
173 tmp->f.offset = AST_FRIENDLY_OFFSET;
174 tmp->f.src = __PRETTY_FUNCTION__;
175 tmp->f.data = tmp->outbuf;
182 * Fill an input buffer with 16-bit signed linear PCM values.
188 * tmp->tail is number of signal values in the input buffer.
192 lintoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
194 struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
197 if (tmp->tail + f->datalen/2 >= sizeof(tmp->outbuf))
199 ast_log (LOG_WARNING, "Out of buffer space\n");
203 for (x=0;x<f->datalen/2;x++)
204 tmp->outbuf[x+tmp->tail] = AST_LIN2MU(s[x]);
205 tmp->tail += f->datalen/2;
211 * Convert a buffer of raw 16-bit signed linear PCM to a buffer
212 * of 4-bit ulaw packed two to a byte (Big Endian).
218 * Leftover inbuf data gets packed, tail gets updated.
221 static struct ast_frame *
222 lintoulaw_frameout (struct ast_translator_pvt *pvt)
224 struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
227 tmp->f.frametype = AST_FRAME_VOICE;
228 tmp->f.subclass = AST_FORMAT_ULAW;
229 tmp->f.samples = tmp->tail;
231 tmp->f.offset = AST_FRIENDLY_OFFSET;
232 tmp->f.src = __PRETTY_FUNCTION__;
233 tmp->f.data = tmp->outbuf;
234 tmp->f.datalen = tmp->tail;
245 static struct ast_frame *
246 ulawtolin_sample (void)
248 static struct ast_frame f;
249 f.frametype = AST_FRAME_VOICE;
250 f.subclass = AST_FORMAT_ULAW;
251 f.datalen = sizeof (ulaw_slin_ex);
252 f.samples = sizeof(ulaw_slin_ex);
255 f.src = __PRETTY_FUNCTION__;
256 f.data = ulaw_slin_ex;
264 static struct ast_frame *
265 lintoulaw_sample (void)
267 static struct ast_frame f;
268 f.frametype = AST_FRAME_VOICE;
269 f.subclass = AST_FORMAT_SLINEAR;
270 f.datalen = sizeof (slin_ulaw_ex);
272 f.samples = sizeof (slin_ulaw_ex) / 2;
275 f.src = __PRETTY_FUNCTION__;
276 f.data = slin_ulaw_ex;
282 * Destroys a private workspace.
292 ulaw_destroy (struct ast_translator_pvt *pvt)
296 ast_update_use_count ();
300 * The complete translator for ulawToLin.
303 static struct ast_translator ulawtolin = {
316 * The complete translator for LinToulaw.
319 static struct ast_translator lintoulaw = {
335 ast_mutex_lock (&localuser_lock);
336 res = ast_unregister_translator (&lintoulaw);
338 res = ast_unregister_translator (&ulawtolin);
341 ast_mutex_unlock (&localuser_lock);
349 res = ast_register_translator (&ulawtolin);
351 res = ast_register_translator (&lintoulaw);
353 ast_unregister_translator (&ulawtolin);
358 * Return a description of this module.
371 STANDARD_USECOUNT (res);
378 return ASTERISK_GPL_KEY;