Let's also include aclocal.m4
[asterisk-bristuff.git] / codecs / codec_adpcm.c
blob7469f056c595f47726bbe91108693bb7c6d20036
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Based on frompcm.c and topcm.c from the Emiliano MIPL browser/
5 * interpreter. See http://www.bsdtelephony.com.mx
7 * Copyright (c) 2001 - 2005 Digium, Inc.
8 * All rights reserved.
10 * Karl Sackett <krs@linux-support.net>, 2001-03-21
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.
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.
23 /*! \file
25 * \brief codec_adpcm.c - translate between signed linear and Dialogic ADPCM
27 * \ingroup codecs
30 #include "asterisk.h"
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include <fcntl.h>
35 #include <netinet/in.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
41 #include "asterisk/lock.h"
42 #include "asterisk/logger.h"
43 #include "asterisk/linkedlists.h"
44 #include "asterisk/module.h"
45 #include "asterisk/config.h"
46 #include "asterisk/options.h"
47 #include "asterisk/translate.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/utils.h"
51 /* define NOT_BLI to use a faster but not bit-level identical version */
52 /* #define NOT_BLI */
54 #define BUFFER_SAMPLES 8096 /* size for the translation buffers */
56 /* Sample frame data */
58 #include "slin_adpcm_ex.h"
59 #include "adpcm_slin_ex.h"
62 * Step size index shift table
65 static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
68 * Step size table, where stpsz[i]=floor[16*(11/10)^i]
71 static int stpsz[49] = {
72 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
73 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
74 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
75 1060, 1166, 1282, 1411, 1552
79 * Decoder/Encoder state
80 * States for both encoder and decoder are synchronized
82 struct adpcm_state {
83 int ssindex;
84 int signal;
85 int zero_count;
86 int next_flag;
90 * Decode(encoded)
91 * Decodes the encoded nibble from the adpcm file.
93 * Results:
94 * Returns the encoded difference.
96 * Side effects:
97 * Sets the index to the step size table for the next encode.
100 static inline short decode(int encoded, struct adpcm_state *state)
102 int diff;
103 int step;
104 int sign;
106 step = stpsz[state->ssindex];
108 sign = encoded & 0x08;
109 encoded &= 0x07;
110 #ifdef NOT_BLI
111 diff = (((encoded << 1) + 1) * step) >> 3;
112 #else /* BLI code */
113 diff = step >> 3;
114 if (encoded & 4)
115 diff += step;
116 if (encoded & 2)
117 diff += step >> 1;
118 if (encoded & 1)
119 diff += step >> 2;
120 if ((encoded >> 1) & step & 0x1)
121 diff++;
122 #endif
123 if (sign)
124 diff = -diff;
126 if (state->next_flag & 0x1)
127 state->signal -= 8;
128 else if (state->next_flag & 0x2)
129 state->signal += 8;
131 state->signal += diff;
133 if (state->signal > 2047)
134 state->signal = 2047;
135 else if (state->signal < -2047)
136 state->signal = -2047;
138 state->next_flag = 0;
140 #ifdef AUTO_RETURN
141 if (encoded)
142 state->zero_count = 0;
143 else if (++(state->zero_count) == 24) {
144 state->zero_count = 0;
145 if (state->signal > 0)
146 state->next_flag = 0x1;
147 else if (state->signal < 0)
148 state->next_flag = 0x2;
150 #endif
152 state->ssindex += indsft[encoded];
153 if (state->ssindex < 0)
154 state->ssindex = 0;
155 else if (state->ssindex > 48)
156 state->ssindex = 48;
158 return state->signal << 4;
162 * Adpcm
163 * Takes a signed linear signal and encodes it as ADPCM
164 * For more information see http://support.dialogic.com/appnotes/adpcm.pdf
166 * Results:
167 * Foo.
169 * Side effects:
170 * signal gets updated with each pass.
173 static inline int adpcm(short csig, struct adpcm_state *state)
175 int diff;
176 int step;
177 int encoded;
180 * Clip csig if too large or too small
182 csig >>= 4;
184 step = stpsz[state->ssindex];
185 diff = csig - state->signal;
187 #ifdef NOT_BLI
188 if (diff < 0) {
189 encoded = (-diff << 2) / step;
190 if (encoded > 7)
191 encoded = 7;
192 encoded |= 0x08;
193 } else {
194 encoded = (diff << 2) / step;
195 if (encoded > 7)
196 encoded = 7;
198 #else /* BLI code */
199 if (diff < 0) {
200 encoded = 8;
201 diff = -diff;
202 } else
203 encoded = 0;
204 if (diff >= step) {
205 encoded |= 4;
206 diff -= step;
208 step >>= 1;
209 if (diff >= step) {
210 encoded |= 2;
211 diff -= step;
213 step >>= 1;
214 if (diff >= step)
215 encoded |= 1;
216 #endif /* NOT_BLI */
218 /* feedback to state */
219 decode(encoded, state);
221 return encoded;
224 /*----------------- Asterisk-codec glue ------------*/
226 /*! \brief Workspace for translating signed linear signals to ADPCM. */
227 struct adpcm_encoder_pvt {
228 struct adpcm_state state;
229 int16_t inbuf[BUFFER_SAMPLES]; /* Unencoded signed linear values */
232 /*! \brief Workspace for translating ADPCM signals to signed linear. */
233 struct adpcm_decoder_pvt {
234 struct adpcm_state state;
237 /*! \brief decode 4-bit adpcm frame data and store in output buffer */
238 static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
240 struct adpcm_decoder_pvt *tmp = pvt->pvt;
241 int x = f->datalen;
242 unsigned char *src = f->data;
243 int16_t *dst = (int16_t *)pvt->outbuf + pvt->samples;
245 while (x--) {
246 *dst++ = decode((*src >> 4) & 0xf, &tmp->state);
247 *dst++ = decode(*src++ & 0x0f, &tmp->state);
249 pvt->samples += f->samples;
250 pvt->datalen += 2*f->samples;
251 return 0;
254 /*! \brief fill input buffer with 16-bit signed linear PCM values. */
255 static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
257 struct adpcm_encoder_pvt *tmp = pvt->pvt;
259 memcpy(&tmp->inbuf[pvt->samples], f->data, f->datalen);
260 pvt->samples += f->samples;
261 return 0;
264 /*! \brief convert inbuf and store into frame */
265 static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
267 struct adpcm_encoder_pvt *tmp = pvt->pvt;
268 struct ast_frame *f;
269 int i;
270 int samples = pvt->samples; /* save original number */
272 if (samples < 2)
273 return NULL;
275 pvt->samples &= ~1; /* atomic size is 2 samples */
277 for (i = 0; i < pvt->samples; i += 2) {
278 pvt->outbuf[i/2] =
279 (adpcm(tmp->inbuf[i ], &tmp->state) << 4) |
280 (adpcm(tmp->inbuf[i+1], &tmp->state) );
283 f = ast_trans_frameout(pvt, pvt->samples/2, 0);
286 * If there is a left over sample, move it to the beginning
287 * of the input buffer.
290 if (samples & 1) { /* move the leftover sample at beginning */
291 tmp->inbuf[0] = tmp->inbuf[samples - 1];
292 pvt->samples = 1;
294 return f;
298 /*! \brief AdpcmToLin_Sample */
299 static struct ast_frame *adpcmtolin_sample(void)
301 static struct ast_frame f;
302 f.frametype = AST_FRAME_VOICE;
303 f.subclass = AST_FORMAT_ADPCM;
304 f.datalen = sizeof(adpcm_slin_ex);
305 f.samples = sizeof(adpcm_slin_ex) * 2;
306 f.mallocd = 0;
307 f.offset = 0;
308 f.src = __PRETTY_FUNCTION__;
309 f.data = adpcm_slin_ex;
310 return &f;
313 /*! \brief LinToAdpcm_Sample */
314 static struct ast_frame *lintoadpcm_sample(void)
316 static struct ast_frame f;
317 f.frametype = AST_FRAME_VOICE;
318 f.subclass = AST_FORMAT_SLINEAR;
319 f.datalen = sizeof(slin_adpcm_ex);
320 /* Assume 8000 Hz */
321 f.samples = sizeof(slin_adpcm_ex) / 2;
322 f.mallocd = 0;
323 f.offset = 0;
324 f.src = __PRETTY_FUNCTION__;
325 f.data = slin_adpcm_ex;
326 return &f;
329 static struct ast_translator adpcmtolin = {
330 .name = "adpcmtolin",
331 .srcfmt = AST_FORMAT_ADPCM,
332 .dstfmt = AST_FORMAT_SLINEAR,
333 .framein = adpcmtolin_framein,
334 .sample = adpcmtolin_sample,
335 .desc_size = sizeof(struct adpcm_decoder_pvt),
336 .buffer_samples = BUFFER_SAMPLES,
337 .buf_size = BUFFER_SAMPLES * 2,
338 .plc_samples = 160,
341 static struct ast_translator lintoadpcm = {
342 .name = "lintoadpcm",
343 .srcfmt = AST_FORMAT_SLINEAR,
344 .dstfmt = AST_FORMAT_ADPCM,
345 .framein = lintoadpcm_framein,
346 .frameout = lintoadpcm_frameout,
347 .sample = lintoadpcm_sample,
348 .desc_size = sizeof (struct adpcm_encoder_pvt),
349 .buffer_samples = BUFFER_SAMPLES,
350 .buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */
353 static void parse_config(void)
355 struct ast_config *cfg = ast_config_load("codecs.conf");
356 struct ast_variable *var;
357 if (cfg == NULL)
358 return;
359 for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) {
360 if (!strcasecmp(var->name, "genericplc")) {
361 adpcmtolin.useplc = ast_true(var->value) ? 1 : 0;
362 if (option_verbose > 2)
363 ast_verbose(VERBOSE_PREFIX_3 "codec_adpcm: %susing generic PLC\n", adpcmtolin.useplc ? "" : "not ");
366 ast_config_destroy(cfg);
369 /*! \brief standard module glue */
370 static int reload(void)
372 parse_config();
373 return 0;
376 static int unload_module(void)
378 int res;
380 res = ast_unregister_translator(&lintoadpcm);
381 res |= ast_unregister_translator(&adpcmtolin);
383 return res;
386 static int load_module(void)
388 int res;
390 parse_config();
391 res = ast_register_translator(&adpcmtolin);
392 if (!res)
393 res = ast_register_translator(&lintoadpcm);
394 else
395 ast_unregister_translator(&adpcmtolin);
397 return res;
400 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
401 .load = load_module,
402 .unload = unload_module,
403 .reload = reload,