Asterisk - The Open Source Telephony Project GIT-master-a358458
codec_adpcm.c
Go to the documentation of this file.
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/*** MODULEINFO
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35
36#include "asterisk/lock.h"
38#include "asterisk/module.h"
39#include "asterisk/config.h"
40#include "asterisk/translate.h"
41#include "asterisk/utils.h"
42
43/* define NOT_BLI to use a faster but not bit-level identical version */
44/* #define NOT_BLI */
45
46#define BUFFER_SAMPLES 8096 /* size for the translation buffers */
47
48/* Sample frame data */
49#include "asterisk/slin.h"
50#include "ex_adpcm.h"
51
52/*
53 * Step size index shift table
54 */
55
56static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
57
58/*
59 * Step size table, where stpsz[i]=floor[16*(11/10)^i]
60 */
61
62static int stpsz[49] = {
63 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73,
64 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279,
65 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
66 1060, 1166, 1282, 1411, 1552
67};
68
69/*
70 * Decoder/Encoder state
71 * States for both encoder and decoder are synchronized
72 */
75 int signal;
78};
79
80/*
81 * Decode(encoded)
82 * Decodes the encoded nibble from the adpcm file.
83 *
84 * Results:
85 * Returns the encoded difference.
86 *
87 * Side effects:
88 * Sets the index to the step size table for the next encode.
89 */
90
91static inline short decode(int encoded, struct adpcm_state *state)
92{
93 int diff;
94 int step;
95 int sign;
96
97 step = stpsz[state->ssindex];
98
99 sign = encoded & 0x08;
100 encoded &= 0x07;
101#ifdef NOT_BLI
102 diff = (((encoded << 1) + 1) * step) >> 3;
103#else /* BLI code */
104 diff = step >> 3;
105 if (encoded & 4)
106 diff += step;
107 if (encoded & 2)
108 diff += step >> 1;
109 if (encoded & 1)
110 diff += step >> 2;
111 if ((encoded >> 1) & step & 0x1)
112 diff++;
113#endif
114 if (sign)
115 diff = -diff;
116
117 if (state->next_flag & 0x1)
118 state->signal -= 8;
119 else if (state->next_flag & 0x2)
120 state->signal += 8;
121
122 state->signal += diff;
123
124 if (state->signal > 2047)
125 state->signal = 2047;
126 else if (state->signal < -2047)
127 state->signal = -2047;
128
129 state->next_flag = 0;
130
131#ifdef AUTO_RETURN
132 if (encoded)
133 state->zero_count = 0;
134 else if (++(state->zero_count) == 24) {
135 state->zero_count = 0;
136 if (state->signal > 0)
137 state->next_flag = 0x1;
138 else if (state->signal < 0)
139 state->next_flag = 0x2;
140 }
141#endif
142
143 state->ssindex += indsft[encoded];
144 if (state->ssindex < 0)
145 state->ssindex = 0;
146 else if (state->ssindex > 48)
147 state->ssindex = 48;
148
149 return state->signal << 4;
150}
151
152/*
153 * Adpcm
154 * Takes a signed linear signal and encodes it as ADPCM
155 * For more information see http://en.wikipedia.org/wiki/Dialogic_ADPCM
156 *
157 * Results:
158 * Foo.
159 *
160 * Side effects:
161 * signal gets updated with each pass.
162 */
163
164static inline int adpcm(short csig, struct adpcm_state *state)
165{
166 int diff;
167 int step;
168 int encoded;
169
170 /*
171 * Clip csig if too large or too small
172 */
173 csig >>= 4;
174
175 step = stpsz[state->ssindex];
176 diff = csig - state->signal;
177
178#ifdef NOT_BLI
179 if (diff < 0) {
180 encoded = (-diff << 2) / step;
181 if (encoded > 7)
182 encoded = 7;
183 encoded |= 0x08;
184 } else {
185 encoded = (diff << 2) / step;
186 if (encoded > 7)
187 encoded = 7;
188 }
189#else /* BLI code */
190 if (diff < 0) {
191 encoded = 8;
192 diff = -diff;
193 } else
194 encoded = 0;
195 if (diff >= step) {
196 encoded |= 4;
197 diff -= step;
198 }
199 step >>= 1;
200 if (diff >= step) {
201 encoded |= 2;
202 diff -= step;
203 }
204 step >>= 1;
205 if (diff >= step)
206 encoded |= 1;
207#endif /* NOT_BLI */
208
209 /* feedback to state */
210 decode(encoded, state);
211
212 return encoded;
213}
214
215/*----------------- Asterisk-codec glue ------------*/
216
217/*! \brief Workspace for translating signed linear signals to ADPCM. */
220 int16_t inbuf[BUFFER_SAMPLES]; /* Unencoded signed linear values */
221};
222
223/*! \brief Workspace for translating ADPCM signals to signed linear. */
226};
227
228/*! \brief decode 4-bit adpcm frame data and store in output buffer */
229static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
230{
231 struct adpcm_decoder_pvt *tmp = pvt->pvt;
232 int x = f->datalen;
233 unsigned char *src = f->data.ptr;
234 int16_t *dst = pvt->outbuf.i16 + pvt->samples;
235
236 while (x--) {
237 *dst++ = decode((*src >> 4) & 0xf, &tmp->state);
238 *dst++ = decode(*src++ & 0x0f, &tmp->state);
239 }
240 pvt->samples += f->samples;
241 pvt->datalen += 2*f->samples;
242 return 0;
243}
244
245/*! \brief fill input buffer with 16-bit signed linear PCM values. */
246static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
247{
248 struct adpcm_encoder_pvt *tmp = pvt->pvt;
249
250 memcpy(&tmp->inbuf[pvt->samples], f->data.ptr, f->datalen);
251 pvt->samples += f->samples;
252 return 0;
253}
254
255/*! \brief convert inbuf and store into frame */
256static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
257{
258 struct adpcm_encoder_pvt *tmp = pvt->pvt;
259 struct ast_frame *f;
260 int i;
261 int samples = pvt->samples; /* save original number */
262
263 if (samples < 2)
264 return NULL;
265
266 pvt->samples &= ~1; /* atomic size is 2 samples */
267
268 for (i = 0; i < pvt->samples; i += 2) {
269 pvt->outbuf.c[i/2] =
270 (adpcm(tmp->inbuf[i ], &tmp->state) << 4) |
271 (adpcm(tmp->inbuf[i+1], &tmp->state) );
272 };
273
274 f = ast_trans_frameout(pvt, pvt->samples/2, 0);
275
276 /*
277 * If there is a left over sample, move it to the beginning
278 * of the input buffer.
279 */
280
281 if (samples & 1) { /* move the leftover sample at beginning */
282 tmp->inbuf[0] = tmp->inbuf[samples - 1];
283 pvt->samples = 1;
284 }
285 return f;
286}
287
288
289static struct ast_translator adpcmtolin = {
290 .name = "adpcmtolin",
291 .src_codec = {
292 .name = "adpcm",
293 .type = AST_MEDIA_TYPE_AUDIO,
294 .sample_rate = 8000,
295 },
296 .dst_codec = {
297 .name = "slin",
298 .type = AST_MEDIA_TYPE_AUDIO,
299 .sample_rate = 8000,
300 },
301 .format = "slin",
302 .framein = adpcmtolin_framein,
303 .sample = adpcm_sample,
304 .desc_size = sizeof(struct adpcm_decoder_pvt),
305 .buffer_samples = BUFFER_SAMPLES,
306 .buf_size = BUFFER_SAMPLES * 2,
307};
308
309static struct ast_translator lintoadpcm = {
310 .name = "lintoadpcm",
311 .src_codec = {
312 .name = "slin",
313 .type = AST_MEDIA_TYPE_AUDIO,
314 .sample_rate = 8000,
315 },
316 .dst_codec = {
317 .name = "adpcm",
318 .type = AST_MEDIA_TYPE_AUDIO,
319 .sample_rate = 8000,
320 },
321 .format = "adpcm",
322 .framein = lintoadpcm_framein,
323 .frameout = lintoadpcm_frameout,
324 .sample = slin8_sample,
325 .desc_size = sizeof (struct adpcm_encoder_pvt),
326 .buffer_samples = BUFFER_SAMPLES,
327 .buf_size = BUFFER_SAMPLES/ 2, /* 2 samples per byte */
328};
329
330static int unload_module(void)
331{
332 int res;
333
336
337 return res;
338}
339
340static int load_module(void)
341{
342 int res = 0;
343
346
347 if (res) {
350 }
351
353}
354
355AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
356 .support_level = AST_MODULE_SUPPORT_CORE,
357 .load = load_module,
358 .unload = unload_module,
Asterisk main include file. File version handling, generic pbx functions.
static int tmp()
Definition: bt_open.c:389
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
#define BUFFER_SAMPLES
Definition: codec_adpcm.c:46
static struct ast_translator adpcmtolin
Definition: codec_adpcm.c:289
static struct ast_translator lintoadpcm
Definition: codec_adpcm.c:309
static int indsft[8]
Definition: codec_adpcm.c:56
static int lintoadpcm_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
fill input buffer with 16-bit signed linear PCM values.
Definition: codec_adpcm.c:246
static int stpsz[49]
Definition: codec_adpcm.c:62
static int load_module(void)
Definition: codec_adpcm.c:340
static int unload_module(void)
Definition: codec_adpcm.c:330
static int adpcm(short csig, struct adpcm_state *state)
Definition: codec_adpcm.c:164
static struct ast_frame * lintoadpcm_frameout(struct ast_trans_pvt *pvt)
convert inbuf and store into frame
Definition: codec_adpcm.c:256
static int adpcmtolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
decode 4-bit adpcm frame data and store in output buffer
Definition: codec_adpcm.c:229
static short decode(int encoded, struct adpcm_state *state)
Definition: codec_adpcm.c:91
short int16_t
Definition: db.h:59
4-bit ADPCM data
static struct ast_frame * adpcm_sample(void)
Definition: ex_adpcm.h:18
Configuration File Parser.
A set of macros to manage forward-linked lists.
Asterisk locking-related definitions:
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:315
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define NULL
Definition: resample.c:96
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
Workspace for translating ADPCM signals to signed linear.
Definition: codec_adpcm.c:224
Workspace for translating signed linear signals to ADPCM.
Definition: codec_adpcm.c:218
int16_t inbuf[BUFFER_SAMPLES]
Definition: codec_adpcm.c:220
int zero_count
Definition: codec_adpcm.c:76
Data structure associated with a single frame of data.
union ast_frame::@226 data
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
void * pvt
Definition: translate.h:219
int datalen
actual space used in outbuf
Definition: translate.h:218
union ast_trans_pvt::@287 outbuf
int16_t * i16
Definition: translate.h:223
Descriptor of a translator.
Definition: translate.h:137
char name[80]
Definition: translate.h:138
Support for translation of data formats. translate.c.
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:258
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given translator.
Definition: translate.c:1350
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:439
Utility functions.