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.
This commit is contained in:
Flyinghead 2024-12-13 15:58:32 +01:00
parent 27a0497dd5
commit 4af1d096de
2 changed files with 31 additions and 8 deletions

View File

@ -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;
}

View File

@ -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);
}