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