Mercurial > SDL_sound_CoreAudio
comparison decoders/wav.c @ 185:6bb68b3bdcf1
ADPCM decoder seems to be complete, other fixes too...
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Thu, 27 Dec 2001 23:05:05 +0000 |
parents | 26996236d790 |
children | 6cd07211a235 |
comparison
equal
deleted
inserted
replaced
184:47cc2de2ae36 | 185:6bb68b3bdcf1 |
---|---|
99 | 99 |
100 /* Chunk management code... */ | 100 /* Chunk management code... */ |
101 | 101 |
102 #define riffID 0x46464952 /* "RIFF", in ascii. */ | 102 #define riffID 0x46464952 /* "RIFF", in ascii. */ |
103 #define waveID 0x45564157 /* "WAVE", in ascii. */ | 103 #define waveID 0x45564157 /* "WAVE", in ascii. */ |
104 #define factID 0x74636166 /* "fact", in ascii. */ | |
104 | 105 |
105 | 106 |
106 /***************************************************************************** | 107 /***************************************************************************** |
107 * The FORMAT chunk... * | 108 * The FORMAT chunk... * |
108 *****************************************************************************/ | 109 *****************************************************************************/ |
112 #define FMT_NORMAL 0x0001 /* Uncompressed waveform data. */ | 113 #define FMT_NORMAL 0x0001 /* Uncompressed waveform data. */ |
113 #define FMT_ADPCM 0x0002 /* ADPCM compressed waveform data. */ | 114 #define FMT_ADPCM 0x0002 /* ADPCM compressed waveform data. */ |
114 | 115 |
115 typedef struct | 116 typedef struct |
116 { | 117 { |
117 Uint16 iCoef1; | 118 Sint16 iCoef1; |
118 Uint16 iCoef2; | 119 Sint16 iCoef2; |
119 } ADPCMCOEFSET; | 120 } ADPCMCOEFSET; |
120 | 121 |
121 typedef struct | 122 typedef struct |
122 { | 123 { |
123 Uint8 bPredictor; | 124 Uint8 bPredictor; |
135 Uint32 dwSamplesPerSec; | 136 Uint32 dwSamplesPerSec; |
136 Uint32 dwAvgBytesPerSec; | 137 Uint32 dwAvgBytesPerSec; |
137 Uint16 wBlockAlign; | 138 Uint16 wBlockAlign; |
138 Uint16 wBitsPerSample; | 139 Uint16 wBitsPerSample; |
139 | 140 |
141 Uint32 sample_frame_size; | |
142 | |
140 void (*free)(struct S_WAV_FMT_T *fmt); | 143 void (*free)(struct S_WAV_FMT_T *fmt); |
141 Uint32 (*read_sample)(Sound_Sample *sample); | 144 Uint32 (*read_sample)(Sound_Sample *sample); |
142 | 145 |
143 union | 146 union |
144 { | 147 { |
147 Uint16 cbSize; | 150 Uint16 cbSize; |
148 Uint16 wSamplesPerBlock; | 151 Uint16 wSamplesPerBlock; |
149 Uint16 wNumCoef; | 152 Uint16 wNumCoef; |
150 ADPCMCOEFSET *aCoef; | 153 ADPCMCOEFSET *aCoef; |
151 ADPCMBLOCKHEADER *blockheaders; | 154 ADPCMBLOCKHEADER *blockheaders; |
155 Uint32 samples_left_in_block; | |
156 int nibble_state; | |
157 Sint8 nibble; | |
152 } adpcm; | 158 } adpcm; |
153 | 159 |
154 /* put other format-specific data here... */ | 160 /* put other format-specific data here... */ |
155 } fmt; | 161 } fmt; |
156 } fmt_t; | 162 } fmt_t; |
224 | 230 |
225 /***************************************************************************** | 231 /***************************************************************************** |
226 * Normal, uncompressed waveform handler... * | 232 * Normal, uncompressed waveform handler... * |
227 *****************************************************************************/ | 233 *****************************************************************************/ |
228 | 234 |
235 /* | |
236 * Sound_Decode() lands here for uncompressed WAVs... | |
237 */ | |
229 static Uint32 read_sample_fmt_normal(Sound_Sample *sample) | 238 static Uint32 read_sample_fmt_normal(Sound_Sample *sample) |
230 { | 239 { |
231 Uint32 retval; | 240 Uint32 retval; |
232 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | 241 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
233 wav_t *w = (wav_t *) internal->decoder_private; | 242 wav_t *w = (wav_t *) internal->decoder_private; |
272 | 281 |
273 /***************************************************************************** | 282 /***************************************************************************** |
274 * ADPCM compression handler... * | 283 * ADPCM compression handler... * |
275 *****************************************************************************/ | 284 *****************************************************************************/ |
276 | 285 |
277 static int read_adpcm_block_headers(SDL_RWops *rw, fmt_t *fmt) | 286 #define FIXED_POINT_COEF_BASE 256 |
278 { | 287 #define FIXED_POINT_ADAPTION_BASE 256 |
279 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; | 288 #define SMALLEST_ADPCM_DELTA 16 |
280 int i; | 289 |
281 int max = fmt->wChannels; | 290 |
282 | 291 static inline int read_adpcm_block_headers(Sound_Sample *sample) |
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 { | 292 { |
301 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | 293 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
302 SDL_RWops *rw = internal->rw; | 294 SDL_RWops *rw = internal->rw; |
303 wav_t *w = (wav_t *) internal->decoder_private; | 295 wav_t *w = (wav_t *) internal->decoder_private; |
304 fmt_t *fmt = w->fmt; | 296 fmt_t *fmt = w->fmt; |
305 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; | 297 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; |
306 int i; | 298 int i; |
307 int max = fmt->wChannels; | 299 int max = fmt->wChannels; |
308 | 300 |
309 if (!read_adpcm_block_headers(rw, fmt)) | 301 if (w->bytesLeft < fmt->wBlockAlign) |
310 { | 302 { |
311 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | 303 sample->flags |= SOUND_SAMPLEFLAG_EOF; |
312 return(0); | 304 return(0); |
313 } /* if */ | 305 } /* if */ |
314 | 306 |
307 w->bytesLeft -= fmt->wBlockAlign; | |
308 | |
315 for (i = 0; i < max; i++) | 309 for (i = 0; i < max; i++) |
316 { | 310 BAIL_IF_MACRO(!read_uint8(rw, &headers[i].bPredictor), NULL, 0); |
317 Uint16 iCoef1 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef1; | 311 |
318 Uint16 iCoef2 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef2; | 312 for (i = 0; i < max; i++) |
319 /* | 313 BAIL_IF_MACRO(!read_le16(rw, &headers[i].iDelta), NULL, 0); |
314 | |
315 for (i = 0; i < max; i++) | |
316 BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp1), NULL, 0); | |
317 | |
318 for (i = 0; i < max; i++) | |
319 BAIL_IF_MACRO(!read_le16(rw, &headers[i].iSamp2), NULL, 0); | |
320 | |
321 fmt->fmt.adpcm.samples_left_in_block = fmt->fmt.adpcm.wSamplesPerBlock; | |
322 fmt->fmt.adpcm.nibble_state = 0; | |
323 return(1); | |
324 } /* read_adpcm_block_headers */ | |
325 | |
326 | |
327 static inline void do_adpcm_nibble(Uint8 nib, | |
328 ADPCMBLOCKHEADER *header, | |
329 Sint32 lPredSamp) | |
330 { | |
331 static const Sint32 max_audioval = ((1<<(16-1))-1); | |
332 static const Sint32 min_audioval = -(1<<(16-1)); | |
333 static const Sint32 AdaptionTable[] = | |
334 { | |
335 230, 230, 230, 230, 307, 409, 512, 614, | |
336 768, 614, 512, 409, 307, 230, 230, 230 | |
337 }; | |
338 | |
339 Sint32 lNewSamp; | |
340 Sint32 delta; | |
341 | |
342 if (nib & 0x08) | |
343 lNewSamp = lPredSamp + (header->iDelta * (nib - 0x10)); | |
344 else | |
345 lNewSamp = lPredSamp + (header->iDelta * nib); | |
346 | |
347 /* clamp value... */ | |
348 if (lNewSamp < min_audioval) | |
349 lNewSamp = min_audioval; | |
350 else if (lNewSamp > max_audioval) | |
351 lNewSamp = max_audioval; | |
352 | |
353 delta = ((Sint32) header->iDelta * AdaptionTable[nib]) / | |
354 FIXED_POINT_ADAPTION_BASE; | |
355 | |
356 if (delta < SMALLEST_ADPCM_DELTA) | |
357 delta = SMALLEST_ADPCM_DELTA; | |
358 | |
359 header->iDelta = delta; | |
360 header->iSamp2 = header->iSamp1; | |
361 header->iSamp1 = lNewSamp; | |
362 } /* do_adpcm_nibble */ | |
363 | |
364 | |
365 static inline int decode_adpcm_sample_frame(Sound_Sample *sample) | |
366 { | |
367 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | |
368 wav_t *w = (wav_t *) internal->decoder_private; | |
369 fmt_t *fmt = w->fmt; | |
370 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; | |
371 SDL_RWops *rw = internal->rw; | |
372 int i; | |
373 int max = fmt->wChannels; | |
374 Sint32 delta; | |
375 Uint8 nib = fmt->fmt.adpcm.nibble; | |
376 | |
377 for (i = 0; i < max; i++) | |
378 { | |
379 Uint8 byte; | |
380 Sint16 iCoef1 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef1; | |
381 Sint16 iCoef2 = fmt->fmt.adpcm.aCoef[headers[i].bPredictor].iCoef2; | |
320 Sint32 lPredSamp = ((headers[i].iSamp1 * iCoef1) + | 382 Sint32 lPredSamp = ((headers[i].iSamp1 * iCoef1) + |
321 (headers[i].iSamp2 * iCoef2)) / | 383 (headers[i].iSamp2 * iCoef2)) / |
322 FIXED_POINT_COEF_BASE; | 384 FIXED_POINT_COEF_BASE; |
323 */ | 385 |
386 if (fmt->fmt.adpcm.nibble_state == 0) | |
387 { | |
388 BAIL_IF_MACRO(!read_uint8(rw, &nib), NULL, 0); | |
389 fmt->fmt.adpcm.nibble_state = 1; | |
390 do_adpcm_nibble(nib >> 4, &headers[i], lPredSamp); | |
391 } /* if */ | |
392 else | |
393 { | |
394 fmt->fmt.adpcm.nibble_state = 0; | |
395 do_adpcm_nibble(nib & 0x0F, &headers[i], lPredSamp); | |
396 } /* else */ | |
324 } /* for */ | 397 } /* for */ |
325 } /* decode_adpcm_block */ | 398 |
326 | 399 fmt->fmt.adpcm.nibble = nib; |
327 | 400 return(1); |
401 } /* decode_adpcm_sample_frame */ | |
402 | |
403 | |
404 static inline void put_adpcm_sample_frame1(Uint8 *_buf, fmt_t *fmt) | |
405 { | |
406 Uint16 *buf = (Uint16 *) _buf; | |
407 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; | |
408 int i; | |
409 for (i = 0; i < fmt->wChannels; i++) | |
410 *(buf++) = headers[i].iSamp1; | |
411 } /* put_adpcm_sample_frame1 */ | |
412 | |
413 | |
414 static inline void put_adpcm_sample_frame2(Uint8 *_buf, fmt_t *fmt) | |
415 { | |
416 Uint16 *buf = (Uint16 *) _buf; | |
417 ADPCMBLOCKHEADER *headers = fmt->fmt.adpcm.blockheaders; | |
418 int i; | |
419 for (i = 0; i < fmt->wChannels; i++) | |
420 *(buf++) = headers[i].iSamp2; | |
421 } /* put_adpcm_sample_frame2 */ | |
422 | |
423 | |
424 /* | |
425 * Sound_Decode() lands here for ADPCM-encoded WAVs... | |
426 */ | |
328 static Uint32 read_sample_fmt_adpcm(Sound_Sample *sample) | 427 static Uint32 read_sample_fmt_adpcm(Sound_Sample *sample) |
329 { | 428 { |
330 /* !!! FIXME: Write this. */ | 429 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
331 Sound_SetError("WAV: Not implemented. Soon."); | 430 wav_t *w = (wav_t *) internal->decoder_private; |
332 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | 431 fmt_t *fmt = w->fmt; |
333 return(0); | 432 Uint32 bw = 0; |
433 | |
434 while (bw < internal->buffer_size) | |
435 { | |
436 /* write ongoing sample frame before reading more data... */ | |
437 switch (fmt->fmt.adpcm.samples_left_in_block) | |
438 { | |
439 case 0: /* need to read a new block... */ | |
440 if (!read_adpcm_block_headers(sample)) | |
441 { | |
442 if ((sample->flags & SOUND_SAMPLEFLAG_EOF) == 0) | |
443 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
444 return(bw); | |
445 } /* if */ | |
446 | |
447 /* only write first sample frame for now. */ | |
448 put_adpcm_sample_frame2(internal->buffer + bw, fmt); | |
449 fmt->fmt.adpcm.samples_left_in_block--; | |
450 bw += fmt->sample_frame_size; | |
451 break; | |
452 | |
453 case 1: /* output last sample frame of block... */ | |
454 put_adpcm_sample_frame1(internal->buffer + bw, fmt); | |
455 fmt->fmt.adpcm.samples_left_in_block--; | |
456 bw += fmt->sample_frame_size; | |
457 break; | |
458 | |
459 default: /* output latest sample frame and read a new one... */ | |
460 put_adpcm_sample_frame1(internal->buffer + bw, fmt); | |
461 fmt->fmt.adpcm.samples_left_in_block--; | |
462 bw += fmt->sample_frame_size; | |
463 | |
464 if (!decode_adpcm_sample_frame(sample)) | |
465 { | |
466 sample->flags |= SOUND_SAMPLEFLAG_ERROR; | |
467 return(bw); | |
468 } /* if */ | |
469 } /* switch */ | |
470 } /* while */ | |
471 | |
472 return(bw); | |
334 } /* read_sample_fmt_adpcm */ | 473 } /* read_sample_fmt_adpcm */ |
335 | 474 |
336 | 475 |
476 /* | |
477 * Sound_FreeSample() lands here for ADPCM-encoded WAVs... | |
478 */ | |
337 static void free_fmt_adpcm(fmt_t *fmt) | 479 static void free_fmt_adpcm(fmt_t *fmt) |
338 { | 480 { |
339 if (fmt->fmt.adpcm.aCoef != NULL) | 481 if (fmt->fmt.adpcm.aCoef != NULL) |
340 free(fmt->fmt.adpcm.aCoef); | 482 free(fmt->fmt.adpcm.aCoef); |
341 | 483 |
359 | 501 |
360 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0); | 502 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0); |
361 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0); | 503 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0); |
362 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0); | 504 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0); |
363 | 505 |
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)); | |
372 } /* if */ | |
373 | |
374 /* fmt->free() is always called, so these malloc()s will be cleaned up. */ | 506 /* fmt->free() is always called, so these malloc()s will be cleaned up. */ |
507 | |
375 i = sizeof (ADPCMCOEFSET) * fmt->fmt.adpcm.wNumCoef; | 508 i = sizeof (ADPCMCOEFSET) * fmt->fmt.adpcm.wNumCoef; |
376 fmt->fmt.adpcm.aCoef = (ADPCMCOEFSET *) malloc(i); | 509 fmt->fmt.adpcm.aCoef = (ADPCMCOEFSET *) malloc(i); |
377 BAIL_IF_MACRO(fmt->fmt.adpcm.aCoef == NULL, ERR_OUT_OF_MEMORY, 0); | 510 BAIL_IF_MACRO(fmt->fmt.adpcm.aCoef == NULL, ERR_OUT_OF_MEMORY, 0); |
378 | 511 |
512 for (i = 0; i < fmt->fmt.adpcm.wNumCoef; i++) | |
513 { | |
514 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.aCoef[i].iCoef1), NULL, 0); | |
515 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.aCoef[i].iCoef2), NULL, 0); | |
516 } /* for */ | |
517 | |
379 i = sizeof (ADPCMBLOCKHEADER) * fmt->wChannels; | 518 i = sizeof (ADPCMBLOCKHEADER) * fmt->wChannels; |
380 fmt->fmt.adpcm.blockheaders = (ADPCMBLOCKHEADER *) malloc(i); | 519 fmt->fmt.adpcm.blockheaders = (ADPCMBLOCKHEADER *) malloc(i); |
381 BAIL_IF_MACRO(fmt->fmt.adpcm.blockheaders == NULL, ERR_OUT_OF_MEMORY, 0); | 520 BAIL_IF_MACRO(fmt->fmt.adpcm.blockheaders == NULL, ERR_OUT_OF_MEMORY, 0); |
382 | |
383 for (i = 0; i < fmt->fmt.adpcm.wNumCoef; i++) | |
384 { | |
385 int rc; | |
386 rc = SDL_RWread(rw, &fmt->fmt.adpcm.aCoef[i].iCoef1, | |
387 sizeof (fmt->fmt.adpcm.aCoef[i].iCoef1), 1); | |
388 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0); | |
389 | |
390 rc = SDL_RWread(rw, &fmt->fmt.adpcm.aCoef[i].iCoef2, | |
391 sizeof (fmt->fmt.adpcm.aCoef[i].iCoef2), 1); | |
392 BAIL_IF_MACRO(rc != 1, ERR_IO_ERROR, 0); | |
393 } /* for */ | |
394 | 521 |
395 return(1); | 522 return(1); |
396 } /* read_fmt_adpcm */ | 523 } /* read_fmt_adpcm */ |
397 | 524 |
398 | 525 |
445 */ | 572 */ |
446 static int find_chunk(SDL_RWops *rw, Uint32 id) | 573 static int find_chunk(SDL_RWops *rw, Uint32 id) |
447 { | 574 { |
448 Sint32 siz = 0; | 575 Sint32 siz = 0; |
449 Uint32 _id = 0; | 576 Uint32 _id = 0; |
577 Uint32 pos = SDL_RWtell(rw); | |
450 | 578 |
451 while (1) | 579 while (1) |
452 { | 580 { |
453 BAIL_IF_MACRO(!read_le32(rw, &_id), NULL, 0); | 581 BAIL_IF_MACRO(!read_le32(rw, &_id), NULL, 0); |
454 if (_id == id) | 582 if (_id == id) |
455 return(1); | 583 return(1); |
456 | 584 |
457 /* skip ahead and see what next chunk is... */ | 585 /* skip ahead and see what next chunk is... */ |
458 BAIL_IF_MACRO(!read_le32(rw, &siz), NULL, 0); | 586 BAIL_IF_MACRO(!read_le32(rw, &siz), NULL, 0); |
459 assert(siz > 0); | 587 assert(siz >= 0); |
460 BAIL_IF_MACRO(SDL_RWseek(rw, siz, SEEK_SET) != siz, NULL, 0); | 588 pos += (sizeof (Uint32) * 2) + siz; |
589 if (siz > 0) | |
590 BAIL_IF_MACRO(SDL_RWseek(rw, pos, SEEK_SET) != pos, NULL, 0); | |
461 } /* while */ | 591 } /* while */ |
462 | 592 |
463 return(0); /* shouldn't hit this, but just in case... */ | 593 return(0); /* shouldn't hit this, but just in case... */ |
464 } /* find_chunk */ | 594 } /* find_chunk */ |
465 | 595 |
468 { | 598 { |
469 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; | 599 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; |
470 SDL_RWops *rw = internal->rw; | 600 SDL_RWops *rw = internal->rw; |
471 data_t d; | 601 data_t d; |
472 wav_t *w; | 602 wav_t *w; |
603 Uint32 pos; | |
473 | 604 |
474 BAIL_IF_MACRO(SDL_ReadLE32(rw) != riffID, "WAV: Not a RIFF file.", 0); | 605 BAIL_IF_MACRO(SDL_ReadLE32(rw) != riffID, "WAV: Not a RIFF file.", 0); |
475 SDL_ReadLE32(rw); /* throw the length away; we get this info later. */ | 606 SDL_ReadLE32(rw); /* throw the length away; we get this info later. */ |
476 BAIL_IF_MACRO(SDL_ReadLE32(rw) != waveID, "WAV: Not a WAVE file.", 0); | 607 BAIL_IF_MACRO(SDL_ReadLE32(rw) != waveID, "WAV: Not a WAVE file.", 0); |
477 BAIL_IF_MACRO(!find_chunk(rw, fmtID), "WAV: No format chunk.", 0); | 608 BAIL_IF_MACRO(!find_chunk(rw, fmtID), "WAV: No format chunk.", 0); |
478 BAIL_IF_MACRO(!read_fmt_chunk(rw, fmt), "WAV: Can't read format chunk.", 0); | 609 BAIL_IF_MACRO(!read_fmt_chunk(rw, fmt), "WAV: Can't read format chunk.", 0); |
479 | 610 |
480 sample->actual.channels = (Uint8) fmt->wChannels; | 611 sample->actual.channels = (Uint8) fmt->wChannels; |
481 sample->actual.rate = fmt->dwSamplesPerSec; | 612 sample->actual.rate = fmt->dwSamplesPerSec; |
482 if (fmt->wBitsPerSample <= 8) | 613 if (fmt->wBitsPerSample == 4) |
614 sample->actual.format = AUDIO_S16SYS; /* !!! FIXME ? */ | |
615 else if (fmt->wBitsPerSample == 8) | |
483 sample->actual.format = AUDIO_U8; | 616 sample->actual.format = AUDIO_U8; |
484 else if (fmt->wBitsPerSample <= 16) | 617 else if (fmt->wBitsPerSample == 16) |
485 sample->actual.format = AUDIO_S16LSB; | 618 sample->actual.format = AUDIO_S16LSB; |
486 else | 619 else |
487 BAIL_MACRO("WAV: Unsupported sample size.", 0); | 620 BAIL_MACRO("WAV: Unsupported sample size.", 0); |
488 | 621 |
489 BAIL_IF_MACRO(!read_fmt(rw, fmt), NULL, 0); | 622 BAIL_IF_MACRO(!read_fmt(rw, fmt), NULL, 0); |
492 | 625 |
493 w = (wav_t *) malloc(sizeof(wav_t)); | 626 w = (wav_t *) malloc(sizeof(wav_t)); |
494 BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0); | 627 BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0); |
495 w->fmt = fmt; | 628 w->fmt = fmt; |
496 w->bytesLeft = d.chunkSize; | 629 w->bytesLeft = d.chunkSize; |
630 | |
631 /* !!! FIXME: Move this to Sound_SampleInfo ? */ | |
632 fmt->sample_frame_size = ( ((sample->actual.format & 0xFF) / 8) * | |
633 sample->actual.channels ); | |
634 | |
497 internal->decoder_private = (void *) w; | 635 internal->decoder_private = (void *) w; |
498 | 636 |
499 sample->flags = SOUND_SAMPLEFLAG_NONE; | 637 sample->flags = SOUND_SAMPLEFLAG_NONE; |
500 | 638 |
501 SNDDBG(("WAV: Accepting data stream.\n")); | 639 SNDDBG(("WAV: Accepting data stream.\n")); |