formats: clarify setting of reverse_bytes
[sox.git] / src / ima_rw.c
blob360758e15d057e17f646b7437adc51113944eb9e
1 /* libSoX ima_rw.c -- codex utilities for WAV_FORMAT_IMA_ADPCM
2 * Copyright (C) 1999 Stanley J. Brooks <stabro@megsinet.net>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or (at
7 * your option) any later version.
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "sox_i.h"
21 #include "ima_rw.h"
23 #include <sys/types.h>
24 #include <stdio.h>
25 #include <stdlib.h>
28 * Lookup tables for IMA ADPCM format
31 #define ISSTMAX 88
33 static const int imaStepSizeTable[ISSTMAX + 1] = {
34 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
35 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
36 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
37 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
38 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
39 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
40 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
41 27086, 29794, 32767
44 #define imaStateAdjust(c) (((c)<4)? -1:(2*(c)-6))
45 /* +0 - +3, decrease step size */
46 /* +4 - +7, increase step size */
47 /* -0 - -3, decrease step size */
48 /* -4 - -7, increase step size */
50 static unsigned char imaStateAdjustTable[ISSTMAX+1][8];
52 void lsx_ima_init_table(void)
54 int i,j,k;
55 for (i=0; i<=ISSTMAX; i++) {
56 for (j=0; j<8; j++) {
57 k = i + imaStateAdjust(j);
58 if (k<0) k=0;
59 else if (k>ISSTMAX) k=ISSTMAX;
60 imaStateAdjustTable[i][j] = k;
65 static void ImaExpandS(
66 unsigned ch, /* channel number to decode, REQUIRE 0 <= ch < chans */
67 unsigned chans, /* total channels */
68 const unsigned char *ibuff,/* input buffer[blockAlign] */
69 SAMPL *obuff, /* obuff[n] will be output samples */
70 int n, /* samples to decode PER channel, REQUIRE n % 8 == 1 */
71 unsigned o_inc /* index difference between successive output samples */
74 const unsigned char *ip;
75 int i_inc;
76 SAMPL *op;
77 int i, val, state;
79 ip = ibuff + 4*ch; /* input pointer to 4-byte block state-initializer */
80 i_inc = 4*(chans-1); /* amount by which to incr ip after each 4-byte read */
81 val = (short)(ip[0] + (ip[1]<<8)); /* need cast for sign-extend */
82 state = ip[2];
83 if (state > ISSTMAX) {
84 lsx_warn("IMA_ADPCM block ch%d initial-state (%d) out of range", ch, state);
85 state = 0;
87 /* specs say to ignore ip[3] , but write it as 0 */
88 ip += 4+i_inc;
90 op = obuff;
91 *op = val; /* 1st output sample for this channel */
92 op += o_inc;
94 for (i = 1; i < n; i++) {
95 int step,dp,c,cm;
97 if (i&1) { /* 1st of pair */
98 cm = *ip & 0x0f;
99 } else {
100 cm = (*ip++)>>4;
101 if ((i&7) == 0) /* ends the 8-sample input block for this channel */
102 ip += i_inc; /* skip ip for next group */
105 step = imaStepSizeTable[state];
106 /* Update the state for the next sample */
107 c = cm & 0x07;
108 state = imaStateAdjustTable[state][c];
110 dp = 0;
111 if (c & 4) dp += step;
112 step = step >> 1;
113 if (c & 2) dp += step;
114 step = step >> 1;
115 if (c & 1) dp += step;
116 step = step >> 1;
117 dp += step;
119 if (c != cm) {
120 val -= dp;
121 if (val<-0x8000) val = -0x8000;
122 } else {
123 val += dp;
124 if (val>0x7fff) val = 0x7fff;
126 *op = val;
127 op += o_inc;
129 return;
132 /* lsx_ima_block_expand_i() outputs interleaved samples into one output buffer */
133 void lsx_ima_block_expand_i(
134 unsigned chans, /* total channels */
135 const unsigned char *ibuff,/* input buffer[blockAlign] */
136 SAMPL *obuff, /* output samples, n*chans */
137 int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
140 unsigned ch;
141 for (ch=0; ch<chans; ch++)
142 ImaExpandS(ch, chans, ibuff, obuff+ch, n, chans);
145 /* lsx_ima_block_expand_m() outputs non-interleaved samples into chan separate output buffers */
146 void lsx_ima_block_expand_m(
147 unsigned chans, /* total channels */
148 const unsigned char *ibuff,/* input buffer[blockAlign] */
149 SAMPL **obuffs, /* chan output sample buffers, each takes n samples */
150 int n /* samples to decode PER channel, REQUIRE n % 8 == 1 */
153 unsigned ch;
154 for (ch=0; ch<chans; ch++)
155 ImaExpandS(ch, chans, ibuff, obuffs[ch], n, 1);
158 static int ImaMashS(
159 unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
160 unsigned chans, /* total channels */
161 int v0, /* value to use as starting prediction0 */
162 const SAMPL *ibuff, /* ibuff[] is interleaved input samples */
163 int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
164 int *st, /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */
165 unsigned char *obuff /* output buffer[blockAlign], or NULL for no output */
168 const SAMPL *ip, *itop;
169 unsigned char *op;
170 int o_inc = 0; /* set 0 only to shut up gcc's 'might be uninitialized' */
171 int i, val;
172 int state;
173 double d2; /* long long is okay also, speed abt the same */
175 ip = ibuff + ch; /* point ip to 1st input sample for this channel */
176 itop = ibuff + n*chans;
177 val = *ip - v0; ip += chans;/* 1st input sample for this channel */
178 d2 = val*val;/* d2 will be sum of squares of errors, given input v0 and *st */
179 val = v0;
181 op = obuff; /* output pointer (or NULL) */
182 if (op) { /* NULL means don't output, just compute the rms error */
183 op += 4*ch; /* where to put this channel's 4-byte block state-initializer */
184 o_inc = 4*(chans-1); /* amount by which to incr op after each 4-byte written */
185 *op++ = val; *op++ = val>>8;
186 *op++ = *st; *op++ = 0; /* they could have put a mid-block state-correction here */
187 op += o_inc; /* _sigh_ NEVER waste a byte. It's a rule! */
190 state = *st;
192 for (i = 0; ip < itop; ip+=chans) {
193 int step,d,dp,c;
195 d = *ip - val; /* difference between last prediction and current sample */
197 step = imaStepSizeTable[state];
198 c = (abs(d)<<2)/step;
199 if (c > 7) c = 7;
200 /* Update the state for the next sample */
201 state = imaStateAdjustTable[state][c];
203 if (op) { /* if we want output, put it in proper place */
204 int cm = c;
205 if (d<0) cm |= 8;
206 if (i&1) { /* odd numbered output */
207 *op++ |= (cm<<4);
208 if (i == 7) /* ends the 8-sample output block for this channel */
209 op += o_inc; /* skip op for next group */
210 } else {
211 *op = cm;
213 i = (i+1) & 0x07;
216 dp = 0;
217 if (c & 4) dp += step;
218 step = step >> 1;
219 if (c & 2) dp += step;
220 step = step >> 1;
221 if (c & 1) dp += step;
222 step = step >> 1;
223 dp += step;
225 if (d<0) {
226 val -= dp;
227 if (val<-0x8000) val = -0x8000;
228 } else {
229 val += dp;
230 if (val>0x7fff) val = 0x7fff;
234 int x = *ip - val;
235 d2 += x*x;
239 d2 /= n; /* be sure it's non-negative */
240 *st = state;
241 return (int) sqrt(d2);
244 /* mash one channel... if you want to use opt>0, 9 is a reasonable value */
245 inline static void ImaMashChannel(
246 unsigned ch, /* channel number to encode, REQUIRE 0 <= ch < chans */
247 unsigned chans, /* total channels */
248 const SAMPL *ip, /* ip[] is interleaved input samples */
249 int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
250 int *st, /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */
251 unsigned char *obuff, /* output buffer[blockAlign] */
252 int opt /* non-zero allows some cpu-intensive code to improve output */
255 int snext;
256 int s0,d0;
258 s0 = *st;
259 if (opt>0) {
260 int low,hi,w;
261 int low0,hi0;
262 snext = s0;
263 d0 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL);
265 w = 0;
266 low=hi=s0;
267 low0 = low-opt; if (low0<0) low0=0;
268 hi0 = hi+opt; if (hi0>ISSTMAX) hi0=ISSTMAX;
269 while (low>low0 || hi<hi0) {
270 if (!w && low>low0) {
271 int d2;
272 snext = --low;
273 d2 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL);
274 if (d2<d0) {
275 d0=d2; s0=low;
276 low0 = low-opt; if (low0<0) low0=0;
277 hi0 = low+opt; if (hi0>ISSTMAX) hi0=ISSTMAX;
280 if (w && hi<hi0) {
281 int d2;
282 snext = ++hi;
283 d2 = ImaMashS(ch, chans, ip[ch], ip,n,&snext, NULL);
284 if (d2<d0) {
285 d0=d2; s0=hi;
286 low0 = hi-opt; if (low0<0) low0=0;
287 hi0 = hi+opt; if (hi0>ISSTMAX) hi0=ISSTMAX;
290 w=1-w;
292 *st = s0;
294 ImaMashS(ch, chans, ip[ch], ip,n,st, obuff);
297 /* mash one block. if you want to use opt>0, 9 is a reasonable value */
298 void lsx_ima_block_mash_i(
299 unsigned chans, /* total channels */
300 const SAMPL *ip, /* ip[] is interleaved input samples */
301 int n, /* samples to encode PER channel, REQUIRE n % 8 == 1 */
302 int *st, /* input/output state, REQUIRE 0 <= *st <= ISSTMAX */
303 unsigned char *obuff, /* output buffer[blockAlign] */
304 int opt /* non-zero allows some cpu-intensive code to improve output */
307 unsigned ch;
308 for (ch=0; ch<chans; ch++)
309 ImaMashChannel(ch, chans, ip, n, st+ch, obuff, opt);
313 * lsx_ima_samples_in(dataLen, chans, blockAlign, samplesPerBlock)
314 * returns the number of samples/channel which would go
315 * in the dataLen, given the other parameters ...
316 * if input samplesPerBlock is 0, then returns the max
317 * samplesPerBlock which would go into a block of size blockAlign
318 * Yes, it is confusing.
320 size_t lsx_ima_samples_in(
321 size_t dataLen,
322 size_t chans,
323 size_t blockAlign,
324 size_t samplesPerBlock
327 size_t m, n;
329 if (samplesPerBlock) {
330 n = (dataLen / blockAlign) * samplesPerBlock;
331 m = (dataLen % blockAlign);
332 } else {
333 n = 0;
334 m = blockAlign;
336 if (m >= (size_t)4*chans) {
337 m -= 4*chans; /* number of bytes beyond block-header */
338 m /= 4*chans; /* number of 4-byte blocks/channel beyond header */
339 m = 8*m + 1; /* samples/chan beyond header + 1 in header */
340 if (samplesPerBlock && m > samplesPerBlock) m = samplesPerBlock;
341 n += m;
343 return n;
344 /*wSamplesPerBlock = ((wBlockAlign - 4*wChannels)/(4*wChannels))*8 + 1;*/
348 * size_t lsx_ima_bytes_per_block(chans, samplesPerBlock)
349 * return minimum blocksize which would be required
350 * to encode number of chans with given samplesPerBlock
352 size_t lsx_ima_bytes_per_block(
353 size_t chans,
354 size_t samplesPerBlock
357 size_t n;
358 /* per channel, ima has blocks of len 4, the 1st has 1st sample, the others
359 * up to 8 samples per block,
360 * so number of later blocks is (nsamp-1 + 7)/8, total blocks/chan is
361 * (nsamp-1+7)/8 + 1 = (nsamp+14)/8
363 n = ((size_t)samplesPerBlock + 14)/8 * 4 * chans;
364 return n;