comparison decoders/wav.c @ 183:26996236d790

Updated comments to reflect change from LICENSE to COPYING file, and put a good chunk of the ADPCM decoder in place. Does NOT work, is NOT complete, but is more than halfway there.
author Ryan C. Gordon <icculus@icculus.org>
date Wed, 26 Dec 2001 10:39:16 +0000
parents bdbe09014724
children 6bb68b3bdcf1
comparison
equal deleted inserted replaced
182:3849438b735e 183:26996236d790
21 * WAV decoder for SDL_sound. 21 * WAV decoder for SDL_sound.
22 * 22 *
23 * This driver handles Microsoft .WAVs, in as many of the thousands of 23 * This driver handles Microsoft .WAVs, in as many of the thousands of
24 * variations as we can. 24 * variations as we can.
25 * 25 *
26 * Please see the file LICENSE in the source's root directory. 26 * Please see the file COPYING in the source's root directory.
27 * 27 *
28 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org) 28 * This file written by Ryan C. Gordon. (icculus@clutteredmind.org)
29 */ 29 */
30 30
31 #if HAVE_CONFIG_H 31 #if HAVE_CONFIG_H
66 WAV_close, /* close() method */ 66 WAV_close, /* close() method */
67 WAV_read /* read() method */ 67 WAV_read /* read() method */
68 }; 68 };
69 69
70 70
71 /* Better than SDL_ReadLE16, since you can detect i/o errors... */
72 static inline int read_le16(SDL_RWops *rw, Uint16 *ui16)
73 {
74 int rc = SDL_RWread(rw, ui16, sizeof (Uint16), 1);
75 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
76 *ui16 = SDL_SwapLE16(*ui16);
77 return(1);
78 } /* read_le16 */
79
80
81 /* Better than SDL_ReadLE32, since you can detect i/o errors... */
82 static inline int read_le32(SDL_RWops *rw, Uint32 *ui32)
83 {
84 int rc = SDL_RWread(rw, ui32, sizeof (Uint32), 1);
85 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
86 *ui32 = SDL_SwapLE32(*ui32);
87 return(1);
88 } /* read_le32 */
89
90
91 /* This is just cleaner on the caller's end... */
92 static inline int read_uint8(SDL_RWops *rw, Uint8 *ui8)
93 {
94 int rc = SDL_RWread(rw, ui8, sizeof (Uint8), 1);
95 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
96 return(1);
97 } /* read_uint8 */
98
99
71 /* Chunk management code... */ 100 /* Chunk management code... */
72 101
73 #define riffID 0x46464952 /* "RIFF", in ascii. */ 102 #define riffID 0x46464952 /* "RIFF", in ascii. */
74 #define waveID 0x45564157 /* "WAVE", in ascii. */ 103 #define waveID 0x45564157 /* "WAVE", in ascii. */
75 104
81 #define fmtID 0x20746D66 /* "fmt ", in ascii. */ 110 #define fmtID 0x20746D66 /* "fmt ", in ascii. */
82 111
83 #define FMT_NORMAL 0x0001 /* Uncompressed waveform data. */ 112 #define FMT_NORMAL 0x0001 /* Uncompressed waveform data. */
84 #define FMT_ADPCM 0x0002 /* ADPCM compressed waveform data. */ 113 #define FMT_ADPCM 0x0002 /* ADPCM compressed waveform data. */
85 114
86 typedef struct { 115 typedef struct
116 {
87 Uint16 iCoef1; 117 Uint16 iCoef1;
88 Uint16 iCoef2; 118 Uint16 iCoef2;
89 } ADPCMCOEFSET; 119 } ADPCMCOEFSET;
120
121 typedef struct
122 {
123 Uint8 bPredictor;
124 Uint16 iDelta;
125 Sint16 iSamp1;
126 Sint16 iSamp2;
127 } ADPCMBLOCKHEADER;
90 128
91 typedef struct S_WAV_FMT_T 129 typedef struct S_WAV_FMT_T
92 { 130 {
93 Uint32 chunkID; 131 Uint32 chunkID;
94 Sint32 chunkSize; 132 Sint32 chunkSize;
98 Uint32 dwAvgBytesPerSec; 136 Uint32 dwAvgBytesPerSec;
99 Uint16 wBlockAlign; 137 Uint16 wBlockAlign;
100 Uint16 wBitsPerSample; 138 Uint16 wBitsPerSample;
101 139
102 void (*free)(struct S_WAV_FMT_T *fmt); 140 void (*free)(struct S_WAV_FMT_T *fmt);
103 Uint32(*read_sample)(Sound_Sample *sample); 141 Uint32 (*read_sample)(Sound_Sample *sample);
104 142
105 union 143 union
106 { 144 {
107 struct 145 struct
108 { 146 {
109 Uint16 cbSize; 147 Uint16 cbSize;
110 Uint16 wSamplesPerBlock; 148 Uint16 wSamplesPerBlock;
111 Uint16 wNumCoef; 149 Uint16 wNumCoef;
112 ADPCMCOEFSET *aCoeff; 150 ADPCMCOEFSET *aCoef;
151 ADPCMBLOCKHEADER *blockheaders;
113 } adpcm; 152 } adpcm;
114 153
115 /* put other format-specific data here... */ 154 /* put other format-specific data here... */
116 } fmt; 155 } fmt;
117 } fmt_t; 156 } fmt_t;
126 static int read_fmt_chunk(SDL_RWops *rw, fmt_t *fmt) 165 static int read_fmt_chunk(SDL_RWops *rw, fmt_t *fmt)
127 { 166 {
128 /* skip reading the chunk ID, since it was already read at this point... */ 167 /* skip reading the chunk ID, since it was already read at this point... */
129 fmt->chunkID = fmtID; 168 fmt->chunkID = fmtID;
130 169
131 if (SDL_RWread(rw, &fmt->chunkSize, sizeof (fmt->chunkSize), 1) != 1) 170 BAIL_IF_MACRO(!read_le32(rw, &fmt->chunkSize), NULL, 0);
132 return(0); 171 BAIL_IF_MACRO(!read_le16(rw, &fmt->wFormatTag), NULL, 0);
133 fmt->chunkSize = SDL_SwapLE32(fmt->chunkSize); 172 BAIL_IF_MACRO(!read_le16(rw, &fmt->wChannels), NULL, 0);
134 173 BAIL_IF_MACRO(!read_le32(rw, &fmt->dwSamplesPerSec), NULL, 0);
135 if (SDL_RWread(rw, &fmt->wFormatTag, sizeof (fmt->wFormatTag), 1) != 1) 174 BAIL_IF_MACRO(!read_le32(rw, &fmt->dwAvgBytesPerSec), NULL, 0);
136 return(0); 175 BAIL_IF_MACRO(!read_le16(rw, &fmt->wBlockAlign), NULL, 0);
137 fmt->wFormatTag = SDL_SwapLE16(fmt->wFormatTag); 176 BAIL_IF_MACRO(!read_le16(rw, &fmt->wBitsPerSample), NULL, 0);
138
139 if (SDL_RWread(rw, &fmt->wChannels, sizeof (fmt->wChannels), 1) != 1)
140 return(0);
141 fmt->wChannels = SDL_SwapLE16(fmt->wChannels);
142
143 if (SDL_RWread(rw, &fmt->dwSamplesPerSec,
144 sizeof (fmt->dwSamplesPerSec), 1) != 1)
145 return(0);
146 fmt->dwSamplesPerSec = SDL_SwapLE32(fmt->dwSamplesPerSec);
147
148 if (SDL_RWread(rw, &fmt->dwAvgBytesPerSec,
149 sizeof (fmt->dwAvgBytesPerSec), 1) != 1)
150 return(0);
151 fmt->dwAvgBytesPerSec = SDL_SwapLE32(fmt->dwAvgBytesPerSec);
152
153 if (SDL_RWread(rw, &fmt->wBlockAlign, sizeof (fmt->wBlockAlign), 1) != 1)
154 return(0);
155 fmt->wBlockAlign = SDL_SwapLE16(fmt->wBlockAlign);
156
157 if (SDL_RWread(rw, &fmt->wBitsPerSample,
158 sizeof (fmt->wBitsPerSample), 1) != 1)
159 return(0);
160 fmt->wBitsPerSample = SDL_SwapLE16(fmt->wBitsPerSample);
161 177
162 return(1); 178 return(1);
163 } /* read_fmt_chunk */ 179 } /* read_fmt_chunk */
164 180
165 181
184 */ 200 */
185 static int read_data_chunk(SDL_RWops *rw, data_t *data) 201 static int read_data_chunk(SDL_RWops *rw, data_t *data)
186 { 202 {
187 /* skip reading the chunk ID, since it was already read at this point... */ 203 /* skip reading the chunk ID, since it was already read at this point... */
188 data->chunkID = dataID; 204 data->chunkID = dataID;
189 205 BAIL_IF_MACRO(!read_le32(rw, &data->chunkSize), NULL, 0);
190 if (SDL_RWread(rw, &data->chunkSize, sizeof (data->chunkSize), 1) != 1)
191 return(0);
192 data->chunkSize = SDL_SwapLE32(data->chunkSize);
193
194 return(1); 206 return(1);
195 } /* read_data_chunk */ 207 } /* read_data_chunk */
196 208
197 209
198 210
245 257
246 return(retval); 258 return(retval);
247 } /* read_sample_fmt_normal */ 259 } /* read_sample_fmt_normal */
248 260
249 261
250 static void free_fmt_normal(fmt_t *fmt)
251 {
252 /* it's a no-op. */
253 } /* free_fmt_normal */
254
255 262
256 static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt) 263 static int read_fmt_normal(SDL_RWops *rw, fmt_t *fmt)
257 { 264 {
258 /* (don't need to read more from the RWops...) */ 265 /* (don't need to read more from the RWops...) */
259 fmt->free = free_fmt_normal; 266 fmt->free = NULL;
260 fmt->read_sample = read_sample_fmt_normal; 267 fmt->read_sample = read_sample_fmt_normal;
261 return(1); 268 return(1);
262 } /* read_fmt_normal */ 269 } /* read_fmt_normal */
263 270
264 271
265 272
266 /***************************************************************************** 273 /*****************************************************************************
267 * ADPCM compression handler... * 274 * ADPCM compression handler... *
268 *****************************************************************************/ 275 *****************************************************************************/
269 276
277 static int read_adpcm_block_headers(SDL_RWops *rw, fmt_t *fmt)
278 {
279 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
280 int i;
281 int max = fmt->wChannels;
282
283 for (i = 0; i < max; i++)
284 BAIL_IF_MACRO(!read_uint8(rw, &headers[i].bPredictor), NULL, 0);
285
286 for (i = 0; i < max; i++)
287 BAIL_IF_MACRO(!read_le16(rw, &headers[i].iDelta), NULL, 0);
288
289 for (i = 0; i < max; i++)
290 BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp1), NULL, 0);
291
292 for (i = 0; i < max; i++)
293 BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp2), NULL, 0);
294
295 return(1);
296 } /* read_adpcm_block_headers */
297
298
299 static int decode_adpcm_block(Sound_Sample *sample)
300 {
301 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
302 SDL_RWops *rw = internal->rw;
303 wav_t *w = (wav_t *) internal->decoder_private;
304 fmt_t *fmt = w->fmt;
305 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders;
306 int i;
307 int max = fmt->wChannels;
308
309 if (!read_adpcm_block_headers(rw, fmt))
310 {
311 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
312 return(0);
313 } /* if */
314
315 for (i = 0; i < max; i++)
316 {
317 Uint16 iCoef1 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef1;
318 Uint16 iCoef2 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef2;
319 /*
320 Sint32 lPredSamp = ((headers[i].iSamp1 * iCoef1) +
321 (headers[i].iSamp2 * iCoef2)) /
322 FIXED_POINT_COEF_BASE;
323 */
324 } /* for */
325 } /* decode_adpcm_block */
326
327
270 static Uint32 read_sample_fmt_adpcm(Sound_Sample *sample) 328 static Uint32 read_sample_fmt_adpcm(Sound_Sample *sample)
271 { 329 {
272 /* !!! FIXME: Write this. */ 330 /* !!! FIXME: Write this. */
273 sample->flags | SOUND_SAMPLEFLAG_ERROR; 331 Sound_SetError("WAV: Not implemented. Soon.");
332 sample->flags |= SOUND_SAMPLEFLAG_ERROR;
274 return(0); 333 return(0);
275 } /* read_sample_fmt_adpcm */ 334 } /* read_sample_fmt_adpcm */
276 335
277 336
278 static void free_fmt_adpcm(fmt_t *fmt) 337 static void free_fmt_adpcm(fmt_t *fmt)
279 { 338 {
280 if (fmt->fmt.adpcm.aCoeff != NULL) 339 if (fmt->fmt.adpcm.aCoef != NULL)
281 free(fmt->fmt.adpcm.aCoeff); 340 free(fmt->fmt.adpcm.aCoef);
341
342 if (fmt->fmt.adpcm.blockheaders != NULL)
343 free(fmt->fmt.adpcm.blockheaders);
282 } /* free_fmt_adpcm */ 344 } /* free_fmt_adpcm */
283 345
284 346
285 /* 347 /*
286 * Read in a the adpcm-specific info from disk. This makes this process 348 * Read in a the adpcm-specific info from disk. This makes this process
289 */ 351 */
290 static int read_fmt_adpcm(SDL_RWops *rw, fmt_t *fmt) 352 static int read_fmt_adpcm(SDL_RWops *rw, fmt_t *fmt)
291 { 353 {
292 size_t i; 354 size_t i;
293 355
294 fmt->fmt.adpcm.aCoeff = NULL; 356 memset(&fmt->fmt.adpcm, '\0', sizeof (fmt->fmt.adpcm));
295 fmt->free = free_fmt_adpcm; 357 fmt->free = free_fmt_adpcm;
296 fmt->read_sample = read_sample_fmt_adpcm; 358 fmt->read_sample = read_sample_fmt_adpcm;
297 359
298 if (SDL_RWread(rw, &fmt->fmt.adpcm.cbSize, 360 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0);
299 sizeof (fmt->fmt.adpcm.cbSize), 1) != 1) 361 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0);
300 { 362 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0);
301 return(0); 363
364 /*
365 * !!! FIXME: SDL seems nervous about this, so I'll make a debug
366 * !!! FIXME: note for the time being...
367 */
368 if (fmt->fmt.adpcm.wNumCoef != 7)
369 {
370 SNDDBG(("WAV: adpcm's wNumCoef is NOT seven (it's %d)!\n",
371 fmt->fmt.adpcm.wNumCoef));
302 } /* if */ 372 } /* if */
303 fmt->fmt.adpcm.cbSize = SDL_SwapLE16(fmt->fmt.adpcm.cbSize); 373
304 374 /* fmt->free() is always called, so these malloc()s will be cleaned up. */
305 if (SDL_RWread(rw, &fmt->fmt.adpcm.wSamplesPerBlock,
306 sizeof (fmt->fmt.adpcm.wSamplesPerBlock), 1) != 1)
307 {
308 return(0);
309 } /* if */
310 fmt->fmt.adpcm.wSamplesPerBlock = SDL_SwapLE16(fmt->fmt.adpcm.wSamplesPerBlock);
311
312 if (SDL_RWread(rw, &fmt->fmt.adpcm.wNumCoef,
313 sizeof (fmt->fmt.adpcm.wNumCoef), 1) != 1)
314 {
315 return(0);
316 } /* if */
317 fmt->fmt.adpcm.wNumCoef = SDL_SwapLE16(fmt->fmt.adpcm.wNumCoef);
318
319 i = sizeof (ADPCMCOEFSET) * fmt->fmt.adpcm.wNumCoef; 375 i = sizeof (ADPCMCOEFSET) * fmt->fmt.adpcm.wNumCoef;
320 fmt->fmt.adpcm.aCoeff = (ADPCMCOEFSET *) malloc(i); 376 fmt->fmt.adpcm.aCoef = (ADPCMCOEFSET *) malloc(i);
321 BAIL_IF_MACRO(fmt->fmt.adpcm.aCoeff == NULL, ERR_OUT_OF_MEMORY, 0); 377 BAIL_IF_MACRO(fmt->fmt.adpcm.aCoef == NULL, ERR_OUT_OF_MEMORY, 0);
378
379 i = sizeof (ADPCMBLOCKHEADER) * fmt->wChannels;
380 fmt->fmt.adpcm.blockheaders = (ADPCMBLOCKHEADER *) malloc(i);
381 BAIL_IF_MACRO(fmt->fmt.adpcm.blockheaders == NULL, ERR_OUT_OF_MEMORY, 0);
322 382
323 for (i = 0; i < fmt->fmt.adpcm.wNumCoef; i++) 383 for (i = 0; i < fmt->fmt.adpcm.wNumCoef; i++)
324 { 384 {
325 if (SDL_RWread(rw, &fmt->fmt.adpcm.aCoeff[i].iCoef1, 385 int rc;
326 sizeof (fmt->fmt.adpcm.aCoeff[i].iCoef1), 1) != 1) 386 rc = SDL_RWread(rw, &fmt->fmt.adpcm.aCoef[i].iCoef1,
327 { 387 sizeof (fmt->fmt.adpcm.aCoef[i].iCoef1), 1);
328 return(0); 388 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
329 } /* if */ 389
330 390 rc = SDL_RWread(rw, &fmt->fmt.adpcm.aCoef[i].iCoef2,
331 if (SDL_RWread(rw, &fmt->fmt.adpcm.aCoeff[i].iCoef2, 391 sizeof (fmt->fmt.adpcm.aCoef[i].iCoef2), 1);
332 sizeof (fmt->fmt.adpcm.aCoeff[i].iCoef2), 1) != 1) 392 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0);
333 {
334 return(0);
335 } /* if */
336 } /* for */ 393 } /* for */
337 394
338 return(1); 395 return(1);
339 } /* read_fmt_adpcm */ 396 } /* read_fmt_adpcm */
340 397
391 Sint32 siz = 0; 448 Sint32 siz = 0;
392 Uint32 _id = 0; 449 Uint32 _id = 0;
393 450
394 while (1) 451 while (1)
395 { 452 {
396 BAIL_IF_MACRO(SDL_RWread(rw, &_id, sizeof (_id), 1) != 1, NULL, 0); 453 BAIL_IF_MACRO(!read_le32(rw, &_id), NULL, 0);
397 if (SDL_SwapLE32(_id) == id) 454 if (_id == id)
398 return(1); 455 return(1);
399 456
400 BAIL_IF_MACRO(SDL_RWread(rw, &siz, sizeof (siz), 1) != 1, NULL, 0); 457 /* skip ahead and see what next chunk is... */
401 siz = SDL_SwapLE32(siz); 458 BAIL_IF_MACRO(!read_le32(rw, &siz), NULL, 0);
402 assert(siz > 0); 459 assert(siz > 0);
403 BAIL_IF_MACRO(SDL_RWseek(rw, siz, SEEK_SET) != siz, NULL, 0); 460 BAIL_IF_MACRO(SDL_RWseek(rw, siz, SEEK_SET) != siz, NULL, 0);
404 } /* while */ 461 } /* while */
405 462
406 return(0); /* shouldn't hit this, but just in case... */ 463 return(0); /* shouldn't hit this, but just in case... */
468 525
469 static void WAV_close(Sound_Sample *sample) 526 static void WAV_close(Sound_Sample *sample)
470 { 527 {
471 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; 528 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
472 wav_t *w = (wav_t *) internal->decoder_private; 529 wav_t *w = (wav_t *) internal->decoder_private;
473 w->fmt->free(w->fmt); 530
531 if (w->fmt->free != NULL)
532 w->fmt->free(w->fmt);
533
474 free(w->fmt); 534 free(w->fmt);
475 free(w); 535 free(w);
476 } /* WAV_close */ 536 } /* WAV_close */
477 537
478 538