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$")
35 #include <netinet/in.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 */
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
91 * Decodes the encoded nibble from the adpcm file.
94 * Returns the encoded difference.
97 * Sets the index to the step size table for the next encode.
100 static inline short decode(int encoded
, struct adpcm_state
*state
)
106 step
= stpsz
[state
->ssindex
];
108 sign
= encoded
& 0x08;
111 diff
= (((encoded
<< 1) + 1) * step
) >> 3;
120 if ((encoded
>> 1) & step
& 0x1)
126 if (state
->next_flag
& 0x1)
128 else if (state
->next_flag
& 0x2)
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;
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;
152 state
->ssindex
+= indsft
[encoded
];
153 if (state
->ssindex
< 0)
155 else if (state
->ssindex
> 48)
158 return state
->signal
<< 4;
163 * Takes a signed linear signal and encodes it as ADPCM
164 * For more information see http://support.dialogic.com/appnotes/adpcm.pdf
170 * signal gets updated with each pass.
173 static inline int adpcm(short csig
, struct adpcm_state
*state
)
180 * Clip csig if too large or too small
184 step
= stpsz
[state
->ssindex
];
185 diff
= csig
- state
->signal
;
189 encoded
= (-diff
<< 2) / step
;
194 encoded
= (diff
<< 2) / step
;
218 /* feedback to state */
219 decode(encoded
, state
);
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
;
242 unsigned char *src
= f
->data
;
243 int16_t *dst
= (int16_t *)pvt
->outbuf
+ pvt
->samples
;
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
;
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
;
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
;
270 int samples
= pvt
->samples
; /* save original number */
275 pvt
->samples
&= ~1; /* atomic size is 2 samples */
277 for (i
= 0; i
< pvt
->samples
; 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];
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;
308 f
.src
= __PRETTY_FUNCTION__
;
309 f
.data
= adpcm_slin_ex
;
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
);
321 f
.samples
= sizeof(slin_adpcm_ex
) / 2;
324 f
.src
= __PRETTY_FUNCTION__
;
325 f
.data
= slin_adpcm_ex
;
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,
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
;
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)
376 static int unload_module(void)
380 res
= ast_unregister_translator(&lintoadpcm
);
381 res
|= ast_unregister_translator(&adpcmtolin
);
386 static int load_module(void)
391 res
= ast_register_translator(&adpcmtolin
);
393 res
= ast_register_translator(&lintoadpcm
);
395 ast_unregister_translator(&adpcmtolin
);
400 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Adaptive Differential PCM Coder/Decoder",
402 .unload
= unload_module
,