more file version tags
[asterisk/asterisk.git] / codecs / codec_a_mu.c
1 /* codec_a_mu.c - translate between alaw and ulaw directly
2  * 
3  * Asterisk -- A telephony toolkit for Linux.
4  *
5  * Copyright (c) 2001 Linux Support Services, Inc.  All rights reserved.
6  *
7  * Mark Spencer <markster@linux-support.net
8  *
9  * This program is free software, distributed under the terms of
10  * the GNU General Public License
11  */
12
13 #include <fcntl.h>
14 #include <netinet/in.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #include "asterisk.h"
21
22 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
23
24 #include "asterisk/lock.h"
25 #include "asterisk/logger.h"
26 #include "asterisk/module.h"
27 #include "asterisk/translate.h"
28 #include "asterisk/channel.h"
29 #include "asterisk/alaw.h"
30 #include "asterisk/ulaw.h"
31
32 #define BUFFER_SIZE   8096      /* size for the translation buffers */
33
34 AST_MUTEX_DEFINE_STATIC(localuser_lock);
35 static int localusecnt = 0;
36
37 static char *tdesc = "A-law and Mulaw direct Coder/Decoder";
38
39 static unsigned char mu2a[256];
40 static unsigned char a2mu[256];
41
42 /* Sample frame data (Mu data is okay) */
43
44 #include "ulaw_slin_ex.h"
45
46 /*
47  * Private workspace for translating signed linear signals to alaw.
48  */
49
50 struct alaw_encoder_pvt
51 {
52   struct ast_frame f;
53   char offset[AST_FRIENDLY_OFFSET];   /* Space to build offset */
54   unsigned char outbuf[BUFFER_SIZE];  /* Encoded alaw, two nibbles to a word */
55   int tail;
56 };
57
58 /*
59  * Private workspace for translating laws.
60  */
61
62 struct ulaw_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 ulaw values */
67   int tail;
68 };
69
70 static struct ast_translator_pvt *
71 alawtoulaw_new (void)
72 {
73   struct ulaw_encoder_pvt *tmp;
74   tmp = malloc (sizeof (struct ulaw_encoder_pvt));
75   if (tmp)
76     {
77           memset(tmp, 0, sizeof(*tmp));
78       tmp->tail = 0;
79       localusecnt++;
80       ast_update_use_count ();
81     }
82   return (struct ast_translator_pvt *) tmp;
83 }
84
85 static struct ast_translator_pvt *
86 ulawtoalaw_new (void)
87 {
88   struct alaw_encoder_pvt *tmp;
89   tmp = malloc (sizeof (struct alaw_encoder_pvt));
90   if (tmp)
91     {
92           memset(tmp, 0, sizeof(*tmp));
93       localusecnt++;
94       ast_update_use_count ();
95       tmp->tail = 0;
96     }
97   return (struct ast_translator_pvt *) tmp;
98 }
99
100 static int
101 alawtoulaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
102 {
103   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
104   int x;
105   unsigned char *b;
106
107   if ((tmp->tail + f->datalen)> sizeof(tmp->outbuf)) {
108         ast_log(LOG_WARNING, "Out of buffer space\n");
109         return -1;
110   }
111
112   /* Reset ssindex and signal to frame's specified values */
113   b = f->data;
114   for (x=0;x<f->datalen;x++)
115         tmp->outbuf[tmp->tail + x] = a2mu[b[x]];
116
117   tmp->tail += f->datalen;
118   return 0;
119 }
120
121 static struct ast_frame *
122 alawtoulaw_frameout (struct ast_translator_pvt *pvt)
123 {
124   struct ulaw_encoder_pvt *tmp = (struct ulaw_encoder_pvt *) pvt;
125
126   if (!tmp->tail)
127     return NULL;
128
129   tmp->f.frametype = AST_FRAME_VOICE;
130   tmp->f.subclass = AST_FORMAT_ULAW;
131   tmp->f.datalen = tmp->tail;
132   tmp->f.samples = tmp->tail;
133   tmp->f.mallocd = 0;
134   tmp->f.offset = AST_FRIENDLY_OFFSET;
135   tmp->f.src = __PRETTY_FUNCTION__;
136   tmp->f.data = tmp->outbuf;
137   tmp->tail = 0;
138   return &tmp->f;
139 }
140
141 static int
142 ulawtoalaw_framein (struct ast_translator_pvt *pvt, struct ast_frame *f)
143 {
144   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
145   int x;
146   unsigned char *s;
147   if (tmp->tail + f->datalen >= sizeof(tmp->outbuf))
148     {
149       ast_log (LOG_WARNING, "Out of buffer space\n");
150       return -1;
151     }
152   s = f->data;
153   for (x=0;x<f->datalen;x++) 
154         tmp->outbuf[x+tmp->tail] = mu2a[s[x]];
155   tmp->tail += f->datalen;
156   return 0;
157 }
158
159 /*
160  * LinToalaw_FrameOut
161  *  Convert a buffer of raw 16-bit signed linear PCM to a buffer
162  *  of 4-bit alaw packed two to a byte (Big Endian).
163  *
164  * Results:
165  *  Foo
166  *
167  * Side effects:
168  *  Leftover inbuf data gets packed, tail gets updated.
169  */
170
171 static struct ast_frame *
172 ulawtoalaw_frameout (struct ast_translator_pvt *pvt)
173 {
174   struct alaw_encoder_pvt *tmp = (struct alaw_encoder_pvt *) pvt;
175   
176   if (tmp->tail) {
177           tmp->f.frametype = AST_FRAME_VOICE;
178           tmp->f.subclass = AST_FORMAT_ALAW;
179           tmp->f.samples = tmp->tail;
180           tmp->f.mallocd = 0;
181           tmp->f.offset = AST_FRIENDLY_OFFSET;
182           tmp->f.src = __PRETTY_FUNCTION__;
183           tmp->f.data = tmp->outbuf;
184           tmp->f.datalen = tmp->tail;
185           tmp->tail = 0;
186           return &tmp->f;
187    } else return NULL;
188 }
189
190
191 /*
192  * alawToLin_Sample
193  */
194
195 static struct ast_frame *
196 alawtoulaw_sample (void)
197 {
198   static struct ast_frame f;
199   f.frametype = AST_FRAME_VOICE;
200   f.subclass = AST_FORMAT_ALAW;
201   f.datalen = sizeof (ulaw_slin_ex);
202   f.samples = sizeof(ulaw_slin_ex);
203   f.mallocd = 0;
204   f.offset = 0;
205   f.src = __PRETTY_FUNCTION__;
206   f.data = ulaw_slin_ex;
207   return &f;
208 }
209
210 static struct ast_frame *
211 ulawtoalaw_sample (void)
212 {
213   static struct ast_frame f;
214   f.frametype = AST_FRAME_VOICE;
215   f.subclass = AST_FORMAT_ULAW;
216   f.datalen = sizeof (ulaw_slin_ex);
217   f.samples = sizeof(ulaw_slin_ex);
218   f.mallocd = 0;
219   f.offset = 0;
220   f.src = __PRETTY_FUNCTION__;
221   f.data = ulaw_slin_ex;
222   return &f;
223 }
224
225
226 /*
227  * alaw_Destroy
228  *  Destroys a private workspace.
229  *
230  * Results:
231  *  It's gone!
232  *
233  * Side effects:
234  *  None.
235  */
236
237 static void
238 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
278 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
292 load_module (void)
293 {
294   int res;
295   int x;
296   for (x=0;x<256;x++) {
297         mu2a[x] = AST_LIN2A(AST_MULAW(x));
298         a2mu[x] = AST_LIN2MU(AST_ALAW(x));
299   }
300   res = ast_register_translator (&alawtoulaw);
301   if (!res)
302     res = ast_register_translator (&ulawtoalaw);
303   else
304     ast_unregister_translator (&alawtoulaw);
305   return res;
306 }
307
308 /*
309  * Return a description of this module.
310  */
311
312 char *
313 description (void)
314 {
315   return tdesc;
316 }
317
318 int
319 usecount (void)
320 {
321   int res;
322   STANDARD_USECOUNT (res);
323   return res;
324 }
325
326 char *
327 key ()
328 {
329   return ASTERISK_GPL_KEY;
330 }