From 672e61d8022aaa178b66bd92f2038d260dc3d104 Mon Sep 17 00:00:00 2001
From: FengChen <vonchenplus@gmail.com>
Date: Sat, 17 Sep 2022 00:28:56 +0800
Subject: [PATCH] core: implement HwOpus GetWorkBufferSizeForMultiStreamEx

---
 src/core/hle/service/audio/hwopus.cpp | 28 ++++++++++++++++++++++++++-
 src/core/hle/service/audio/hwopus.h   | 11 +++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 4f2ed2d52e..8bafc3a983 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -255,6 +255,32 @@ void HwOpus::GetWorkBufferSizeEx(Kernel::HLERequestContext& ctx) {
     GetWorkBufferSize(ctx);
 }
 
+void HwOpus::GetWorkBufferSizeForMultiStreamEx(Kernel::HLERequestContext& ctx) {
+    OpusMultiStreamParametersEx param;
+    std::memcpy(&param, ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
+
+    const auto sample_rate = param.sample_rate;
+    const auto channel_count = param.channel_count;
+    const auto number_streams = param.number_streams;
+    const auto number_stereo_streams = param.number_stereo_streams;
+
+    LOG_DEBUG(
+        Audio,
+        "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}",
+        sample_rate, channel_count, number_streams, number_stereo_streams);
+
+    ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
+                   sample_rate == 12000 || sample_rate == 8000,
+               "Invalid sample rate");
+
+    const u32 worker_buffer_sz =
+        static_cast<u32>(opus_multistream_decoder_get_size(number_streams, number_stereo_streams));
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(worker_buffer_sz);
+}
+
 void HwOpus::OpenHardwareOpusDecoder(Kernel::HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto sample_rate = rp.Pop<u32>();
@@ -335,7 +361,7 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
         {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
         {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
         {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"},
-        {7, nullptr, "GetWorkBufferSizeForMultiStreamEx"},
+        {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
     };
     RegisterHandlers(functions);
 }
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index 265dd0cc63..e6092e2903 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -11,6 +11,16 @@ class System;
 
 namespace Service::Audio {
 
+struct OpusMultiStreamParametersEx {
+    u32 sample_rate;
+    u32 channel_count;
+    u32 number_streams;
+    u32 number_stereo_streams;
+    u32 use_large_frame_size;
+    u32 padding;
+    std::array<u32, 64> channel_mappings;
+};
+
 class HwOpus final : public ServiceFramework<HwOpus> {
 public:
     explicit HwOpus(Core::System& system_);
@@ -21,6 +31,7 @@ private:
     void OpenHardwareOpusDecoderEx(Kernel::HLERequestContext& ctx);
     void GetWorkBufferSize(Kernel::HLERequestContext& ctx);
     void GetWorkBufferSizeEx(Kernel::HLERequestContext& ctx);
+    void GetWorkBufferSizeForMultiStreamEx(Kernel::HLERequestContext& ctx);
 };
 
 } // namespace Service::Audio