From ea5dd02db9bdb9759a400907672ec6606bebb96b Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 18 Mar 2023 20:57:00 +0000 Subject: audio: Wait for samples on the emulated DSP side to avoid desyncs Waiting on the host side is inaccurate and leads to desyncs in the event of the sink missing a deadline that require stalls to fix. By waiting for the sink to have space before even starting rendering such desyncs can be avoided. --- src/audio_core/sink/sink_stream.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/audio_core/sink/sink_stream.cpp') diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 1af96f793..a54c61845 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -205,6 +205,10 @@ void SinkStream::ProcessAudioOutAndRender(std::span output_buffer, std::siz // If we're paused or going to shut down, we don't want to consume buffers as coretiming is // paused and we'll desync, so just play silence. if (system.IsPaused() || system.IsShuttingDown()) { + if (system.IsShuttingDown()) { + release_cv.notify_one(); + } + static constexpr std::array silence{}; for (size_t i = frames_written; i < num_frames; i++) { std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes); @@ -240,6 +244,12 @@ void SinkStream::ProcessAudioOutAndRender(std::span output_buffer, std::siz } // Successfully dequeued a new buffer. queued_buffers--; + + { + std::unique_lock lk{release_mutex}; + } + + release_cv.notify_one(); } // Get the minimum frames available between the currently playing buffer, and the @@ -303,4 +313,9 @@ u64 SinkStream::GetExpectedPlayedSampleCount() { return std::min(exp_played_sample_count, max_played_sample_count); } +void SinkStream::WaitFreeSpace() { + std::unique_lock lk{release_mutex}; + release_cv.wait(lk, [this]() { return queued_buffers < max_queue_size || system.IsShuttingDown(); }); +} + } // namespace AudioCore::Sink -- cgit v1.2.3