Asterisk - The Open Source Telephony Project  GIT-master-0190e70
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"
37 #include "asterisk/linkedlists.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 
56 static 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 
62 static 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  */
73 struct adpcm_state {
74  int ssindex;
75  int signal;
77  int next_flag;
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 
91 static 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 
164 static 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 */
229 static 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. */
246 static 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 */
256 static 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 
289 static 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 
309 static 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 
330 static int unload_module(void)
331 {
332  int res;
333 
334  res = ast_unregister_translator(&lintoadpcm);
335  res |= ast_unregister_translator(&adpcmtolin);
336 
337  return res;
338 }
339 
340 static int load_module(void)
341 {
342  int res = 0;
343 
344  res = ast_register_translator(&adpcmtolin);
345  res |= ast_register_translator(&lintoadpcm);
346 
347  if (res) {
348  unload_module();
350  }
351 
353 }
354 
355 AST_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,
359 );
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout function
Definition: translate.c:432
int datalen
actual space used in outbuf
Definition: translate.h:218
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_frame * adpcm_sample(void)
Definition: ex_adpcm.h:18
Workspace for translating ADPCM signals to signed linear.
Definition: codec_adpcm.c:224
static int load_module(void)
Definition: codec_adpcm.c:340
Descriptor of a translator.
Definition: translate.h:137
short int16_t
Definition: db.h:59
union ast_trans_pvt::@321 outbuf
static struct ast_translator lintoadpcm
Definition: codec_adpcm.c:309
Support for translation of data formats. translate.c.
union ast_frame::@257 data
static int tmp()
Definition: bt_open.c:389
static int adpcm(short csig, struct adpcm_state *state)
Definition: codec_adpcm.c:164
static struct ast_frame * slin8_sample(void)
Definition: slin.h:64
#define NULL
Definition: resample.c:96
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
void * pvt
Definition: translate.h:219
#define BUFFER_SAMPLES
Definition: codec_adpcm.c:46
int16_t * i16
Definition: translate.h:223
Utility functions.
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
Configuration File Parser.
static struct ast_frame * lintoadpcm_frameout(struct ast_trans_pvt *pvt)
convert inbuf and store into frame
Definition: codec_adpcm.c:256
#define ast_register_translator(t)
See __ast_register_translator()
Definition: translate.h:257
int ast_unregister_translator(struct ast_translator *t)
Unregister a translator Unregisters the given tranlator.
Definition: translate.c:1327
A set of macros to manage forward-linked lists.
static struct ast_translator adpcmtolin
Definition: codec_adpcm.c:289
int zero_count
Definition: codec_adpcm.c:76
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
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
Data structure associated with a single frame of data.
Workspace for translating signed linear signals to ADPCM.
Definition: codec_adpcm.c:218
4-bit ADPCM data
int16_t inbuf[BUFFER_SAMPLES]
Definition: codec_adpcm.c:220
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
struct adpcm_state state
Definition: codec_adpcm.c:219
static int stpsz[49]
Definition: codec_adpcm.c:62
struct adpcm_state state
Definition: codec_adpcm.c:225
static int unload_module(void)
Definition: codec_adpcm.c:330
char name[80]
Definition: translate.h:138
static short decode(int encoded, struct adpcm_state *state)
Definition: codec_adpcm.c:91