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