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