1 /***********************************************************
2 * Portions of this file are Copyright (c) Ryan C. Gordon
3 ***********************************************************/
9 typedef struct adpcmcoef_tag{
14 typedef struct adpcmblockheader_tag {
21 typedef struct adpcmwaveformat_tag {
23 WORD wSamplesPerBlock;
28 typedef struct ADPCM_FMT_T {
29 ADPCMWAVEFORMAT adpcm;
30 ADPCMBLOCKHEADER *header;
35 uint sample_frame_size;
36 uint samples_left_in_block;
42 // similar to BIAL_IF_MACRO in SDL_sound
43 #define IF_ERR(a, b) if (a) { printf("IF_ERR-ACM, function: %s, line %d...\n", __FUNCTION__, __LINE__); return b; }
45 static int ACM_inited = 0;
48 /*****************************************************************************
49 * Begin ADPCM compression handler... */
52 * ADPCM decoding routines taken with permission from SDL_sound
53 * Copyright (C) 2001 Ryan C. Gordon.
56 #define FIXED_POINT_COEF_BASE 256
57 #define FIXED_POINT_ADAPTION_BASE 256
58 #define SMALLEST_ADPCM_DELTA 16
62 static int read_ushort(SDL_RWops *rw, ushort *i)
64 int rc = SDL_RWread(rw, i, sizeof(ushort), 1);
70 static int read_word(SDL_RWops *rw, WORD *i)
72 int rc = SDL_RWread(rw, i, sizeof(WORD), 1);
77 // same as read_word() but swapped
78 static int read_word_s(SDL_RWops *rw, WORD *i)
80 int rc = SDL_RWread(rw, i, sizeof(WORD), 1);
86 static int read_short(SDL_RWops *rw, short *i)
88 int rc = SDL_RWread(rw, i, sizeof(short), 1);
94 static int read_dword(SDL_RWops *rw, DWORD *i)
96 int rc = SDL_RWread(rw, i, sizeof(DWORD), 1);
101 static int read_ubyte(SDL_RWops *rw, ubyte *i)
103 int rc = SDL_RWread(rw, i, sizeof(ubyte), 1);
108 // decoding functions
109 static int read_adpcm_block_headers(SDL_RWops *rw, adpcm_fmt_t *fmt)
112 int max = fmt->adpcm.wav.nChannels;
114 if (fmt->bytes_remaining < fmt->adpcm.wav.nBlockAlign) {
118 fmt->bytes_remaining -= fmt->adpcm.wav.nBlockAlign;
119 fmt->bytes_processed += fmt->adpcm.wav.nBlockAlign;
121 for (i = 0; i < max; i++)
122 IF_ERR(!read_ubyte(rw, &fmt->header[i].bPredictor), 0);
124 for (i = 0; i < max; i++)
125 IF_ERR(!read_ushort(rw, &fmt->header[i].iDelta), 0);
127 for (i = 0; i < max; i++)
128 IF_ERR(!read_short(rw, &fmt->header[i].iSamp1), 0);
130 for (i = 0; i < max; i++)
131 IF_ERR(!read_short(rw, &fmt->header[i].iSamp2), 0);
133 fmt->samples_left_in_block = fmt->adpcm.wSamplesPerBlock;
134 fmt->nibble_state = 0;
139 static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp)
141 static const short max_audioval = ((1<<(16-1))-1);
142 static const short min_audioval = -(1<<(16-1));
143 static const ushort AdaptionTable[] = {
144 230, 230, 230, 230, 307, 409, 512, 614,
145 768, 614, 512, 409, 307, 230, 230, 230
152 lNewSamp = lPredSamp + (header->iDelta * (nib - 0x10));
154 lNewSamp = lPredSamp + (header->iDelta * nib);
158 if (lNewSamp < min_audioval) {
159 lNewSamp = min_audioval;
160 } else if (lNewSamp > max_audioval) {
161 lNewSamp = max_audioval;
164 delta = (header->iDelta * AdaptionTable[nib]) / FIXED_POINT_ADAPTION_BASE;
166 if (delta < SMALLEST_ADPCM_DELTA)
167 delta = SMALLEST_ADPCM_DELTA;
169 header->iDelta = delta;
170 header->iSamp2 = header->iSamp1;
171 header->iSamp1 = lNewSamp;
174 static int decode_adpcm_sample_frame(SDL_RWops *rw, adpcm_fmt_t *fmt)
177 int max = fmt->adpcm.wav.nChannels;
178 ubyte nib = fmt->nibble;
179 short iCoef1, iCoef2;
182 for (i = 0; i < max; i++) {
183 iCoef1 = fmt->adpcm.aCoef[fmt->header[i].bPredictor].iCoef1;
184 iCoef2 = fmt->adpcm.aCoef[fmt->header[i].bPredictor].iCoef2;
185 lPredSamp = ((fmt->header[i].iSamp1 * iCoef1) + (fmt->header[i].iSamp2 * iCoef2)) / FIXED_POINT_COEF_BASE;
187 if (fmt->nibble_state == 0) {
188 IF_ERR(!read_ubyte(rw, &nib), 0);
189 fmt->nibble_state = 1;
190 do_adpcm_nibble(nib >> 4, &fmt->header[i], lPredSamp);
192 fmt->nibble_state = 0;
193 do_adpcm_nibble(nib & 0x0F, &fmt->header[i], lPredSamp);
202 static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt)
204 short *buf = (short *)_buf;
207 for (i = 0; i < fmt->adpcm.wav.nChannels; i++)
208 *buf++ = fmt->header[i].iSamp1;
211 static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt)
213 short *buf = (short *)_buf;
216 for (i = 0; i < fmt->adpcm.wav.nChannels; i++)
217 *buf++ = fmt->header[i].iSamp2;
220 static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops *rw, adpcm_fmt_t *fmt)
224 while (bw < fmt->buffer_size) {
225 // write ongoing sample frame before reading more data...
226 switch (fmt->samples_left_in_block) {
227 case 0: // need to read a new block...
228 if (!read_adpcm_block_headers(rw, fmt))
231 // only write first sample frame for now.
232 put_adpcm_sample_frame2(data + bw, fmt);
233 fmt->samples_left_in_block--;
234 bw += fmt->sample_frame_size;
237 case 1: // output last sample frame of block...
238 put_adpcm_sample_frame1(data + bw, fmt);
239 fmt->samples_left_in_block--;
240 bw += fmt->sample_frame_size;
243 default: // output latest sample frame and read a new one...
244 put_adpcm_sample_frame1(data + bw, fmt);
245 fmt->samples_left_in_block--;
246 bw += fmt->sample_frame_size;
248 if (!decode_adpcm_sample_frame(rw, fmt))
256 /* End ADPCM Compression Handler *
257 *****************************************************************************/
259 static void adpcm_memory_free(adpcm_fmt_t *fmt)
261 if (fmt->adpcm.aCoef != NULL) {
262 free(fmt->adpcm.aCoef);
263 fmt->adpcm.aCoef = NULL;
266 if (fmt->header != NULL) {
277 // =============================================================================
278 // ACM_convert_ADPCM_to_PCM()
280 // Convert an ADPCM wave file to a PCM wave file using the Audio Compression Manager
282 // parameters: *pwfxSrc => address of WAVEFORMATEX structure describing the source wave
283 // *src => pointer to raw source wave data
284 // src_len => num bytes of source wave data
285 // **dest => pointer to pointer to dest buffer for wave data
286 // (mem is allocated in this function if *dest is NULL)
287 // max_dest_bytes => Maximum memory allocated to dest
288 // *dest_len => returns num bytes of wave data in converted form (OUTPUT PARAMETER)
289 // *src_bytes_used => returns num bytes of src actually used in the conversion
290 // dest_bps => bits per sample that data should be uncompressed to
292 // returns: 0 => success
293 // -1 => could not convert wav file
297 // 1. Storage for the decompressed audio will be allocated in this function if *dest in NULL.
298 // The caller is responsible for freeing this memory later.
300 int ACM_convert_ADPCM_to_PCM(WAVEFORMATEX *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int max_dest_bytes, int *dest_len, unsigned int *src_bytes_used, unsigned short dest_bps)
302 Assert( pwfxSrc != NULL );
303 Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM );
304 Assert( src != NULL );
305 Assert( src_len > 0 );
306 Assert( dest_len != NULL );
308 SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize);
309 SDL_RWops *rw = SDL_RWFromMem(src, src_len);
313 if ( ACM_inited == 0 ) {
319 // estimate size of uncompressed data
320 new_size = src_len * ( (dest_bps * pwfxSrc->nChannels * pwfxSrc->wBitsPerSample) / 8 );
322 // DO NOT free() here, *estimated size*
323 if ( *dest == NULL ) {
324 *dest = (ubyte *)malloc(new_size);
326 IF_ERR(*dest == NULL, -1);
328 memset(*dest, 0x80, new_size); // silence (for 8 bits/sec)
331 adpcm_fmt_t *fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t));
332 IF_ERR(fmt == NULL, -1);
333 memset(fmt, '\0', sizeof(adpcm_fmt_t));
335 // wav header info (WAVEFORMATEX)
336 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), -1);
337 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nChannels), -1);
338 IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nSamplesPerSec), -1);
339 IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nAvgBytesPerSec), -1);
340 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nBlockAlign), -1);
341 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wBitsPerSample), -1);
342 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.cbSize), -1);
343 // adpcm specific header info
344 IF_ERR(!read_word_s(hdr, &fmt->adpcm.wSamplesPerBlock), -1);
345 IF_ERR(!read_word_s(hdr, &fmt->adpcm.wNumCoef), -1);
347 // allocate memory for COEF struct and fill it
348 fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef);
349 IF_ERR(fmt->adpcm.aCoef == NULL, -1);
351 for (int i=0; i<fmt->adpcm.wNumCoef; i++) {
352 IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1), -1);
353 IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2), -1);
356 // allocate memory for the ADPCM block header that's to be filled later
357 fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels);
358 IF_ERR(fmt->header == NULL, -1);
360 // buffer to estimated size since we have to process the whole thing at once
361 fmt->buffer_size = new_size;
362 fmt->bytes_remaining = src_len;
363 fmt->bytes_processed = 0;
365 // sanity check, should always be 4
366 if (fmt->adpcm.wav.wBitsPerSample != 4) {
367 adpcm_memory_free(fmt);
371 fmt->sample_frame_size = 2;
373 if ( !max_dest_bytes ) {
374 max_dest_bytes = new_size;
378 rc = read_sample_fmt_adpcm(*dest, rw, fmt);
380 // send back actual sizes
382 *src_bytes_used = fmt->bytes_processed;
385 adpcm_memory_free(fmt);
390 int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream, int dest_bps)
395 int ACM_stream_close(void *stream)
400 int ACM_query_source_size(void *stream, int dest_len)
405 int ACM_query_dest_size(void *stream, int src_len)
410 int ACM_convert(void *stream, ubyte *src, int src_len, ubyte *dest, int max_dest_bytes, unsigned int *dest_len, unsigned int *src_bytes_used)
415 // ACM_init() - decoding should always work
418 if ( ACM_inited == 1 )
429 if ( ACM_inited == 0 )
435 // Query if the ACM system is initialized