diff options
| -rw-r--r-- | src/audio_core/device/device_session.cpp | 3 | ||||
| -rw-r--r-- | src/audio_core/renderer/system_manager.cpp | 1 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_stream.cpp | 21 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_stream.h | 17 |
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 | ||
| 123 | std::optional<std::chrono::nanoseconds> DeviceSession::ThreadFunc() { | 123 | std::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 | ||
| 17 | namespace AudioCore::AudioRenderer { | 17 | namespace AudioCore::AudioRenderer { |
| 18 | constexpr std::chrono::nanoseconds RENDER_TIME{5'000'000UL}; | ||
| 19 | 18 | ||
| 20 | SystemManager::SystemManager(Core::System& core_) | 19 | SystemManager::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 | ||
| 18 | namespace AudioCore::Sink { | 20 | namespace 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 | ||
| 296 | u64 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 | ||
| 18 | namespace Core { | 20 | namespace Core { |
| 19 | class System; | 21 | class 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 | |||
| 213 | protected: | 222 | protected: |
| 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 |