Compare commits

...

7 Commits

Author SHA1 Message Date
lizzie 1fe88221d1 2026-09-23 11:51:29
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-23 11:51:29 +00:00
lizzie e9bfd97c7f 2026-09-23 09:25:56
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-23 09:25:56 +00:00
lizzie 773c29ed85 2026-09-09 16:05:11
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-23 10:42:17 +02:00
lizzie 09f05f0313 2026-09-07 23:31:06
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-23 10:42:17 +02:00
lizzie 3b03ade8d8 2026-09-07 23:30:42
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-23 10:42:17 +02:00
lizzie 78cacac308 fix span shit 2026-09-23 10:42:17 +02:00
lizzie 84f43f2c63 [audio_core] remove dangling Core::System& references
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-23 10:42:17 +02:00
26 changed files with 223 additions and 253 deletions
+1 -1
View File
@@ -12,7 +12,7 @@
namespace AudioCore { namespace AudioCore {
AudioCore::AudioCore(Core::System& system) { AudioCore::AudioCore(Core::System& system) {
audio_manager.emplace(); audio_manager.emplace(system);
CreateSinks(); CreateSinks();
// Must be created after the sinks // Must be created after the sinks
adsp.emplace(system, *output_sink); adsp.emplace(system, *output_sink);
+12 -15
View File
@@ -15,12 +15,12 @@
namespace AudioCore::AudioIn { namespace AudioCore::AudioIn {
Manager::Manager(Core::System& system_) : system{system_} { Manager::Manager(Core::System& system) {
std::iota(session_ids.begin(), session_ids.end(), 0); std::iota(session_ids.begin(), session_ids.end(), 0);
num_free_sessions = MaxInSessions; num_free_sessions = MaxInSessions;
} }
Result Manager::AcquireSessionId(size_t& session_id) { Result Manager::AcquireSessionId(Core::System& system, size_t& session_id) {
if (num_free_sessions == 0) { if (num_free_sessions == 0) {
LOG_ERROR(Service_Audio, "All 4 AudioIn sessions are in use, cannot create any more"); LOG_ERROR(Service_Audio, "All 4 AudioIn sessions are in use, cannot create any more");
return Service::Audio::ResultOutOfSessions; return Service::Audio::ResultOutOfSessions;
@@ -31,7 +31,7 @@ Result Manager::AcquireSessionId(size_t& session_id) {
return ResultSuccess; return ResultSuccess;
} }
void Manager::ReleaseSessionId(const size_t session_id) { void Manager::ReleaseSessionId(Core::System& system, const size_t session_id) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LOG_DEBUG(Service_Audio, "Freeing AudioIn session {}", session_id); LOG_DEBUG(Service_Audio, "Freeing AudioIn session {}", session_id);
session_ids[free_session_id] = session_id; session_ids[free_session_id] = session_id;
@@ -41,21 +41,20 @@ void Manager::ReleaseSessionId(const size_t session_id) {
applet_resource_user_ids[session_id] = 0; applet_resource_user_ids[session_id] = 0;
} }
Result Manager::LinkToManager() { Result Manager::LinkToManager(Core::System& system) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
if (!linked_to_manager) { if (!linked_to_manager) {
system.AudioCore().GetAudioManager().SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this)); system.AudioCore().GetAudioManager().SetInManager(this, &Manager::BufferReleaseAndRegister);
linked_to_manager = true; linked_to_manager = true;
} }
return ResultSuccess; return ResultSuccess;
} }
void Manager::Start() { void Manager::Start(Core::System& system) {
if (sessions_started) { if (sessions_started) {
return; return;
} }
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
for (auto& session : sessions) { for (auto& session : sessions) {
if (session) { if (session) {
@@ -66,21 +65,19 @@ void Manager::Start() {
sessions_started = true; sessions_started = true;
} }
void Manager::BufferReleaseAndRegister() { void Manager::BufferReleaseAndRegister(void *data, Core::System& system) noexcept {
std::scoped_lock l{mutex}; Manager* this_ = (Manager*)data;
for (auto& session : sessions) { std::scoped_lock l{this_->mutex};
for (auto& session : this_->sessions) {
if (session != nullptr) { if (session != nullptr) {
session->ReleaseAndRegisterBuffers(); session->ReleaseAndRegisterBuffers();
} }
} }
} }
u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, u32 Manager::GetDeviceNames(Core::System& system, std::span<Renderer::AudioDevice::AudioDeviceName> names, [[maybe_unused]] const bool filter) {
[[maybe_unused]] const bool filter) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LinkToManager(system);
LinkToManager();
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)}; auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
if (!input_devices.empty() && !names.empty()) { if (!input_devices.empty() && !names.empty()) {
names[0] = Renderer::AudioDevice::AudioDeviceName("Uac"); names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
+10 -11
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,31 +33,29 @@ public:
* @param session_id - Output session_id. * @param session_id - Output session_id.
* @return Result code. * @return Result code.
*/ */
Result AcquireSessionId(size_t& session_id); Result AcquireSessionId(Core::System& system, size_t& session_id);
/** /**
* Release a session id on close. * Release a session id on close.
* *
* @param session_id - Session id to free. * @param session_id - Session id to free.
*/ */
void ReleaseSessionId(size_t session_id); void ReleaseSessionId(Core::System& system, const size_t session_id);
/** /**
* Link the audio in manager to the main audio manager. * Link the audio in manager to the main audio manager.
* *
* @return Result code. * @return Result code.
*/ */
Result LinkToManager(); Result LinkToManager(Core::System& system);
/** /**
* Start the audio in manager. * Start the audio in manager.
*/ */
void Start(); void Start(Core::System& system);
/** /// @brief Callback function, called by the audio manager when the audio in event is signalled.
* Callback function, called by the audio manager when the audio in event is signalled. static void BufferReleaseAndRegister(void *data, Core::System& system) noexcept;
*/
void BufferReleaseAndRegister();
/** /**
* Get a list of audio in device names. * Get a list of audio in device names.
@@ -64,10 +65,8 @@ public:
* *
* @return Number of names written. * @return Number of names written.
*/ */
u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter); u32 GetDeviceNames(Core::System& system, std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
/// Core system
Core::System& system;
/// Array of session ids /// Array of session ids
std::array<size_t, MaxInSessions> session_ids{}; std::array<size_t, MaxInSessions> session_ids{};
/// Array of resource user ids /// Array of resource user ids
+7 -5
View File
@@ -11,8 +11,8 @@
namespace AudioCore { namespace AudioCore {
AudioManager::AudioManager() { AudioManager::AudioManager(Core::System& system) {
thread = std::jthread([this](std::stop_token stop_token) { thread = std::jthread([&](std::stop_token stop_token) {
Common::SetCurrentThreadName("AudioManager"); Common::SetCurrentThreadName("AudioManager");
std::unique_lock l{events.GetAudioEventLock()}; std::unique_lock l{events.GetAudioEventLock()};
events.ClearEvents(); events.ClearEvents();
@@ -25,7 +25,7 @@ AudioManager::AudioManager() {
const auto event_type = Event::Type(i); const auto event_type = Event::Type(i);
if (events.CheckAudioEventSet(event_type) || timed_out) { if (events.CheckAudioEventSet(event_type) || timed_out) {
if (buffer_events[i]) { if (buffer_events[i]) {
buffer_events[i](); buffer_events[i](buffer_data[i], system);
} }
} }
events.SetAudioEvent(event_type, false); events.SetAudioEvent(event_type, false);
@@ -42,12 +42,13 @@ void AudioManager::Shutdown() {
} }
} }
Result AudioManager::SetOutManager(BufferEventFunc buffer_func) { Result AudioManager::SetOutManager(void *data, BufferEventFunc buffer_func) {
if (thread.joinable()) { if (thread.joinable()) {
std::scoped_lock l{lock}; std::scoped_lock l{lock};
const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)}; const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)};
if (buffer_events[index] == nullptr) { if (buffer_events[index] == nullptr) {
buffer_events[index] = std::move(buffer_func); buffer_events[index] = std::move(buffer_func);
buffer_data[index] = data;
needs_update = true; needs_update = true;
events.SetAudioEvent(Event::Type::AudioOutManager, true); events.SetAudioEvent(Event::Type::AudioOutManager, true);
} }
@@ -56,12 +57,13 @@ Result AudioManager::SetOutManager(BufferEventFunc buffer_func) {
return Service::Audio::ResultOperationFailed; return Service::Audio::ResultOperationFailed;
} }
Result AudioManager::SetInManager(BufferEventFunc buffer_func) { Result AudioManager::SetInManager(void *data, BufferEventFunc buffer_func) {
if (thread.joinable()) { if (thread.joinable()) {
std::scoped_lock l{lock}; std::scoped_lock l{lock};
const auto index{events.GetManagerIndex(Event::Type::AudioInManager)}; const auto index{events.GetManagerIndex(Event::Type::AudioInManager)};
if (buffer_events[index] == nullptr) { if (buffer_events[index] == nullptr) {
buffer_events[index] = std::move(buffer_func); buffer_events[index] = std::move(buffer_func);
buffer_data[index] = data;
needs_update = true; needs_update = true;
events.SetAudioEvent(Event::Type::AudioInManager, true); events.SetAudioEvent(Event::Type::AudioInManager, true);
} }
+16 -18
View File
@@ -16,6 +16,10 @@
#include "audio_core/audio_event.h" #include "audio_core/audio_event.h"
namespace Core {
class System;
}
union Result; union Result;
namespace AudioCore { namespace AudioCore {
@@ -34,31 +38,24 @@ namespace AudioCore {
* This is only used by audio in and audio out. * This is only used by audio in and audio out.
*/ */
class AudioManager { class AudioManager {
using BufferEventFunc = std::function<void()>; using BufferEventFunc = void (*)(void *data, Core::System& system) noexcept;
public: public:
explicit AudioManager(); explicit AudioManager(Core::System& system);
/** /**
* Shutdown the audio manager. * Shutdown the audio manager.
*/ */
void Shutdown(); void Shutdown();
/** /// Register the out manager, keeping a function to be called when the out event is signalled.
* Register the out manager, keeping a function to be called when the out event is signalled. /// @param buffer_func - Function to be called on signal.
* /// @return Result code.
* @param buffer_func - Function to be called on signal. Result SetOutManager(void *data, BufferEventFunc buffer_func);
* @return Result code.
*/
Result SetOutManager(BufferEventFunc buffer_func);
/** /// Register the in manager, keeping a function to be called when the in event is signalled.
* Register the in manager, keeping a function to be called when the in event is signalled. /// @param buffer_func - Function to be called on signal.
* /// @return Result code.
* @param buffer_func - Function to be called on signal. Result SetInManager(void *data, BufferEventFunc buffer_func);
* @return Result code.
*/
Result SetInManager(BufferEventFunc buffer_func);
/** /**
* Set an event to signalled, and signal the thread. * Set an event to signalled, and signal the thread.
@@ -73,8 +70,9 @@ private:
bool needs_update{}; bool needs_update{};
/// Events to be set and signalled /// Events to be set and signalled
Event events{}; Event events{};
/// Callbacks for each manager /// Callbacks (and user data) for each manager
std::array<BufferEventFunc, 3> buffer_events{}; std::array<BufferEventFunc, 3> buffer_events{};
std::array<void*, 3> buffer_data{};
/// General lock /// General lock
std::mutex lock{}; std::mutex lock{};
/// Main thread for waiting and callbacks /// Main thread for waiting and callbacks
+17 -25
View File
@@ -14,12 +14,12 @@
namespace AudioCore::AudioOut { namespace AudioCore::AudioOut {
Manager::Manager(Core::System& system_) : system{system_} { Manager::Manager(Core::System& system) {
std::iota(session_ids.begin(), session_ids.end(), 0); std::iota(session_ids.begin(), session_ids.end(), 0);
num_free_sessions = MaxOutSessions; num_free_sessions = MaxOutSessions;
} }
Result Manager::AcquireSessionId(size_t& session_id) { Result Manager::AcquireSessionId(Core::System& system, size_t& session_id) {
if (num_free_sessions == 0) { if (num_free_sessions == 0) {
LOG_ERROR(Service_Audio, "All 12 Audio Out sessions are in use, cannot create any more"); LOG_ERROR(Service_Audio, "All 12 Audio Out sessions are in use, cannot create any more");
return Service::Audio::ResultOutOfSessions; return Service::Audio::ResultOutOfSessions;
@@ -30,7 +30,7 @@ Result Manager::AcquireSessionId(size_t& session_id) {
return ResultSuccess; return ResultSuccess;
} }
void Manager::ReleaseSessionId(const size_t session_id) { void Manager::ReleaseSessionId(Core::System& system, const size_t session_id) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LOG_DEBUG(Service_Audio, "Freeing AudioOut session {}", session_id); LOG_DEBUG(Service_Audio, "Freeing AudioOut session {}", session_id);
session_ids[free_session_id] = session_id; session_ids[free_session_id] = session_id;
@@ -40,44 +40,36 @@ void Manager::ReleaseSessionId(const size_t session_id) {
applet_resource_user_ids[session_id] = 0; applet_resource_user_ids[session_id] = 0;
} }
Result Manager::LinkToManager() { Result Manager::LinkToManager(Core::System& system) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
if (!linked_to_manager) { if (!linked_to_manager) {
system.AudioCore().GetAudioManager().SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this)); system.AudioCore().GetAudioManager().SetOutManager(this, &Manager::BufferReleaseAndRegister);
linked_to_manager = true; linked_to_manager = true;
} }
return ResultSuccess; return ResultSuccess;
} }
void Manager::Start() { void Manager::Start(Core::System& system) {
if (sessions_started) { if (!sessions_started) {
return; std::scoped_lock l{mutex};
} for (auto& session : sessions) {
if (session) {
std::scoped_lock l{mutex}; session->StartSession();
for (auto& session : sessions) { }
if (session) {
session->StartSession();
} }
sessions_started = true;
} }
sessions_started = true;
} }
void Manager::BufferReleaseAndRegister() { void Manager::BufferReleaseAndRegister(void *data, Core::System& system) noexcept {
std::scoped_lock l{mutex}; Manager* this_ = (Manager*)data;
for (auto& session : sessions) { std::scoped_lock l{this_->mutex};
for (auto& session : this_->sessions) {
if (session != nullptr) { if (session != nullptr) {
session->ReleaseAndRegisterBuffers(); session->ReleaseAndRegisterBuffers();
} }
} }
} }
u32 Manager::GetAudioOutDeviceNames(
std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const {
names.emplace_back("DeviceOut");
return 1;
}
} // namespace AudioCore::AudioOut } // namespace AudioCore::AudioOut
+8 -15
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -29,42 +32,32 @@ public:
* @param session_id - Output session_id. * @param session_id - Output session_id.
* @return Result code. * @return Result code.
*/ */
Result AcquireSessionId(size_t& session_id); Result AcquireSessionId(Core::System& system, size_t& session_id);
/** /**
* Release a session id on close. * Release a session id on close.
* *
* @param session_id - Session id to free. * @param session_id - Session id to free.
*/ */
void ReleaseSessionId(size_t session_id); void ReleaseSessionId(Core::System& system, const size_t session_id);
/** /**
* Link this manager to the main audio manager. * Link this manager to the main audio manager.
* *
* @return Result code. * @return Result code.
*/ */
Result LinkToManager(); Result LinkToManager(Core::System& system);
/** /**
* Start the audio out manager. * Start the audio out manager.
*/ */
void Start(); void Start(Core::System& system);
/** /**
* Callback function, called by the audio manager when the audio out event is signalled. * Callback function, called by the audio manager when the audio out event is signalled.
*/ */
void BufferReleaseAndRegister(); static void BufferReleaseAndRegister(void* data, Core::System& system) noexcept;
/**
* Get a list of audio out device names.
*
* @param names - Output container to write names to.
* @return Number of names written.
*/
u32 GetAudioOutDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const;
/// Core system
Core::System& system;
/// Array of session ids /// Array of session ids
std::array<size_t, MaxOutSessions> session_ids{}; std::array<size_t, MaxOutSessions> session_ids{};
/// Array of resource user ids /// Array of resource user ids
+4 -4
View File
@@ -6,14 +6,14 @@
#include "audio_core/audio_render_manager.h" #include "audio_core/audio_render_manager.h"
#include "audio_core/common/audio_renderer_parameter.h" #include "audio_core/common/audio_renderer_parameter.h"
#include "audio_core/renderer/system_manager.h"
#include "audio_core/common/feature_support.h" #include "audio_core/common/feature_support.h"
#include "core/core.h" #include "core/core.h"
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
Manager::Manager(Core::System& system_) Manager::Manager(Core::System& system_)
: system{system_} : system_manager{std::make_unique<SystemManager>(system_)}
, system_manager{std::make_unique<SystemManager>(system)}
{ {
std::iota(session_ids.begin(), session_ids.end(), 0); std::iota(session_ids.begin(), session_ids.end(), 0);
} }
@@ -62,11 +62,11 @@ u32 Manager::GetSessionCount() const {
return session_count; return session_count;
} }
bool Manager::AddSystem(System& system_) { bool Manager::AddSystem(Renderer::System& system_) {
return system_manager->Add(system_); return system_manager->Add(system_);
} }
bool Manager::RemoveSystem(System& system_) { bool Manager::RemoveSystem(Renderer::System& system_) {
return system_manager->Remove(system_); return system_manager->Remove(system_);
} }
+5 -4
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -71,7 +74,7 @@ public:
* @param system - The system to add. * @param system - The system to add.
* @return True if the system was successfully added, otherwise false. * @return True if the system was successfully added, otherwise false.
*/ */
bool AddSystem(System& system); bool AddSystem(Renderer::System& system);
/** /**
* Remove a renderer system from the manager. * Remove a renderer system from the manager.
@@ -79,7 +82,7 @@ public:
* @param system - The system to remove. * @param system - The system to remove.
* @return True if the system was successfully removed, otherwise false. * @return True if the system was successfully removed, otherwise false.
*/ */
bool RemoveSystem(System& system); bool RemoveSystem(Renderer::System& system);
/** /**
* Free a session id when the system wants to shut down. * Free a session id when the system wants to shut down.
@@ -89,8 +92,6 @@ public:
void ReleaseSessionId(s32 session_id); void ReleaseSessionId(s32 session_id);
private: private:
/// Core system
Core::System& system;
/// Session ids, -1 when in use /// Session ids, -1 when in use
std::array<s32, MaxRendererSessions> session_ids{}; std::array<s32, MaxRendererSessions> session_ids{};
/// Number of active renderers /// Number of active renderers
+24 -20
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,42 +11,43 @@
namespace AudioCore::AudioIn { namespace AudioCore::AudioIn {
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_) In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event, : manager{manager_}, parent_mutex{manager.mutex}, event{event_}
session_id_} {} , audio_system{system_, event, session_id_}
{}
void In::Free() { void In::Free(Core::System& system) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
manager.ReleaseSessionId(system.GetSessionId()); manager.ReleaseSessionId(system, audio_system.GetSessionId());
} }
System& In::GetSystem() { System& In::GetSystem() {
return system; return audio_system;
} }
AudioIn::State In::GetState() { AudioIn::State In::GetState() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetState(); return audio_system.GetState();
} }
Result In::StartSystem() { Result In::StartSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Start(); return audio_system.Start();
} }
void In::StartSession() { void In::StartSession() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.StartSession(); audio_system.StartSession();
} }
Result In::StopSystem() { Result In::StopSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Stop(); return audio_system.Stop();
} }
Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) { Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.AppendBuffer(buffer, tag)) { if (audio_system.AppendBuffer(buffer, tag)) {
return ResultSuccess; return ResultSuccess;
} }
return Service::Audio::ResultBufferCountReached; return Service::Audio::ResultBufferCountReached;
@@ -51,20 +55,20 @@ Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
void In::ReleaseAndRegisterBuffers() { void In::ReleaseAndRegisterBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.GetState() == State::Started) { if (audio_system.GetState() == State::Started) {
system.ReleaseBuffers(); audio_system.ReleaseBuffers();
system.RegisterBuffers(); audio_system.RegisterBuffers();
} }
} }
bool In::FlushAudioInBuffers() { bool In::FlushAudioInBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.FlushAudioInBuffers(); return audio_system.FlushAudioInBuffers();
} }
u32 In::GetReleasedBuffers(std::span<u64> tags) { u32 In::GetReleasedBuffers(std::span<u64> tags) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetReleasedBuffers(tags); return audio_system.GetReleasedBuffers(tags);
} }
Kernel::KReadableEvent& In::GetBufferEvent() { Kernel::KReadableEvent& In::GetBufferEvent() {
@@ -74,27 +78,27 @@ Kernel::KReadableEvent& In::GetBufferEvent() {
f32 In::GetVolume() const { f32 In::GetVolume() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetVolume(); return audio_system.GetVolume();
} }
void In::SetVolume(f32 volume) { void In::SetVolume(f32 volume) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.SetVolume(volume); audio_system.SetVolume(volume);
} }
bool In::ContainsAudioBuffer(u64 tag) const { bool In::ContainsAudioBuffer(u64 tag) const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag); return audio_system.ContainsAudioBuffer(tag);
} }
u32 In::GetBufferCount() const { u32 In::GetBufferCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetBufferCount(); return audio_system.GetBufferCount();
} }
u64 In::GetPlayedSampleCount() const { u64 In::GetPlayedSampleCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount(); return audio_system.GetPlayedSampleCount();
} }
} // namespace AudioCore::AudioIn } // namespace AudioCore::AudioIn
+5 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,7 +33,7 @@ public:
/** /**
* Free this audio in from the audio in manager. * Free this audio in from the audio in manager.
*/ */
void Free(); void Free(Core::System& system);
/** /**
* Get this audio in's system. * Get this audio in's system.
@@ -141,7 +144,7 @@ private:
/// Buffer event, signalled when buffers are ready to be released /// Buffer event, signalled when buffers are ready to be released
Kernel::KEvent* event; Kernel::KEvent* event;
/// Main audio in system /// Main audio in system
System system; System audio_system;
}; };
} // namespace AudioCore::AudioIn } // namespace AudioCore::AudioIn
+24 -20
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,42 +11,43 @@
namespace AudioCore::AudioOut { namespace AudioCore::AudioOut {
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_) Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event, : manager{manager_}, parent_mutex{manager.mutex}, event{event_}
session_id_} {} , audio_system{system_, event, session_id_}
{}
void Out::Free() { void Out::Free(Core::System& system) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
manager.ReleaseSessionId(system.GetSessionId()); manager.ReleaseSessionId(system, audio_system.GetSessionId());
} }
System& Out::GetSystem() { System& Out::GetSystem() {
return system; return audio_system;
} }
AudioOut::State Out::GetState() { AudioOut::State Out::GetState() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetState(); return audio_system.GetState();
} }
Result Out::StartSystem() { Result Out::StartSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Start(); return audio_system.Start();
} }
void Out::StartSession() { void Out::StartSession() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.StartSession(); audio_system.StartSession();
} }
Result Out::StopSystem() { Result Out::StopSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Stop(); return audio_system.Stop();
} }
Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) { Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.AppendBuffer(buffer, tag)) { if (audio_system.AppendBuffer(buffer, tag)) {
return ResultSuccess; return ResultSuccess;
} }
return Service::Audio::ResultBufferCountReached; return Service::Audio::ResultBufferCountReached;
@@ -51,20 +55,20 @@ Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
void Out::ReleaseAndRegisterBuffers() { void Out::ReleaseAndRegisterBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.GetState() == State::Started) { if (audio_system.GetState() == State::Started) {
system.ReleaseBuffers(); audio_system.ReleaseBuffers();
system.RegisterBuffers(); audio_system.RegisterBuffers();
} }
} }
bool Out::FlushAudioOutBuffers() { bool Out::FlushAudioOutBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.FlushAudioOutBuffers(); return audio_system.FlushAudioOutBuffers();
} }
u32 Out::GetReleasedBuffers(std::span<u64> tags) { u32 Out::GetReleasedBuffers(std::span<u64> tags) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetReleasedBuffers(tags); return audio_system.GetReleasedBuffers(tags);
} }
Kernel::KReadableEvent& Out::GetBufferEvent() { Kernel::KReadableEvent& Out::GetBufferEvent() {
@@ -74,27 +78,27 @@ Kernel::KReadableEvent& Out::GetBufferEvent() {
f32 Out::GetVolume() const { f32 Out::GetVolume() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetVolume(); return audio_system.GetVolume();
} }
void Out::SetVolume(const f32 volume) { void Out::SetVolume(const f32 volume) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.SetVolume(volume); audio_system.SetVolume(volume);
} }
bool Out::ContainsAudioBuffer(const u64 tag) const { bool Out::ContainsAudioBuffer(const u64 tag) const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag); return audio_system.ContainsAudioBuffer(tag);
} }
u32 Out::GetBufferCount() const { u32 Out::GetBufferCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetBufferCount(); return audio_system.GetBufferCount();
} }
u64 Out::GetPlayedSampleCount() const { u64 Out::GetPlayedSampleCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount(); return audio_system.GetPlayedSampleCount();
} }
} // namespace AudioCore::AudioOut } // namespace AudioCore::AudioOut
+5 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,7 +33,7 @@ public:
/** /**
* Free this audio out from the audio out manager. * Free this audio out from the audio out manager.
*/ */
void Free(); void Free(Core::System& system);
/** /**
* Get this audio out's system. * Get this audio out's system.
@@ -141,7 +144,7 @@ private:
/// Buffer event, signalled when buffers are ready to be released /// Buffer event, signalled when buffers are ready to be released
Kernel::KEvent* event; Kernel::KEvent* event;
/// Main audio out system /// Main audio out system
System system; System audio_system;
}; };
} // namespace AudioCore::AudioOut } // namespace AudioCore::AudioOut
+13 -18
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -34,42 +34,37 @@ constexpr std::array output_device_names{
AudioDevice::AudioDeviceName{"AudioExternalOutput"}, AudioDevice::AudioDeviceName{"AudioExternalOutput"},
}; };
AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id_, AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id_, const u32 revision)
const u32 revision) : applet_resource_user_id{applet_resource_user_id_}
: output_sink{system.AudioCore().GetOutputSink()}, , user_revision{revision}
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {} {}
u32 AudioDevice::ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const { u32 AudioDevice::ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const {
std::span<const AudioDeviceName> names{}; std::span<const AudioDeviceName> names{};
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) { if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
names = usb_device_names; names = usb_device_names;
} else { } else {
names = device_names; names = device_names;
} }
const u32 out_count = u32((std::min)(out_buffer.size(), names.size()));
const u32 out_count{static_cast<u32>((std::min)(out_buffer.size(), names.size()))}; for (u32 i = 0; i < out_count; i++)
for (u32 i = 0; i < out_count; i++) {
out_buffer[i] = names[i]; out_buffer[i] = names[i];
}
return out_count; return out_count;
} }
u32 AudioDevice::ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const { u32 AudioDevice::ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const {
const u32 out_count{static_cast<u32>((std::min)(out_buffer.size(), output_device_names.size()))}; const u32 out_count = u32((std::min)(out_buffer.size(), output_device_names.size()));
for (u32 i = 0; i < out_count; i++)
for (u32 i = 0; i < out_count; i++) {
out_buffer[i] = output_device_names[i]; out_buffer[i] = output_device_names[i];
}
return out_count; return out_count;
} }
void AudioDevice::SetDeviceVolumes(const f32 volume) { void AudioDevice::SetDeviceVolumes(Core::System& system, const f32 volume) {
output_sink.SetDeviceVolume(volume); system.AudioCore().GetOutputSink().SetDeviceVolume(volume);
} }
f32 AudioDevice::GetDeviceVolume([[maybe_unused]] std::string_view name) const { f32 AudioDevice::GetDeviceVolume(Core::System& system, [[maybe_unused]] std::string_view name) const {
return output_sink.GetDeviceVolume(); return system.AudioCore().GetOutputSink().GetDeviceVolume();
} }
} // namespace AudioCore::Renderer } // namespace AudioCore::Renderer
+5 -4
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -54,7 +57,7 @@ public:
* *
* @param volume - Volume to set. * @param volume - Volume to set.
*/ */
void SetDeviceVolumes(f32 volume); void SetDeviceVolumes(Core::System& system, f32 volume);
/** /**
* Get the volume for a given device name. * Get the volume for a given device name.
@@ -63,11 +66,9 @@ public:
* @param name - Name of the device to check. Unused. * @param name - Name of the device to check. Unused.
* @return Volume of the device. * @return Volume of the device.
*/ */
f32 GetDeviceVolume(std::string_view name) const; f32 GetDeviceVolume(Core::System& system, std::string_view name) const;
private: private:
/// Backend output sink for the device
Sink::Sink& output_sink;
/// Resource id this device is used for /// Resource id this device is used for
const u64 applet_resource_user_id; const u64 applet_resource_user_id;
/// User audio renderer revision /// User audio renderer revision
+18 -25
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,56 +16,46 @@
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* rendered_event) Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* rendered_event)
: core{system_}, manager{manager_}, system{system_, rendered_event} {} : manager{manager_}
, audio_system{system_, rendered_event}
{}
Result Renderer::Initialize(const AudioRendererParameterInternal& params, Result Renderer::Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, const u64 transfer_memory_size, Kernel::KProcess* process_handle, const u64 applet_resource_user_id, const s32 session_id) {
Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, Kernel::KProcess* process_handle,
const u64 applet_resource_user_id, const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) { if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) { if (!manager.AddSystem(audio_system)) {
LOG_ERROR(Service_Audio, LOG_ERROR(Service_Audio, "Both Audio Render sessions are in use, cannot create any more");
"Both Audio Render sessions are in use, cannot create any more");
return Service::Audio::ResultOutOfSessions; return Service::Audio::ResultOutOfSessions;
} }
system_registered = true; system_registered = true;
} }
audio_system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, applet_resource_user_id, session_id);
initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
applet_resource_user_id, session_id);
return ResultSuccess; return ResultSuccess;
} }
void Renderer::Finalize() { void Renderer::Finalize() {
auto session_id{system.GetSessionId()}; auto const session_id{audio_system.GetSessionId()};
audio_system.Finalize();
system.Finalize();
if (system_registered) { if (system_registered) {
manager.RemoveSystem(system); manager.RemoveSystem(audio_system);
system_registered = false; system_registered = false;
} }
manager.ReleaseSessionId(session_id); manager.ReleaseSessionId(session_id);
} }
System& Renderer::GetSystem() { System& Renderer::GetSystem() {
return system; return audio_system;
} }
void Renderer::Start() { void Renderer::Start() {
system.Start(); audio_system.Start();
} }
void Renderer::Stop() { void Renderer::Stop() {
system.Stop(); audio_system.Stop();
} }
Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performance, Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performance, std::span<u8> output) {
std::span<u8> output) { return audio_system.Update(input, performance, output);
return system.Update(input, performance, output);
} }
} // namespace AudioCore::Renderer } // namespace AudioCore::Renderer
+4 -5
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -83,16 +86,12 @@ public:
std::span<u8> output); std::span<u8> output);
private: private:
/// System core
Core::System& core;
/// Manager this renderer is registered with /// Manager this renderer is registered with
Manager& manager; Manager& manager;
/// Is the audio renderer initialized?
bool initialized{};
/// Is the system registered with the manager? /// Is the system registered with the manager?
bool system_registered{}; bool system_registered{};
/// Audio render system, main driver of audio rendering /// Audio render system, main driver of audio rendering
System system; System audio_system;
}; };
} // namespace Renderer } // namespace Renderer
+10 -12
View File
@@ -100,8 +100,9 @@ u64 System::GetWorkBufferSize(const AudioRendererParameterInternal& params) {
} }
System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_) System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
: core{core_}, audio_renderer{core.AudioCore().ADSP().AudioRenderer()}, : core{core_}
adsp_rendered_event{adsp_rendered_event_} {} , adsp_rendered_event{adsp_rendered_event_}
{}
Result System::Initialize(const AudioRendererParameterInternal& params, Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
@@ -406,7 +407,7 @@ void System::Finalize() {
return; return;
} }
if (active) { if (IsActive()) {
Stop(); Stop();
} }
@@ -433,14 +434,12 @@ void System::Start() {
std::scoped_lock l{lock}; std::scoped_lock l{lock};
frames_elapsed = 0; frames_elapsed = 0;
state = State::Started; state = State::Started;
active = true;
} }
void System::Stop() { void System::Stop() {
{ {
std::scoped_lock l{lock}; std::scoped_lock l{lock};
state = State::Stopped; state = State::Stopped;
active = false;
} }
if (execution_mode == ExecutionMode::Auto) { if (execution_mode == ExecutionMode::Auto) {
@@ -480,8 +479,7 @@ Result System::Update(std::span<const u8> input, std::span<u8> performance, std:
return result; return result;
} }
result = info_updater.UpdateEffects(effect_context, active, memory_pool_workbuffer, result = info_updater.UpdateEffects(effect_context, IsActive(), memory_pool_workbuffer, memory_pool_count);
memory_pool_count);
if (result.IsError()) { if (result.IsError()) {
LOG_ERROR(Service_Audio, "Failed to update Effects!"); LOG_ERROR(Service_Audio, "Failed to update Effects!");
return result; return result;
@@ -582,16 +580,16 @@ u32 System::GetRenderingDevice() const {
} }
bool System::IsActive() const { bool System::IsActive() const {
return active; return state == State::Started;
} }
void System::SendCommandToDsp() { void System::SendCommandToDsp() {
std::scoped_lock l{lock}; std::scoped_lock l{lock};
auto& audio_renderer = core.AudioCore().ADSP().AudioRenderer();
if (initialized) { if (initialized) {
if (active) { if (IsActive()) {
terminate_event.Reset(); terminate_event.Reset();
const auto remaining_command_count{audio_renderer.GetRemainCommandCount(session_id)}; const auto remaining_command_count = audio_renderer.GetRemainCommandCount(session_id);
u64 command_size{0}; u64 command_size{0};
if (remaining_command_count) { if (remaining_command_count) {
@@ -738,7 +736,7 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer,
const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()}; const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()};
total_ticks_elapsed += end_time - start_time; total_ticks_elapsed += end_time - start_time;
num_command_lists_generated++; num_command_lists_generated++;
render_start_tick = audio_renderer.GetRenderingStartTick(session_id); render_start_tick = core.AudioCore().ADSP().AudioRenderer().GetRenderingStartTick(session_id);
frames_elapsed++; frames_elapsed++;
return command_buffer.size; return command_buffer.size;
+3 -4
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -219,12 +222,8 @@ public:
private: private:
/// Core system /// Core system
Core::System& core; Core::System& core;
/// Reference to the ADSP's AudioRenderer for communication
::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer;
/// Is this system initialized? /// Is this system initialized?
bool initialized{}; bool initialized{};
/// Is this system currently active?
std::atomic<bool> active{};
/// State of the system /// State of the system
State state{State::Stopped}; State state{State::Stopped};
/// Sample rate for the system /// Sample rate for the system
+17 -25
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -16,22 +16,22 @@
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
SystemManager::SystemManager(Core::System& core_) SystemManager::SystemManager(Core::System& core_)
: core{core_}, audio_renderer{core.AudioCore().ADSP().AudioRenderer()} {} : core{core_}
{}
SystemManager::~SystemManager() { SystemManager::~SystemManager() {
Stop(); Stop();
} }
void SystemManager::InitializeUnsafe() { void SystemManager::InitializeUnsafe() {
if (!active) { if (!thread.joinable()) {
active = true; core.AudioCore().ADSP().AudioRenderer().Start();
audio_renderer.Start();
thread = std::jthread([this](std::stop_token stop_token) { thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("AudioRenderSystemManager"); Common::SetCurrentThreadName("AudioRenderSystemManager");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High); auto& audio_renderer = core.AudioCore().ADSP().AudioRenderer();
while (active && !stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
{ {
std::scoped_lock l{mutex1}; std::scoped_lock lk{mutex};
for (auto system : systems) for (auto system : systems)
system->SendCommandToDsp(); system->SendCommandToDsp();
} }
@@ -43,39 +43,31 @@ void SystemManager::InitializeUnsafe() {
} }
void SystemManager::Stop() { void SystemManager::Stop() {
if (active) { if (thread.joinable()) {
active = false;
thread.request_stop(); thread.request_stop();
thread.join(); thread.join();
audio_renderer.Stop(); core.AudioCore().ADSP().AudioRenderer().Stop();
} }
} }
bool SystemManager::Add(System& system_) { bool SystemManager::Add(System& system_) {
std::scoped_lock l2{mutex2}; std::scoped_lock lk{mutex};
if (systems.size() + 1 > MaxRendererSessions) { if (systems.size() + 1 > MaxRendererSessions) {
LOG_ERROR(Service_Audio, "Maximum AudioRenderer Systems active, cannot add more!"); LOG_ERROR(Service_Audio, "Maximum AudioRenderer Systems active, cannot add more!");
return false; return false;
} }
{ if (systems.empty())
std::scoped_lock l{mutex1}; InitializeUnsafe();
if (systems.empty())
InitializeUnsafe();
}
systems.push_back(&system_); systems.push_back(&system_);
return true; return true;
} }
bool SystemManager::Remove(System& system_) { bool SystemManager::Remove(System& system_) {
std::scoped_lock l2{mutex2}; std::scoped_lock lk{mutex};
{ if (systems.remove(&system_) == 0) {
std::scoped_lock l{mutex1}; LOG_ERROR(Service_Audio, "Failed to remove a render system, it was not found in the list!");
if (systems.remove(&system_) == 0) { return false;
LOG_ERROR(Service_Audio, "Failed to remove a render system, it was not found in the list!");
return false;
}
} }
if (systems.empty()) if (systems.empty())
Stop(); Stop();
return true; return true;
+3 -9
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -75,14 +75,8 @@ private:
std::list<System*> systems{}; std::list<System*> systems{};
/// Main worker thread for generating command lists /// Main worker thread for generating command lists
std::jthread thread; std::jthread thread;
/// Mutex for the systems /// Mutex for the systems list
std::mutex mutex1{}; std::mutex mutex{};
/// Mutex for adding/removing systems
std::mutex mutex2{};
/// Is the system manager thread active?
std::atomic<bool> active{};
/// Reference to the ADSP's AudioRenderer for communication
::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer;
}; };
} // namespace AudioCore::Renderer } // namespace AudioCore::Renderer
+2 -2
View File
@@ -97,7 +97,7 @@ Result IAudioDevice::SetAudioDeviceOutputVolumeAuto(
LOG_DEBUG(Service_Audio, "called. name={}, volume={}", device_name, volume); LOG_DEBUG(Service_Audio, "called. name={}, volume={}", device_name, volume);
if (device_name == "AudioTvOutput") { if (device_name == "AudioTvOutput") {
impl->SetDeviceVolumes(volume); impl->SetDeviceVolumes(system, volume);
} }
R_SUCCEED(); R_SUCCEED();
@@ -112,7 +112,7 @@ Result IAudioDevice::GetAudioDeviceOutputVolumeAuto(
*out_volume = 1.0f; *out_volume = 1.0f;
if (device_name == "AudioTvOutput") { if (device_name == "AudioTvOutput") {
*out_volume = impl->GetDeviceVolume(device_name); *out_volume = impl->GetDeviceVolume(system, device_name);
} }
R_SUCCEED(); R_SUCCEED();
+1 -1
View File
@@ -50,7 +50,7 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
} }
IAudioIn::~IAudioIn() { IAudioIn::~IAudioIn() {
impl->Free(); impl->Free(system);
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close(system.Kernel()); process->Close(system.Kernel());
} }
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -65,7 +68,7 @@ Result IAudioInManager::OpenAudioInAuto(
Result IAudioInManager::ListAudioInsAutoFiltered( Result IAudioInManager::ListAudioInsAutoFiltered(
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) { OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
*out_count = impl->GetDeviceNames(out_audio_ins, true); *out_count = impl->GetDeviceNames(system, out_audio_ins, true);
R_SUCCEED(); R_SUCCEED();
} }
@@ -90,8 +93,8 @@ Result IAudioInManager::OpenAudioInProtocolSpecified(
size_t new_session_id{}; size_t new_session_id{};
R_TRY(impl->LinkToManager()); R_TRY(impl->LinkToManager(system));
R_TRY(impl->AcquireSessionId(new_session_id)); R_TRY(impl->AcquireSessionId(system, new_session_id));
LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
+1 -1
View File
@@ -46,7 +46,7 @@ IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
} }
IAudioOut::~IAudioOut() { IAudioOut::~IAudioOut() {
impl->Free(); impl->Free(system);
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close(system.Kernel()); process->Close(system.Kernel());
} }
@@ -77,8 +77,8 @@ Result IAudioOutManager::OpenAudioOutAuto(
} }
size_t new_session_id{}; size_t new_session_id{};
R_TRY(impl->LinkToManager()); R_TRY(impl->LinkToManager(system));
R_TRY(impl->AcquireSessionId(new_session_id)); R_TRY(impl->AcquireSessionId(system, new_session_id));
const auto device_name = Common::StringFromBuffer(name[0].name); const auto device_name = Common::StringFromBuffer(name[0].name);
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,