diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 68b940af36..5a1fc83bd3 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -489,6 +489,10 @@ add_library(core STATIC
     hle/service/apm/apm_controller.h
     hle/service/apm/apm_interface.cpp
     hle/service/apm/apm_interface.h
+    hle/service/audio/audio_controller.cpp
+    hle/service/audio/audio_controller.h
+    hle/service/audio/audio_device.cpp
+    hle/service/audio/audio_device.h
     hle/service/audio/audio_in_manager.cpp
     hle/service/audio/audio_in_manager.h
     hle/service/audio/audio_in.cpp
@@ -497,12 +501,12 @@ add_library(core STATIC
     hle/service/audio/audio_out_manager.h
     hle/service/audio/audio_out.cpp
     hle/service/audio/audio_out.h
+    hle/service/audio/audio_renderer_manager.cpp
+    hle/service/audio/audio_renderer_manager.h
+    hle/service/audio/audio_renderer.cpp
+    hle/service/audio/audio_renderer.h
     hle/service/audio/audio.cpp
     hle/service/audio/audio.h
-    hle/service/audio/audio_controller.cpp
-    hle/service/audio/audio_controller.h
-    hle/service/audio/audren_u.cpp
-    hle/service/audio/audren_u.h
     hle/service/audio/errors.h
     hle/service/audio/final_output_recorder_manager_for_applet.cpp
     hle/service/audio/final_output_recorder_manager_for_applet.h
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 02773aee5e..82a2ae2835 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -6,7 +6,7 @@
 #include "core/hle/service/audio/audio_controller.h"
 #include "core/hle/service/audio/audio_in_manager.h"
 #include "core/hle/service/audio/audio_out_manager.h"
-#include "core/hle/service/audio/audren_u.h"
+#include "core/hle/service/audio/audio_renderer_manager.h"
 #include "core/hle/service/audio/final_output_recorder_manager.h"
 #include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
 #include "core/hle/service/audio/hwopus.h"
@@ -25,7 +25,8 @@ void LoopProcess(Core::System& system) {
         "audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
     server_manager->RegisterNamedService("audrec:u",
                                          std::make_shared<IFinalOutputRecorderManager>(system));
-    server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
+    server_manager->RegisterNamedService("audren:u",
+                                         std::make_shared<IAudioRendererManager>(system));
     server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
     ServerManager::RunServer(std::move(server_manager));
 }
diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp
new file mode 100644
index 0000000000..3608d08c78
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.cpp
@@ -0,0 +1,183 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "audio_core/audio_core.h"
+#include "common/string_util.h"
+#include "core/hle/service/audio/audio_device.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+using namespace AudioCore::Renderer;
+
+IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
+                           u32 device_num)
+    : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
+      impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
+      event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
+    static const FunctionInfo functions[] = {
+        {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
+        {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
+        {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
+        {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
+        {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
+        {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
+        {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
+        {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
+        {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
+        {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
+        {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
+        {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
+        {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
+        {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
+    };
+    RegisterHandlers(functions);
+
+    event->Signal();
+}
+
+IAudioDevice::~IAudioDevice() {
+    service_context.CloseEvent(event);
+}
+
+void IAudioDevice::ListAudioDeviceName(HLERequestContext& ctx) {
+    const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
+
+    std::vector<AudioDevice::AudioDeviceName> out_names{};
+
+    const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
+
+    std::string out{};
+    for (u32 i = 0; i < out_count; i++) {
+        std::string a{};
+        u32 j = 0;
+        while (out_names[i].name[j] != '\0') {
+            a += out_names[i].name[j];
+            j++;
+        }
+        out += "\n\t" + a;
+    }
+
+    LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+
+    ctx.WriteBuffer(out_names);
+
+    rb.Push(ResultSuccess);
+    rb.Push(out_count);
+}
+
+void IAudioDevice::SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const f32 volume = rp.Pop<f32>();
+
+    const auto device_name_buffer = ctx.ReadBuffer();
+    const std::string name = Common::StringFromBuffer(device_name_buffer);
+
+    LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
+
+    if (name == "AudioTvOutput") {
+        impl->SetDeviceVolumes(volume);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioDevice::GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
+    const auto device_name_buffer = ctx.ReadBuffer();
+    const std::string name = Common::StringFromBuffer(device_name_buffer);
+
+    LOG_DEBUG(Service_Audio, "called. Name={}", name);
+
+    f32 volume{1.0f};
+    if (name == "AudioTvOutput") {
+        volume = impl->GetDeviceVolume(name);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(volume);
+}
+
+void IAudioDevice::GetActiveAudioDeviceName(HLERequestContext& ctx) {
+    const auto write_size = ctx.GetWriteBufferSize();
+    std::string out_name{"AudioTvOutput"};
+
+    LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
+
+    out_name.resize(write_size);
+
+    ctx.WriteBuffer(out_name);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioDevice::QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "(STUBBED) called");
+
+    event->Signal();
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(event->GetReadableEvent());
+}
+
+void IAudioDevice::GetActiveChannelCount(HLERequestContext& ctx) {
+    const auto& sink{system.AudioCore().GetOutputSink()};
+    u32 channel_count{sink.GetSystemChannels()};
+
+    LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(channel_count);
+}
+
+void IAudioDevice::QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(event->GetReadableEvent());
+}
+
+void IAudioDevice::QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(event->GetReadableEvent());
+}
+
+void IAudioDevice::ListAudioOutputDeviceName(HLERequestContext& ctx) {
+    const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
+
+    std::vector<AudioDevice::AudioDeviceName> out_names{};
+
+    const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
+
+    std::string out{};
+    for (u32 i = 0; i < out_count; i++) {
+        std::string a{};
+        u32 j = 0;
+        while (out_names[i].name[j] != '\0') {
+            a += out_names[i].name[j];
+            j++;
+        }
+        out += "\n\t" + a;
+    }
+
+    LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+
+    ctx.WriteBuffer(out_names);
+
+    rb.Push(ResultSuccess);
+    rb.Push(out_count);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_device.h b/src/core/hle/service/audio/audio_device.h
new file mode 100644
index 0000000000..850c60051f
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/renderer/audio_device.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IAudioDevice final : public ServiceFramework<IAudioDevice> {
+
+public:
+    explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
+                          u32 device_num);
+    ~IAudioDevice() override;
+
+private:
+    void ListAudioDeviceName(HLERequestContext& ctx);
+    void SetAudioDeviceOutputVolume(HLERequestContext& ctx);
+    void GetAudioDeviceOutputVolume(HLERequestContext& ctx);
+    void GetActiveAudioDeviceName(HLERequestContext& ctx);
+    void QueryAudioDeviceSystemEvent(HLERequestContext& ctx);
+    void GetActiveChannelCount(HLERequestContext& ctx);
+    void QueryAudioDeviceInputEvent(HLERequestContext& ctx);
+    void QueryAudioDeviceOutputEvent(HLERequestContext& ctx);
+    void ListAudioOutputDeviceName(HLERequestContext& ctx);
+
+    KernelHelpers::ServiceContext service_context;
+    std::unique_ptr<AudioCore::Renderer::AudioDevice> impl;
+    Kernel::KEvent* event;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp
new file mode 100644
index 0000000000..68415eb8f8
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.cpp
@@ -0,0 +1,210 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/audio/audio_renderer.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+using namespace AudioCore::Renderer;
+
+IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
+                               AudioCore::AudioRendererParameterInternal& params,
+                               Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
+                               u32 process_handle, Kernel::KProcess& process_,
+                               u64 applet_resource_user_id, s32 session_id)
+    : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
+      rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
+      impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
+        {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
+        {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
+        {3, &IAudioRenderer::GetState, "GetState"},
+        {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
+        {5, &IAudioRenderer::Start, "Start"},
+        {6, &IAudioRenderer::Stop, "Stop"},
+        {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
+        {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
+        {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
+        {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
+        {11, nullptr, "ExecuteAudioRendererRendering"},
+        {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
+        {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
+    };
+    // clang-format on
+    RegisterHandlers(functions);
+
+    process.Open();
+    impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
+                     applet_resource_user_id, session_id);
+}
+
+IAudioRenderer::~IAudioRenderer() {
+    impl->Finalize();
+    service_context.CloseEvent(rendered_event);
+    process.Close();
+}
+
+void IAudioRenderer::GetSampleRate(HLERequestContext& ctx) {
+    const auto sample_rate{impl->GetSystem().GetSampleRate()};
+
+    LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(sample_rate);
+}
+
+void IAudioRenderer::GetSampleCount(HLERequestContext& ctx) {
+    const auto sample_count{impl->GetSystem().GetSampleCount()};
+
+    LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(sample_count);
+}
+
+void IAudioRenderer::GetState(HLERequestContext& ctx) {
+    const u32 state{!impl->GetSystem().IsActive()};
+
+    LOG_DEBUG(Service_Audio, "called, state {}", state);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(state);
+}
+
+void IAudioRenderer::GetMixBufferCount(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(buffer_count);
+}
+
+void IAudioRenderer::RequestUpdate(HLERequestContext& ctx) {
+    LOG_TRACE(Service_Audio, "called");
+
+    const auto input{ctx.ReadBuffer(0)};
+
+    // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
+    // checking size 0. Performance size is 0 for most games.
+
+    auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
+    if (is_buffer_b) {
+        const auto buffersB{ctx.BufferDescriptorB()};
+        output_buffer.resize_destructive(buffersB[0].Size());
+        performance_buffer.resize_destructive(buffersB[1].Size());
+    } else {
+        const auto buffersC{ctx.BufferDescriptorC()};
+        output_buffer.resize_destructive(buffersC[0].Size());
+        performance_buffer.resize_destructive(buffersC[1].Size());
+    }
+
+    auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
+
+    if (result.IsSuccess()) {
+        if (is_buffer_b) {
+            ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
+            ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
+        } else {
+            ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
+            ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
+        }
+    } else {
+        LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(result);
+}
+
+void IAudioRenderer::Start(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    impl->Start();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::Stop(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    impl->Stop();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::QuerySystemEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(Audio::ResultNotSupported);
+        return;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(rendered_event->GetReadableEvent());
+}
+
+void IAudioRenderer::SetRenderingTimeLimit(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    IPC::RequestParser rp{ctx};
+    auto limit = rp.PopRaw<u32>();
+
+    auto& system_ = impl->GetSystem();
+    system_.SetRenderingTimeLimit(limit);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::GetRenderingTimeLimit(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    auto& system_ = impl->GetSystem();
+    auto time = system_.GetRenderingTimeLimit();
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(time);
+}
+
+void IAudioRenderer::ExecuteAudioRendererRendering(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+}
+
+void IAudioRenderer::SetVoiceDropParameter(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    IPC::RequestParser rp{ctx};
+    auto voice_drop_param{rp.Pop<f32>()};
+
+    auto& system_ = impl->GetSystem();
+    system_.SetVoiceDropParameter(voice_drop_param);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::GetVoiceDropParameter(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Audio, "called");
+
+    auto& system_ = impl->GetSystem();
+    auto voice_drop_param{system_.GetVoiceDropParameter()};
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(voice_drop_param);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer.h b/src/core/hle/service/audio/audio_renderer.h
new file mode 100644
index 0000000000..f8c48154b4
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.h
@@ -0,0 +1,45 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/renderer/audio_renderer.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
+public:
+    explicit IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
+                            AudioCore::AudioRendererParameterInternal& params,
+                            Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
+                            u32 process_handle, Kernel::KProcess& process_,
+                            u64 applet_resource_user_id, s32 session_id);
+    ~IAudioRenderer() override;
+
+private:
+    void GetSampleRate(HLERequestContext& ctx);
+    void GetSampleCount(HLERequestContext& ctx);
+    void GetState(HLERequestContext& ctx);
+    void GetMixBufferCount(HLERequestContext& ctx);
+    void RequestUpdate(HLERequestContext& ctx);
+    void Start(HLERequestContext& ctx);
+    void Stop(HLERequestContext& ctx);
+    void QuerySystemEvent(HLERequestContext& ctx);
+    void SetRenderingTimeLimit(HLERequestContext& ctx);
+    void GetRenderingTimeLimit(HLERequestContext& ctx);
+    void ExecuteAudioRendererRendering(HLERequestContext& ctx);
+    void SetVoiceDropParameter(HLERequestContext& ctx);
+    void GetVoiceDropParameter(HLERequestContext& ctx);
+
+    KernelHelpers::ServiceContext service_context;
+    Kernel::KEvent* rendered_event;
+    AudioCore::Renderer::Manager& manager;
+    std::unique_ptr<AudioCore::Renderer::Renderer> impl;
+    Kernel::KProcess& process;
+    Common::ScratchBuffer<u8> output_buffer;
+    Common::ScratchBuffer<u8> performance_buffer;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer_manager.cpp b/src/core/hle/service/audio/audio_renderer_manager.cpp
new file mode 100644
index 0000000000..7baa9d8cfe
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer_manager.cpp
@@ -0,0 +1,143 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "audio_core/audio_render_manager.h"
+#include "audio_core/common/feature_support.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/service/audio/audio_device.h"
+#include "core/hle/service/audio/audio_renderer.h"
+#include "core/hle/service/audio/audio_renderer_manager.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+
+using namespace AudioCore::Renderer;
+
+IAudioRendererManager::IAudioRendererManager(Core::System& system_)
+    : ServiceFramework{system_, "audren:u"}, service_context{system_, "audren:u"},
+      impl{std::make_unique<Manager>(system_)} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &IAudioRendererManager::OpenAudioRenderer, "OpenAudioRenderer"},
+        {1, &IAudioRendererManager::GetWorkBufferSize, "GetWorkBufferSize"},
+        {2, &IAudioRendererManager::GetAudioDeviceService, "GetAudioDeviceService"},
+        {3, nullptr, "OpenAudioRendererForManualExecution"},
+        {4, &IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IAudioRendererManager::~IAudioRendererManager() = default;
+
+void IAudioRendererManager::OpenAudioRenderer(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    AudioCore::AudioRendererParameterInternal params;
+    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
+    rp.Skip(1, false);
+    auto transfer_memory_size = rp.Pop<u64>();
+    auto applet_resource_user_id = rp.Pop<u64>();
+    auto transfer_memory_handle = ctx.GetCopyHandle(0);
+    auto process_handle = ctx.GetCopyHandle(1);
+
+    if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
+        LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(Audio::ResultOutOfSessions);
+        return;
+    }
+
+    auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
+    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
+
+    const auto session_id{impl->GetSessionId()};
+    if (session_id == -1) {
+        LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(Audio::ResultOutOfSessions);
+        return;
+    }
+
+    LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
+              impl->GetSessionCount());
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
+                                        transfer_memory_size, process_handle, *process,
+                                        applet_resource_user_id, session_id);
+}
+
+void IAudioRendererManager::GetWorkBufferSize(HLERequestContext& ctx) {
+    AudioCore::AudioRendererParameterInternal params;
+
+    IPC::RequestParser rp{ctx};
+    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
+
+    u64 size{0};
+    auto result = impl->GetWorkBufferSize(params, size);
+
+    std::string output_info{};
+    output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
+    output_info +=
+        fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
+    output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
+                               static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
+    output_info += fmt::format(
+        "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
+        "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
+        "Context {:04X}",
+        params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
+        params.splitter_destinations, params.voices, params.perf_frames,
+        params.external_context_size);
+
+    LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
+              output_info, size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push<u64>(size);
+}
+
+void IAudioRendererManager::GetAudioDeviceService(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const auto applet_resource_user_id = rp.Pop<u64>();
+
+    LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
+                                      ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
+}
+
+void IAudioRendererManager::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
+    LOG_ERROR(Service_Audio, "called. Implement me!");
+}
+
+void IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
+    struct Parameters {
+        u32 revision;
+        u64 applet_resource_user_id;
+    };
+
+    IPC::RequestParser rp{ctx};
+
+    const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
+
+    LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
+              AudioCore::GetRevisionNum(revision), applet_resource_user_id);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
+                                      num_audio_devices++);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audio_renderer_manager.h
similarity index 81%
rename from src/core/hle/service/audio/audren_u.h
rename to src/core/hle/service/audio/audio_renderer_manager.h
index 3d7993a169..3623f91c68 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audio_renderer_manager.h
@@ -4,7 +4,6 @@
 #pragma once
 
 #include "audio_core/audio_render_manager.h"
-#include "common/scratch_buffer.h"
 #include "core/hle/service/kernel_helpers.h"
 #include "core/hle/service/service.h"
 
@@ -15,10 +14,10 @@ class System;
 namespace Service::Audio {
 class IAudioRenderer;
 
-class AudRenU final : public ServiceFramework<AudRenU> {
+class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
 public:
-    explicit AudRenU(Core::System& system_);
-    ~AudRenU() override;
+    explicit IAudioRendererManager(Core::System& system_);
+    ~IAudioRendererManager() override;
 
 private:
     void OpenAudioRenderer(HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
deleted file mode 100644
index 10108abc06..0000000000
--- a/src/core/hle/service/audio/audren_u.cpp
+++ /dev/null
@@ -1,552 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <array>
-#include <memory>
-
-#include "audio_core/audio_core.h"
-#include "audio_core/common/audio_renderer_parameter.h"
-#include "audio_core/common/feature_support.h"
-#include "audio_core/renderer/audio_device.h"
-#include "audio_core/renderer/audio_renderer.h"
-#include "audio_core/renderer/voice/voice_info.h"
-#include "common/alignment.h"
-#include "common/bit_util.h"
-#include "common/common_funcs.h"
-#include "common/logging/log.h"
-#include "common/polyfill_ranges.h"
-#include "common/scratch_buffer.h"
-#include "common/string_util.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/k_transfer_memory.h"
-#include "core/hle/service/audio/audren_u.h"
-#include "core/hle/service/audio/errors.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/memory.h"
-
-using namespace AudioCore::Renderer;
-
-namespace Service::Audio {
-
-class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
-public:
-    explicit IAudioRenderer(Core::System& system_, Manager& manager_,
-                            AudioCore::AudioRendererParameterInternal& params,
-                            Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
-                            u32 process_handle, Kernel::KProcess& process_,
-                            u64 applet_resource_user_id, s32 session_id)
-        : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
-          rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
-          impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
-            {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
-            {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
-            {3, &IAudioRenderer::GetState, "GetState"},
-            {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
-            {5, &IAudioRenderer::Start, "Start"},
-            {6, &IAudioRenderer::Stop, "Stop"},
-            {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
-            {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
-            {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
-            {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
-            {11, nullptr, "ExecuteAudioRendererRendering"},
-            {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
-            {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
-        };
-        // clang-format on
-        RegisterHandlers(functions);
-
-        process.Open();
-        impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
-                         applet_resource_user_id, session_id);
-    }
-
-    ~IAudioRenderer() override {
-        impl->Finalize();
-        service_context.CloseEvent(rendered_event);
-        process.Close();
-    }
-
-private:
-    void GetSampleRate(HLERequestContext& ctx) {
-        const auto sample_rate{impl->GetSystem().GetSampleRate()};
-
-        LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(sample_rate);
-    }
-
-    void GetSampleCount(HLERequestContext& ctx) {
-        const auto sample_count{impl->GetSystem().GetSampleCount()};
-
-        LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(sample_count);
-    }
-
-    void GetState(HLERequestContext& ctx) {
-        const u32 state{!impl->GetSystem().IsActive()};
-
-        LOG_DEBUG(Service_Audio, "called, state {}", state);
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(state);
-    }
-
-    void GetMixBufferCount(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(buffer_count);
-    }
-
-    void RequestUpdate(HLERequestContext& ctx) {
-        LOG_TRACE(Service_Audio, "called");
-
-        const auto input{ctx.ReadBuffer(0)};
-
-        // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
-        // checking size 0. Performance size is 0 for most games.
-
-        auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
-        if (is_buffer_b) {
-            const auto buffersB{ctx.BufferDescriptorB()};
-            output_buffer.resize_destructive(buffersB[0].Size());
-            performance_buffer.resize_destructive(buffersB[1].Size());
-        } else {
-            const auto buffersC{ctx.BufferDescriptorC()};
-            output_buffer.resize_destructive(buffersC[0].Size());
-            performance_buffer.resize_destructive(buffersC[1].Size());
-        }
-
-        auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
-
-        if (result.IsSuccess()) {
-            if (is_buffer_b) {
-                ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
-                ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
-            } else {
-                ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
-                ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
-            }
-        } else {
-            LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!",
-                      result.GetDescription());
-        }
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(result);
-    }
-
-    void Start(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        impl->Start();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void Stop(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        impl->Stop();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void QuerySystemEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
-            IPC::ResponseBuilder rb{ctx, 2};
-            rb.Push(Audio::ResultNotSupported);
-            return;
-        }
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(rendered_event->GetReadableEvent());
-    }
-
-    void SetRenderingTimeLimit(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        IPC::RequestParser rp{ctx};
-        auto limit = rp.PopRaw<u32>();
-
-        auto& system_ = impl->GetSystem();
-        system_.SetRenderingTimeLimit(limit);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void GetRenderingTimeLimit(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        auto& system_ = impl->GetSystem();
-        auto time = system_.GetRenderingTimeLimit();
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(time);
-    }
-
-    void ExecuteAudioRendererRendering(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-    }
-
-    void SetVoiceDropParameter(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        IPC::RequestParser rp{ctx};
-        auto voice_drop_param{rp.Pop<f32>()};
-
-        auto& system_ = impl->GetSystem();
-        system_.SetVoiceDropParameter(voice_drop_param);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void GetVoiceDropParameter(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        auto& system_ = impl->GetSystem();
-        auto voice_drop_param{system_.GetVoiceDropParameter()};
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(voice_drop_param);
-    }
-
-    KernelHelpers::ServiceContext service_context;
-    Kernel::KEvent* rendered_event;
-    Manager& manager;
-    std::unique_ptr<Renderer> impl;
-    Kernel::KProcess& process;
-    Common::ScratchBuffer<u8> output_buffer;
-    Common::ScratchBuffer<u8> performance_buffer;
-};
-
-class IAudioDevice final : public ServiceFramework<IAudioDevice> {
-
-public:
-    explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
-                          u32 device_num)
-        : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
-          impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
-          event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
-        static const FunctionInfo functions[] = {
-            {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
-            {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
-            {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
-            {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
-            {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
-            {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
-            {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
-            {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
-            {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
-            {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
-            {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
-            {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
-            {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
-            {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
-        };
-        RegisterHandlers(functions);
-
-        event->Signal();
-    }
-
-    ~IAudioDevice() override {
-        service_context.CloseEvent(event);
-    }
-
-private:
-    void ListAudioDeviceName(HLERequestContext& ctx) {
-        const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
-
-        std::vector<AudioDevice::AudioDeviceName> out_names{};
-
-        const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
-
-        std::string out{};
-        for (u32 i = 0; i < out_count; i++) {
-            std::string a{};
-            u32 j = 0;
-            while (out_names[i].name[j] != '\0') {
-                a += out_names[i].name[j];
-                j++;
-            }
-            out += "\n\t" + a;
-        }
-
-        LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
-
-        IPC::ResponseBuilder rb{ctx, 3};
-
-        ctx.WriteBuffer(out_names);
-
-        rb.Push(ResultSuccess);
-        rb.Push(out_count);
-    }
-
-    void SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-        const f32 volume = rp.Pop<f32>();
-
-        const auto device_name_buffer = ctx.ReadBuffer();
-        const std::string name = Common::StringFromBuffer(device_name_buffer);
-
-        LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
-
-        if (name == "AudioTvOutput") {
-            impl->SetDeviceVolumes(volume);
-        }
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
-        const auto device_name_buffer = ctx.ReadBuffer();
-        const std::string name = Common::StringFromBuffer(device_name_buffer);
-
-        LOG_DEBUG(Service_Audio, "called. Name={}", name);
-
-        f32 volume{1.0f};
-        if (name == "AudioTvOutput") {
-            volume = impl->GetDeviceVolume(name);
-        }
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push(volume);
-    }
-
-    void GetActiveAudioDeviceName(HLERequestContext& ctx) {
-        const auto write_size = ctx.GetWriteBufferSize();
-        std::string out_name{"AudioTvOutput"};
-
-        LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
-
-        out_name.resize(write_size);
-
-        ctx.WriteBuffer(out_name);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "(STUBBED) called");
-
-        event->Signal();
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(event->GetReadableEvent());
-    }
-
-    void GetActiveChannelCount(HLERequestContext& ctx) {
-        const auto& sink{system.AudioCore().GetOutputSink()};
-        u32 channel_count{sink.GetSystemChannels()};
-
-        LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
-
-        IPC::ResponseBuilder rb{ctx, 3};
-
-        rb.Push(ResultSuccess);
-        rb.Push<u32>(channel_count);
-    }
-
-    void QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "(STUBBED) called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(event->GetReadableEvent());
-    }
-
-    void QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_Audio, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(event->GetReadableEvent());
-    }
-
-    void ListAudioOutputDeviceName(HLERequestContext& ctx) {
-        const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
-
-        std::vector<AudioDevice::AudioDeviceName> out_names{};
-
-        const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
-
-        std::string out{};
-        for (u32 i = 0; i < out_count; i++) {
-            std::string a{};
-            u32 j = 0;
-            while (out_names[i].name[j] != '\0') {
-                a += out_names[i].name[j];
-                j++;
-            }
-            out += "\n\t" + a;
-        }
-
-        LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
-
-        IPC::ResponseBuilder rb{ctx, 3};
-
-        ctx.WriteBuffer(out_names);
-
-        rb.Push(ResultSuccess);
-        rb.Push(out_count);
-    }
-
-    KernelHelpers::ServiceContext service_context;
-    std::unique_ptr<AudioDevice> impl;
-    Kernel::KEvent* event;
-};
-
-AudRenU::AudRenU(Core::System& system_)
-    : ServiceFramework{system_, "audren:u"},
-      service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
-        {1, &AudRenU::GetWorkBufferSize, "GetWorkBufferSize"},
-        {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
-        {3, nullptr, "OpenAudioRendererForManualExecution"},
-        {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-AudRenU::~AudRenU() = default;
-
-void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    AudioCore::AudioRendererParameterInternal params;
-    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
-    rp.Skip(1, false);
-    auto transfer_memory_size = rp.Pop<u64>();
-    auto applet_resource_user_id = rp.Pop<u64>();
-    auto transfer_memory_handle = ctx.GetCopyHandle(0);
-    auto process_handle = ctx.GetCopyHandle(1);
-
-    if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
-        LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(Audio::ResultOutOfSessions);
-        return;
-    }
-
-    auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
-    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
-
-    const auto session_id{impl->GetSessionId()};
-    if (session_id == -1) {
-        LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(Audio::ResultOutOfSessions);
-        return;
-    }
-
-    LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
-              impl->GetSessionCount());
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
-                                        transfer_memory_size, process_handle, *process,
-                                        applet_resource_user_id, session_id);
-}
-
-void AudRenU::GetWorkBufferSize(HLERequestContext& ctx) {
-    AudioCore::AudioRendererParameterInternal params;
-
-    IPC::RequestParser rp{ctx};
-    rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
-
-    u64 size{0};
-    auto result = impl->GetWorkBufferSize(params, size);
-
-    std::string output_info{};
-    output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
-    output_info +=
-        fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
-    output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
-                               static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
-    output_info += fmt::format(
-        "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
-        "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
-        "Context {:04X}",
-        params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
-        params.splitter_destinations, params.voices, params.perf_frames,
-        params.external_context_size);
-
-    LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
-              output_info, size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push<u64>(size);
-}
-
-void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const auto applet_resource_user_id = rp.Pop<u64>();
-
-    LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
-                                      ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
-}
-
-void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
-    LOG_ERROR(Service_Audio, "called. Implement me!");
-}
-
-void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
-    struct Parameters {
-        u32 revision;
-        u64 applet_resource_user_id;
-    };
-
-    IPC::RequestParser rp{ctx};
-
-    const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
-
-    LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
-              AudioCore::GetRevisionNum(revision), applet_resource_user_id);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
-                                      num_audio_devices++);
-}
-
-} // namespace Service::Audio