]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/acm.cpp
clean up stats saving a bit more
[taylor/freespace2.git] / src / sound / acm.cpp
1 /***********************************************************
2  * Portions of this file are Copyright (c) Ryan C. Gordon
3  ***********************************************************/
4  
5 /*
6  * $Logfile: /Freespace2/code/Sound/ACM.cpp $
7  * $Revision$
8  * $Date$
9  * $Author$
10  *
11  * ADPCM decoder
12  *
13  * $Log$
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
20  *
21  *
22  * $NoKeywords: $
23  */
24  
25  
26 #include "pstypes.h"
27 #include "acm.h"
28 #include "oal.h"
29
30
31 typedef struct adpcmcoef_tag{
32         short iCoef1;
33         short iCoef2;
34 } ADPCMCOEFSET;
35
36 typedef struct adpcmblockheader_tag {
37         ubyte bPredictor;
38         ushort iDelta;
39         short iSamp1;
40         short iSamp2;
41 } ADPCMBLOCKHEADER;
42
43 typedef struct adpcmwaveformat_tag {
44         WAVE_chunk wav;
45         ushort wSamplesPerBlock;
46         ushort wNumCoef;
47         ADPCMCOEFSET *aCoef;
48 } ADPCMWAVEFORMAT;
49
50 typedef struct ADPCM_FMT_T {
51         ADPCMWAVEFORMAT adpcm;
52         ADPCMBLOCKHEADER *header;
53
54         int bytes_remaining;
55         uint bytes_processed;
56         uint buffer_size;
57         uint sample_frame_size;
58         uint samples_left_in_block;
59         int nibble_state;
60         ubyte nibble;
61 } adpcm_fmt_t;
62
63 typedef struct acm_stream_t {
64         adpcm_fmt_t *fmt;
65         ushort dest_bps;
66         ushort src_bps;
67 } acm_stream_t;
68
69 // similar to BIAL_IF_MACRO in SDL_sound
70 #define IF_ERR(a, b) if (a) { printf("IF_ERR-ACM, function: %s, line %d...\n", __FUNCTION__, __LINE__); return b; }
71
72
73 /*****************************************************************************
74  * Begin ADPCM compression handler...                                       */
75
76 /*
77  * ADPCM decoding routines taken with permission from SDL_sound
78  * Copyright (C) 2001  Ryan C. Gordon.
79  */
80
81 #define FIXED_POINT_COEF_BASE      256
82 #define FIXED_POINT_ADAPTION_BASE  256
83 #define SMALLEST_ADPCM_DELTA       16
84
85
86 // utility functions
87 static int read_ushort(SDL_RWops *rw, ushort *i)
88 {
89         int rc = SDL_RWread(rw, i, sizeof(ushort), 1);
90         IF_ERR(rc != 1, 0);
91         *i = INTEL_SHORT(*i);
92         return 1;
93 }
94
95 static int read_short(SDL_RWops *rw, short *i)
96 {
97         int rc = SDL_RWread(rw, i, sizeof(short), 1);
98         IF_ERR(rc != 1, 0);
99         *i = INTEL_SHORT(*i);
100         return 1;
101 }
102
103 static int read_ubyte(SDL_RWops *rw, ubyte *i)
104 {
105         int rc = SDL_RWread(rw, i, sizeof(ubyte), 1);
106         IF_ERR(rc != 1, 0);
107         return 1;
108 }
109
110 // decoding functions
111 static int read_adpcm_block_headers(SDL_RWops *rw, adpcm_fmt_t *fmt)
112 {
113         int i;
114         int max = fmt->adpcm.wav.num_channels;
115
116         if (fmt->bytes_remaining < fmt->adpcm.wav.block_align) {
117                 return 0;
118         }
119
120         fmt->bytes_remaining -= fmt->adpcm.wav.block_align;
121         fmt->bytes_processed += fmt->adpcm.wav.block_align;
122
123         for (i = 0; i < max; i++)
124                 IF_ERR(!read_ubyte(rw, &fmt->header[i].bPredictor), 0);
125
126         for (i = 0; i < max; i++)
127                 IF_ERR(!read_ushort(rw, &fmt->header[i].iDelta), 0);
128
129         for (i = 0; i < max; i++)
130                 IF_ERR(!read_short(rw, &fmt->header[i].iSamp1), 0);
131
132         for (i = 0; i < max; i++)
133                 IF_ERR(!read_short(rw, &fmt->header[i].iSamp2), 0);
134         
135         fmt->samples_left_in_block = fmt->adpcm.wSamplesPerBlock;
136         fmt->nibble_state = 0;
137
138         return 1;
139 }
140
141 static void do_adpcm_nibble(ubyte nib, ADPCMBLOCKHEADER *header, int lPredSamp)
142 {
143         static const short max_audioval = ((1<<(16-1))-1);
144         static const short min_audioval = -(1<<(16-1));
145         static const ushort AdaptionTable[] = {
146                 230, 230, 230, 230, 307, 409, 512, 614,
147                 768, 614, 512, 409, 307, 230, 230, 230
148         };
149
150         int lNewSamp;
151         ushort delta;
152
153         if (nib & 0x08) {
154                 lNewSamp = lPredSamp + (header->iDelta * (nib - 0x10));
155         } else {
156                 lNewSamp = lPredSamp + (header->iDelta * nib);
157         }
158
159         // clamp value...
160         if (lNewSamp < min_audioval) {
161                 lNewSamp = min_audioval;
162         } else if (lNewSamp > max_audioval) {
163                 lNewSamp = max_audioval;
164         }
165
166         delta = (header->iDelta * AdaptionTable[nib]) / FIXED_POINT_ADAPTION_BASE;
167
168         if (delta < SMALLEST_ADPCM_DELTA)
169                 delta = SMALLEST_ADPCM_DELTA;
170
171         header->iDelta = delta;
172         header->iSamp2 = header->iSamp1;
173         header->iSamp1 = (short)lNewSamp;
174 }
175
176 static int decode_adpcm_sample_frame(SDL_RWops *rw, adpcm_fmt_t *fmt)
177 {
178         int i;
179         int max = fmt->adpcm.wav.num_channels;
180         ubyte nib = fmt->nibble;
181         short iCoef1, iCoef2;
182         int lPredSamp;
183
184         for (i = 0; i < max; i++) {
185                 iCoef1 = fmt->adpcm.aCoef[fmt->header[i].bPredictor].iCoef1;
186                 iCoef2 = fmt->adpcm.aCoef[fmt->header[i].bPredictor].iCoef2;
187                 lPredSamp = ((fmt->header[i].iSamp1 * iCoef1) + (fmt->header[i].iSamp2 * iCoef2)) / FIXED_POINT_COEF_BASE;
188
189                 if (fmt->nibble_state == 0) {
190                         IF_ERR(!read_ubyte(rw, &nib), 0);
191                         fmt->nibble_state = 1;
192                         do_adpcm_nibble(nib >> 4, &fmt->header[i], lPredSamp);
193                 } else {
194                         fmt->nibble_state = 0;
195                         do_adpcm_nibble(nib & 0x0F, &fmt->header[i], lPredSamp);
196                 }
197         }
198
199         fmt->nibble = nib;
200
201         return 1;
202 }
203
204 static void put_adpcm_sample_frame1(ubyte *_buf, adpcm_fmt_t *fmt)
205 {
206         short *buf = (short *)_buf;
207         int i;
208         
209         for (i = 0; i < fmt->adpcm.wav.num_channels; i++)
210                 *buf++ = fmt->header[i].iSamp1;
211 }
212
213 static void put_adpcm_sample_frame2(ubyte *_buf, adpcm_fmt_t *fmt)
214 {
215         short *buf = (short *)_buf;
216         int i;
217
218         for (i = 0; i < fmt->adpcm.wav.num_channels; i++)
219                 *buf++ = fmt->header[i].iSamp2;
220 }
221
222 static uint read_sample_fmt_adpcm(ubyte *data, SDL_RWops *rw, adpcm_fmt_t *fmt)
223 {
224         uint bw = 0;
225
226         while (bw < fmt->buffer_size) {
227                 // write ongoing sample frame before reading more data...
228                 switch (fmt->samples_left_in_block) {
229                         case 0:  // need to read a new block...
230                                 if (!read_adpcm_block_headers(rw, fmt))
231                                         return(bw);             // EOF
232
233                                 // only write first sample frame for now.
234                                 put_adpcm_sample_frame2(data + bw, fmt);
235                                 fmt->samples_left_in_block--;
236                                 bw += fmt->sample_frame_size;
237                                 break;
238
239                         case 1:  // output last sample frame of block...
240                                 put_adpcm_sample_frame1(data + bw, fmt);
241                                 fmt->samples_left_in_block--;
242                                 bw += fmt->sample_frame_size;
243                                 break;
244
245                         default: // output latest sample frame and read a new one...
246                                 put_adpcm_sample_frame1(data + bw, fmt);
247                                 fmt->samples_left_in_block--;
248                                 bw += fmt->sample_frame_size;
249
250                                 if (!decode_adpcm_sample_frame(rw, fmt))
251                                         return(bw);
252                 }
253         }
254
255         return(bw);
256 }
257
258 /* End ADPCM Compression Handler                                              *
259  *****************************************************************************/
260
261 static void adpcm_memory_free(adpcm_fmt_t *fmt)
262 {
263         SDL_assert( fmt != NULL );
264
265         if (fmt->adpcm.aCoef != NULL) {
266                 free(fmt->adpcm.aCoef);
267                 fmt->adpcm.aCoef = NULL;
268         }
269         
270         if (fmt->header != NULL) {
271                 free(fmt->header);
272                 fmt->header = NULL;
273         }
274
275         free(fmt);
276 }
277
278 // =============================================================================
279 // ACM_convert_ADPCM_to_PCM()
280 //
281 // Convert an ADPCM wave file to a PCM wave file using the Audio Compression Manager
282 //
283 // parameters:  *pwfxSrc   => address of WAVE_chunk structure describing the source wave
284 //                              *src       => pointer to raw source wave data
285 //                              src_len    => num bytes of source wave data
286 //                              **dest     => pointer to pointer to dest buffer for wave data
287 //                                                        (mem is allocated in this function if *dest is NULL)
288 //                              max_dest_bytes   => Maximum memory allocated to dest
289 //                              *dest_len        => returns num bytes of wave data in converted form (OUTPUT PARAMETER)
290 //                              *src_bytes_used  =>     returns num bytes of src actually used in the conversion
291 //                              dest_bps         => bits per sample that data should be uncompressed to
292 //
293 // returns:        0 => success
294 //                         -1 => could not convert wav file
295 //
296 //
297 // NOTES:
298 // 1. Storage for the decompressed audio will be allocated in this function if *dest in NULL.
299 //    The caller is responsible for freeing this memory later.
300 //
301 int ACM_convert_ADPCM_to_PCM(WAVE_chunk *pwfxSrc, ubyte *src, int src_len, ubyte **dest, int *dest_len, unsigned int *src_bytes_used, unsigned short dest_bps)
302 {
303         SDL_assert( pwfxSrc != NULL );
304         SDL_assert( pwfxSrc->code == WAVE_FORMAT_ADPCM );
305         SDL_assert( pwfxSrc->extra_data != NULL );
306         SDL_assert( src != NULL );
307         SDL_assert( src_len > 0 );
308         SDL_assert( dest_len != NULL );
309
310         uint rc;
311         uint new_size = 0;
312
313         SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc->extra_data, pwfxSrc->extra_size);
314         SDL_RWops *rw = SDL_RWFromMem(src, src_len);
315
316         adpcm_fmt_t *fmt = NULL;
317
318         // estimate size of uncompressed data
319         // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits
320         // compressed data has:   channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample
321         new_size = ( src_len * dest_bps ) / pwfxSrc->bits_per_sample;
322         new_size *= 2;//buffer must be large enough for all data
323
324         // DO NOT free() here, *estimated size*
325         if ( *dest == NULL ) {
326                 *dest = (ubyte *)malloc(new_size);
327
328                 if (*dest == NULL) {
329                         goto Fail;
330                 }
331
332 //              memset(*dest, 0x80, new_size);  // silence (for 8 bits/sample)
333                 memset(*dest, 0x00, new_size);  // silence (for 16 bits/sample)
334         }
335
336         fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t));
337
338         if (fmt == NULL) {
339                 goto Fail;
340         }
341
342         memset(fmt, '\0', sizeof(adpcm_fmt_t));
343
344         // wav header info (WAVE_chunk)
345         fmt->adpcm.wav.code = pwfxSrc->code;
346         fmt->adpcm.wav.num_channels = pwfxSrc->num_channels;
347         fmt->adpcm.wav.sample_rate = pwfxSrc->sample_rate;
348         fmt->adpcm.wav.bytes_per_second = pwfxSrc->bytes_per_second;
349         fmt->adpcm.wav.block_align = pwfxSrc->block_align;
350         fmt->adpcm.wav.bits_per_sample = pwfxSrc->bits_per_sample;
351
352         // sanity check, should always be 4
353         if (fmt->adpcm.wav.bits_per_sample != 4) {
354                 goto Fail;
355         }
356
357         // adpcm specific header info
358         if ( !read_ushort(hdr, &fmt->adpcm.wSamplesPerBlock) ) {
359                 goto Fail;
360         }
361
362         if ( !read_ushort(hdr, &fmt->adpcm.wNumCoef) ) {
363                 goto Fail;
364         }
365
366         // allocate memory for COEF struct and fill it
367         fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef);
368
369         if (fmt->adpcm.aCoef == NULL) {
370                 goto Fail;
371         }
372
373         for (int i=0; i<fmt->adpcm.wNumCoef; i++) {
374                 if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1) ) {
375                         goto Fail;
376                 }
377
378                 if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2) ) {
379                         goto Fail;
380                 }
381         }
382
383         // allocate memory for the ADPCM block header that's to be filled later
384         fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.num_channels);
385
386         if (fmt->header == NULL) {
387                 goto Fail;
388         }
389
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;
394
395         fmt->sample_frame_size = dest_bps/8*pwfxSrc->num_channels;
396
397         // convert to PCM
398         rc = read_sample_fmt_adpcm(*dest, rw, fmt);
399
400         if (rc == 0) {
401                 goto Fail;
402         }
403
404         // send back actual sizes
405         *dest_len = rc;
406         *src_bytes_used = fmt->bytes_processed;
407
408         // cleanup
409         adpcm_memory_free(fmt);
410         SDL_RWclose(hdr);
411         SDL_RWclose(rw);
412
413         return 0;
414
415 Fail:
416         if (fmt) {
417                 adpcm_memory_free(fmt);
418         }
419
420         SDL_RWclose(hdr);
421         SDL_RWclose(rw);
422
423         return -1;
424 }
425
426 int ACM_stream_open(WAVE_chunk *pwfxSrc, WAVE_chunk *pwfxDest, void **stream, int dest_bps)
427 {
428         SDL_assert( pwfxSrc != NULL );
429         SDL_assert( pwfxSrc->code == WAVE_FORMAT_ADPCM );
430         SDL_assert( pwfxSrc->extra_data != NULL );
431         SDL_assert( stream != NULL );
432
433         SDL_RWops *hdr = SDL_RWFromMem(pwfxSrc->extra_data, pwfxSrc->extra_size);
434         acm_stream_t *str = NULL;
435
436         adpcm_fmt_t *fmt = (adpcm_fmt_t *)malloc(sizeof(adpcm_fmt_t));
437
438         if (fmt == NULL) {
439                 goto Fail;
440         }
441
442         memset(fmt, '\0', sizeof(adpcm_fmt_t));
443
444         // wav header info (WAVE_chunk)
445         fmt->adpcm.wav.code = pwfxSrc->code;
446         fmt->adpcm.wav.num_channels = pwfxSrc->num_channels;
447         fmt->adpcm.wav.sample_rate = pwfxSrc->sample_rate;
448         fmt->adpcm.wav.bytes_per_second = pwfxSrc->bytes_per_second;
449         fmt->adpcm.wav.block_align = pwfxSrc->block_align;
450         fmt->adpcm.wav.bits_per_sample = pwfxSrc->bits_per_sample;
451
452         // sanity check, should always be 4
453         if (fmt->adpcm.wav.bits_per_sample != 4) {
454                 goto Fail;
455         }
456
457         // adpcm specific header info
458         if ( !read_ushort(hdr, &fmt->adpcm.wSamplesPerBlock) ) {
459                 goto Fail;
460         }
461
462         if ( !read_ushort(hdr, &fmt->adpcm.wNumCoef) ) {
463                 goto Fail;
464         }
465
466         // allocate memory for COEF struct and fill it
467         fmt->adpcm.aCoef = (ADPCMCOEFSET *)malloc(sizeof(ADPCMCOEFSET) * fmt->adpcm.wNumCoef);
468
469         if (fmt->adpcm.aCoef == NULL) {
470                 goto Fail;
471         }
472
473         for (int i=0; i<fmt->adpcm.wNumCoef; i++) {
474                 if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef1) ) {
475                         goto Fail;
476                 }
477
478                 if ( !read_short(hdr, &fmt->adpcm.aCoef[i].iCoef2) ) {
479                         goto Fail;
480                 }
481         }
482
483         // allocate memory for the ADPCM block header that's to be filled later
484         fmt->header = (ADPCMBLOCKHEADER *)malloc(sizeof(ADPCMBLOCKHEADER) * fmt->adpcm.wav.num_channels);
485
486         if (fmt->header == NULL) {
487                 goto Fail;
488         }
489
490         fmt->sample_frame_size = dest_bps/8*pwfxSrc->num_channels;
491         
492         str = (acm_stream_t *)malloc(sizeof(acm_stream_t));
493
494         if (str == NULL) {
495                 goto Fail;
496         }
497
498         str->fmt = fmt;
499         str->dest_bps = (ushort)dest_bps;
500         str->src_bps = pwfxSrc->bits_per_sample;
501         *stream = str;
502
503         SDL_RWclose(hdr);
504
505         return 0;
506
507 Fail:
508         if (fmt) {
509                 adpcm_memory_free(fmt);
510         }
511
512         SDL_RWclose(hdr);
513
514         return -1;
515 }
516
517 int ACM_stream_close(void *stream)
518 {
519         SDL_assert(stream != NULL);
520
521         acm_stream_t *str = (acm_stream_t *)stream;
522
523         adpcm_memory_free(str->fmt);
524         free(str);
525
526         return 0;
527 }
528
529 /*
530  * How many bytes are needed to get approximately dest_len bytes output?
531  */
532 int ACM_query_source_size(void *stream, int dest_len)
533 {
534         SDL_assert(stream != NULL);
535
536         acm_stream_t *str = (acm_stream_t *)stream;
537
538         // estimate size of compressed data
539         // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits
540         // compressed data has:   channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample
541         return (dest_len * str->src_bps) / str->dest_bps;
542 }
543
544 /*
545  * How many output bytes would approximately be produced by src_len bytes input?
546  */
547 int ACM_query_dest_size(void *stream, int src_len)
548 {
549         SDL_assert(stream != NULL);
550
551         acm_stream_t *str = (acm_stream_t *)stream;
552
553         // estimate size of uncompressed data
554         // uncompressed data has: channels=pfwxScr->nChannels, bitPerSample=destbits
555         // compressed data has:   channels=pfwxScr->nChannels, bitPerSample=pwfxSrc->wBitsPerSample
556         return ( src_len * str->dest_bps ) / str->src_bps;
557 }
558
559 /*
560  * We are allowed to use fewer bytes than delivered to us
561  */
562 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)
563 {
564         SDL_assert(stream != NULL);
565         SDL_assert( src != NULL );
566         SDL_assert( src_len > 0 );
567         SDL_assert( dest_len != NULL );
568
569         acm_stream_t *str = (acm_stream_t *)stream;
570         uint rc;
571
572         SDL_RWops *rw = SDL_RWFromMem(src, src_len);
573
574         // buffer to estimated size since we have to process the whole thing at once
575         str->fmt->buffer_size = max_dest_bytes;
576         str->fmt->bytes_remaining = src_len;
577         str->fmt->bytes_processed = 0;
578
579         // convert to PCM
580         rc = read_sample_fmt_adpcm(dest, rw, str->fmt);
581
582         // send back actual sizes
583         *dest_len = rc;
584         *src_bytes_used = str->fmt->bytes_processed;
585
586         SDL_RWclose(rw);
587
588         return 0;
589 }