diff --git a/include/snd_render.h b/include/snd_render.h index 0ca04d188..4198043cf 100644 --- a/include/snd_render.h +++ b/include/snd_render.h @@ -60,6 +60,7 @@ struct sfxbuffer_s { unsigned int bps; // bytes per sample: 1 2 4 usually void (*paint) (channel_t *ch, sfxbuffer_t *buffer, int count); void (*advance) (sfxbuffer_t *buffer, unsigned int count); + void (*setpos) (sfxbuffer_t *buffer, unsigned int pos); sfx_t *sfx; byte data[4]; }; @@ -147,6 +148,7 @@ void SND_CacheRelease (sfx_t *sfx); sfxbuffer_t *SND_StreamRetain (sfx_t *sfx); void SND_StreamRelease (sfx_t *sfx); void SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count); +void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos); void SND_WriteLinearBlastStereo16 (void); void SND_PaintChannelFrom8 (channel_t *ch, sfxbuffer_t *sc, int count); diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index e79cf69b1..b19a2a3d9 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -156,16 +156,77 @@ read_samples (sfxbuffer_t *buffer, int count, void *prev) } } +static void +fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer, + wavinfo_t *info, unsigned int headpos) +{ + void *prev; + unsigned int samples; + unsigned int loop_samples = 0; + + // find out how many samples can be read into the buffer + samples = buffer->tail - buffer->head - SAMPLE_GAP; + if (buffer->tail <= buffer->head) + samples += buffer->length; + + if (headpos + samples > sfx->length) { + if (sfx->loopstart == (unsigned int)-1) { + samples = sfx->length - headpos; + } else { + loop_samples = headpos + samples - sfx->length; + samples -= loop_samples; + } + } + if (samples) { + if (buffer->head != buffer->tail) { + int s = buffer->head - 1; + if (!buffer->head) + s += buffer->length; + prev = buffer->data + s * buffer->bps; + } else { + prev = 0; + } + read_samples (buffer, samples, prev); + } + if (loop_samples) { + if (buffer->head != buffer->tail) { + int s = buffer->head - 1; + if (!buffer->head) + s += buffer->length; + prev = buffer->data + s * buffer->bps; + } else { + prev = 0; + } + stream->seek (stream->file, info->loopstart, info); + read_samples (buffer, loop_samples, prev); + } +} + +void +SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos) +{ + float stepscale; + sfx_t *sfx = buffer->sfx; + sfxstream_t *stream = (sfxstream_t *) sfx->data; + wavinfo_t *info = &stream->wavinfo; + + stepscale = (float) info->rate / shm->speed; // usually 0.5, 1, or 2 + + buffer->head = buffer->tail = 0; + buffer->pos = pos; + stream->pos = pos; + stream->seek (stream->file, buffer->pos * stepscale, info); + fill_buffer (sfx, stream, buffer, info, pos); +} + void SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) { float stepscale; unsigned int headpos, samples; - unsigned int loop_samples = 0; sfx_t *sfx = buffer->sfx; sfxstream_t *stream = (sfxstream_t *) sfx->data; wavinfo_t *info = &stream->wavinfo; - void *prev; stream->pos += count; count = (stream->pos - buffer->pos) & ~255; @@ -223,43 +284,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) if (buffer->tail >= buffer->length) buffer->tail -= buffer->length; } - - // find out how many samples can be read into the buffer - samples = buffer->tail - buffer->head - SAMPLE_GAP; - if (buffer->tail <= buffer->head) - samples += buffer->length; - - if (headpos + samples > sfx->length) { - if (sfx->loopstart == (unsigned int)-1) { - samples = sfx->length - headpos; - } else { - loop_samples = headpos + samples - sfx->length; - samples -= loop_samples; - } - } - if (samples) { - if (buffer->head != buffer->tail) { - int s = buffer->head - 1; - if (!buffer->head) - s += buffer->length; - prev = buffer->data + s * buffer->bps; - } else { - prev = 0; - } - read_samples (buffer, samples, prev); - } - if (loop_samples) { - if (buffer->head != buffer->tail) { - int s = buffer->head - 1; - if (!buffer->head) - s += buffer->length; - prev = buffer->data + s * buffer->bps; - } else { - prev = 0; - } - stream->seek (stream->file, info->loopstart, info); - read_samples (buffer, loop_samples, prev); - } + fill_buffer (sfx, stream, buffer, info, headpos); } void diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 1610d4ddc..8573e2c7e 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -423,11 +423,9 @@ SND_PaintChannelFrom8 (channel_t *ch, sfxbuffer_t *sc, int count) unsigned int pos; byte *samps; + if (ch->pos < sc->pos) + sc->setpos (sc, ch->pos); pos = (ch->pos - sc->pos + sc->tail) % sc->length; - if (pos < 0) { // FIXME need a better way to handle shared streams - pos = sc->tail; - ch->pos = sc->pos; - } samps = sc->data + pos; if (pos + count > sc->length) { @@ -446,11 +444,9 @@ SND_PaintChannelFrom16 (channel_t *ch, sfxbuffer_t *sc, int count) unsigned int pos; short *samps; + if (ch->pos < sc->pos) + sc->setpos (sc, ch->pos); pos = (ch->pos - sc->pos + sc->tail) % sc->length; - if (pos < 0) { // FIXME need a better way to handle shared streams - pos = sc->tail; - ch->pos = sc->pos; - } samps = (short *) sc->data + pos; if (pos + count > sc->length) { @@ -469,11 +465,9 @@ SND_PaintChannelStereo8 (channel_t *ch, sfxbuffer_t *sc, int count) unsigned int pos; short *samps; + if (ch->pos < sc->pos) + sc->setpos (sc, ch->pos); pos = (ch->pos - sc->pos + sc->tail) % sc->length; - if (pos < 0) { // FIXME need a better way to handle shared streams - pos = sc->tail; - ch->pos = sc->pos; - } samps = (short *) sc->data + pos; if (pos + count > sc->length) { @@ -492,11 +486,9 @@ SND_PaintChannelStereo16 (channel_t *ch, sfxbuffer_t *sc, int count) unsigned int pos; int *samps; + if (ch->pos < sc->pos) + sc->setpos (sc, ch->pos); pos = (ch->pos - sc->pos + sc->tail) % sc->length; - if (pos < 0) { // FIXME need a better way to handle shared streams - pos = sc->tail; - ch->pos = sc->pos; - } samps = (int *) sc->data + pos; if (pos + count > sc->length) { diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 436b74fb4..220de84c5 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -298,6 +298,7 @@ vorbis_stream_open (sfx_t *_sfx) stream->buffer.length = samples; stream->buffer.advance = SND_StreamAdvance; + stream->buffer.setpos = SND_StreamSetPos; stream->buffer.sfx = sfx; stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index f5450b00b..33fec985c 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -162,6 +162,7 @@ wav_stream_open (sfx_t *_sfx) stream->buffer.length = samples; stream->buffer.advance = SND_StreamAdvance; + stream->buffer.setpos = SND_StreamSetPos; stream->buffer.sfx = sfx; stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly