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.
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.
25 * \brief codec_adpcm.c - translate between signed linear and Dialogic ADPCM
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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"
41 /* define NOT_BLI to use a faster but not bit-level identical version */
44 #define BUFFER_SAMPLES 8096 /* size for the translation buffers */
46 /* Sample frame data */
47 #include "asterisk/slin.h"
51 * Step size index shift table
54 static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
57 * Step size table, where stpsz[i]=floor[16*(11/10)^i]
60 static int stpsz[49] = {
61 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
62 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
63 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
64 1060, 1166, 1282, 1411, 1552
68 * Decoder/Encoder state
69 * States for both encoder and decoder are synchronized
80 * Decodes the encoded nibble from the adpcm file.
83 * Returns the encoded difference.
86 * Sets the index to the step size table for the next encode.
89 static inline short decode(int encoded, struct adpcm_state *state)
95 step = stpsz[state->ssindex];
97 sign = encoded & 0x08;
100 diff = (((encoded << 1) + 1) * step) >> 3;
109 if ((encoded >> 1) & step & 0x1)
115 if (state->next_flag & 0x1)
117 else if (state->next_flag & 0x2)
120 state->signal += diff;
122 if (state->signal > 2047)
123 state->signal = 2047;
124 else if (state->signal < -2047)
125 state->signal = -2047;
127 state->next_flag = 0;
131 state->zero_count = 0;
132 else if (++(state->zero_count) == 24) {
133 state->zero_count = 0;
134 if (state->signal > 0)
135 state->next_flag = 0x1;
136 else if (state->signal < 0)
137 state->next_flag = 0x2;
141 state->ssindex += indsft[encoded];
142 if (state->ssindex < 0)
144 else if (state->ssindex > 48)
147 return state->signal << 4;
152 * Takes a signed linear signal and encodes it as ADPCM
153 * For more information see http://support.dialogic.com/appnotes/adpcm.pdf
159 * signal gets updated with each pass.
162 static inline int adpcm(short csig, struct adpcm_state *state)
169 * Clip csig if too large or too small
173 step = stpsz[state->ssindex];
174 diff = csig - state->signal;
178 encoded = (-diff << 2) / step;
183 encoded = (diff << 2) / step;
207 /* feedback to state */
208 decode(encoded, state);
213 /*----------------- Asterisk-codec glue ------------*/
215 /*! \brief Workspace for translating signed linear signals to ADPCM. */
216 struct adpcm_encoder_pvt {
217 struct adpcm_state state;
218 int16_t inbuf[BUFFER_SAMPLES]; /* Unencoded signed linear values */
221 /*! \brief Workspace for translating ADPCM signals to signed linear. */
222 struct adpcm_decoder_pvt {
223 struct adpcm_state state;
226 /*! \brief decode 4-bit adpcm frame data and store in output buffer */
227 static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
229 struct adpcm_decoder_pvt *tmp = pvt->pvt;
231 unsigned char *src = f->data.ptr;
232 int16_t *dst = pvt->outbuf.i16 + pvt->samples;
235 *dst++ = decode((*src >> 4) & 0xf, &tmp->state);
236 *dst++ = decode(*src++ & 0x0f, &tmp->state);
238 pvt->samples += f->samples;
239 pvt->datalen += 2*f->samples;
243 /*! \brief fill input buffer with 16-bit signed linear PCM values. */
244 static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
246 struct adpcm_encoder_pvt *tmp = pvt->pvt;
248 memcpy(&tmp->inbuf[pvt->samples], f->data.ptr, f->datalen);
249 pvt->samples += f->samples;
253 /*! \brief convert inbuf and store into frame */
254 static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
256 struct adpcm_encoder_pvt *tmp = pvt->pvt;
259 int samples = pvt->samples; /* save original number */
264 pvt->samples &= ~1; /* atomic size is 2 samples */
266 for (i = 0; i < pvt->samples; i += 2) {
268 (adpcm(tmp->inbuf[i ], &tmp->state) << 4) |
269 (adpcm(tmp->inbuf[i+1], &tmp->state) );
272 f = ast_trans_frameout(pvt, pvt->samples/2, 0);
275 * If there is a left over sample, move it to the beginning
276 * of the input buffer.
279 if (samples & 1) { /* move the leftover sample at beginning */
280 tmp->inbuf[0] = tmp->inbuf[samples - 1];
287 static struct ast_translator adpcmtolin = {
288 .name = "adpcmtolin",
289 .srcfmt = AST_FORMAT_ADPCM,
290 .dstfmt = AST_FORMAT_SLINEAR,
291 .framein = adpcmtolin_framein,
292 .sample = adpcm_sample,
293 .desc_size = sizeof(struct adpcm_decoder_pvt),
294 .buffer_samples = BUFFER_SAMPLES,
295 .buf_size = BUFFER_SAMPLES * 2,
299 static struct ast_translator lintoadpcm = {
300 .name = "lintoadpcm",
301 .srcfmt = AST_FORMAT_SLINEAR,
302 .dstfmt = AST_FORMAT_ADPCM,
303 .framein = lintoadpcm_framein,
304 .frameout = lintoadpcm_frameout,
305 .sample = slin8_sample,
306 .desc_size = sizeof (struct adpcm_encoder_pvt),
307 .buffer_samples = BUFFER_SAMPLES,
308 .buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */
311 static int parse_config(int reload)
313 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
314 struct ast_config *cfg = ast_config_load("codecs.conf", config_flags);
315 struct ast_variable *var;
316 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
318 for (var = ast_variable_browse(cfg, "plc"); var ; var = var->next) {
319 if (!strcasecmp(var->name, "genericplc")) {
320 adpcmtolin.useplc = ast_true(var->value) ? 1 : 0;
321 ast_verb(3, "codec_adpcm: %susing generic PLC\n", adpcmtolin.useplc ? "" : "not ");
324 ast_config_destroy(cfg);
328 /*! \brief standard module glue */
329 static int reload(void)
332 return AST_MODULE_LOAD_DECLINE;
333 return AST_MODULE_LOAD_SUCCESS;
336 static int unload_module(void)
340 res = ast_unregister_translator(&lintoadpcm);
341 res |= ast_unregister_translator(&adpcmtolin);
346 static int load_module(void)
351 return AST_MODULE_LOAD_DECLINE;
352 res = ast_register_translator(&adpcmtolin);
354 res = ast_register_translator(&lintoadpcm);
356 ast_unregister_translator(&adpcmtolin);
358 return AST_MODULE_LOAD_FAILURE;
359 return AST_MODULE_LOAD_SUCCESS;
362 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
364 .unload = unload_module,