Wed Jan 8 2020 09:49:46

Asterisk developer's documentation


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