summaryrefslogtreecommitdiff
path: root/src/audio_core/sink
diff options
context:
space:
mode:
authorGravatar Billy Laws2023-03-18 20:57:00 +0000
committerGravatar Billy Laws2023-03-27 21:34:28 +0100
commitea5dd02db9bdb9759a400907672ec6606bebb96b (patch)
tree9f6f4f4662eb48ad57fe713e29f6b98778f263bf /src/audio_core/sink
parentaudio: Interpolate system manager sample count using host sink sample info (diff)
downloadyuzu-ea5dd02db9bdb9759a400907672ec6606bebb96b.tar.gz
yuzu-ea5dd02db9bdb9759a400907672ec6606bebb96b.tar.xz
yuzu-ea5dd02db9bdb9759a400907672ec6606bebb96b.zip
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.
Diffstat (limited to 'src/audio_core/sink')
-rw-r--r--src/audio_core/sink/sink_stream.cpp15
-rw-r--r--src/audio_core/sink/sink_stream.h9
2 files changed, 24 insertions, 0 deletions
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<s16> output_buffer, std::siz
205 // If we're paused or going to shut down, we don't want to consume buffers as coretiming is 205 // If we're paused or going to shut down, we don't want to consume buffers as coretiming is
206 // paused and we'll desync, so just play silence. 206 // paused and we'll desync, so just play silence.
207 if (system.IsPaused() || system.IsShuttingDown()) { 207 if (system.IsPaused() || system.IsShuttingDown()) {
208 if (system.IsShuttingDown()) {
209 release_cv.notify_one();
210 }
211
208 static constexpr std::array<s16, 6> silence{}; 212 static constexpr std::array<s16, 6> silence{};
209 for (size_t i = frames_written; i < num_frames; i++) { 213 for (size_t i = frames_written; i < num_frames; i++) {
210 std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes); 214 std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes);
@@ -240,6 +244,12 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
240 } 244 }
241 // Successfully dequeued a new buffer. 245 // Successfully dequeued a new buffer.
242 queued_buffers--; 246 queued_buffers--;
247
248 {
249 std::unique_lock lk{release_mutex};
250 }
251
252 release_cv.notify_one();
243 } 253 }
244 254
245 // Get the minimum frames available between the currently playing buffer, and the 255 // Get the minimum frames available between the currently playing buffer, and the
@@ -303,4 +313,9 @@ u64 SinkStream::GetExpectedPlayedSampleCount() {
303 return std::min<u64>(exp_played_sample_count, max_played_sample_count); 313 return std::min<u64>(exp_played_sample_count, max_played_sample_count);
304} 314}
305 315
316void SinkStream::WaitFreeSpace() {
317 std::unique_lock lk{release_mutex};
318 release_cv.wait(lk, [this]() { return queued_buffers < max_queue_size || system.IsShuttingDown(); });
319}
320
306} // namespace AudioCore::Sink 321} // namespace AudioCore::Sink
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h
index 2340c936c..709f3b0ec 100644
--- a/src/audio_core/sink/sink_stream.h
+++ b/src/audio_core/sink/sink_stream.h
@@ -16,6 +16,7 @@
16#include "common/reader_writer_queue.h" 16#include "common/reader_writer_queue.h"
17#include "common/ring_buffer.h" 17#include "common/ring_buffer.h"
18#include "common/thread.h" 18#include "common/thread.h"
19#include "common/polyfill_thread.h"
19 20
20namespace Core { 21namespace Core {
21class System; 22class System;
@@ -219,6 +220,11 @@ public:
219 */ 220 */
220 u64 GetExpectedPlayedSampleCount(); 221 u64 GetExpectedPlayedSampleCount();
221 222
223 /**
224 * Waits for free space in the sample ring buffer
225 */
226 void WaitFreeSpace();
227
222protected: 228protected:
223 /// Core system 229 /// Core system
224 Core::System& system; 230 Core::System& system;
@@ -258,6 +264,9 @@ private:
258 f32 system_volume{1.0f}; 264 f32 system_volume{1.0f};
259 /// Set via IAudioDevice service calls 265 /// Set via IAudioDevice service calls
260 f32 device_volume{1.0f}; 266 f32 device_volume{1.0f};
267 /// Signalled when ring buffer entries are consumed
268 std::condition_variable release_cv;
269 std::mutex release_mutex;
261 std::mutex stall_guard; 270 std::mutex stall_guard;
262 std::unique_lock<std::mutex> stalled_lock; 271 std::unique_lock<std::mutex> stalled_lock;
263}; 272};