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
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.
37 #include <sys/types.h>
41 sox_sample_t step
; /* step size */
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
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] = {
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
)
86 /** Compute next step value **/
90 nstep
= (stepAdjustTable
[c
] * step
) >> 8;
91 state
->step
= (nstep
< 16)? 16:nstep
;
94 /** make linear prediction for next sample **/
96 ((sample1
* state
->coef
[0]) +
97 (sample2
* state
->coef
[1])) >> 8;
98 /** then add the code*step adjustment **/
100 sample
= (c
* step
) + vlin
;
102 if (sample
> 0x7fff) sample
= 0x7fff;
103 else if (sample
< -0x8000) sample
= -0x8000;
108 /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */
109 const char *lsx_ms_adpcm_block_expand_i(
111 unsigned chans
, /* total channels */
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
;
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 */
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";
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
);
150 short *op
, *top
, *tmp
;
152 /* already have 1st 2 samples from block-header */
153 op
= obuff
+ 2*chans
;
154 top
= obuff
+ n
*chans
;
157 while (op
< top
) { /*** N.B. Without int casts, crashes on 64-bit arch ***/
160 *op
++ = AdpcmDecode(b
>> 4, state
+ch2
, tmp
[-(int)chans
], tmp
[-(int)(2*chans
)]);
161 if (++ch2
== chans
) ch2
= 0;
163 *op
++ = AdpcmDecode(b
&0x0f, state
+ch2
, tmp
[-(int)chans
], tmp
[-(int)(2*chans
)]);
164 if (++ch2
== chans
) ch2
= 0;
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
;
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
;
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 */
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 */
210 for (; ip
< itop
; ip
+=chans
) {
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);
223 dp
= c
* step
; /* quantized estimate of samp - vlin */
224 c
&= 0x0f; /* mask to 4 bits */
226 v1
= v0
; /* shift history */
228 if (v0
<-0x8000) v0
= -0x8000;
229 else if (v0
>0x7fff) v0
= 0x7fff;
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);
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
));
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] */
263 int n0
,s0
,s1
,ss
,smin
;
266 n0
= n
/2; if (n0
>32) n0
=32;
267 if (*st
<16) *st
= 16;
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
++) {
279 d0
=AdpcmMashS(ch
, chans
, v
, lsx_ms_adpcm_i_coef
[k
], ip
, n
, &ss
, NULL
); /* with step 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
) {
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
);
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 */
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(
336 size_t samplesPerBlock
340 if (samplesPerBlock
) {
341 n
= (dataLen
/ blockAlign
) * samplesPerBlock
;
342 m
= (dataLen
% 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
;
356 size_t lsx_ms_adpcm_bytes_per_block(
358 size_t samplesPerBlock
362 n
= 7*chans
; /* header */
363 if (samplesPerBlock
> 2)
364 n
+= (((size_t)samplesPerBlock
-2)*chans
+ 1)/2;