From 4af1d096deebdebbca6d19456b19eb00ae42c01a Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Fri, 13 Dec 2024 15:58:32 +0100 Subject: [PATCH] audio: reset buffer on loadstate/term. Fix null audio driver on windows Eliminate audio clicks when loading a state or starting the next game. Fix overflow in null audio driver on windows. Detect fast forward and reset time counter. --- core/audio/audiobackend_null.cpp | 19 +++++++++++-------- core/audio/audiostream.cpp | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/core/audio/audiobackend_null.cpp b/core/audio/audiobackend_null.cpp index 67c935a7b..95a6b5647 100644 --- a/core/audio/audiobackend_null.cpp +++ b/core/audio/audiobackend_null.cpp @@ -19,17 +19,20 @@ public: u32 push(const void* frame, u32 samples, bool wait) override { - if (wait) + if (wait && last_time.time_since_epoch() != the_clock::duration::zero()) { - if (last_time.time_since_epoch() != the_clock::duration::zero()) - { - auto fduration = std::chrono::nanoseconds(1000000000L * samples / 44100); - auto duration = fduration - (the_clock::now() - last_time); + auto fduration = std::chrono::nanoseconds(1'000'000'000LL * samples / 44100); + auto duration = fduration - (the_clock::now() - last_time); + if (duration > std::chrono::nanoseconds::zero()) std::this_thread::sleep_for(duration); - last_time += fduration; - } - else + if (duration < -std::chrono::milliseconds(67)) + // if ~4 frames ahead, reset time (fast forward detection) last_time = the_clock::now(); + else + last_time += fduration; + } + else { + last_time = the_clock::now(); } return 1; } diff --git a/core/audio/audiostream.cpp b/core/audio/audiostream.cpp index 4a6694edf..15f9a3965 100644 --- a/core/audio/audiostream.cpp +++ b/core/audio/audiostream.cpp @@ -1,5 +1,8 @@ #include "audiostream.h" #include "cfg/option.h" +#include "emulator.h" + +static void registerForEvents(); struct SoundFrame { s16 l; s16 r; }; @@ -60,6 +63,7 @@ void WriteSample(s16 r, s16 l) void InitAudio() { + registerForEvents(); TermAudio(); std::string slug = config::AudioBackend; @@ -138,3 +142,19 @@ void StopAudioRecording() currentBackend->termRecord(); audio_recording_started = false; } + +static void registerForEvents() +{ + static bool done; + if (done) + return; + done = true; + // Empty the audio buffer when loading a state or terminating the game + const auto& callback = [](Event, void *) { + writePtr = 0; + }; + EventManager::listen(Event::Terminate, callback); + EventManager::listen(Event::LoadState, callback); +} + +