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
23 #include <sys/types.h>
28 * Lookup tables for IMA ADPCM format
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,
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)
55 for (i
=0; i
<=ISSTMAX
; i
++) {
57 k
= i
+ imaStateAdjust(j
);
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
;
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 */
83 if (state
> ISSTMAX
) {
84 lsx_warn("IMA_ADPCM block ch%d initial-state (%d) out of range", ch
, state
);
87 /* specs say to ignore ip[3] , but write it as 0 */
91 *op
= val
; /* 1st output sample for this channel */
94 for (i
= 1; i
< n
; i
++) {
97 if (i
&1) { /* 1st of pair */
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 */
108 state
= imaStateAdjustTable
[state
][c
];
111 if (c
& 4) dp
+= step
;
113 if (c
& 2) dp
+= step
;
115 if (c
& 1) dp
+= step
;
121 if (val
<-0x8000) val
= -0x8000;
124 if (val
>0x7fff) val
= 0x7fff;
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 */
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 */
154 for (ch
=0; ch
<chans
; ch
++)
155 ImaExpandS(ch
, chans
, ibuff
, obuffs
[ch
], n
, 1);
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
;
170 int o_inc
= 0; /* set 0 only to shut up gcc's 'might be uninitialized' */
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 */
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! */
192 for (i
= 0; ip
< itop
; ip
+=chans
) {
195 d
= *ip
- val
; /* difference between last prediction and current sample */
197 step
= imaStepSizeTable
[state
];
198 c
= (abs(d
)<<2)/step
;
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 */
206 if (i
&1) { /* odd numbered output */
208 if (i
== 7) /* ends the 8-sample output block for this channel */
209 op
+= o_inc
; /* skip op for next group */
217 if (c
& 4) dp
+= step
;
219 if (c
& 2) dp
+= step
;
221 if (c
& 1) dp
+= step
;
227 if (val
<-0x8000) val
= -0x8000;
230 if (val
>0x7fff) val
= 0x7fff;
239 d2
/= n
; /* be sure it's non-negative */
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 */
263 d0
= ImaMashS(ch
, chans
, ip
[ch
], ip
,n
,&snext
, NULL
);
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
) {
273 d2
= ImaMashS(ch
, chans
, ip
[ch
], ip
,n
,&snext
, NULL
);
276 low0
= low
-opt
; if (low0
<0) low0
=0;
277 hi0
= low
+opt
; if (hi0
>ISSTMAX
) hi0
=ISSTMAX
;
283 d2
= ImaMashS(ch
, chans
, ip
[ch
], ip
,n
,&snext
, NULL
);
286 low0
= hi
-opt
; if (low0
<0) low0
=0;
287 hi0
= hi
+opt
; if (hi0
>ISSTMAX
) hi0
=ISSTMAX
;
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 */
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(
324 size_t samplesPerBlock
329 if (samplesPerBlock
) {
330 n
= (dataLen
/ blockAlign
) * samplesPerBlock
;
331 m
= (dataLen
% 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
;
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(
354 size_t samplesPerBlock
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
;