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