1 /***********************************************************
2 * Portions of this file are Copyright (c) Ryan C. Gordon
3 ***********************************************************/
6 * $Logfile: /Freespace2/code/Sound/ACM.cpp $
14 * Revision 1.6 2005/03/29 02:18:47 taylor
15 * Various 64-bit platform fixes
16 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
17 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
18 * Streaming audio support (big thanks to Pierre Willenbrock!!)
19 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
30 typedef struct adpcmcoef_tag{
35 typedef struct adpcmblockheader_tag {
42 typedef struct adpcmwaveformat_tag {
44 WORD wSamplesPerBlock;
49 typedef struct ADPCM_FMT_T {
50 ADPCMWAVEFORMAT adpcm;
51 ADPCMBLOCKHEADER *header;
56 uint sample_frame_size;
57 uint samples_left_in_block;
62 typedef struct acm_stream_t {
68 // similar to BIAL_IF_MACRO in SDL_sound
69 #define IF_ERR(a, b) if (a) { printf("IF_ERR-ACM, function: %s, line %d...\n", __FUNCTION__, __LINE__); return b; }
71 static int ACM_inited = 0;
74 /*****************************************************************************
75 * Begin ADPCM compression handler... */
78 * ADPCM decoding routines taken with permission from SDL_sound
79 * Copyright (C) 2001 Ryan C. Gordon.
82 #define FIXED_POINT_COEF_BASE 256
83 #define FIXED_POINT_ADAPTION_BASE 256
84 #define SMALLEST_ADPCM_DELTA 16
88 static int read_ushort(SDL_RWops *rw, ushort *i)
90 int rc = SDL_RWread(rw, i, sizeof(ushort), 1);
96 static int read_word(SDL_RWops *rw, WORD *i)
98 int rc = SDL_RWread(rw, i, sizeof(WORD), 1);
103 // same as read_word() but swapped
104 static int read_word_s(SDL_RWops *rw, WORD *i)
106 int rc = SDL_RWread(rw, i, sizeof(WORD), 1);
108 *i = INTEL_SHORT(*i);
112 static int read_short(SDL_RWops *rw, short *i)
114 int rc = SDL_RWread(rw, i, sizeof(short), 1);
116 *i = INTEL_SHORT(*i);
120 static int read_dword(SDL_RWops *rw, DWORD *i)
122 int rc = SDL_RWread(rw, i, sizeof(DWORD), 1);
127 static int read_ubyte(SDL_RWops *rw, ubyte *i)
129 int rc = SDL_RWread(rw, i, sizeof(ubyte), 1);
134 // decoding functions
135 static int read_adpcm_block_headers(SDL_RWops *rw, adpcm_fmt_t *fmt)
138 int max = fmt->adpcm.wav.nChannels;
140 if (fmt->bytes_remaining < fmt->adpcm.wav.nBlockAlign) {
144 fmt->bytes_remaining -= fmt->adpcm.wav.nBlockAlign;
145 fmt->bytes_processed += fmt->adpcm.wav.nBlockAlign;
147 for (i = 0; i < max; i++)
148 IF_ERR(!read_ubyte(rw, &fmt->header[i].bPredictor), 0);
150 for (i = 0; i < max; i++)
151 IF_ERR(!read_ushort(rw, &fmt->header[i].iDelta), 0);
153 for (i = 0; i < max; i++)
154 IF_ERR(!read_short(rw, &fmt->header[i].iSamp1), 0);
156 for (i = 0; i < max; i++)
157 IF_ERR(!read_short(rw, &fmt->header[i].iSamp2), 0);
159 fmt->samples_left_in_block = fmt->adpcm.wSamplesPerBlock;
160 fmt->nibble_state = 0;
165 static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp)
167 static const short max_audioval = ((1<<(16-1))-1);
168 static const short min_audioval = -(1<<(16-1));
169 static const ushort AdaptionTable[] = {
170 230, 230, 230, 230, 307, 409, 512, 614,
171 768, 614, 512, 409, 307, 230, 230, 230
178 lNewSamp = lPredSamp + (header->iDelta * (nib - 0x10));
180 lNewSamp = lPredSamp + (header->iDelta * nib);
184 if (lNewSamp < min_audioval) {
185 lNewSamp = min_audioval;
186 } else if (lNewSamp > max_audioval) {
187 lNewSamp = max_audioval;
190 delta = (header->iDelta * AdaptionTable[nib]) / FIXED_POINT_ADAPTION_BASE;
192 if (delta < SMALLEST_ADPCM_DELTA)
193 delta = SMALLEST_ADPCM_DELTA;
195 header->iDelta = delta;
196 header->iSamp2 = header->iSamp1;
197 header->iSamp1 = lNewSamp;
200 static int decode_adpcm_sample_frame(SDL_RWops *rw, adpcm_fmt_t *fmt)
203 int max = fmt->adpcm.wav.nChannels;
204 ubyte nib = fmt->nibble;
205 short iCoef1, iCoef2;
208 for (i = 0; i < max; i++) {
209 iCoef1 = fmt->adpcm.aCoef[fmt->header[i].bPredictor].iCoef1;
210 iCoef2 = fmt->adpcm.aCoef[fmt->header[i].bPredictor].iCoef2;
211 lPredSamp = ((fmt->header[i].iSamp1 * iCoef1) + (fmt->header[i].iSamp2 * iCoef2)) / FIXED_POINT_COEF_BASE;
213 if (fmt->nibble_state == 0) {
214 IF_ERR(!read_ubyte(rw, &nib), 0);
215 fmt->nibble_state = 1;
216 do_adpcm_nibble(nib >> 4, &fmt->header[i], lPredSamp);
218 fmt->nibble_state = 0;
219 do_adpcm_nibble(nib & 0x0F, &fmt->header[i], lPredSamp);
228 static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt)
230 short *buf = (short *)_buf;
233 for (i = 0; i < fmt->adpcm.wav.nChannels; i++)
234 *buf++ = fmt->header[i].iSamp1;
237 static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt)
239 short *buf = (short *)_buf;
242 for (i = 0; i < fmt->adpcm.wav.nChannels; i++)
243 *buf++ = fmt->header[i].iSamp2;
246 static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops *rw, adpcm_fmt_t *fmt)
250 while (bw < fmt->buffer_size) {
251 // write ongoing sample frame before reading more data...
252 switch (fmt->samples_left_in_block) {
253 case 0: // need to read a new block...
254 if (!read_adpcm_block_headers(rw, fmt))
257 // only write first sample frame for now.
258 put_adpcm_sample_frame2(data + bw, fmt);
259 fmt->samples_left_in_block--;
260 bw += fmt->sample_frame_size;
263 case 1: // output last sample frame of block...
264 put_adpcm_sample_frame1(data + bw, fmt);
265 fmt->samples_left_in_block--;
266 bw += fmt->sample_frame_size;
269 default: // output latest sample frame and read a new one...
270 put_adpcm_sample_frame1(data + bw, fmt);
271 fmt->samples_left_in_block--;
272 bw += fmt->sample_frame_size;
274 if (!decode_adpcm_sample_frame(rw, fmt))
282 /* End ADPCM Compression Handler *
283 *****************************************************************************/
285 static void adpcm_memory_free(adpcm_fmt_t *fmt)
287 if (fmt->adpcm.aCoef != NULL) {
288 free(fmt->adpcm.aCoef);
289 fmt->adpcm.aCoef = NULL;
292 if (fmt->header != NULL) {
303 // =============================================================================
304 // ACM_convert_ADPCM_to_PCM()
306 // Convert an ADPCM wave file to a PCM wave file using the Audio Compression Manager
308 // parameters: *pwfxSrc => address of WAVEFORMATEX structure describing the source wave
309 // *src => pointer to raw source wave data
310 // src_len => num bytes of source wave data
311 // **dest => pointer to pointer to dest buffer for wave data
312 // (mem is allocated in this function if *dest is NULL)
313 // max_dest_bytes => Maximum memory allocated to dest
314 // *dest_len => returns num bytes of wave data in converted form (OUTPUT PARAMETER)
315 // *src_bytes_used => returns num bytes of src actually used in the conversion
316 // dest_bps => bits per sample that data should be uncompressed to
318 // returns: 0 => success
319 // -1 => could not convert wav file
323 // 1. Storage for the decompressed audio will be allocated in this function if *dest in NULL.
324 // The caller is responsible for freeing this memory later.
326 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)
328 Assert( pwfxSrc != NULL );
329 Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM );
330 Assert( src != NULL );
331 Assert( src_len > 0 );
332 Assert( dest_len != NULL );
334 SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize);
335 SDL_RWops *rw = SDL_RWFromMem(src, src_len);
339 if ( ACM_inited == 0 ) {
345 // estimate size of uncompressed data
346 // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits
347 // compressed data has: channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample
348 new_size = ( src_len * dest_bps ) / pwfxSrc->wBitsPerSample;
349 new_size *= 2;//buffer must be large enough for all data
351 // DO NOT free() here, *estimated size*
352 if ( *dest == NULL ) {
353 *dest = (ubyte *)malloc(new_size);
355 IF_ERR(*dest == NULL, -1);
357 // memset(*dest, 0x80, new_size); // silence (for 8 bits/sample)
358 memset(*dest, 0x00, new_size); // silence (for 16 bits/sample)
361 adpcm_fmt_t *fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t));
362 IF_ERR(fmt == NULL, -1);
363 memset(fmt, '\0', sizeof(adpcm_fmt_t));
365 // wav header info (WAVEFORMATEX)
366 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), -1);
367 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nChannels), -1);
368 IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nSamplesPerSec), -1);
369 IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nAvgBytesPerSec), -1);
370 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nBlockAlign), -1);
371 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wBitsPerSample), -1);
372 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.cbSize), -1);
373 // adpcm specific header info
374 IF_ERR(!read_word_s(hdr, &fmt->adpcm.wSamplesPerBlock), -1);
375 IF_ERR(!read_word_s(hdr, &fmt->adpcm.wNumCoef), -1);
377 // allocate memory for COEF struct and fill it
378 fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef);
379 IF_ERR(fmt->adpcm.aCoef == NULL, -1);
381 for (int i=0; i<fmt->adpcm.wNumCoef; i++) {
382 IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1), -1);
383 IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2), -1);
386 // allocate memory for the ADPCM block header that's to be filled later
387 fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels);
388 IF_ERR(fmt->header == NULL, -1);
390 // buffer to estimated size since we have to process the whole thing at once
391 fmt->buffer_size = new_size;
392 fmt->bytes_remaining = src_len;
393 fmt->bytes_processed = 0;
395 // sanity check, should always be 4
396 if (fmt->adpcm.wav.wBitsPerSample != 4) {
397 adpcm_memory_free(fmt);
403 fmt->sample_frame_size = dest_bps/8*pwfxSrc->nChannels;
405 if ( !max_dest_bytes ) {
406 max_dest_bytes = new_size;
410 rc = read_sample_fmt_adpcm(*dest, rw, fmt);
412 // send back actual sizes
414 *src_bytes_used = fmt->bytes_processed;
417 adpcm_memory_free(fmt);
424 int ACM_stream_open(WAVEFORMATEX *pwfxSrc, WAVEFORMATEX *pwfxDest, void **stream, int dest_bps)
426 Assert( pwfxSrc != NULL );
427 Assert( pwfxSrc->wFormatTag == WAVE_FORMAT_ADPCM );
428 Assert( stream != NULL );
430 SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc, sizeof(WAVEFORMATEX) + pwfxSrc->cbSize);
433 if ( ACM_inited == 0 ) {
439 adpcm_fmt_t *fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t));
440 IF_ERR(fmt == NULL, -1);
441 memset(fmt, '\0', sizeof(adpcm_fmt_t));
443 // wav header info (WAVEFORMATEX)
444 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wFormatTag), -1);
445 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nChannels), -1);
446 IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nSamplesPerSec), -1);
447 IF_ERR(!read_dword(hdr, &fmt->adpcm.wav.nAvgBytesPerSec), -1);
448 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.nBlockAlign), -1);
449 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.wBitsPerSample), -1);
450 IF_ERR(!read_word(hdr, &fmt->adpcm.wav.cbSize), -1);
451 // adpcm specific header info
452 IF_ERR(!read_word_s(hdr, &fmt->adpcm.wSamplesPerBlock), -1);
453 IF_ERR(!read_word_s(hdr, &fmt->adpcm.wNumCoef), -1);
455 // allocate memory for COEF struct and fill it
456 fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef);
457 IF_ERR(fmt->adpcm.aCoef == NULL, -1);
459 for (int i=0; i<fmt->adpcm.wNumCoef; i++) {
460 IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1), -1);
461 IF_ERR(!read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2), -1);
464 // allocate memory for the ADPCM block header that's to be filled later
465 fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.nChannels);
466 IF_ERR(fmt->header == NULL, -1);
468 // sanity check, should always be 4
469 if (fmt->adpcm.wav.wBitsPerSample != 4) {
470 adpcm_memory_free(fmt);
475 fmt->sample_frame_size = dest_bps/8*pwfxSrc->nChannels;
477 acm_stream_t *str = (acm_stream_t *)malloc(sizeof(acm_stream_t));
478 IF_ERR(str == NULL, -1);
480 str->dest_bps = dest_bps;
481 str->src_bps = pwfxSrc->wBitsPerSample;
489 int ACM_stream_close(void *stream)
491 Assert(stream != NULL);
492 acm_stream_t *str = (acm_stream_t *)stream;
493 adpcm_memory_free(str->fmt);
499 * How many bytes are needed to get approximately dest_len bytes output?
501 int ACM_query_source_size(void *stream, int dest_len)
503 Assert(stream != NULL);
504 acm_stream_t *str = (acm_stream_t *)stream;
505 // estimate size of compressed data
506 // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits
507 // compressed data has: channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample
508 return (dest_len * str->src_bps) / str->dest_bps;
512 * How many output bytes would approximately be produced by src_len bytes input?
514 int ACM_query_dest_size(void *stream, int src_len)
516 Assert(stream != NULL);
517 acm_stream_t *str = (acm_stream_t *)stream;
518 // estimate size of uncompressed data
519 // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits
520 // compressed data has: channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample
521 return ( src_len * str->dest_bps ) / str->src_bps;
525 * We are allowed to use fewer bytes than delivered to us
527 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)
529 Assert(stream != NULL);
530 Assert( src != NULL );
531 Assert( src_len > 0 );
532 Assert( dest_len != NULL );
533 acm_stream_t *str = (acm_stream_t *)stream;
536 SDL_RWops *rw = SDL_RWFromMem(src, src_len);
538 // buffer to estimated size since we have to process the whole thing at once
539 str->fmt->buffer_size = max_dest_bytes;
540 str->fmt->bytes_remaining = src_len;
541 str->fmt->bytes_processed = 0;
544 rc = read_sample_fmt_adpcm(dest, rw, str->fmt);
546 // send back actual sizes
548 *src_bytes_used = str->fmt->bytes_processed;
555 // ACM_init() - decoding should always work
558 if ( ACM_inited == 1 )
569 if ( ACM_inited == 0 )
575 // Query if the ACM system is initialized