1 /*****************************************************************************/
2 /* adpcm.cpp Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* This module contains implementation of adpcm decompression method used by */
5 /* Storm.dll to decompress WAVE files. Thanks to Tom Amigo for releasing */
6 /* his sources. */
7 /*---------------------------------------------------------------------------*/
8 /* Date Ver Who Comment */
9 /* -------- ---- --- ------- */
10 /* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
11 /* 20.05.03 2.00 Lad Added compression */
12 /* 19.11.03 2.01 Dan Big endian handling */
13 /* 10.01.13 3.00 Lad Refactored, beautified, documented :-) */
14 /*****************************************************************************/
15
16 #include <stddef.h>
17
18 #include "adpcm.h"
19
20 //-----------------------------------------------------------------------------
21 // Tables necessary dor decompression
22
23 static int NextStepTable[] =
24 {
25 -1, 0, -1, 4, -1, 2, -1, 6,
26 -1, 1, -1, 5, -1, 3, -1, 7,
27 -1, 1, -1, 5, -1, 3, -1, 7,
28 -1, 2, -1, 4, -1, 6, -1, 8
29 };
30
31 static int StepSizeTable[] =
32 {
33 7, 8, 9, 10, 11, 12, 13, 14,
34 16, 17, 19, 21, 23, 25, 28, 31,
35 34, 37, 41, 45, 50, 55, 60, 66,
36 73, 80, 88, 97, 107, 118, 130, 143,
37 157, 173, 190, 209, 230, 253, 279, 307,
38 337, 371, 408, 449, 494, 544, 598, 658,
39 724, 796, 876, 963, 1060, 1166, 1282, 1411,
40 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
41 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
42 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
43 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
44 32767
45 };
46
47 //-----------------------------------------------------------------------------
48 // Helper class for writing output ADPCM data
49
50 class TADPCMStream
51 {
52 public:
53
TADPCMStream(void * pvBuffer,size_t cbBuffer)54 TADPCMStream(void * pvBuffer, size_t cbBuffer)
55 {
56 pbBufferEnd = (unsigned char *)pvBuffer + cbBuffer;
57 pbBuffer = (unsigned char *)pvBuffer;
58 }
59
ReadByteSample(unsigned char & ByteSample)60 bool ReadByteSample(unsigned char & ByteSample)
61 {
62 // Check if there is enough space in the buffer
63 if(pbBuffer >= pbBufferEnd)
64 return false;
65
66 ByteSample = *pbBuffer++;
67 return true;
68 }
69
WriteByteSample(unsigned char ByteSample)70 bool WriteByteSample(unsigned char ByteSample)
71 {
72 // Check if there is enough space in the buffer
73 if(pbBuffer >= pbBufferEnd)
74 return false;
75
76 *pbBuffer++ = ByteSample;
77 return true;
78 }
79
ReadWordSample(short & OneSample)80 bool ReadWordSample(short & OneSample)
81 {
82 // Check if we have enough space in the output buffer
83 if((size_t)(pbBufferEnd - pbBuffer) < sizeof(short))
84 return false;
85
86 // Write the sample
87 OneSample = pbBuffer[0] + (((short)pbBuffer[1]) << 0x08);
88 pbBuffer += sizeof(short);
89 return true;
90 }
91
WriteWordSample(short OneSample)92 bool WriteWordSample(short OneSample)
93 {
94 // Check if we have enough space in the output buffer
95 if((size_t)(pbBufferEnd - pbBuffer) < sizeof(short))
96 return false;
97
98 // Write the sample
99 *pbBuffer++ = (unsigned char)(OneSample & 0xFF);
100 *pbBuffer++ = (unsigned char)(OneSample >> 0x08);
101 return true;
102 }
103
LengthProcessed(void * pvOutBuffer)104 int LengthProcessed(void * pvOutBuffer)
105 {
106 return (int)((unsigned char *)pbBuffer - (unsigned char *)pvOutBuffer);
107 }
108
109 unsigned char * pbBufferEnd;
110 unsigned char * pbBuffer;
111 };
112
113 //----------------------------------------------------------------------------
114 // Local functions
115
GetNextStepIndex(int StepIndex,unsigned int EncodedSample)116 static inline short GetNextStepIndex(int StepIndex, unsigned int EncodedSample)
117 {
118 // Get the next step index
119 StepIndex = StepIndex + NextStepTable[EncodedSample & 0x1F];
120
121 // Don't make the step index overflow
122 if(StepIndex < 0)
123 StepIndex = 0;
124 else if(StepIndex > 88)
125 StepIndex = 88;
126
127 return (short)StepIndex;
128 }
129
UpdatePredictedSample(int PredictedSample,int EncodedSample,int Difference)130 static inline int UpdatePredictedSample(int PredictedSample, int EncodedSample, int Difference)
131 {
132 // Is the sign bit set?
133 if(EncodedSample & 0x40)
134 {
135 PredictedSample -= Difference;
136 if(PredictedSample <= -32768)
137 PredictedSample = -32768;
138 }
139 else
140 {
141 PredictedSample += Difference;
142 if(PredictedSample >= 32767)
143 PredictedSample = 32767;
144 }
145
146 return PredictedSample;
147 }
148
DecodeSample(int PredictedSample,int EncodedSample,int StepSize,int Difference)149 static inline int DecodeSample(int PredictedSample, int EncodedSample, int StepSize, int Difference)
150 {
151 if(EncodedSample & 0x01)
152 Difference += (StepSize >> 0);
153
154 if(EncodedSample & 0x02)
155 Difference += (StepSize >> 1);
156
157 if(EncodedSample & 0x04)
158 Difference += (StepSize >> 2);
159
160 if(EncodedSample & 0x08)
161 Difference += (StepSize >> 3);
162
163 if(EncodedSample & 0x10)
164 Difference += (StepSize >> 4);
165
166 if(EncodedSample & 0x20)
167 Difference += (StepSize >> 5);
168
169 return UpdatePredictedSample(PredictedSample, EncodedSample, Difference);
170 }
171
172 //----------------------------------------------------------------------------
173 // Compression routine
174
CompressADPCM(void * pvOutBuffer,int cbOutBuffer,void * pvInBuffer,int cbInBuffer,int ChannelCount,int CompressionLevel)175 int CompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount, int CompressionLevel)
176 {
177 TADPCMStream os(pvOutBuffer, cbOutBuffer); // The output stream
178 TADPCMStream is(pvInBuffer, cbInBuffer); // The input stream
179 unsigned char BitShift = (unsigned char)(CompressionLevel - 1);
180 short PredictedSamples[MAX_ADPCM_CHANNEL_COUNT];// Predicted samples for each channel
181 short StepIndexes[MAX_ADPCM_CHANNEL_COUNT]; // Step indexes for each channel
182 short InputSample; // Input sample for the current channel
183 int TotalStepSize;
184 int ChannelIndex;
185 int AbsDifference;
186 int Difference;
187 int MaxBitMask;
188 int StepSize;
189
190 // _tprintf(_T("== CMPR Started ==============\n"));
191
192 // First byte in the output stream contains zero. The second one contains the compression level
193 os.WriteByteSample(0);
194 if(!os.WriteByteSample(BitShift))
195 return 2;
196
197 // Set the initial step index for each channel
198 PredictedSamples[0] = PredictedSamples[1] = 0;
199 StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
200
201 // Next, InitialSample value for each channel follows
202 for(int i = 0; i < ChannelCount; i++)
203 {
204 // Get the initial sample from the input stream
205 if(!is.ReadWordSample(InputSample))
206 return os.LengthProcessed(pvOutBuffer);
207
208 // Store the initial sample to our sample array
209 PredictedSamples[i] = InputSample;
210
211 // Also store the loaded sample to the output stream
212 if(!os.WriteWordSample(InputSample))
213 return os.LengthProcessed(pvOutBuffer);
214 }
215
216 // Get the initial index
217 ChannelIndex = ChannelCount - 1;
218
219 // Now keep reading the input data as long as there is something in the input buffer
220 while(is.ReadWordSample(InputSample))
221 {
222 int EncodedSample = 0;
223
224 // If we have two channels, we need to flip the channel index
225 ChannelIndex = (ChannelIndex + 1) % ChannelCount;
226
227 // Get the difference from the previous sample.
228 // If the difference is negative, set the sign bit to the encoded sample
229 AbsDifference = InputSample - PredictedSamples[ChannelIndex];
230 if(AbsDifference < 0)
231 {
232 AbsDifference = -AbsDifference;
233 EncodedSample |= 0x40;
234 }
235
236 // If the difference is too low (higher that difference treshold),
237 // write a step index modifier marker
238 StepSize = StepSizeTable[StepIndexes[ChannelIndex]];
239 if(AbsDifference < (StepSize >> CompressionLevel))
240 {
241 if(StepIndexes[ChannelIndex] != 0)
242 StepIndexes[ChannelIndex]--;
243
244 os.WriteByteSample(0x80);
245 }
246 else
247 {
248 // If the difference is too high, write marker that
249 // indicates increase in step size
250 while(AbsDifference > (StepSize << 1))
251 {
252 if(StepIndexes[ChannelIndex] >= 0x58)
253 break;
254
255 // Modify the step index
256 StepIndexes[ChannelIndex] += 8;
257 if(StepIndexes[ChannelIndex] > 0x58)
258 StepIndexes[ChannelIndex] = 0x58;
259
260 // Write the "modify step index" marker
261 StepSize = StepSizeTable[StepIndexes[ChannelIndex]];
262 os.WriteByteSample(0x81);
263 }
264
265 // Get the limit bit value
266 MaxBitMask = (1 << (BitShift - 1));
267 MaxBitMask = (MaxBitMask > 0x20) ? 0x20 : MaxBitMask;
268 Difference = StepSize >> BitShift;
269 TotalStepSize = 0;
270
271 for(int BitVal = 0x01; BitVal <= MaxBitMask; BitVal <<= 1)
272 {
273 if((TotalStepSize + StepSize) <= AbsDifference)
274 {
275 TotalStepSize += StepSize;
276 EncodedSample |= BitVal;
277 }
278 StepSize >>= 1;
279 }
280
281 PredictedSamples[ChannelIndex] = (short)UpdatePredictedSample(PredictedSamples[ChannelIndex],
282 EncodedSample,
283 Difference + TotalStepSize);
284 // Write the encoded sample to the output stream
285 if(!os.WriteByteSample((unsigned char)EncodedSample))
286 break;
287
288 // Calculates the step index to use for the next encode
289 StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndexes[ChannelIndex], EncodedSample);
290 }
291 }
292
293 // _tprintf(_T("== CMPR Ended ================\n"));
294 return os.LengthProcessed(pvOutBuffer);
295 }
296
297 //----------------------------------------------------------------------------
298 // Decompression routine
299
DecompressADPCM(void * pvOutBuffer,int cbOutBuffer,void * pvInBuffer,int cbInBuffer,int ChannelCount)300 int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount)
301 {
302 TADPCMStream os(pvOutBuffer, cbOutBuffer); // Output stream
303 TADPCMStream is(pvInBuffer, cbInBuffer); // Input stream
304 unsigned char EncodedSample;
305 unsigned char BitShift;
306 short PredictedSamples[MAX_ADPCM_CHANNEL_COUNT]; // Predicted sample for each channel
307 short StepIndexes[MAX_ADPCM_CHANNEL_COUNT]; // Predicted step index for each channel
308 int ChannelIndex; // Current channel index
309
310 // Initialize the StepIndex for each channel
311 PredictedSamples[0] = PredictedSamples[1] = 0;
312 StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX;
313
314 // _tprintf(_T("== DCMP Started ==============\n"));
315
316 // The first byte is always zero, the second one contains bit shift (compression level - 1)
317 is.ReadByteSample(BitShift);
318 is.ReadByteSample(BitShift);
319 // _tprintf(_T("DCMP: BitShift = %u\n"), (unsigned int)(unsigned char)BitShift);
320
321 // Next, InitialSample value for each channel follows
322 for(int i = 0; i < ChannelCount; i++)
323 {
324 // Get the initial sample from the input stream
325 short InitialSample;
326
327 // Attempt to read the initial sample
328 if(!is.ReadWordSample(InitialSample))
329 return os.LengthProcessed(pvOutBuffer);
330
331 // _tprintf(_T("DCMP: Loaded InitialSample[%u]: %04X\n"), i, (unsigned int)(unsigned short)InitialSample);
332
333 // Store the initial sample to our sample array
334 PredictedSamples[i] = InitialSample;
335
336 // Also store the loaded sample to the output stream
337 if(!os.WriteWordSample(InitialSample))
338 return os.LengthProcessed(pvOutBuffer);
339 }
340
341 // Get the initial index
342 ChannelIndex = ChannelCount - 1;
343
344 // Keep reading as long as there is something in the input buffer
345 while(is.ReadByteSample(EncodedSample))
346 {
347 // _tprintf(_T("DCMP: Loaded Encoded Sample: %02X\n"), (unsigned int)(unsigned char)EncodedSample);
348
349 // If we have two channels, we need to flip the channel index
350 ChannelIndex = (ChannelIndex + 1) % ChannelCount;
351
352 if(EncodedSample == 0x80)
353 {
354 if(StepIndexes[ChannelIndex] != 0)
355 StepIndexes[ChannelIndex]--;
356
357 // _tprintf(_T("DCMP: Writing Decoded Sample: %04lX\n"), (unsigned int)(unsigned short)PredictedSamples[ChannelIndex]);
358 if(!os.WriteWordSample(PredictedSamples[ChannelIndex]))
359 return os.LengthProcessed(pvOutBuffer);
360 }
361 else if(EncodedSample == 0x81)
362 {
363 // Modify the step index
364 StepIndexes[ChannelIndex] += 8;
365 if(StepIndexes[ChannelIndex] > 0x58)
366 StepIndexes[ChannelIndex] = 0x58;
367
368 // _tprintf(_T("DCMP: New value of StepIndex: %04lX\n"), (unsigned int)(unsigned short)StepIndexes[ChannelIndex]);
369
370 // Next pass, keep going on the same channel
371 ChannelIndex = (ChannelIndex + 1) % ChannelCount;
372 }
373 else
374 {
375 int StepIndex = StepIndexes[ChannelIndex];
376 int StepSize = StepSizeTable[StepIndex];
377
378 // Encode one sample
379 PredictedSamples[ChannelIndex] = (short)DecodeSample(PredictedSamples[ChannelIndex],
380 EncodedSample,
381 StepSize,
382 StepSize >> BitShift);
383
384 // _tprintf(_T("DCMP: Writing decoded sample: %04X\n"), (unsigned int)(unsigned short)PredictedSamples[ChannelIndex]);
385
386 // Write the decoded sample to the output stream
387 if(!os.WriteWordSample(PredictedSamples[ChannelIndex]))
388 break;
389
390 // Calculates the step index to use for the next encode
391 StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndex, EncodedSample);
392 // _tprintf(_T("DCMP: New step index: %04X\n"), (unsigned int)(unsigned short)StepIndexes[ChannelIndex]);
393 }
394 }
395
396 // _tprintf(_T("DCMP: Total length written: %u\n"), (unsigned int)os.LengthProcessed(pvOutBuffer));
397 // _tprintf(_T("== DCMP Ended ================\n"));
398
399 // Return total bytes written since beginning of the output buffer
400 return os.LengthProcessed(pvOutBuffer);
401 }
402