formats: clarify setting of reverse_bytes
[sox.git] / src / adpcm.c
blobf64b7d5c2787c4ae93d25a90e4aefae4b9573c69
1 /* adpcm.c codex functions for MS_ADPCM data
2 * (hopefully) provides interoperability with
3 * Microsoft's ADPCM format, but, as usual,
4 * see LACK-OF-WARRANTY information below.
6 * Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net>
8 * This library is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or (at
11 * your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
16 * General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * November 22, 1999
26 * specs I've seen are unclear about ADPCM supporting more than 2 channels,
27 * but these routines support more channels in a manner which looks (IMHO)
28 * like the most natural extension.
30 * Remark: code still turbulent, encoding very new.
34 #include "sox_i.h"
35 #include "adpcm.h"
37 #include <sys/types.h>
38 #include <stdio.h>
40 typedef struct {
41 sox_sample_t step; /* step size */
42 short coef[2];
43 } MsState_t;
45 #define lsbshortldi(x,p) { (x)=((short)((int)(p)[0] + ((int)(p)[1]<<8))); (p) += 2; }
48 * Lookup tables for MS ADPCM format
51 /* these are step-size adjust factors, where
52 * 1.0 is scaled to 0x100
54 static const
55 sox_sample_t stepAdjustTable[] = {
56 230, 230, 230, 230, 307, 409, 512, 614,
57 768, 614, 512, 409, 307, 230, 230, 230
60 /* TODO : The first 7 lsx_ms_adpcm_i_coef sets are always hardcoded and must
61 appear in the actual WAVE file. They should be read in
62 in case a sound program added extras to the list. */
64 const short lsx_ms_adpcm_i_coef[7][2] = {
65 { 256, 0},
66 { 512,-256},
67 { 0, 0},
68 { 192, 64},
69 { 240, 0},
70 { 460,-208},
71 { 392,-232}
74 extern void *lsx_ms_adpcm_alloc(unsigned chans)
76 return lsx_malloc(chans * sizeof(MsState_t));
79 static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state,
80 sox_sample_t sample1, sox_sample_t sample2)
82 sox_sample_t vlin;
83 sox_sample_t sample;
84 sox_sample_t step;
86 /** Compute next step value **/
87 step = state->step;
89 sox_sample_t nstep;
90 nstep = (stepAdjustTable[c] * step) >> 8;
91 state->step = (nstep < 16)? 16:nstep;
94 /** make linear prediction for next sample **/
95 vlin =
96 ((sample1 * state->coef[0]) +
97 (sample2 * state->coef[1])) >> 8;
98 /** then add the code*step adjustment **/
99 c -= (c & 0x08) << 1;
100 sample = (c * step) + vlin;
102 if (sample > 0x7fff) sample = 0x7fff;
103 else if (sample < -0x8000) sample = -0x8000;
105 return (sample);
108 /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */
109 const char *lsx_ms_adpcm_block_expand_i(
110 void *priv,
111 unsigned chans, /* total channels */
112 int nCoef,
113 const short *coef,
114 const unsigned char *ibuff,/* input buffer[blockAlign] */
115 SAMPL *obuff, /* output samples, n*chans */
116 int n /* samples to decode PER channel */
119 const unsigned char *ip;
120 unsigned ch;
121 const char *errmsg = NULL;
122 MsState_t *state = priv; /* One decompressor state for each channel */
124 /* Read the four-byte header for each channel */
125 ip = ibuff;
126 for (ch = 0; ch < chans; ch++) {
127 unsigned char bpred = *ip++;
128 if (bpred >= nCoef) {
129 errmsg = "MSADPCM bpred >= nCoef, arbitrarily using 0\n";
130 bpred = 0;
132 state[ch].coef[0] = coef[(int)bpred*2+0];
133 state[ch].coef[1] = coef[(int)bpred*2+1];
136 for (ch = 0; ch < chans; ch++)
137 lsbshortldi(state[ch].step, ip);
139 /* sample1's directly into obuff */
140 for (ch = 0; ch < chans; ch++)
141 lsbshortldi(obuff[chans+ch], ip);
143 /* sample2's directly into obuff */
144 for (ch = 0; ch < chans; ch++)
145 lsbshortldi(obuff[ch], ip);
148 unsigned ch2;
149 unsigned char b;
150 short *op, *top, *tmp;
152 /* already have 1st 2 samples from block-header */
153 op = obuff + 2*chans;
154 top = obuff + n*chans;
156 ch2 = 0;
157 while (op < top) { /*** N.B. Without int casts, crashes on 64-bit arch ***/
158 b = *ip++;
159 tmp = op;
160 *op++ = AdpcmDecode(b >> 4, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]);
161 if (++ch2 == chans) ch2 = 0;
162 tmp = op;
163 *op++ = AdpcmDecode(b&0x0f, state+ch2, tmp[-(int)chans], tmp[-(int)(2*chans)]);
164 if (++ch2 == chans) ch2 = 0;
167 return errmsg;
170 static int AdpcmMashS(
171 unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
172 unsigned chans, /* total channels */
173 SAMPL v[2], /* values to use as starting 2 */
174 const short coef[2],/* lin predictor coeffs */
175 const SAMPL *ibuff, /* ibuff[] is interleaved input samples */
176 int n, /* samples to encode PER channel */
177 int *iostep, /* input/output step, REQUIRE 16 <= *st <= 0x7fff */
178 unsigned char *obuff /* output buffer[blockAlign], or NULL for no output */
181 const SAMPL *ip, *itop;
182 unsigned char *op;
183 int ox = 0; /* */
184 int d, v0, v1, step;
185 double d2; /* long long is okay also, speed abt the same */
187 ip = ibuff + ch; /* point ip to 1st input sample for this channel */
188 itop = ibuff + n*chans;
189 v0 = v[0];
190 v1 = v[1];
191 d = *ip - v1; ip += chans; /* 1st input sample for this channel */
192 d2 = d*d; /* d2 will be sum of squares of errors, given input v0 and *st */
193 d = *ip - v0; ip += chans; /* 2nd input sample for this channel */
194 d2 += d*d;
196 step = *iostep;
198 op = obuff; /* output pointer (or NULL) */
199 if (op) { /* NULL means don't output, just compute the rms error */
200 op += chans; /* skip bpred indices */
201 op += 2*ch; /* channel's stepsize */
202 op[0] = step; op[1] = step>>8;
203 op += 2*chans; /* skip to v0 */
204 op[0] = v0; op[1] = v0>>8;
205 op += 2*chans; /* skip to v1 */
206 op[0] = v1; op[1] = v1>>8;
207 op = obuff+7*chans; /* point to base of output nibbles */
208 ox = 4*ch;
210 for (; ip < itop; ip+=chans) {
211 int vlin,d3,dp,c;
213 /* make linear prediction for next sample */
214 vlin = (v0 * coef[0] + v1 * coef[1]) >> 8;
215 d3 = *ip - vlin; /* difference between linear prediction and current sample */
216 dp = d3 + (step<<3) + (step>>1);
217 c = 0;
218 if (dp>0) {
219 c = dp/step;
220 if (c>15) c = 15;
222 c -= 8;
223 dp = c * step; /* quantized estimate of samp - vlin */
224 c &= 0x0f; /* mask to 4 bits */
226 v1 = v0; /* shift history */
227 v0 = vlin + dp;
228 if (v0<-0x8000) v0 = -0x8000;
229 else if (v0>0x7fff) v0 = 0x7fff;
231 d3 = *ip - v0;
232 d2 += d3*d3; /* update square-error */
234 if (op) { /* if we want output, put it in proper place */
235 op[ox>>3] |= (ox&4)? c:(c<<4);
236 ox += 4*chans;
237 lsx_debug_more("%.1x",c);
241 /* Update the step for the next sample */
242 step = (stepAdjustTable[c] * step) >> 8;
243 if (step < 16) step = 16;
246 if (op) lsx_debug_more("\n");
247 d2 /= n; /* be sure it's non-negative */
248 lsx_debug_more("ch%d: st %d->%d, d %.1f\n", ch, *iostep, step, sqrt(d2));
249 *iostep = step;
250 return (int) sqrt(d2);
253 static inline void AdpcmMashChannel(
254 unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
255 unsigned chans, /* total channels */
256 const SAMPL *ip, /* ip[] is interleaved input samples */
257 int n, /* samples to encode PER channel, REQUIRE */
258 int *st, /* input/output steps, 16<=st[i] */
259 unsigned char *obuff /* output buffer[blockAlign] */
262 SAMPL v[2];
263 int n0,s0,s1,ss,smin;
264 int dmin,k,kmin;
266 n0 = n/2; if (n0>32) n0=32;
267 if (*st<16) *st = 16;
268 v[1] = ip[ch];
269 v[0] = ip[ch+chans];
271 dmin = 0; kmin = 0; smin = 0;
272 /* for each of 7 standard coeff sets, we try compression
273 * beginning with last step-value, and with slightly
274 * forward-adjusted step-value, taking best of the 14
276 for (k=0; k<7; k++) {
277 int d0,d1;
278 ss = s0 = *st;
279 d0=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s0 */
281 s1 = s0;
282 AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n0, &s1, NULL);
283 lsx_debug_more(" s32 %d\n",s1);
284 ss = s1 = (3*s0+s1)/4;
285 d1=AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[k], ip, n, &ss, NULL); /* with step s1 */
286 if (!k || d0<dmin || d1<dmin) {
287 kmin = k;
288 if (d0<=d1) {
289 dmin = d0;
290 smin = s0;
291 }else{
292 dmin = d1;
293 smin = s1;
297 *st = smin;
298 lsx_debug_more("kmin %d, smin %5d, ",kmin,smin);
299 AdpcmMashS(ch, chans, v, lsx_ms_adpcm_i_coef[kmin], ip, n, st, obuff);
300 obuff[ch] = kmin;
303 void lsx_ms_adpcm_block_mash_i(
304 unsigned chans, /* total channels */
305 const SAMPL *ip, /* ip[n*chans] is interleaved input samples */
306 int n, /* samples to encode PER channel */
307 int *st, /* input/output steps, 16<=st[i] */
308 unsigned char *obuff, /* output buffer[blockAlign] */
309 int blockAlign /* >= 7*chans + chans*(n-2)/2.0 */
312 unsigned ch;
313 unsigned char *p;
315 lsx_debug_more("AdpcmMashI(chans %d, ip %p, n %d, st %p, obuff %p, bA %d)\n",
316 chans, (void *)ip, n, (void *)st, obuff, blockAlign);
318 for (p=obuff+7*chans; p<obuff+blockAlign; p++) *p=0;
320 for (ch=0; ch<chans; ch++)
321 AdpcmMashChannel(ch, chans, ip, n, st+ch, obuff);
325 * lsx_ms_adpcm_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
326 * returns the number of samples/channel which would be
327 * in the dataLen, given the other parameters ...
328 * if input samplesPerBlock is 0, then returns the max
329 * samplesPerBlock which would go into a block of size blockAlign
330 * Yes, it is confusing usage.
332 size_t lsx_ms_adpcm_samples_in(
333 size_t dataLen,
334 size_t chans,
335 size_t blockAlign,
336 size_t samplesPerBlock
338 size_t m, n;
340 if (samplesPerBlock) {
341 n = (dataLen / blockAlign) * samplesPerBlock;
342 m = (dataLen % blockAlign);
343 } else {
344 n = 0;
345 m = blockAlign;
347 if (m >= (size_t)(7*chans)) {
348 m -= 7*chans; /* bytes beyond block-header */
349 m = (2*m)/chans + 2; /* nibbles/chans + 2 in header */
350 if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock;
351 n += m;
353 return n;
356 size_t lsx_ms_adpcm_bytes_per_block(
357 size_t chans,
358 size_t samplesPerBlock
361 size_t n;
362 n = 7*chans; /* header */
363 if (samplesPerBlock > 2)
364 n += (((size_t)samplesPerBlock-2)*chans + 1)/2;
365 return n;