comparison decoders/wav.c @ 333:565ae12fa74e

Implemented seek support for ADPCM-compressed WAVs.
author Ryan C. Gordon <icculus@icculus.org>
date Mon, 20 May 2002 11:19:50 +0000
parents eb7c929193dd
children 069ce624d6cf
comparison
equal deleted inserted replaced
332:8ba541e81c1e 333:565ae12fa74e
525 } /* rewind_sample_fmt_adpcm */ 525 } /* rewind_sample_fmt_adpcm */
526 526
527 527
528 static int seek_sample_fmt_adpcm(Sound_Sample *sample, Uint32 ms) 528 static int seek_sample_fmt_adpcm(Sound_Sample *sample, Uint32 ms)
529 { 529 {
530 return(0); /* !!! FIXME: Can we reasonably implement this? */ 530 Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
531 wav_t *w = (wav_t *) internal->decoder_private;
532 fmt_t *fmt = w->fmt;
533 Uint32 origsampsleft = fmt->fmt.adpcm.samples_left_in_block;
534 int origpos = SDL_RWtell(internal->rw);
535 int offset = __Sound_convertMsToBytePos(&sample->actual, ms);
536 int bpb = (fmt->fmt.adpcm.wSamplesPerBlock * fmt->sample_frame_size);
537 int skipsize = (offset / bpb) * fmt->wBlockAlign;
538 int pos = skipsize + fmt->data_starting_offset;
539 int rc = SDL_RWseek(internal->rw, pos, SEEK_SET);
540 BAIL_IF_MACRO(rc != pos, ERR_IO_ERROR, 0);
541
542 /* The offset we need is in this block, so we need to decode to there. */
543 skipsize += (offset % bpb);
544 rc = (offset % bpb); /* bytes into this block we need to decode */
545 if (!read_adpcm_block_headers(sample))
546 {
547 SDL_RWseek(internal->rw, origpos, SEEK_SET); /* try to make sane. */
548 return(0);
549 } /* if */
550
551 /* first sample frame of block is a freebie. :) */
552 fmt->fmt.adpcm.samples_left_in_block--;
553 rc -= fmt->sample_frame_size;
554 while (rc > 0)
555 {
556 if (!decode_adpcm_sample_frame(sample))
557 {
558 SDL_RWseek(internal->rw, origpos, SEEK_SET);
559 fmt->fmt.adpcm.samples_left_in_block = origsampsleft;
560 return(0);
561 } /* if */
562
563 fmt->fmt.adpcm.samples_left_in_block--;
564 rc -= fmt->sample_frame_size;
565 } /* while */
566
567 w->bytesLeft = fmt->total_bytes - skipsize;
568 return(1); /* success. */
531 } /* seek_sample_fmt_adpcm */ 569 } /* seek_sample_fmt_adpcm */
532 570
533 571
534 /* 572 /*
535 * Read in the adpcm-specific info from disk. This makes this process 573 * Read in the adpcm-specific info from disk. This makes this process
542 580
543 memset(&fmt->fmt.adpcm, '\0', sizeof (fmt->fmt.adpcm)); 581 memset(&fmt->fmt.adpcm, '\0', sizeof (fmt->fmt.adpcm));
544 fmt->free = free_fmt_adpcm; 582 fmt->free = free_fmt_adpcm;
545 fmt->read_sample = read_sample_fmt_adpcm; 583 fmt->read_sample = read_sample_fmt_adpcm;
546 fmt->rewind_sample = rewind_sample_fmt_adpcm; 584 fmt->rewind_sample = rewind_sample_fmt_adpcm;
585 fmt->seek_sample = seek_sample_fmt_adpcm;
547 586
548 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0); 587 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.cbSize), NULL, 0);
549 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0); 588 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wSamplesPerBlock), NULL, 0);
550 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0); 589 BAIL_IF_MACRO(!read_le16(rw, &fmt->fmt.adpcm.wNumCoef), NULL, 0);
551 590
675 w = (wav_t *) malloc(sizeof(wav_t)); 714 w = (wav_t *) malloc(sizeof(wav_t));
676 BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0); 715 BAIL_IF_MACRO(w == NULL, ERR_OUT_OF_MEMORY, 0);
677 w->fmt = fmt; 716 w->fmt = fmt;
678 fmt->total_bytes = w->bytesLeft = d.chunkSize; 717 fmt->total_bytes = w->bytesLeft = d.chunkSize;
679 fmt->data_starting_offset = SDL_RWtell(rw); 718 fmt->data_starting_offset = SDL_RWtell(rw);
680
681 /* !!! FIXME: Move this to Sound_SampleInfo ? */
682 fmt->sample_frame_size = ( ((sample->actual.format & 0xFF) / 8) * 719 fmt->sample_frame_size = ( ((sample->actual.format & 0xFF) / 8) *
683 sample->actual.channels ); 720 sample->actual.channels );
684 721
685 internal->decoder_private = (void *) w; 722 internal->decoder_private = (void *) w;
686 723
687 sample->flags = SOUND_SAMPLEFLAG_NONE; 724 sample->flags = SOUND_SAMPLEFLAG_NONE;
688 if (fmt->wFormatTag == FMT_NORMAL) 725 if (fmt->seek_sample != NULL)
689 sample->flags |= SOUND_SAMPLEFLAG_CANSEEK; 726 sample->flags |= SOUND_SAMPLEFLAG_CANSEEK;
690 727
691 SNDDBG(("WAV: Accepting data stream.\n")); 728 SNDDBG(("WAV: Accepting data stream.\n"));
692 return(1); /* we'll handle this data. */ 729 return(1); /* we'll handle this data. */
693 } /* WAV_open_internal */ 730 } /* WAV_open_internal */