From f65539504f009bb18409907fef429bf8c70e0508 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Tue, 20 Feb 2024 00:55:02 -0500
Subject: [PATCH] audio: split IHardwarweOpusDecoder, move
 IHardwareOpusDecoderManager

---
 src/core/CMakeLists.txt                       |   6 +-
 src/core/hle/service/audio/audio.cpp          |   5 +-
 .../service/audio/hardware_opus_decoder.cpp   | 265 +++++++++
 .../hle/service/audio/hardware_opus_decoder.h |  38 ++
 .../audio/hardware_opus_decoder_manager.cpp   | 243 +++++++++
 ...opus.h => hardware_opus_decoder_manager.h} |   6 +-
 src/core/hle/service/audio/hwopus.cpp         | 502 ------------------
 7 files changed, 556 insertions(+), 509 deletions(-)
 create mode 100644 src/core/hle/service/audio/hardware_opus_decoder.cpp
 create mode 100644 src/core/hle/service/audio/hardware_opus_decoder.h
 create mode 100644 src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
 rename src/core/hle/service/audio/{hwopus.h => hardware_opus_decoder_manager.h} (83%)
 delete mode 100644 src/core/hle/service/audio/hwopus.cpp

diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 5a1fc83bd..c49560789 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -512,8 +512,10 @@ add_library(core STATIC
     hle/service/audio/final_output_recorder_manager_for_applet.h
     hle/service/audio/final_output_recorder_manager.cpp
     hle/service/audio/final_output_recorder_manager.h
-    hle/service/audio/hwopus.cpp
-    hle/service/audio/hwopus.h
+    hle/service/audio/hardware_opus_decoder_manager.cpp
+    hle/service/audio/hardware_opus_decoder_manager.h
+    hle/service/audio/hardware_opus_decoder.cpp
+    hle/service/audio/hardware_opus_decoder.h
     hle/service/bcat/backend/backend.cpp
     hle/service/bcat/backend/backend.h
     hle/service/bcat/bcat.cpp
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 82a2ae283..331176bf7 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -9,7 +9,7 @@
 #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"
+#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
 #include "core/hle/service/server_manager.h"
 #include "core/hle/service/service.h"
 
@@ -27,7 +27,8 @@ void LoopProcess(Core::System& system) {
                                          std::make_shared<IFinalOutputRecorderManager>(system));
     server_manager->RegisterNamedService("audren:u",
                                          std::make_shared<IAudioRendererManager>(system));
-    server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
+    server_manager->RegisterNamedService("hwopus",
+                                         std::make_shared<IHardwareOpusDecoderManager>(system));
     ServerManager::RunServer(std::move(server_manager));
 }
 
diff --git a/src/core/hle/service/audio/hardware_opus_decoder.cpp b/src/core/hle/service/audio/hardware_opus_decoder.cpp
new file mode 100644
index 000000000..876bfe334
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder.cpp
@@ -0,0 +1,265 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/audio/hardware_opus_decoder.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+
+using namespace AudioCore::OpusDecoder;
+
+IHardwareOpusDecoder::IHardwareOpusDecoder(Core::System& system_, HardwareOpus& hardware_opus)
+    : ServiceFramework{system_, "IHardwareOpusDecoder"},
+      impl{std::make_unique<AudioCore::OpusDecoder::OpusDecoder>(system_, hardware_opus)} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &IHardwareOpusDecoder::DecodeInterleavedOld, "DecodeInterleavedOld"},
+        {1, &IHardwareOpusDecoder::SetContext, "SetContext"},
+        {2, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld, "DecodeInterleavedForMultiStreamOld"},
+        {3, &IHardwareOpusDecoder::SetContextForMultiStream, "SetContextForMultiStream"},
+        {4, &IHardwareOpusDecoder::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
+        {5, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld, "DecodeInterleavedForMultiStreamWithPerfOld"},
+        {6, &IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld, "DecodeInterleavedWithPerfAndResetOld"},
+        {7, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
+        {8, &IHardwareOpusDecoder::DecodeInterleaved, "DecodeInterleaved"},
+        {9, &IHardwareOpusDecoder::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IHardwareOpusDecoder::~IHardwareOpusDecoder() = default;
+
+Result IHardwareOpusDecoder::Initialize(OpusParametersEx& params,
+                                        Kernel::KTransferMemory* transfer_memory,
+                                        u64 transfer_memory_size) {
+    return impl->Initialize(params, transfer_memory, transfer_memory_size);
+}
+
+Result IHardwareOpusDecoder::Initialize(OpusMultiStreamParametersEx& params,
+                                        Kernel::KTransferMemory* transfer_memory,
+                                        u64 transfer_memory_size) {
+    return impl->Initialize(params, transfer_memory, transfer_memory_size);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedOld(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    auto result =
+        impl->DecodeInterleaved(&size, nullptr, &sample_count, input_data, output_data, false);
+
+    LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {}", size, sample_count);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+}
+
+void IHardwareOpusDecoder::SetContext(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    LOG_DEBUG(Service_Audio, "called");
+
+    auto input_data{ctx.ReadBuffer(0)};
+    auto result = impl->SetContext(input_data);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(result);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    auto result = impl->DecodeInterleavedForMultiStream(&size, nullptr, &sample_count, input_data,
+                                                        output_data, false);
+
+    LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {}", size, sample_count);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+}
+
+void IHardwareOpusDecoder::SetContextForMultiStream(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    LOG_DEBUG(Service_Audio, "called");
+
+    auto input_data{ctx.ReadBuffer(0)};
+    auto result = impl->SetContext(input_data);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(result);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedWithPerfOld(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    u64 time_taken{};
+    auto result =
+        impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data, output_data, false);
+
+    LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {} time taken {}", size,
+              sample_count, time_taken);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+    rb.Push(time_taken);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    u64 time_taken{};
+    auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
+                                                        input_data, output_data, false);
+
+    LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {} time taken {}", size,
+              sample_count, time_taken);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+    rb.Push(time_taken);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto reset{rp.Pop<bool>()};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    u64 time_taken{};
+    auto result =
+        impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data, output_data, reset);
+
+    LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}", reset,
+              size, sample_count, time_taken);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+    rb.Push(time_taken);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld(
+    HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto reset{rp.Pop<bool>()};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    u64 time_taken{};
+    auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
+                                                        input_data, output_data, reset);
+
+    LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}", reset,
+              size, sample_count, time_taken);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+    rb.Push(time_taken);
+}
+
+void IHardwareOpusDecoder::DecodeInterleaved(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto reset{rp.Pop<bool>()};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    u64 time_taken{};
+    auto result =
+        impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data, output_data, reset);
+
+    LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}", reset,
+              size, sample_count, time_taken);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+    rb.Push(time_taken);
+}
+
+void IHardwareOpusDecoder::DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto reset{rp.Pop<bool>()};
+
+    auto input_data{ctx.ReadBuffer(0)};
+    output_data.resize_destructive(ctx.GetWriteBufferSize());
+
+    u32 size{};
+    u32 sample_count{};
+    u64 time_taken{};
+    auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
+                                                        input_data, output_data, reset);
+
+    LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}", reset,
+              size, sample_count, time_taken);
+
+    ctx.WriteBuffer(output_data);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(result);
+    rb.Push(size);
+    rb.Push(sample_count);
+    rb.Push(time_taken);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder.h b/src/core/hle/service/audio/hardware_opus_decoder.h
new file mode 100644
index 000000000..fe6636ce6
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder.h
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/opus/decoder.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IHardwareOpusDecoder final : public ServiceFramework<IHardwareOpusDecoder> {
+public:
+    explicit IHardwareOpusDecoder(Core::System& system_,
+                                  AudioCore::OpusDecoder::HardwareOpus& hardware_opus);
+    ~IHardwareOpusDecoder() override;
+
+    Result Initialize(AudioCore::OpusDecoder::OpusParametersEx& params,
+                      Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
+    Result Initialize(AudioCore::OpusDecoder::OpusMultiStreamParametersEx& params,
+                      Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
+
+private:
+    void DecodeInterleavedOld(HLERequestContext& ctx);
+    void SetContext(HLERequestContext& ctx);
+    void DecodeInterleavedForMultiStreamOld(HLERequestContext& ctx);
+    void SetContextForMultiStream(HLERequestContext& ctx);
+    void DecodeInterleavedWithPerfOld(HLERequestContext& ctx);
+    void DecodeInterleavedForMultiStreamWithPerfOld(HLERequestContext& ctx);
+    void DecodeInterleavedWithPerfAndResetOld(HLERequestContext& ctx);
+    void DecodeInterleavedForMultiStreamWithPerfAndResetOld(HLERequestContext& ctx);
+    void DecodeInterleaved(HLERequestContext& ctx);
+    void DecodeInterleavedForMultiStream(HLERequestContext& ctx);
+
+    std::unique_ptr<AudioCore::OpusDecoder::OpusDecoder> impl;
+    Common::ScratchBuffer<u8> output_data;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp b/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
new file mode 100644
index 000000000..6d7205cd2
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
@@ -0,0 +1,243 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/audio/hardware_opus_decoder.h"
+#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+
+using namespace AudioCore::OpusDecoder;
+
+void IHardwareOpusDecoderManager::OpenHardwareOpusDecoder(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto params = rp.PopRaw<OpusParameters>();
+    auto transfer_memory_size{rp.Pop<u32>()};
+    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
+    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
+
+    LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
+              params.sample_rate, params.channel_count, transfer_memory_size);
+
+    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
+
+    OpusParametersEx ex{
+        .sample_rate = params.sample_rate,
+        .channel_count = params.channel_count,
+        .use_large_frame_size = false,
+    };
+    auto result = decoder->Initialize(ex, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(result);
+    rb.PushIpcInterface(decoder);
+}
+
+void IHardwareOpusDecoderManager::GetWorkBufferSize(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    auto params = rp.PopRaw<OpusParameters>();
+
+    u64 size{};
+    auto result = impl.GetWorkBufferSize(params, size);
+
+    LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} -- returned size 0x{:X}",
+              params.sample_rate, params.channel_count, size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+}
+
+void IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input{ctx.ReadBuffer()};
+    OpusMultiStreamParameters params;
+    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParameters));
+
+    auto transfer_memory_size{rp.Pop<u32>()};
+    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
+    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
+
+    LOG_DEBUG(Service_Audio,
+              "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
+              "transfer_memory_size 0x{:X}",
+              params.sample_rate, params.channel_count, params.total_stream_count,
+              params.stereo_stream_count, transfer_memory_size);
+
+    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
+
+    OpusMultiStreamParametersEx ex{
+        .sample_rate = params.sample_rate,
+        .channel_count = params.channel_count,
+        .total_stream_count = params.total_stream_count,
+        .stereo_stream_count = params.stereo_stream_count,
+        .use_large_frame_size = false,
+        .mappings{},
+    };
+    std::memcpy(ex.mappings.data(), params.mappings.data(), sizeof(params.mappings));
+    auto result = decoder->Initialize(ex, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(result);
+    rb.PushIpcInterface(decoder);
+}
+
+void IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input{ctx.ReadBuffer()};
+    OpusMultiStreamParameters params;
+    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParameters));
+
+    u64 size{};
+    auto result = impl.GetWorkBufferSizeForMultiStream(params, size);
+
+    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+}
+
+void IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto params = rp.PopRaw<OpusParametersEx>();
+    auto transfer_memory_size{rp.Pop<u32>()};
+    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
+    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
+
+    LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
+              params.sample_rate, params.channel_count, transfer_memory_size);
+
+    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
+
+    auto result =
+        decoder->Initialize(params, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(result);
+    rb.PushIpcInterface(decoder);
+}
+
+void IHardwareOpusDecoderManager::GetWorkBufferSizeEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    auto params = rp.PopRaw<OpusParametersEx>();
+
+    u64 size{};
+    auto result = impl.GetWorkBufferSizeEx(params, size);
+
+    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+}
+
+void IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input{ctx.ReadBuffer()};
+    OpusMultiStreamParametersEx params;
+    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
+
+    auto transfer_memory_size{rp.Pop<u32>()};
+    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
+    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
+
+    LOG_DEBUG(Service_Audio,
+              "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
+              "use_large_frame_size {}"
+              "transfer_memory_size 0x{:X}",
+              params.sample_rate, params.channel_count, params.total_stream_count,
+              params.stereo_stream_count, params.use_large_frame_size, transfer_memory_size);
+
+    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
+
+    auto result =
+        decoder->Initialize(params, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(result);
+    rb.PushIpcInterface(decoder);
+}
+
+void IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input{ctx.ReadBuffer()};
+    OpusMultiStreamParametersEx params;
+    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
+
+    u64 size{};
+    auto result = impl.GetWorkBufferSizeForMultiStreamEx(params, size);
+
+    LOG_DEBUG(Service_Audio,
+              "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
+              "use_large_frame_size {} -- returned size 0x{:X}",
+              params.sample_rate, params.channel_count, params.total_stream_count,
+              params.stereo_stream_count, params.use_large_frame_size, size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+}
+
+void IHardwareOpusDecoderManager::GetWorkBufferSizeExEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    auto params = rp.PopRaw<OpusParametersEx>();
+
+    u64 size{};
+    auto result = impl.GetWorkBufferSizeExEx(params, size);
+
+    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+}
+
+void IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    auto input{ctx.ReadBuffer()};
+    OpusMultiStreamParametersEx params;
+    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
+
+    u64 size{};
+    auto result = impl.GetWorkBufferSizeForMultiStreamExEx(params, size);
+
+    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(result);
+    rb.Push(size);
+}
+
+IHardwareOpusDecoderManager::IHardwareOpusDecoderManager(Core::System& system_)
+    : ServiceFramework{system_, "hwopus"}, system{system_}, impl{system} {
+    static const FunctionInfo functions[] = {
+        {0, &IHardwareOpusDecoderManager::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
+        {1, &IHardwareOpusDecoderManager::GetWorkBufferSize, "GetWorkBufferSize"},
+        {2, &IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream,
+         "OpenOpusDecoderForMultiStream"},
+        {3, &IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream,
+         "GetWorkBufferSizeForMultiStream"},
+        {4, &IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
+        {5, &IHardwareOpusDecoderManager::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
+        {6, &IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx,
+         "OpenHardwareOpusDecoderForMultiStreamEx"},
+        {7, &IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx,
+         "GetWorkBufferSizeForMultiStreamEx"},
+        {8, &IHardwareOpusDecoderManager::GetWorkBufferSizeExEx, "GetWorkBufferSizeExEx"},
+        {9, &IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx,
+         "GetWorkBufferSizeForMultiStreamExEx"},
+    };
+    RegisterHandlers(functions);
+}
+
+IHardwareOpusDecoderManager::~IHardwareOpusDecoderManager() = default;
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hardware_opus_decoder_manager.h
similarity index 83%
rename from src/core/hle/service/audio/hwopus.h
rename to src/core/hle/service/audio/hardware_opus_decoder_manager.h
index d3960065e..29b1f16f5 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hardware_opus_decoder_manager.h
@@ -12,10 +12,10 @@ class System;
 
 namespace Service::Audio {
 
-class HwOpus final : public ServiceFramework<HwOpus> {
+class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
 public:
-    explicit HwOpus(Core::System& system_);
-    ~HwOpus() override;
+    explicit IHardwareOpusDecoderManager(Core::System& system_);
+    ~IHardwareOpusDecoderManager() override;
 
 private:
     void OpenHardwareOpusDecoder(HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
deleted file mode 100644
index 91f33aabd..000000000
--- a/src/core/hle/service/audio/hwopus.cpp
+++ /dev/null
@@ -1,502 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <memory>
-#include <vector>
-
-#include "audio_core/opus/decoder.h"
-#include "audio_core/opus/parameters.h"
-#include "common/assert.h"
-#include "common/logging/log.h"
-#include "common/scratch_buffer.h"
-#include "core/core.h"
-#include "core/hle/service/audio/hwopus.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::Audio {
-using namespace AudioCore::OpusDecoder;
-
-class IHardwareOpusDecoder final : public ServiceFramework<IHardwareOpusDecoder> {
-public:
-    explicit IHardwareOpusDecoder(Core::System& system_, HardwareOpus& hardware_opus)
-        : ServiceFramework{system_, "IHardwareOpusDecoder"},
-          impl{std::make_unique<AudioCore::OpusDecoder::OpusDecoder>(system_, hardware_opus)} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &IHardwareOpusDecoder::DecodeInterleavedOld, "DecodeInterleavedOld"},
-            {1, &IHardwareOpusDecoder::SetContext, "SetContext"},
-            {2, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld, "DecodeInterleavedForMultiStreamOld"},
-            {3, &IHardwareOpusDecoder::SetContextForMultiStream, "SetContextForMultiStream"},
-            {4, &IHardwareOpusDecoder::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
-            {5, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld, "DecodeInterleavedForMultiStreamWithPerfOld"},
-            {6, &IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld, "DecodeInterleavedWithPerfAndResetOld"},
-            {7, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
-            {8, &IHardwareOpusDecoder::DecodeInterleaved, "DecodeInterleaved"},
-            {9, &IHardwareOpusDecoder::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-
-    Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
-                      u64 transfer_memory_size) {
-        return impl->Initialize(params, transfer_memory, transfer_memory_size);
-    }
-
-    Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
-                      u64 transfer_memory_size) {
-        return impl->Initialize(params, transfer_memory, transfer_memory_size);
-    }
-
-private:
-    void DecodeInterleavedOld(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        auto result =
-            impl->DecodeInterleaved(&size, nullptr, &sample_count, input_data, output_data, false);
-
-        LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {}", size, sample_count);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 4};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-    }
-
-    void SetContext(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        LOG_DEBUG(Service_Audio, "called");
-
-        auto input_data{ctx.ReadBuffer(0)};
-        auto result = impl->SetContext(input_data);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(result);
-    }
-
-    void DecodeInterleavedForMultiStreamOld(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        auto result = impl->DecodeInterleavedForMultiStream(&size, nullptr, &sample_count,
-                                                            input_data, output_data, false);
-
-        LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {}", size, sample_count);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 4};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-    }
-
-    void SetContextForMultiStream(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        LOG_DEBUG(Service_Audio, "called");
-
-        auto input_data{ctx.ReadBuffer(0)};
-        auto result = impl->SetContext(input_data);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(result);
-    }
-
-    void DecodeInterleavedWithPerfOld(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        u64 time_taken{};
-        auto result = impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data,
-                                              output_data, false);
-
-        LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {} time taken {}", size,
-                  sample_count, time_taken);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 6};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-        rb.Push(time_taken);
-    }
-
-    void DecodeInterleavedForMultiStreamWithPerfOld(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        u64 time_taken{};
-        auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
-                                                            input_data, output_data, false);
-
-        LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {} time taken {}", size,
-                  sample_count, time_taken);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 6};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-        rb.Push(time_taken);
-    }
-
-    void DecodeInterleavedWithPerfAndResetOld(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto reset{rp.Pop<bool>()};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        u64 time_taken{};
-        auto result = impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data,
-                                              output_data, reset);
-
-        LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
-                  reset, size, sample_count, time_taken);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 6};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-        rb.Push(time_taken);
-    }
-
-    void DecodeInterleavedForMultiStreamWithPerfAndResetOld(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto reset{rp.Pop<bool>()};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        u64 time_taken{};
-        auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
-                                                            input_data, output_data, reset);
-
-        LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
-                  reset, size, sample_count, time_taken);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 6};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-        rb.Push(time_taken);
-    }
-
-    void DecodeInterleaved(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto reset{rp.Pop<bool>()};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        u64 time_taken{};
-        auto result = impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data,
-                                              output_data, reset);
-
-        LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
-                  reset, size, sample_count, time_taken);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 6};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-        rb.Push(time_taken);
-    }
-
-    void DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
-        IPC::RequestParser rp{ctx};
-
-        auto reset{rp.Pop<bool>()};
-
-        auto input_data{ctx.ReadBuffer(0)};
-        output_data.resize_destructive(ctx.GetWriteBufferSize());
-
-        u32 size{};
-        u32 sample_count{};
-        u64 time_taken{};
-        auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
-                                                            input_data, output_data, reset);
-
-        LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
-                  reset, size, sample_count, time_taken);
-
-        ctx.WriteBuffer(output_data);
-
-        IPC::ResponseBuilder rb{ctx, 6};
-        rb.Push(result);
-        rb.Push(size);
-        rb.Push(sample_count);
-        rb.Push(time_taken);
-    }
-
-    std::unique_ptr<AudioCore::OpusDecoder::OpusDecoder> impl;
-    Common::ScratchBuffer<u8> output_data;
-};
-
-void HwOpus::OpenHardwareOpusDecoder(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto params = rp.PopRaw<OpusParameters>();
-    auto transfer_memory_size{rp.Pop<u32>()};
-    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
-    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
-
-    LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
-              params.sample_rate, params.channel_count, transfer_memory_size);
-
-    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
-
-    OpusParametersEx ex{
-        .sample_rate = params.sample_rate,
-        .channel_count = params.channel_count,
-        .use_large_frame_size = false,
-    };
-    auto result = decoder->Initialize(ex, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(result);
-    rb.PushIpcInterface(decoder);
-}
-
-void HwOpus::GetWorkBufferSize(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    auto params = rp.PopRaw<OpusParameters>();
-
-    u64 size{};
-    auto result = impl.GetWorkBufferSize(params, size);
-
-    LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} -- returned size 0x{:X}",
-              params.sample_rate, params.channel_count, size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push(size);
-}
-
-void HwOpus::OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto input{ctx.ReadBuffer()};
-    OpusMultiStreamParameters params;
-    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParameters));
-
-    auto transfer_memory_size{rp.Pop<u32>()};
-    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
-    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
-
-    LOG_DEBUG(Service_Audio,
-              "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
-              "transfer_memory_size 0x{:X}",
-              params.sample_rate, params.channel_count, params.total_stream_count,
-              params.stereo_stream_count, transfer_memory_size);
-
-    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
-
-    OpusMultiStreamParametersEx ex{
-        .sample_rate = params.sample_rate,
-        .channel_count = params.channel_count,
-        .total_stream_count = params.total_stream_count,
-        .stereo_stream_count = params.stereo_stream_count,
-        .use_large_frame_size = false,
-        .mappings{},
-    };
-    std::memcpy(ex.mappings.data(), params.mappings.data(), sizeof(params.mappings));
-    auto result = decoder->Initialize(ex, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(result);
-    rb.PushIpcInterface(decoder);
-}
-
-void HwOpus::GetWorkBufferSizeForMultiStream(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto input{ctx.ReadBuffer()};
-    OpusMultiStreamParameters params;
-    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParameters));
-
-    u64 size{};
-    auto result = impl.GetWorkBufferSizeForMultiStream(params, size);
-
-    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push(size);
-}
-
-void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto params = rp.PopRaw<OpusParametersEx>();
-    auto transfer_memory_size{rp.Pop<u32>()};
-    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
-    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
-
-    LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
-              params.sample_rate, params.channel_count, transfer_memory_size);
-
-    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
-
-    auto result =
-        decoder->Initialize(params, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(result);
-    rb.PushIpcInterface(decoder);
-}
-
-void HwOpus::GetWorkBufferSizeEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    auto params = rp.PopRaw<OpusParametersEx>();
-
-    u64 size{};
-    auto result = impl.GetWorkBufferSizeEx(params, size);
-
-    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push(size);
-}
-
-void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto input{ctx.ReadBuffer()};
-    OpusMultiStreamParametersEx params;
-    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
-
-    auto transfer_memory_size{rp.Pop<u32>()};
-    auto transfer_memory_handle{ctx.GetCopyHandle(0)};
-    auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
-
-    LOG_DEBUG(Service_Audio,
-              "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
-              "use_large_frame_size {}"
-              "transfer_memory_size 0x{:X}",
-              params.sample_rate, params.channel_count, params.total_stream_count,
-              params.stereo_stream_count, params.use_large_frame_size, transfer_memory_size);
-
-    auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
-
-    auto result =
-        decoder->Initialize(params, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(result);
-    rb.PushIpcInterface(decoder);
-}
-
-void HwOpus::GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto input{ctx.ReadBuffer()};
-    OpusMultiStreamParametersEx params;
-    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
-
-    u64 size{};
-    auto result = impl.GetWorkBufferSizeForMultiStreamEx(params, size);
-
-    LOG_DEBUG(Service_Audio,
-              "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
-              "use_large_frame_size {} -- returned size 0x{:X}",
-              params.sample_rate, params.channel_count, params.total_stream_count,
-              params.stereo_stream_count, params.use_large_frame_size, size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push(size);
-}
-
-void HwOpus::GetWorkBufferSizeExEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    auto params = rp.PopRaw<OpusParametersEx>();
-
-    u64 size{};
-    auto result = impl.GetWorkBufferSizeExEx(params, size);
-
-    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push(size);
-}
-
-void HwOpus::GetWorkBufferSizeForMultiStreamExEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    auto input{ctx.ReadBuffer()};
-    OpusMultiStreamParametersEx params;
-    std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
-
-    u64 size{};
-    auto result = impl.GetWorkBufferSizeForMultiStreamExEx(params, size);
-
-    LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(result);
-    rb.Push(size);
-}
-
-HwOpus::HwOpus(Core::System& system_)
-    : ServiceFramework{system_, "hwopus"}, system{system_}, impl{system} {
-    static const FunctionInfo functions[] = {
-        {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
-        {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
-        {2, &HwOpus::OpenHardwareOpusDecoderForMultiStream, "OpenOpusDecoderForMultiStream"},
-        {3, &HwOpus::GetWorkBufferSizeForMultiStream, "GetWorkBufferSizeForMultiStream"},
-        {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
-        {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
-        {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx,
-         "OpenHardwareOpusDecoderForMultiStreamEx"},
-        {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
-        {8, &HwOpus::GetWorkBufferSizeExEx, "GetWorkBufferSizeExEx"},
-        {9, &HwOpus::GetWorkBufferSizeForMultiStreamExEx, "GetWorkBufferSizeForMultiStreamExEx"},
-    };
-    RegisterHandlers(functions);
-}
-
-HwOpus::~HwOpus() = default;
-
-} // namespace Service::Audio