# HG changeset patch # User Ryan C. Gordon # Date 1021896715 0 # Node ID f6475949cd590af3cc01ae5f86ce6722991c9e9d # Parent f0f894d897bf636fe3fceb167603df86e12c452b Implemented seek method. diff -r f0f894d897bf -r f6475949cd59 decoders/voc.c --- a/decoders/voc.c Mon May 20 11:20:39 2002 +0000 +++ b/decoders/voc.c Mon May 20 12:11:55 2002 +0000 @@ -380,10 +380,10 @@ } return 1; -} +} /* voc_get_block */ -static int voc_read_waveform(Sound_Sample *sample) +static int voc_read_waveform(Sound_Sample *sample, int fill_buf, Uint32 max) { Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; SDL_RWops *src = internal->rw; @@ -396,30 +396,45 @@ { if (!voc_get_block(sample)) return 0; - } + } /* if */ if (v->rest == 0) return 0; + max = (v->rest < max) ? v->rest : max; + if (v->silent) { if (v->size == ST_SIZE_WORD) silence = 0x00; /* Fill in silence */ - memset(buf, silence, v->rest); - done = v->rest; - v->rest = 0; - } + if (fill_buf) + memset(buf + v->bufpos, silence, max); + + done = max; + v->rest -= done; + } /* if */ else { - Uint32 max = (v->rest < internal->buffer_size) ? - v->rest : internal->buffer_size; - done = SDL_RWread(src, buf + v->bufpos, 1, max); + if (fill_buf) + done = SDL_RWread(src, buf + v->bufpos, 1, max); + else + { + int cur, rc; + cur = SDL_RWtell(src); + if (cur >= 0) + { + rc = SDL_RWseek(src, max, SEEK_CUR); + if (rc >= 0) + done = rc - cur; + } /* if */ + } /* else */ + v->rest -= done; v->bufpos += done; - } + } /* else */ return done; } /* voc_read_waveform */ @@ -456,7 +471,7 @@ SNDDBG(("VOC: Accepting data stream.\n")); sample->actual.format = (v->size == ST_SIZE_WORD) ? AUDIO_S16LSB:AUDIO_U8; sample->actual.channels = v->channels; - sample->flags = SOUND_SAMPLEFLAG_NONE; + sample->flags = SOUND_SAMPLEFLAG_CANSEEK; return(1); } /* VOC_open */ @@ -476,7 +491,7 @@ v->bufpos = 0; while (v->bufpos < internal->buffer_size) { - Uint32 rc = voc_read_waveform(sample); + Uint32 rc = voc_read_waveform(sample, 1, internal->buffer_size); if (rc == 0) /* !!! FIXME: Could be an error... */ { sample->flags |= SOUND_SAMPLEFLAG_EOF; @@ -507,10 +522,42 @@ static int VOC_seek(Sound_Sample *sample, Uint32 ms) { - BAIL_MACRO("!!! FIXME: Not implemented", 0); + /* + * VOCs don't lend themselves well to seeking, since you have to + * parse each section, which is an arbitrary size. The best we can do + * is rewind, set a flag saying not to write the waveforms to a buffer, + * and decode to the point that we want. Ugh. Fortunately, there's + * really no such thing as a large VOC, due to the era and hardware that + * spawned them, so even though this is inefficient, this is still a + * relatively fast operation in most cases. + */ + + Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; + vs_t *v = (vs_t *) internal->decoder_private; + int offset = __Sound_convertMsToBytePos(&sample->actual, ms); + int origpos = SDL_RWtell(internal->rw); + int origrest = v->rest; + + BAIL_IF_MACRO(!VOC_rewind(sample), NULL, 0); + + v->bufpos = 0; + + while (offset > 0) + { + Uint32 rc = voc_read_waveform(sample, 0, offset); + if ( (rc == 0) || (!voc_get_block(sample)) ) + { + SDL_RWseek(internal->rw, origpos, SEEK_SET); + v->rest = origrest; + return(0); + } /* if */ + + offset -= rc; + } /* while */ + + return(1); } /* VOC_seek */ - #endif /* SOUND_SUPPORTS_VOC */ /* end of voc.c ... */