diff options
author | Kelebek1 <eeeedddccc@hotmail.co.uk> | 2022-08-01 03:58:13 +0200 |
---|---|---|
committer | Kelebek1 <eeeedddccc@hotmail.co.uk> | 2022-09-02 05:43:04 +0200 |
commit | ea9ff71725113b8dbb159917c57aa536bba0cb53 (patch) | |
tree | 512cce0fea5eb511aa7803bc67f741815885bfcb /src/audio_core/device | |
parent | Merge pull request #8752 from vonchenplus/rectangle_texture (diff) | |
download | yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.tar yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.tar.gz yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.tar.bz2 yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.tar.lz yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.tar.xz yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.tar.zst yuzu-ea9ff71725113b8dbb159917c57aa536bba0cb53.zip |
Diffstat (limited to 'src/audio_core/device')
-rw-r--r-- | src/audio_core/device/audio_buffer.h | 4 | ||||
-rw-r--r-- | src/audio_core/device/audio_buffers.h | 13 | ||||
-rw-r--r-- | src/audio_core/device/device_session.cpp | 52 | ||||
-rw-r--r-- | src/audio_core/device/device_session.h | 27 |
4 files changed, 75 insertions, 21 deletions
diff --git a/src/audio_core/device/audio_buffer.h b/src/audio_core/device/audio_buffer.h index cae7fa970..7128ef72a 100644 --- a/src/audio_core/device/audio_buffer.h +++ b/src/audio_core/device/audio_buffer.h @@ -8,6 +8,10 @@ namespace AudioCore { struct AudioBuffer { + /// Timestamp this buffer started playing. + u64 start_timestamp; + /// Timestamp this buffer should finish playing. + u64 end_timestamp; /// Timestamp this buffer completed playing. s64 played_timestamp; /// Game memory address for these samples. diff --git a/src/audio_core/device/audio_buffers.h b/src/audio_core/device/audio_buffers.h index 5d1979ea0..57c78d439 100644 --- a/src/audio_core/device/audio_buffers.h +++ b/src/audio_core/device/audio_buffers.h @@ -58,6 +58,7 @@ public: if (index < 0) { index += N; } + out_buffers.push_back(buffers[index]); registered_count++; registered_index = (registered_index + 1) % append_limit; @@ -100,7 +101,7 @@ public: } // Check with the backend if this buffer can be released yet. - if (!session.IsBufferConsumed(buffers[index].tag)) { + if (!session.IsBufferConsumed(buffers[index])) { break; } @@ -280,6 +281,16 @@ public: return true; } + u64 GetNextTimestamp() const { + // Iterate backwards through the buffer queue, and take the most recent buffer's end + std::scoped_lock l{lock}; + auto index{appended_index - 1}; + if (index < 0) { + index += append_limit; + } + return buffers[index].end_timestamp; + } + private: /// Buffer lock mutable std::recursive_mutex lock{}; diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp index 095fc96ce..c71c3a376 100644 --- a/src/audio_core/device/device_session.cpp +++ b/src/audio_core/device/device_session.cpp @@ -7,11 +7,20 @@ #include "audio_core/device/device_session.h" #include "audio_core/sink/sink_stream.h" #include "core/core.h" +#include "core/core_timing.h" #include "core/memory.h" namespace AudioCore { -DeviceSession::DeviceSession(Core::System& system_) : system{system_} {} +using namespace std::literals; +constexpr auto INCREMENT_TIME{5ms}; + +DeviceSession::DeviceSession(Core::System& system_) + : system{system_}, thread_event{Core::Timing::CreateEvent( + "AudioOutSampleTick", + [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) { + return ThreadFunc(); + })} {} DeviceSession::~DeviceSession() { Finalize(); @@ -50,20 +59,21 @@ void DeviceSession::Finalize() { } void DeviceSession::Start() { - stream->SetPlayedSampleCount(played_sample_count); - stream->Start(); + if (stream) { + stream->Start(); + system.CoreTiming().ScheduleLoopingEvent(std::chrono::nanoseconds::zero(), INCREMENT_TIME, + thread_event); + } } void DeviceSession::Stop() { if (stream) { - played_sample_count = stream->GetPlayedSampleCount(); stream->Stop(); + system.CoreTiming().UnscheduleEvent(thread_event, {}); } } void DeviceSession::AppendBuffers(std::span<AudioBuffer> buffers) const { - auto& memory{system.Memory()}; - for (size_t i = 0; i < buffers.size(); i++) { Sink::SinkBuffer new_buffer{ .frames = buffers[i].size / (channel_count * sizeof(s16)), @@ -77,7 +87,7 @@ void DeviceSession::AppendBuffers(std::span<AudioBuffer> buffers) const { stream->AppendBuffer(new_buffer, samples); } else { std::vector<s16> samples(buffers[i].size / sizeof(s16)); - memory.ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size); + system.Memory().ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size); stream->AppendBuffer(new_buffer, samples); } } @@ -85,17 +95,13 @@ void DeviceSession::AppendBuffers(std::span<AudioBuffer> buffers) const { void DeviceSession::ReleaseBuffer(AudioBuffer& buffer) const { if (type == Sink::StreamType::In) { - auto& memory{system.Memory()}; auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))}; - memory.WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size); + system.Memory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size); } } -bool DeviceSession::IsBufferConsumed(u64 tag) const { - if (stream) { - return stream->IsBufferConsumed(tag); - } - return true; +bool DeviceSession::IsBufferConsumed(AudioBuffer& buffer) const { + return played_sample_count >= buffer.end_timestamp; } void DeviceSession::SetVolume(f32 volume) const { @@ -105,10 +111,22 @@ void DeviceSession::SetVolume(f32 volume) const { } u64 DeviceSession::GetPlayedSampleCount() const { - if (stream) { - return stream->GetPlayedSampleCount(); + return played_sample_count; +} + +std::optional<std::chrono::nanoseconds> DeviceSession::ThreadFunc() { + // Add 5ms of samples at a 48K sample rate. + played_sample_count += 48'000 * INCREMENT_TIME / 1s; + if (type == Sink::StreamType::Out) { + system.AudioCore().GetAudioManager().SetEvent(Event::Type::AudioOutManager, true); + } else { + system.AudioCore().GetAudioManager().SetEvent(Event::Type::AudioInManager, true); } - return 0; + return std::nullopt; +} + +void DeviceSession::SetRingSize(u32 ring_size) { + stream->SetRingSize(ring_size); } } // namespace AudioCore diff --git a/src/audio_core/device/device_session.h b/src/audio_core/device/device_session.h index 4a031b765..3414e2c06 100644 --- a/src/audio_core/device/device_session.h +++ b/src/audio_core/device/device_session.h @@ -3,6 +3,9 @@ #pragma once +#include <chrono> +#include <memory> +#include <optional> #include <span> #include "audio_core/common/common.h" @@ -11,9 +14,13 @@ namespace Core { class System; -} +namespace Timing { +struct EventType; +} // namespace Timing +} // namespace Core namespace AudioCore { + namespace Sink { class SinkStream; struct SinkBuffer; @@ -70,7 +77,7 @@ public: * @param tag - Unqiue tag of the buffer to check. * @return true if the buffer has been consumed, otherwise false. */ - bool IsBufferConsumed(u64 tag) const; + bool IsBufferConsumed(AudioBuffer& buffer) const; /** * Start this device session, starting the backend stream. @@ -96,6 +103,16 @@ public: */ u64 GetPlayedSampleCount() const; + /* + * CoreTiming callback to increment played_sample_count over time. + */ + std::optional<std::chrono::nanoseconds> ThreadFunc(); + + /* + * Set the size of the ring buffer. + */ + void SetRingSize(u32 ring_size); + private: /// System Core::System& system; @@ -118,9 +135,13 @@ private: /// Applet resource user id of this device session u64 applet_resource_user_id{}; /// Total number of samples played by this device session - u64 played_sample_count{}; + std::atomic<u64> played_sample_count{}; + /// Event increasing the played sample count every 5ms + std::shared_ptr<Core::Timing::EventType> thread_event; /// Is this session initialised? bool initialized{}; + /// Buffer queue + std::vector<AudioBuffer> buffer_queue{}; }; } // namespace AudioCore |