summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio_core/device/device_session.cpp3
-rw-r--r--src/audio_core/renderer/system_manager.cpp1
-rw-r--r--src/audio_core/sink/sink_stream.cpp21
-rw-r--r--src/audio_core/sink/sink_stream.h17
4 files changed, 39 insertions, 3 deletions
diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp
index 5a327a606..ad0f40e28 100644
--- a/src/audio_core/device/device_session.cpp
+++ b/src/audio_core/device/device_session.cpp
@@ -121,8 +121,7 @@ u64 DeviceSession::GetPlayedSampleCount() const {
121} 121}
122 122
123std::optional<std::chrono::nanoseconds> DeviceSession::ThreadFunc() { 123std::optional<std::chrono::nanoseconds> DeviceSession::ThreadFunc() {
124 // Add 5ms of samples at a 48K sample rate. 124 played_sample_count = stream->GetExpectedPlayedSampleCount();
125 played_sample_count += 48'000 * INCREMENT_TIME / 1s;
126 if (type == Sink::StreamType::Out) { 125 if (type == Sink::StreamType::Out) {
127 system.AudioCore().GetAudioManager().SetEvent(Event::Type::AudioOutManager, true); 126 system.AudioCore().GetAudioManager().SetEvent(Event::Type::AudioOutManager, true);
128 } else { 127 } else {
diff --git a/src/audio_core/renderer/system_manager.cpp b/src/audio_core/renderer/system_manager.cpp
index ce631f810..9ddfa4a91 100644
--- a/src/audio_core/renderer/system_manager.cpp
+++ b/src/audio_core/renderer/system_manager.cpp
@@ -15,7 +15,6 @@ MICROPROFILE_DEFINE(Audio_RenderSystemManager, "Audio", "Render System Manager",
15 MP_RGB(60, 19, 97)); 15 MP_RGB(60, 19, 97));
16 16
17namespace AudioCore::AudioRenderer { 17namespace AudioCore::AudioRenderer {
18constexpr std::chrono::nanoseconds RENDER_TIME{5'000'000UL};
19 18
20SystemManager::SystemManager(Core::System& core_) 19SystemManager::SystemManager(Core::System& core_)
21 : core{core_}, adsp{core.AudioCore().GetADSP()}, mailbox{adsp.GetRenderMailbox()}, 20 : core{core_}, adsp{core.AudioCore().GetADSP()}, mailbox{adsp.GetRenderMailbox()},
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp
index 39a21b0f0..1af96f793 100644
--- a/src/audio_core/sink/sink_stream.cpp
+++ b/src/audio_core/sink/sink_stream.cpp
@@ -14,6 +14,8 @@
14#include "common/fixed_point.h" 14#include "common/fixed_point.h"
15#include "common/settings.h" 15#include "common/settings.h"
16#include "core/core.h" 16#include "core/core.h"
17#include "core/core_timing.h"
18#include "core/core_timing_util.h"
17 19
18namespace AudioCore::Sink { 20namespace AudioCore::Sink {
19 21
@@ -198,6 +200,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
198 const std::size_t frame_size = num_channels; 200 const std::size_t frame_size = num_channels;
199 const std::size_t frame_size_bytes = frame_size * sizeof(s16); 201 const std::size_t frame_size_bytes = frame_size * sizeof(s16);
200 size_t frames_written{0}; 202 size_t frames_written{0};
203 size_t actual_frames_written{0};
201 204
202 // 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
203 // paused and we'll desync, so just play silence. 206 // paused and we'll desync, so just play silence.
@@ -248,6 +251,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
248 frames_available * frame_size); 251 frames_available * frame_size);
249 252
250 frames_written += frames_available; 253 frames_written += frames_available;
254 actual_frames_written += frames_available;
251 playing_buffer.frames_played += frames_available; 255 playing_buffer.frames_played += frames_available;
252 256
253 // If that's all the frames in the current buffer, add its samples and mark it as 257 // If that's all the frames in the current buffer, add its samples and mark it as
@@ -260,6 +264,13 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
260 std::memcpy(&last_frame[0], &output_buffer[(frames_written - 1) * frame_size], 264 std::memcpy(&last_frame[0], &output_buffer[(frames_written - 1) * frame_size],
261 frame_size_bytes); 265 frame_size_bytes);
262 266
267 {
268 std::scoped_lock lk{sample_count_lock};
269 last_sample_count_update_time = Core::Timing::CyclesToUs(system.CoreTiming().GetClockTicks());
270 min_played_sample_count = max_played_sample_count;
271 max_played_sample_count += actual_frames_written;
272 }
273
263 if (system.IsMulticore() && queued_buffers <= max_queue_size) { 274 if (system.IsMulticore() && queued_buffers <= max_queue_size) {
264 Unstall(); 275 Unstall();
265 } 276 }
@@ -282,4 +293,14 @@ void SinkStream::Unstall() {
282 stalled_lock.unlock(); 293 stalled_lock.unlock();
283} 294}
284 295
296u64 SinkStream::GetExpectedPlayedSampleCount() {
297 std::scoped_lock lk{sample_count_lock};
298 auto cur_time{Core::Timing::CyclesToUs(system.CoreTiming().GetClockTicks())};
299 auto time_delta{cur_time - last_sample_count_update_time};
300 auto exp_played_sample_count{min_played_sample_count +
301 (TargetSampleRate * time_delta) / std::chrono::seconds{1}};
302
303 return std::min<u64>(exp_played_sample_count, max_played_sample_count);
304}
305
285} // namespace AudioCore::Sink 306} // namespace AudioCore::Sink
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h
index 5fea72ab7..2340c936c 100644
--- a/src/audio_core/sink/sink_stream.h
+++ b/src/audio_core/sink/sink_stream.h
@@ -5,6 +5,7 @@
5 5
6#include <array> 6#include <array>
7#include <atomic> 7#include <atomic>
8#include <chrono>
8#include <memory> 9#include <memory>
9#include <mutex> 10#include <mutex>
10#include <span> 11#include <span>
@@ -14,6 +15,7 @@
14#include "common/common_types.h" 15#include "common/common_types.h"
15#include "common/reader_writer_queue.h" 16#include "common/reader_writer_queue.h"
16#include "common/ring_buffer.h" 17#include "common/ring_buffer.h"
18#include "common/thread.h"
17 19
18namespace Core { 20namespace Core {
19class System; 21class System;
@@ -210,6 +212,13 @@ public:
210 */ 212 */
211 void Unstall(); 213 void Unstall();
212 214
215 /**
216 * Get the total number of samples expected to have been played by this stream.
217 *
218 * @return The number of samples.
219 */
220 u64 GetExpectedPlayedSampleCount();
221
213protected: 222protected:
214 /// Core system 223 /// Core system
215 Core::System& system; 224 Core::System& system;
@@ -237,6 +246,14 @@ private:
237 std::atomic<u32> queued_buffers{}; 246 std::atomic<u32> queued_buffers{};
238 /// The ring size for audio out buffers (usually 4, rarely 2 or 8) 247 /// The ring size for audio out buffers (usually 4, rarely 2 or 8)
239 u32 max_queue_size{}; 248 u32 max_queue_size{};
249 /// Locks access to sample count tracking info
250 std::mutex sample_count_lock;
251 /// Minimum number of total samples that have been played since the last callback
252 u64 min_played_sample_count{};
253 /// Maximum number of total samples that can be played since the last callback
254 u64 max_played_sample_count{};
255 /// The time the two above tracking variables were last written to
256 std::chrono::microseconds last_sample_count_update_time{};
240 /// Set by the audio render/in/out system which uses this stream 257 /// Set by the audio render/in/out system which uses this stream
241 f32 system_volume{1.0f}; 258 f32 system_volume{1.0f};
242 /// Set via IAudioDevice service calls 259 /// Set via IAudioDevice service calls