From 567ee60d01a010beeb88db8eb3fb652080f5e7a8 Mon Sep 17 00:00:00 2001 From: Splendide Imaginarius <119545140+Splendide-Imaginarius@users.noreply.github.com> Date: Wed, 15 Nov 2023 03:33:24 +0000 Subject: [PATCH] Audio: use double for seeking At moderately large positions (e.g. 6 minutes at 48 KHz), float32 is only precise to 2 samples. --- src/audio/aldatasource.h | 2 +- src/audio/alstream.cpp | 9 +++++---- src/audio/alstream.h | 8 ++++---- src/audio/audio.cpp | 8 ++++---- src/audio/audio.h | 8 ++++---- src/audio/audiostream.cpp | 6 +++--- src/audio/audiostream.h | 6 +++--- src/audio/midisource.cpp | 2 +- src/audio/sdlsoundsource.cpp | 9 ++++++++- src/audio/vorbissource.cpp | 3 ++- 10 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/audio/aldatasource.h b/src/audio/aldatasource.h index 94dea90d..c2493d1f 100644 --- a/src/audio/aldatasource.h +++ b/src/audio/aldatasource.h @@ -44,7 +44,7 @@ struct ALDataSource /* If the source doesn't support seeking, it will * reset back to the beginning */ - virtual void seekToOffset(float seconds) = 0; + virtual void seekToOffset(double seconds) = 0; /* The frame count right after wrap around */ virtual uint32_t loopStartFrames() = 0; diff --git a/src/audio/alstream.cpp b/src/audio/alstream.cpp index 31690577..7b8abba1 100644 --- a/src/audio/alstream.cpp +++ b/src/audio/alstream.cpp @@ -123,7 +123,7 @@ void ALStream::stop() state = Stopped; } -void ALStream::play(float offset) +void ALStream::play(double offset) { if (!source) return; @@ -184,13 +184,14 @@ ALStream::State ALStream::queryState() return state; } -float ALStream::queryOffset() +double ALStream::queryOffset() { if (state == Closed || !source) return 0; - float procOffset = static_cast(procFrames) / source->sampleRate(); + double procOffset = static_cast(procFrames) / source->sampleRate(); + // TODO: getSecOffset returns a float, we should improve precision to double. return procOffset + AL::Source::getSecOffset(alSrc); } @@ -290,7 +291,7 @@ void ALStream::stopStream() procFrames = 0; } -void ALStream::startStream(float offset) +void ALStream::startStream(double offset) { AL::Source::clearQueue(alSrc); diff --git a/src/audio/alstream.h b/src/audio/alstream.h index 7391c4b5..48075503 100644 --- a/src/audio/alstream.h +++ b/src/audio/alstream.h @@ -64,7 +64,7 @@ struct ALStream AtomicFlag threadTermReq; AtomicFlag needsRewind; - float startOffset; + double startOffset; float pitch; @@ -95,13 +95,13 @@ struct ALStream void close(); void open(const std::string &filename); void stop(); - void play(float offset = 0); + void play(double offset = 0); void pause(); void setVolume(float value); void setPitch(float value); State queryState(); - float queryOffset(); + double queryOffset(); bool queryNativePitch(); private: @@ -109,7 +109,7 @@ private: void openSource(const std::string &filename); void stopStream(); - void startStream(float offset); + void startStream(double offset); void pauseStream(); void resumeStream(); diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 6fec3486..eaf4cc63 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -292,7 +292,7 @@ Audio::Audio(RGSSThreadData &rtData) void Audio::bgmPlay(const char *filename, int volume, int pitch, - float pos, + double pos, int track) { if (track == -127) { @@ -356,7 +356,7 @@ void Audio::bgmSetVolume(int volume, int track) void Audio::bgsPlay(const char *filename, int volume, int pitch, - float pos) + double pos) { p->bgs.play(filename, volume, pitch, pos); } @@ -407,12 +407,12 @@ void Audio::setupMidi() shState->midiState().initIfNeeded(shState->config()); } -float Audio::bgmPos(int track) +double Audio::bgmPos(int track) { return p->getTrackByIndex(track)->playingOffset(); } -float Audio::bgsPos() +double Audio::bgsPos() { return p->bgs.playingOffset(); } diff --git a/src/audio/audio.h b/src/audio/audio.h index 8231fcaa..b7d565a7 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -41,7 +41,7 @@ public: void bgmPlay(const char *filename, int volume = 100, int pitch = 100, - float pos = 0, + double pos = 0, int track = -127); void bgmStop(int track = -127); void bgmFade(int time, int track = -127); @@ -51,7 +51,7 @@ public: void bgsPlay(const char *filename, int volume = 100, int pitch = 100, - float pos = 0); + double pos = 0); void bgsStop(); void bgsFade(int time); @@ -67,8 +67,8 @@ public: void seStop(); void setupMidi(); - float bgmPos(int track = 0); - float bgsPos(); + double bgmPos(int track = 0); + double bgsPos(); void reset(); diff --git a/src/audio/audiostream.cpp b/src/audio/audiostream.cpp index 606016ee..76ec4e57 100644 --- a/src/audio/audiostream.cpp +++ b/src/audio/audiostream.cpp @@ -76,7 +76,7 @@ AudioStream::~AudioStream() void AudioStream::play(const std::string &filename, int volume, int pitch, - float offset) + double offset) { finiFadeOutInt(); @@ -222,7 +222,7 @@ void AudioStream::fadeOut(int duration) unlockStream(); } -void AudioStream::seek(float offset) +void AudioStream::seek(double offset) { lockStream(); stream.play(offset); @@ -253,7 +253,7 @@ float AudioStream::getVolume(VolumeType type) return volumes[type]; } -float AudioStream::playingOffset() +double AudioStream::playingOffset() { return stream.queryOffset(); } diff --git a/src/audio/audiostream.h b/src/audio/audiostream.h index 5f97fcca..f0805b30 100644 --- a/src/audio/audiostream.h +++ b/src/audio/audiostream.h @@ -127,10 +127,10 @@ struct AudioStream void play(const std::string &filename, int volume, int pitch, - float offset = 0); + double offset = 0); void stop(); void fadeOut(int duration); - void seek(float offset); + void seek(double offset); /* Any access to this classes 'stream' member, * whether state query or modification, must be @@ -141,7 +141,7 @@ struct AudioStream void setVolume(VolumeType type, float value); float getVolume(VolumeType type); - float playingOffset(); + double playingOffset(); private: float volumes[VolumeTypeCount]; diff --git a/src/audio/midisource.cpp b/src/audio/midisource.cpp index 431f07d1..d0c6bc35 100644 --- a/src/audio/midisource.cpp +++ b/src/audio/midisource.cpp @@ -891,7 +891,7 @@ struct MidiSource : ALDataSource, MidiReadHandler } /* Midi sources cannot seek, and so always reset to beginning */ - void seekToOffset(float) + void seekToOffset(double) { /* Reset synth */ fluid.synth_system_reset(synth); diff --git a/src/audio/sdlsoundsource.cpp b/src/audio/sdlsoundsource.cpp index 83bda06b..b9264fd8 100644 --- a/src/audio/sdlsoundsource.cpp +++ b/src/audio/sdlsoundsource.cpp @@ -101,12 +101,19 @@ struct SDLSoundSource : ALDataSource return sample->actual.rate; } - void seekToOffset(float seconds) + void seekToOffset(double seconds) { if (seconds <= 0) + { Sound_Rewind(sample); + } else + { + // Unfortunately there is no easy API in SDL_sound for seeking with better precision than 1ms. + // TODO: Work around this by manually consuming the remaining samples. + // TODO: Also we're flooring here when we probably should be rounding. Sound_Seek(sample, static_cast(seconds * 1000)); + } } uint32_t loopStartFrames() diff --git a/src/audio/vorbissource.cpp b/src/audio/vorbissource.cpp index d6deeeab..fc4687e0 100644 --- a/src/audio/vorbissource.cpp +++ b/src/audio/vorbissource.cpp @@ -156,7 +156,7 @@ struct VorbisSource : ALDataSource return info.rate; } - void seekToOffset(float seconds) + void seekToOffset(double seconds) { if (seconds <= 0) { @@ -164,6 +164,7 @@ struct VorbisSource : ALDataSource currentFrame = 0; } + // TODO: We're flooring here when we probably should be rounding. currentFrame = seconds * info.rate; if (loop.valid && currentFrame > loop.end)