formatting and doxygen fixes (issue #6300)
[asterisk/asterisk.git] / codecs / codec_a_mu.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_a_mu.c - translate between alaw and ulaw directly
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/translate.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/alaw.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 = "A-law and Mulaw direct Coder/Decoder";
51
52 static unsigned char mu2a[256];
53 static unsigned char a2mu[256];
54
55 /* Sample frame data (Mu data is okay) */
56
57 #include "ulaw_slin_ex.h"
58
59 /*
60  * Private workspace for translating signed linear signals to alaw.
61  */
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  * Private workspace for translating laws.
73  */
74
75 struct ulaw_encoder_pvt
76 {
77         struct ast_frame f;
78         char offset[AST_FRIENDLY_OFFSET];       /* Space to build offset */
79         unsigned char outbuf[BUFFER_SIZE];      /* Encoded ulaw values */
80         int tail;
81 };
82
83 static struct ast_translator_pvt *alawtoulaw_new(void)
84 {
85         struct ulaw_encoder_pvt *tmp;
86         tmp = malloc(sizeof(struct ulaw_encoder_pvt));
87         if (tmp) {
88                 memset(tmp, 0, sizeof(*tmp));
89                 tmp->tail = 0;
90                 localusecnt++;
91                 ast_update_use_count();
92         }
93         return (struct ast_translator_pvt *)tmp;
94 }
95
96 static struct ast_translator_pvt *ulawtoalaw_new(void)
97 {
98         struct alaw_encoder_pvt *tmp;
99         tmp = malloc(sizeof(struct alaw_encoder_pvt));
100         if (tmp) {
101                 memset(tmp, 0, sizeof(*tmp));
102                 localusecnt++;
103                 ast_update_use_count();
104                 tmp->tail = 0;
105         }
106         return (struct ast_translator_pvt *)tmp;
107 }
108
109 static int alawtoulaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
110 {
111         struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
112         int x;
113         unsigned char *b;
114
115         if ((tmp->tail + f->datalen) > sizeof(tmp->outbuf)) {
116                 ast_log(LOG_WARNING, "Out of buffer space\n");
117                 return -1;
118         }
119
120         /* Reset ssindex and signal to frame's specified values */
121         b = f->data;
122         for (x=0;x<f->datalen;x++)
123                 tmp->outbuf[tmp->tail + x] = a2mu[b[x]];
124
125         tmp->tail += f->datalen;
126         return 0;
127 }
128
129 static struct ast_frame *alawtoulaw_frameout(struct ast_translator_pvt *pvt)
130 {
131         struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *)pvt;
132
133         if (!tmp->tail)
134                 return NULL;
135
136         tmp->f.frametype = AST_FRAME_VOICE;
137         tmp->f.subclass = AST_FORMAT_ULAW;
138         tmp->f.datalen = tmp->tail;
139         tmp->f.samples = tmp->tail;
140         tmp->f.mallocd = 0;
141         tmp->f.offset = AST_FRIENDLY_OFFSET;
142         tmp->f.src = __PRETTY_FUNCTION__;
143         tmp->f.data = tmp->outbuf;
144         tmp->tail = 0;
145         return &tmp->f;
146 }
147
148 static int ulawtoalaw_framein(struct ast_translator_pvt *pvt, struct ast_frame *f)
149 {
150         struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
151         int x;
152         unsigned char *s;
153         if (tmp->tail + f->datalen >= sizeof(tmp->outbuf)) {
154                 ast_log(LOG_WARNING, "Out of buffer space\n");
155                 return -1;
156         }
157         s = f->data;
158         for (x=0;x<f->datalen;x++) 
159                 tmp->outbuf[x+tmp->tail] = mu2a[s[x]];
160         tmp->tail += f->datalen;
161         return 0;
162 }
163
164 /*
165  * LinToalaw_FrameOut
166  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
167  *  of 4-bit alaw packed two to a byte (Big Endian).
168  *
169  * Results:
170  *  Foo
171  *
172  * Side effects:
173  *  Leftover inbuf data gets packed, tail gets updated.
174  */
175
176 static struct ast_frame *ulawtoalaw_frameout(struct ast_translator_pvt *pvt)
177 {
178         struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *)pvt;
179   
180         if (tmp->tail) {
181                 tmp->f.frametype = AST_FRAME_VOICE;
182                 tmp->f.subclass = AST_FORMAT_ALAW;
183                 tmp->f.samples = tmp->tail;
184                 tmp->f.mallocd = 0;
185                 tmp->f.offset = AST_FRIENDLY_OFFSET;
186                 tmp->f.src = __PRETTY_FUNCTION__;
187                 tmp->f.data = tmp->outbuf;
188                 tmp->f.datalen = tmp->tail;
189                 tmp->tail = 0;
190                 return &tmp->f;
191         } else
192                 return NULL;
193 }
194
195 /*
196  * alawToLin_Sample
197  */
198
199 static struct ast_frame *alawtoulaw_sample(void)
200 {
201         static struct ast_frame f;
202         f.frametype = AST_FRAME_VOICE;
203         f.subclass = AST_FORMAT_ALAW;
204         f.datalen = sizeof(ulaw_slin_ex);
205         f.samples = sizeof(ulaw_slin_ex);
206         f.mallocd = 0;
207         f.offset = 0;
208         f.src = __PRETTY_FUNCTION__;
209         f.data = ulaw_slin_ex;
210         return &f;
211 }
212
213 static struct ast_frame *ulawtoalaw_sample(void)
214 {
215         static struct ast_frame f;
216         f.frametype = AST_FRAME_VOICE;
217         f.subclass = AST_FORMAT_ULAW;
218         f.datalen = sizeof(ulaw_slin_ex);
219         f.samples = sizeof(ulaw_slin_ex);
220         f.mallocd = 0;
221         f.offset = 0;
222         f.src = __PRETTY_FUNCTION__;
223         f.data = ulaw_slin_ex;
224         return &f;
225 }
226
227 /*
228  * alaw_Destroy
229  *  Destroys a private workspace.
230  *
231  * Results:
232  *  It's gone!
233  *
234  * Side effects:
235  *  None.
236  */
237
238 static void alaw_destroy(struct ast_translator_pvt *pvt)
239 {
240         free(pvt);
241         localusecnt--;
242         ast_update_use_count();
243 }
244
245 /*
246  * The complete translator for alawToLin.
247  */
248
249 static struct ast_translator alawtoulaw = {
250         "alawtoulaw",
251         AST_FORMAT_ALAW,
252         AST_FORMAT_ULAW,
253         alawtoulaw_new,
254         alawtoulaw_framein,
255         alawtoulaw_frameout,
256         alaw_destroy,
257         /* NULL */
258         alawtoulaw_sample
259 };
260
261 /*
262  * The complete translator for LinToalaw.
263  */
264
265 static struct ast_translator ulawtoalaw = {
266         "ulawtoalaw",
267         AST_FORMAT_ULAW,
268         AST_FORMAT_ALAW,
269         ulawtoalaw_new,
270         ulawtoalaw_framein,
271         ulawtoalaw_frameout,
272         alaw_destroy,
273         /* NULL */
274         ulawtoalaw_sample
275 };
276
277 int unload_module(void)
278 {
279         int res;
280         ast_mutex_lock(&localuser_lock);
281         res = ast_unregister_translator(&ulawtoalaw);
282         if (!res)
283                 res = ast_unregister_translator(&alawtoulaw);
284         if (localusecnt)
285                 res = -1;
286         ast_mutex_unlock(&localuser_lock);
287         return res;
288 }
289
290 int load_module(void)
291 {
292         int res;
293         int x;
294         for (x=0;x<256;x++) {
295                 mu2a[x] = AST_LIN2A(AST_MULAW(x));
296                 a2mu[x] = AST_LIN2MU(AST_ALAW(x));
297         }
298         res = ast_register_translator(&alawtoulaw);
299         if (!res)
300                 res = ast_register_translator(&ulawtoalaw);
301         else
302                 ast_unregister_translator(&alawtoulaw);
303         return res;
304 }
305
306 /*
307  * Return a description of this module.
308  */
309
310 char *description(void)
311 {
312         return tdesc;
313 }
314
315 int usecount(void)
316 {
317         int res;
318         STANDARD_USECOUNT(res);
319         return res;
320 }
321
322 char *key()
323 {
324         return ASTERISK_GPL_KEY;
325 }