convert line ends
[canaan.git] / prj / tech / libsrc / sndutil / imaadpcm.cpp
blobf5ca1c8ea2fa4190a3c99023780d324bf6556531
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // (c) 1996 Looking Glass Technologies Inc.
4 // Pat McElhatton
5 //
6 // Module name: IMA ADPCM definitions
7 // File name: imaadpcm.h
8 //
9 // Description: IMA ADPCM (aka DVI) compress/decompress definitions
11 ////////////////////////////////////////////////////////////////////////
13 /**************************************************************************
15 Program to read in and code digitized stereo audio
16 using Intel/DVI's implementation of the classic ADPCM algorithm
17 described in the following references:
19 N. S. Jayant, "Adaptive Quantization With a One Word Memory,"
20 Bell System Tech. J., pp. 119-1144, Sep. 1973
22 L. R. Rabiner / R. W. Schafer, Digital Processing of Speech
23 Signals, Prentice Hall, 1978
25 Mark Stout, Compaq Computer, 1/92
27 4-feb-92 patmc Broken into routines
28 11-jul-96 patmc converted to C++
30 ****************************************************************************/
32 #include "imaadpcm.h"
34 static int indextab[16] = {-1,-1,-1,-1, 2, 4, 6, 8,
35 -1,-1,-1,-1, 2, 4, 6, 8};
37 static int steptab[89]={
38 7, 8, 9, 10, 11, 12, 13, 14, /* DVI exten. */
39 16, 17, 19, 21, 23, 25, 28, /* OKI lookup table */
40 31, 34, 37, 41, 45, 50, 55,
41 60, 66, 73, 80, 88, 97, 107,
42 118, 130, 143, 157, 173, 190, 209,
43 230, 253, 279, 307, 337, 371, 408,
44 449, 494, 544, 598, 658, 724, 796,
45 876, 963,1060,1166,1282,1411,1552,
47 1707,1878, /* DVI exten. */
49 2066,2272,2499,2749,3024,3327,3660,4026,
50 4428,4871,5358,5894,6484,7132,7845,8630,
51 9493,10442,11487,12635,13899,15289,16818,
52 18500,20350,22385,24623,27086,29794,32767
56 IMAADPCM::IMAADPCM( void )
58 mPredictedSample = 0;
59 mNybbleToggle = 0;
60 mSpareNybble = 0;
61 mIndex = 0;
65 IMAADPCM::~IMAADPCM( void )
71 * initialize compressor state
73 void
74 IMAADPCM::Init(
75 int predSample,
76 int index
79 mPredictedSample = predSample;
80 mIndex = index;
81 mNybbleToggle = 0;
82 mSpareNybble = 0;
87 * get compressor state packed into a longword
89 unsigned long
90 IMAADPCM::GetState( void )
92 unsigned short hiWord;
93 unsigned long val;
95 val = mPredictedSample & 0xFFFF;
96 hiWord = (unsigned short) ((mIndex & 0xFF) | ((mSpareNybble & 0xF0) << 4)
97 | ((mNybbleToggle & 1) << 12));
98 return val | (hiWord << 16);
103 * set compressor state from packed longword
105 void
106 IMAADPCM::SetState( unsigned long state )
108 short val = (short) (state & 0xFFFF);
110 mPredictedSample = val;
111 state >>= 16;
112 mIndex = state & 0xFF;
113 mSpareNybble = (state >> 4) & 0xF0;
114 mNybbleToggle = (state >> 12) & 1;
119 * compress a short block of size numSamples
120 * returns # of bytes written to outBlock
122 long
123 IMAADPCM::Compress(
124 short *inBlock,
125 char *outBlock,
126 long numSamples
129 int inSampleIndex, outSampleIndex;
130 int tempstep, mask;
132 int code; /* 4-bit quantized difference */
133 long diff; /* difference between 2 consecutive samples */
134 long pdiff; /* difference between 2 consecutive samples */
135 int step; /* step sizes at encoding and decoding portion */
137 outSampleIndex = 0;
139 /* process buffer */
140 for (inSampleIndex = 0; inSampleIndex < numSamples; inSampleIndex++) {
142 step = steptab[mIndex];
143 /* difference between actual sample & predicted value */
144 diff = (long)inBlock[ inSampleIndex] - mPredictedSample;
146 if( diff >= 0 ) {
147 code=0; /* set sign bit */
148 } else {
149 code=8;
150 diff = -diff;
152 mask = 4;
153 pdiff = 0;
154 tempstep = step;
156 if( diff >= tempstep ){
157 code |= 4;
158 diff -= tempstep;
159 pdiff += step;
161 tempstep >>=1;
162 if( diff >= tempstep ){
163 code |= 2;
164 diff -= tempstep;
165 pdiff += (step >> 1);
167 tempstep >>=1;
168 if( diff >= tempstep ){
169 code |= 1;
170 diff -= tempstep;
171 pdiff += (step >> 2);
173 pdiff += (step >> 3);
174 if ( code & 8 ) {
175 pdiff = -pdiff;
178 /* lower 4-bit of code can be sent out or stored at this point */
180 if ( mNybbleToggle ) {
181 outBlock[ outSampleIndex ] = (char) (mSpareNybble + (code & 0xF));
182 outSampleIndex++;
183 } else {
184 /* hiNybble is even sample */
185 mSpareNybble = code << 4;
187 mNybbleToggle ^= 1;
189 /* compute new sample estimate mPredictedSample */
190 mPredictedSample += pdiff;
192 if (mPredictedSample > 32767) /* check for overflow */
193 mPredictedSample = 32767;
194 else if (mPredictedSample < -32768)
195 mPredictedSample = -32768;
197 /* compute new stepsize step */
198 mIndex += indextab[code];
199 if(mIndex < 0)mIndex = 0;
200 else if(mIndex > 88)mIndex = 88;
203 return outSampleIndex;
207 * end compression - flush last nybble, if any to buffer
208 * return # of bytes written to buffer (0 or 1)
210 long
211 IMAADPCM::EndCompress(
212 char *outBlock
215 if ( mNybbleToggle ) {
216 *outBlock = (char) mSpareNybble;
217 return 1;
218 } else {
219 return 0;
225 * decompress a short block of size numSamples
226 * returns # of bytes consumed from inBlock
228 long
229 IMAADPCM::Decompress(
230 char *inBlock,
231 short *outBlock,
232 long numSamples
235 int inByteIndex, outSampleIndex;
236 int code; /* 4-bit quantized difference */
237 long diff; /* difference between 2 consecutive samples */
238 int step; /* step sizes at encoding and decoding portion */
240 inByteIndex = 0;
242 /* process buffer */
243 for (outSampleIndex = 0; outSampleIndex < numSamples; outSampleIndex++) {
245 // NOTE: The nybble order for PCs is opposite from Unix
246 // Unix has high nybble first, PCs have low nybble first
247 /* fetch a nybble code to decompress */
248 if ( mNybbleToggle ) {
249 // code = mSpareNybble & 0xF;
250 code = (mSpareNybble & 0xF0) >> 4;
251 inByteIndex++;
252 } else {
253 mSpareNybble = inBlock[ inByteIndex ];
254 code = mSpareNybble & 0xF;
255 // code = (mSpareNybble & 0xF0) >> 4;
257 mNybbleToggle ^= 1;
259 /* compute new sample estimate mPredictedSample */
260 diff = 0;
261 step = steptab[mIndex];
262 if (code & 4) diff += step;
263 if (code & 2) diff += (step >> 1);
264 if (code & 1) diff += (step >> 2);
265 diff += step >> 3;
266 if (code & 8) diff = -diff;
267 mPredictedSample += diff;
269 if (mPredictedSample > 32767) /* check for overflow */
270 mPredictedSample = 32767;
271 else if (mPredictedSample < -32768)
272 mPredictedSample = -32768;
274 /* compute new stepsize step */
275 mIndex += indextab[code];
276 if (mIndex < 0) mIndex = 0;
277 else if (mIndex > 88) mIndex = 88;
279 /* output predicted sample */
280 outBlock[outSampleIndex] = (short) mPredictedSample;
283 // return # of bytes consumed (not including partially consumed)
284 return inByteIndex;
289 // decompress a block of IMA ADPCM data (RIFF WAVE block format)
291 long
292 DecompressIMABlock(
293 char *pInBuff,
294 short *pOutBuff,
295 long nSamples,
296 int nChannels
299 IMAADPCM leftDecomp, rightDecomp;
300 IMAHeaderWord *pIMAHdr;
302 // Each block starts with a IMAHeaderWord, which contains
303 // the predicted first sample of the block and the stepsize
304 // index. Note that
305 if ( nSamples > 1 ) {
306 switch( nChannels ) {
307 case 1:
308 // decompress a block
309 pIMAHdr = (IMAHeaderWord *) pInBuff;
310 pOutBuff[0] = pIMAHdr->curValue;
311 leftDecomp.Init( pIMAHdr->curValue, pIMAHdr->stepIndex );
312 leftDecomp.Decompress( pInBuff + sizeof(IMAHeaderWord),
313 pOutBuff + 1, nSamples - 1 );
314 break;
315 case 2:
316 // stereo - channels are interleaved every 8 samples
317 // TBD!
318 leftDecomp.Init( pIMAHdr->curValue, pIMAHdr->stepIndex );
319 rightDecomp.Init( pIMAHdr->curValue, pIMAHdr->stepIndex );
320 break;
321 default:
322 return -1;
325 return nSamples;
330 // decompress a block of IMA ADPCM data (RIFF WAVE block format)
331 // returns ptr to next byte in input buffer
333 char *
334 DecompressIMABlockPartial( char *pInBuff,
335 short *pOutBuff,
336 long nSamples,
337 BOOL getHeader,
338 unsigned long *pState )
340 IMAADPCM decomp;
341 IMAHeaderWord *pIMAHdr;
342 long bytesEaten;
344 // decompress a block
345 if ( getHeader ) {
346 // This is first fetch in this block, so we must set
347 // the decompressor state from the header word at the
348 // start of the block
349 pIMAHdr = (IMAHeaderWord *) pInBuff;
350 pOutBuff[0] = pIMAHdr->curValue;
351 if ( nSamples > 1 ) {
352 decomp.Init( pIMAHdr->curValue, pIMAHdr->stepIndex );
353 bytesEaten = decomp.Decompress( pInBuff + sizeof(IMAHeaderWord),
354 pOutBuff + 1, nSamples - 1 );
356 // save the decompressor state for future calls
357 *pState = decomp.GetState();
358 pInBuff += ( sizeof(IMAHeaderWord) + bytesEaten );
359 } else {
360 // this is not the first fetch in the block, so we must
361 // set the state from our saved packed state
362 decomp.SetState( *pState );
363 bytesEaten = decomp.Decompress( pInBuff, pOutBuff, nSamples );
364 // save the decompressor state for future calls
365 *pState = decomp.GetState();
366 pInBuff += bytesEaten;
369 return pInBuff;