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