Merged revisions 278023 via svnmerge from
[asterisk/asterisk.git] / codecs / codec_adpcm.c
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 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
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"
40
41 /* define NOT_BLI to use a faster but not bit-level identical version */
42 /* #define NOT_BLI */
43
44 #define BUFFER_SAMPLES   8096   /* size for the translation buffers */
45
46 /* Sample frame data */
47 #include "asterisk/slin.h"
48 #include "ex_adpcm.h"
49
50 /*
51  * Step size index shift table 
52  */
53
54 static int indsft[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
55
56 /*
57  * Step size table, where stpsz[i]=floor[16*(11/10)^i]
58  */
59
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
65 };
66
67 /*
68  * Decoder/Encoder state
69  *   States for both encoder and decoder are synchronized
70  */
71 struct adpcm_state {
72         int ssindex;
73         int signal;
74         int zero_count;
75         int next_flag;
76 };
77
78 /*
79  * Decode(encoded)
80  *  Decodes the encoded nibble from the adpcm file.
81  *
82  * Results:
83  *  Returns the encoded difference.
84  *
85  * Side effects:
86  *  Sets the index to the step size table for the next encode.
87  */
88
89 static inline short decode(int encoded, struct adpcm_state *state)
90 {
91         int diff;
92         int step;
93         int sign;
94
95         step = stpsz[state->ssindex];
96
97         sign = encoded & 0x08;
98         encoded &= 0x07;
99 #ifdef NOT_BLI
100         diff = (((encoded << 1) + 1) * step) >> 3;
101 #else /* BLI code */
102         diff = step >> 3;
103         if (encoded & 4)
104                 diff += step;
105         if (encoded & 2)
106                 diff += step >> 1;
107         if (encoded & 1)
108                 diff += step >> 2;
109         if ((encoded >> 1) & step & 0x1)
110                 diff++;
111 #endif
112         if (sign)
113                 diff = -diff;
114
115         if (state->next_flag & 0x1)
116                 state->signal -= 8;
117         else if (state->next_flag & 0x2)
118                 state->signal += 8;
119
120         state->signal += diff;
121
122         if (state->signal > 2047)
123                 state->signal = 2047;
124         else if (state->signal < -2047)
125                 state->signal = -2047;
126
127         state->next_flag = 0;
128
129 #ifdef AUTO_RETURN
130         if (encoded)
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;
138         }
139 #endif
140
141         state->ssindex += indsft[encoded];
142         if (state->ssindex < 0)
143                 state->ssindex = 0;
144         else if (state->ssindex > 48)
145                 state->ssindex = 48;
146
147         return state->signal << 4;
148 }
149
150 /*
151  * Adpcm
152  *  Takes a signed linear signal and encodes it as ADPCM
153  *  For more information see http://support.dialogic.com/appnotes/adpcm.pdf
154  *
155  * Results:
156  *  Foo.
157  *
158  * Side effects:
159  *  signal gets updated with each pass.
160  */
161
162 static inline int adpcm(short csig, struct adpcm_state *state)
163 {
164         int diff;
165         int step;
166         int encoded;
167
168         /* 
169          * Clip csig if too large or too small
170          */
171         csig >>= 4;
172
173         step = stpsz[state->ssindex];
174         diff = csig - state->signal;
175
176 #ifdef NOT_BLI
177         if (diff < 0) {
178                 encoded = (-diff << 2) / step;
179                 if (encoded > 7)
180                         encoded = 7;
181                 encoded |= 0x08;
182         } else {
183                 encoded = (diff << 2) / step;
184                 if (encoded > 7)
185                         encoded = 7;
186         }
187 #else /* BLI code */
188         if (diff < 0) {
189                 encoded = 8;
190                 diff = -diff;
191         } else
192                 encoded = 0;
193         if (diff >= step) {
194                 encoded |= 4;
195                 diff -= step;
196         }
197         step >>= 1;
198         if (diff >= step) {
199                 encoded |= 2;
200                 diff -= step;
201         }
202         step >>= 1;
203         if (diff >= step)
204                 encoded |= 1;
205 #endif /* NOT_BLI */
206
207         /* feedback to state */
208         decode(encoded, state);
209         
210         return encoded;
211 }
212
213 /*----------------- Asterisk-codec glue ------------*/
214
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 */
219 };
220
221 /*! \brief Workspace for translating ADPCM signals to signed linear. */
222 struct adpcm_decoder_pvt {
223         struct adpcm_state state;
224 };
225
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)
228 {
229         struct adpcm_decoder_pvt *tmp = pvt->pvt;
230         int x = f->datalen;
231         unsigned char *src = f->data.ptr;
232         int16_t *dst = pvt->outbuf.i16 + pvt->samples;
233
234         while (x--) {
235                 *dst++ = decode((*src >> 4) & 0xf, &tmp->state);
236                 *dst++ = decode(*src++ & 0x0f, &tmp->state);
237         }
238         pvt->samples += f->samples;
239         pvt->datalen += 2*f->samples;
240         return 0;
241 }
242
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)
245 {
246         struct adpcm_encoder_pvt *tmp = pvt->pvt;
247
248         memcpy(&tmp->inbuf[pvt->samples], f->data.ptr, f->datalen);
249         pvt->samples += f->samples;
250         return 0;
251 }
252
253 /*! \brief convert inbuf and store into frame */
254 static struct ast_frame *lintoadpcm_frameout(struct ast_trans_pvt *pvt)
255 {
256         struct adpcm_encoder_pvt *tmp = pvt->pvt;
257         struct ast_frame *f;
258         int i;
259         int samples = pvt->samples;     /* save original number */
260   
261         if (samples < 2)
262                 return NULL;
263
264         pvt->samples &= ~1; /* atomic size is 2 samples */
265
266         for (i = 0; i < pvt->samples; i += 2) {
267                 pvt->outbuf.c[i/2] =
268                         (adpcm(tmp->inbuf[i  ], &tmp->state) << 4) |
269                         (adpcm(tmp->inbuf[i+1], &tmp->state)     );
270         };
271
272         f = ast_trans_frameout(pvt, pvt->samples/2, 0);
273
274         /*
275          * If there is a left over sample, move it to the beginning
276          * of the input buffer.
277          */
278
279         if (samples & 1) {      /* move the leftover sample at beginning */
280                 tmp->inbuf[0] = tmp->inbuf[samples - 1];
281                 pvt->samples = 1;
282         }
283         return f;
284 }
285
286
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,
296 };
297
298 static struct ast_translator lintoadpcm = {
299         .name = "lintoadpcm",
300         .srcfmt = AST_FORMAT_SLINEAR,
301         .dstfmt = AST_FORMAT_ADPCM,
302         .framein = lintoadpcm_framein,
303         .frameout = lintoadpcm_frameout,
304         .sample = slin8_sample,
305         .desc_size = sizeof (struct adpcm_encoder_pvt),
306         .buffer_samples = BUFFER_SAMPLES,
307         .buf_size = BUFFER_SAMPLES/ 2,  /* 2 samples per byte */
308 };
309
310 /*! \brief standard module glue */
311 static int reload(void)
312 {
313         return AST_MODULE_LOAD_SUCCESS;
314 }
315
316 static int unload_module(void)
317 {
318         int res;
319
320         res = ast_unregister_translator(&lintoadpcm);
321         res |= ast_unregister_translator(&adpcmtolin);
322
323         return res;
324 }
325
326 static int load_module(void)
327 {
328         int res;
329
330         res = ast_register_translator(&adpcmtolin);
331         if (!res)
332                 res = ast_register_translator(&lintoadpcm);
333         else
334                 ast_unregister_translator(&adpcmtolin);
335         if (res)
336                 return AST_MODULE_LOAD_FAILURE;
337         return AST_MODULE_LOAD_SUCCESS;
338 }
339
340 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Adaptive Differential PCM Coder/Decoder",
341                 .load = load_module,
342                 .unload = unload_module,
343                 .reload = reload,
344                );