Convert casts to unions, to fix alignment issues on Solaris
[asterisk/asterisk.git] / codecs / codec_adpcm.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Based on frompcm.c and topcm.c from the Emiliano MIPL browser/
5  * interpreter.  See http://www.bsdtelephony.com.mx
6  *
7  * Copyright (c) 2001 - 2005 Digium, Inc.
8  * All rights reserved.
9  *
10  * Karl Sackett <krs@linux-support.net>, 2001-03-21
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22
23 /*! \file
24  *
25  * \brief codec_adpcm.c - translate between signed linear and Dialogic ADPCM
26  * 
27  * \ingroup codecs
28  */
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/lock.h"
35 #include "asterisk/linkedlists.h"
36 #include "asterisk/module.h"
37 #include "asterisk/config.h"
38 #include "asterisk/translate.h"
39 #include "asterisk/utils.h"
40
41 /* define NOT_BLI to use a faster but not bit-level identical version */
42 /* #define NOT_BLI */
43
44 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
45
46 /* Sample frame data */
47
48 #include "slin_adpcm_ex.h"
49 #include "adpcm_slin_ex.h"
50
51 /*
52  * Step size index shift table 
53  */
54
55 static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
56
57 /*
58  * Step size table, where stpsz[i]=floor[16*(11/10)^i]
59  */
60
61 static int stpsz[49] = {
62   16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
63   80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
64   307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
65   1060, 1166, 1282, 1411, 1552
66 };
67
68 /*
69  * Decoder/Encoder state
70  *   States for both encoder and decoder are synchronized
71  */
72 struct adpcm_state {
73         int ssindex;
74         int signal;
75         int zero_count;
76         int next_flag;
77 };
78
79 /*
80  * Decode(encoded)
81  *  Decodes the encoded nibble from the adpcm file.
82  *
83  * Results:
84  *  Returns the encoded difference.
85  *
86  * Side effects:
87  *  Sets the index to the step size table for the next encode.
88  */
89
90 static inline short decode(int encoded, struct adpcm_state *state)
91 {
92         int diff;
93         int step;
94         int sign;
95
96         step = stpsz[state->ssindex];
97
98         sign = encoded & 0x08;
99         encoded &= 0x07;
100 #ifdef NOT_BLI
101         diff = (((encoded << 1) + 1) * step) >> 3;
102 #else /* BLI code */
103         diff = step >> 3;
104         if (encoded & 4)
105                 diff += step;
106         if (encoded & 2)
107                 diff += step >> 1;
108         if (encoded & 1)
109                 diff += step >> 2;
110         if ((encoded >> 1) & step & 0x1)
111                 diff++;
112 #endif
113         if (sign)
114                 diff = -diff;
115
116         if (state->next_flag & 0x1)
117                 state->signal -= 8;
118         else if (state->next_flag & 0x2)
119                 state->signal += 8;
120
121         state->signal += diff;
122
123         if (state->signal > 2047)
124                 state->signal = 2047;
125         else if (state->signal < -2047)
126                 state->signal = -2047;
127
128         state->next_flag = 0;
129
130 #ifdef AUTO_RETURN
131         if (encoded)
132                 state->zero_count = 0;
133         else if (++(state->zero_count) == 24) {
134                 state->zero_count = 0;
135                 if (state->signal > 0)
136                         state->next_flag = 0x1;
137                 else if (state->signal < 0)
138                         state->next_flag = 0x2;
139         }
140 #endif
141
142         state->ssindex += indsft[encoded];
143         if (state->ssindex < 0)
144                 state->ssindex = 0;
145         else if (state->ssindex > 48)
146                 state->ssindex = 48;
147
148         return state->signal << 4;
149 }
150
151 /*
152  * Adpcm
153  *  Takes a signed linear signal and encodes it as ADPCM
154  *  For more information see http://support.dialogic.com/appnotes/adpcm.pdf
155  *
156  * Results:
157  *  Foo.
158  *
159  * Side effects:
160  *  signal gets updated with each pass.
161  */
162
163 static inline int adpcm(short csig, struct adpcm_state *state)
164 {
165         int diff;
166         int step;
167         int encoded;
168
169         /* 
170          * Clip csig if too large or too small
171          */
172         csig >>= 4;
173
174         step = stpsz[state->ssindex];
175         diff = csig - state->signal;
176
177 #ifdef NOT_BLI
178         if (diff < 0) {
179                 encoded = (-diff << 2) / step;
180                 if (encoded > 7)
181                         encoded = 7;
182                 encoded |= 0x08;
183         } else {
184                 encoded = (diff << 2) / step;
185                 if (encoded > 7)
186                         encoded = 7;
187         }
188 #else /* BLI code */
189         if (diff < 0) {
190                 encoded = 8;
191                 diff = -diff;
192         } else
193                 encoded = 0;
194         if (diff >= step) {
195                 encoded |= 4;
196                 diff -= step;
197         }
198         step >>= 1;
199         if (diff >= step) {
200                 encoded |= 2;
201                 diff -= step;
202         }
203         step >>= 1;
204         if (diff >= step)
205                 encoded |= 1;
206 #endif /* NOT_BLI */
207
208         /* feedback to state */
209         decode(encoded, state);
210         
211         return encoded;
212 }
213
214 /*----------------- Asterisk-codec glue ------------*/
215
216 /*! \brief Workspace for translating signed linear signals to ADPCM. */
217 struct adpcm_encoder_pvt {
218         struct adpcm_state state;
219         int16_t inbuf[BUFFER_SAMPLES];  /* Unencoded signed linear values */
220 };
221
222 /*! \brief Workspace for translating ADPCM signals to signed linear. */
223 struct adpcm_decoder_pvt {
224         struct adpcm_state state;
225 };
226
227 /*! \brief decode 4-bit adpcm frame data and store in output buffer */
228 static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
229 {
230         struct adpcm_decoder_pvt *tmp = pvt->pvt;
231         int x = f->datalen;
232         unsigned char *src = f->data.ptr;
233         int16_t *dst = pvt->outbuf.i16 + pvt->samples;
234
235         while (x--) {
236                 *dst++ = decode((*src >> 4) & 0xf, &tmp->state);
237                 *dst++ = decode(*src++ & 0x0f, &tmp->state);
238         }
239         pvt->samples += f->samples;
240         pvt->datalen += 2*f->samples;
241         return 0;
242 }
243
244 /*! \brief fill input buffer with 16-bit signed linear PCM values. */
245 static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
246 {
247         struct adpcm_encoder_pvt *tmp = pvt->pvt;
248
249         memcpy(&tmp->inbuf[pvt->samples], f->data.ptr, f->datalen);
250         pvt->samples += f->samples;
251         return 0;
252 }
253
254 /*! \brief convert inbuf and store into frame */
255 static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
256 {
257         struct adpcm_encoder_pvt *tmp = pvt->pvt;
258         struct ast_frame *f;
259         int i;
260         int samples = pvt->samples;     /* save original number */
261   
262         if (samples < 2)
263                 return NULL;
264
265         pvt->samples &= ~1; /* atomic size is 2 samples */
266
267         for (i = 0; i < pvt->samples; i += 2) {
268                 pvt->outbuf.c[i/2] =
269                         (adpcm(tmp->inbuf[i  ], &tmp->state) << 4) |
270                         (adpcm(tmp->inbuf[i+1], &tmp->state)     );
271         };
272
273         f = ast_trans_frameout(pvt, pvt->samples/2, 0);
274
275         /*
276          * If there is a left over sample, move it to the beginning
277          * of the input buffer.
278          */
279
280         if (samples & 1) {      /* move the leftover sample at beginning */
281                 tmp->inbuf[0] = tmp->inbuf[samples - 1];
282                 pvt->samples = 1;
283         }
284         return f;
285 }
286
287
288 /*! \brief AdpcmToLin_Sample */
289 static struct ast_frame *adpcmtolin_sample(void)
290 {
291         static struct ast_frame f;
292         f.frametype = AST_FRAME_VOICE;
293         f.subclass = AST_FORMAT_ADPCM;
294         f.datalen = sizeof(adpcm_slin_ex);
295         f.samples = sizeof(adpcm_slin_ex) * 2;
296         f.mallocd = 0;
297         f.offset = 0;
298         f.src = __PRETTY_FUNCTION__;
299         f.data.ptr = adpcm_slin_ex;
300         return &f;
301 }
302
303 /*! \brief LinToAdpcm_Sample */
304 static struct ast_frame *lintoadpcm_sample(void)
305 {
306         static struct ast_frame f;
307         f.frametype = AST_FRAME_VOICE;
308         f.subclass = AST_FORMAT_SLINEAR;
309         f.datalen = sizeof(slin_adpcm_ex);
310         /* Assume 8000 Hz */
311         f.samples = sizeof(slin_adpcm_ex) / 2;
312         f.mallocd = 0;
313         f.offset = 0;
314         f.src = __PRETTY_FUNCTION__;
315         f.data.ptr = slin_adpcm_ex;
316         return &f;
317 }
318
319 static struct ast_translator adpcmtolin = {
320         .name = "adpcmtolin",
321         .srcfmt = AST_FORMAT_ADPCM,
322         .dstfmt = AST_FORMAT_SLINEAR,
323         .framein = adpcmtolin_framein,
324         .sample = adpcmtolin_sample,
325         .desc_size = sizeof(struct adpcm_decoder_pvt),
326         .buffer_samples = BUFFER_SAMPLES,
327         .buf_size = BUFFER_SAMPLES * 2,
328         .plc_samples = 160,
329 };
330
331 static struct ast_translator lintoadpcm = {
332         .name = "lintoadpcm",
333         .srcfmt = AST_FORMAT_SLINEAR,
334         .dstfmt = AST_FORMAT_ADPCM,
335         .framein = lintoadpcm_framein,
336         .frameout = lintoadpcm_frameout,
337         .sample = lintoadpcm_sample,
338         .desc_size = sizeof (struct adpcm_encoder_pvt),
339         .buffer_samples = BUFFER_SAMPLES,
340         .buf_size = BUFFER_SAMPLES/ 2,  /* 2 samples per byte */
341 };
342
343 static int parse_config(int reload)
344 {
345         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
346         struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
347         struct ast_variable *var;
348         if (cfg == NULL)
349                 return 0;
350         if (cfg == CONFIG_STATUS_FILEUNCHANGED)
351                 return 0;
352         for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) {
353                 if (!strcasecmp(var->name, "genericplc")) {
354                         adpcmtolin.useplc = ast_true(var->value) ? 1 : 0;
355                         ast_verb(3, "codec_adpcm: %susing generic PLC\n", adpcmtolin.useplc ? "" : "not ");
356                 }
357         }
358         ast_config_destroy(cfg);
359         return 0;
360 }
361
362 /*! \brief standard module glue */
363 static int reload(void)
364 {
365         if (parse_config(1))
366                 return AST_MODULE_LOAD_DECLINE;
367         return AST_MODULE_LOAD_SUCCESS;
368 }
369
370 static int unload_module(void)
371 {
372         int res;
373
374         res = ast_unregister_translator(&lintoadpcm);
375         res |= ast_unregister_translator(&adpcmtolin);
376
377         return res;
378 }
379
380 static int load_module(void)
381 {
382         int res;
383
384         if (parse_config(0))
385                 return AST_MODULE_LOAD_DECLINE;
386         res = ast_register_translator(&adpcmtolin);
387         if (!res)
388                 res = ast_register_translator(&lintoadpcm);
389         else
390                 ast_unregister_translator(&adpcmtolin);
391         if (res)
392                 return AST_MODULE_LOAD_FAILURE;
393         return AST_MODULE_LOAD_SUCCESS;
394 }
395
396 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
397                 .load = load_module,
398                 .unload = unload_module,
399                 .reload = reload,
400                );