aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/audio/audin_u.cpp393
-rw-r--r--src/core/hle/service/audio/audin_u.h38
-rw-r--r--src/core/hle/service/audio/audio.cpp28
-rw-r--r--src/core/hle/service/audio/audio_controller.cpp31
-rw-r--r--src/core/hle/service/audio/audio_controller.h1
-rw-r--r--src/core/hle/service/audio/audio_device.cpp163
-rw-r--r--src/core/hle/service/audio/audio_device.h58
-rw-r--r--src/core/hle/service/audio/audio_in.cpp146
-rw-r--r--src/core/hle/service/audio/audio_in.h53
-rw-r--r--src/core/hle/service/audio/audio_in_manager.cpp125
-rw-r--r--src/core/hle/service/audio/audio_in_manager.h57
-rw-r--r--src/core/hle/service/audio/audio_out.cpp146
-rw-r--r--src/core/hle/service/audio/audio_out.h58
-rw-r--r--src/core/hle/service/audio/audio_out_manager.cpp101
-rw-r--r--src/core/hle/service/audio/audio_out_manager.h44
-rw-r--r--src/core/hle/service/audio/audio_renderer.cpp139
-rw-r--r--src/core/hle/service/audio/audio_renderer.h54
-rw-r--r--src/core/hle/service/audio/audio_renderer_manager.cpp104
-rw-r--r--src/core/hle/service/audio/audio_renderer_manager.h37
-rw-r--r--src/core/hle/service/audio/audout_u.cpp323
-rw-r--r--src/core/hle/service/audio/audout_u.h37
-rw-r--r--src/core/hle/service/audio/audren_u.cpp552
-rw-r--r--src/core/hle/service/audio/audren_u.h35
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager.cpp (renamed from src/core/hle/service/audio/audrec_u.cpp)7
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager.h (renamed from src/core/hle/service/audio/audrec_a.h)6
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp (renamed from src/core/hle/service/audio/audrec_a.cpp)7
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager_for_applet.h (renamed from src/core/hle/service/audio/audrec_u.h)7
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder.cpp145
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder.h63
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder_manager.cpp156
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder_manager.h53
-rw-r--r--src/core/hle/service/audio/hwopus.cpp502
-rw-r--r--src/core/hle/service/audio/hwopus.h36
-rw-r--r--src/core/hle/service/cmif_serialization.h2
34 files changed, 1753 insertions, 1954 deletions
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
deleted file mode 100644
index de2aa6906..000000000
--- a/src/core/hle/service/audio/audin_u.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "audio_core/in/audio_in_system.h"
-#include "audio_core/renderer/audio_device.h"
-#include "common/common_funcs.h"
-#include "common/logging/log.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/service/audio/audin_u.h"
-#include "core/hle/service/ipc_helpers.h"
-
-namespace Service::Audio {
-using namespace AudioCore::AudioIn;
-
-class IAudioIn final : public ServiceFramework<IAudioIn> {
-public:
- explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
- const std::string& device_name, const AudioInParameter& in_params,
- Kernel::KProcess* handle, u64 applet_resource_user_id)
- : ServiceFramework{system_, "IAudioIn"},
- service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")},
- process{handle}, impl{std::make_shared<In>(system_, manager, event, session_id)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IAudioIn::GetAudioInState, "GetAudioInState"},
- {1, &IAudioIn::Start, "Start"},
- {2, &IAudioIn::Stop, "Stop"},
- {3, &IAudioIn::AppendAudioInBuffer, "AppendAudioInBuffer"},
- {4, &IAudioIn::RegisterBufferEvent, "RegisterBufferEvent"},
- {5, &IAudioIn::GetReleasedAudioInBuffer, "GetReleasedAudioInBuffer"},
- {6, &IAudioIn::ContainsAudioInBuffer, "ContainsAudioInBuffer"},
- {7, &IAudioIn::AppendAudioInBuffer, "AppendUacInBuffer"},
- {8, &IAudioIn::AppendAudioInBuffer, "AppendAudioInBufferAuto"},
- {9, &IAudioIn::GetReleasedAudioInBuffer, "GetReleasedAudioInBuffersAuto"},
- {10, &IAudioIn::AppendAudioInBuffer, "AppendUacInBufferAuto"},
- {11, &IAudioIn::GetAudioInBufferCount, "GetAudioInBufferCount"},
- {12, &IAudioIn::SetDeviceGain, "SetDeviceGain"},
- {13, &IAudioIn::GetDeviceGain, "GetDeviceGain"},
- {14, &IAudioIn::FlushAudioInBuffers, "FlushAudioInBuffers"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- process->Open();
-
- if (impl->GetSystem()
- .Initialize(device_name, in_params, handle, applet_resource_user_id)
- .IsError()) {
- LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
- }
- }
-
- ~IAudioIn() override {
- impl->Free();
- service_context.CloseEvent(event);
- process->Close();
- }
-
- [[nodiscard]] std::shared_ptr<In> GetImpl() {
- return impl;
- }
-
-private:
- void GetAudioInState(HLERequestContext& ctx) {
- const auto state = static_cast<u32>(impl->GetState());
-
- LOG_DEBUG(Service_Audio, "called. State={}", state);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(state);
- }
-
- void Start(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto result = impl->StartSystem();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void Stop(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto result = impl->StopSystem();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void AppendAudioInBuffer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- u64 tag = rp.PopRaw<u64>();
-
- const auto in_buffer_size{ctx.GetReadBufferSize()};
- if (in_buffer_size < sizeof(AudioInBuffer)) {
- LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
- }
-
- const auto& in_buffer = ctx.ReadBuffer();
- AudioInBuffer buffer{};
- std::memcpy(&buffer, in_buffer.data(), sizeof(AudioInBuffer));
-
- [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()};
- LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", sessionid, tag);
-
- auto result = impl->AppendBuffer(buffer, tag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void RegisterBufferEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto& buffer_event = impl->GetBufferEvent();
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(buffer_event);
- }
-
- void GetReleasedAudioInBuffer(HLERequestContext& ctx) {
- const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>();
- released_buffer.resize_destructive(write_buffer_size);
- released_buffer[0] = 0;
-
- const auto count = impl->GetReleasedBuffers(released_buffer);
-
- LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
- impl->GetSystem().GetSessionId(), count);
-
- ctx.WriteBuffer(released_buffer);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(count);
- }
-
- void ContainsAudioInBuffer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const u64 tag{rp.Pop<u64>()};
- const auto buffer_queued{impl->ContainsAudioBuffer(tag)};
-
- LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", tag, buffer_queued);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(buffer_queued);
- }
-
- void GetAudioInBufferCount(HLERequestContext& ctx) {
- const auto buffer_count = impl->GetBufferCount();
-
- LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(buffer_count);
- }
-
- void SetDeviceGain(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto volume{rp.Pop<f32>()};
- LOG_DEBUG(Service_Audio, "called. Gain {}", volume);
-
- impl->SetVolume(volume);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDeviceGain(HLERequestContext& ctx) {
- auto volume{impl->GetVolume()};
-
- LOG_DEBUG(Service_Audio, "called. Gain {}", volume);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(volume);
- }
-
- void FlushAudioInBuffers(HLERequestContext& ctx) {
- bool flushed{impl->FlushAudioInBuffers()};
-
- LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", flushed);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(flushed);
- }
-
- KernelHelpers::ServiceContext service_context;
- Kernel::KEvent* event;
- Kernel::KProcess* process;
- std::shared_ptr<AudioCore::AudioIn::In> impl;
- Common::ScratchBuffer<u64> released_buffer;
-};
-
-AudInU::AudInU(Core::System& system_)
- : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"},
- impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &AudInU::ListAudioIns, "ListAudioIns"},
- {1, &AudInU::OpenAudioIn, "OpenAudioIn"},
- {2, &AudInU::ListAudioIns, "ListAudioInsAuto"},
- {3, &AudInU::OpenAudioIn, "OpenAudioInAuto"},
- {4, &AudInU::ListAudioInsAutoFiltered, "ListAudioInsAutoFiltered"},
- {5, &AudInU::OpenAudioInProtocolSpecified, "OpenAudioInProtocolSpecified"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-AudInU::~AudInU() = default;
-
-void AudInU::ListAudioIns(HLERequestContext& ctx) {
- using namespace AudioCore::Renderer;
-
- LOG_DEBUG(Service_Audio, "called");
-
- const auto write_count =
- static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
- std::vector<AudioDevice::AudioDeviceName> device_names{};
-
- u32 out_count{0};
- if (write_count > 0) {
- out_count = impl->GetDeviceNames(device_names, write_count, false);
- ctx.WriteBuffer(device_names);
- }
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(out_count);
-}
-
-void AudInU::ListAudioInsAutoFiltered(HLERequestContext& ctx) {
- using namespace AudioCore::Renderer;
-
- LOG_DEBUG(Service_Audio, "called");
-
- const auto write_count =
- static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
- std::vector<AudioDevice::AudioDeviceName> device_names{};
-
- u32 out_count{0};
- if (write_count > 0) {
- out_count = impl->GetDeviceNames(device_names, write_count, true);
- ctx.WriteBuffer(device_names);
- }
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(out_count);
-}
-
-void AudInU::OpenAudioIn(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- auto in_params{rp.PopRaw<AudioInParameter>()};
- auto applet_resource_user_id{rp.PopRaw<u64>()};
- const auto device_name_data{ctx.ReadBuffer()};
- auto device_name = Common::StringFromBuffer(device_name_data);
- auto handle{ctx.GetCopyHandle(0)};
-
- auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
- if (process.IsNull()) {
- LOG_ERROR(Service_Audio, "Failed to get process handle");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- std::scoped_lock l{impl->mutex};
- auto link{impl->LinkToManager()};
- if (link.IsError()) {
- LOG_ERROR(Service_Audio, "Failed to link Audio In to Audio Manager");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(link);
- return;
- }
-
- size_t new_session_id{};
- auto result{impl->AcquireSessionId(new_session_id)};
- if (result.IsError()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
- impl->num_free_sessions);
-
- auto audio_in =
- std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
- process.GetPointerUnsafe(), applet_resource_user_id);
- impl->sessions[new_session_id] = audio_in->GetImpl();
- impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
-
- auto& out_system = impl->sessions[new_session_id]->GetSystem();
- AudioInParameterInternal out_params{.sample_rate = out_system.GetSampleRate(),
- .channel_count = out_system.GetChannelCount(),
- .sample_format =
- static_cast<u32>(out_system.GetSampleFormat()),
- .state = static_cast<u32>(out_system.GetState())};
-
- IPC::ResponseBuilder rb{ctx, 6, 0, 1};
-
- std::string out_name{out_system.GetName()};
- ctx.WriteBuffer(out_name);
-
- rb.Push(ResultSuccess);
- rb.PushRaw<AudioInParameterInternal>(out_params);
- rb.PushIpcInterface<IAudioIn>(audio_in);
-}
-
-void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- auto protocol_specified{rp.PopRaw<u64>()};
- auto in_params{rp.PopRaw<AudioInParameter>()};
- auto applet_resource_user_id{rp.PopRaw<u64>()};
- const auto device_name_data{ctx.ReadBuffer()};
- auto device_name = Common::StringFromBuffer(device_name_data);
- auto handle{ctx.GetCopyHandle(0)};
-
- auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
- if (process.IsNull()) {
- LOG_ERROR(Service_Audio, "Failed to get process handle");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- std::scoped_lock l{impl->mutex};
- auto link{impl->LinkToManager()};
- if (link.IsError()) {
- LOG_ERROR(Service_Audio, "Failed to link Audio In to Audio Manager");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(link);
- return;
- }
-
- size_t new_session_id{};
- auto result{impl->AcquireSessionId(new_session_id)};
- if (result.IsError()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
- impl->num_free_sessions);
-
- auto audio_in =
- std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
- process.GetPointerUnsafe(), applet_resource_user_id);
- impl->sessions[new_session_id] = audio_in->GetImpl();
- impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
-
- auto& out_system = impl->sessions[new_session_id]->GetSystem();
- AudioInParameterInternal out_params{.sample_rate = out_system.GetSampleRate(),
- .channel_count = out_system.GetChannelCount(),
- .sample_format =
- static_cast<u32>(out_system.GetSampleFormat()),
- .state = static_cast<u32>(out_system.GetState())};
-
- IPC::ResponseBuilder rb{ctx, 6, 0, 1};
-
- std::string out_name{out_system.GetName()};
- if (protocol_specified == 0) {
- if (out_system.IsUac()) {
- out_name = "UacIn";
- } else {
- out_name = "DeviceIn";
- }
- }
-
- ctx.WriteBuffer(out_name);
-
- rb.Push(ResultSuccess);
- rb.PushRaw<AudioInParameterInternal>(out_params);
- rb.PushIpcInterface<IAudioIn>(audio_in);
-}
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h
deleted file mode 100644
index 51e770ff9..000000000
--- a/src/core/hle/service/audio/audin_u.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "audio_core/audio_in_manager.h"
-#include "audio_core/in/audio_in.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace AudioCore::AudioOut {
-class Manager;
-class In;
-} // namespace AudioCore::AudioOut
-
-namespace Service::Audio {
-
-class AudInU final : public ServiceFramework<AudInU> {
-public:
- explicit AudInU(Core::System& system_);
- ~AudInU() override;
-
-private:
- void ListAudioIns(HLERequestContext& ctx);
- void ListAudioInsAutoFiltered(HLERequestContext& ctx);
- void OpenInOutImpl(HLERequestContext& ctx);
- void OpenAudioIn(HLERequestContext& ctx);
- void OpenAudioInProtocolSpecified(HLERequestContext& ctx);
-
- KernelHelpers::ServiceContext service_context;
- std::unique_ptr<AudioCore::AudioIn::Manager> impl;
-};
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 44af030eb..331176bf7 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -2,14 +2,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
-#include "core/hle/service/audio/audin_u.h"
#include "core/hle/service/audio/audio.h"
#include "core/hle/service/audio/audio_controller.h"
-#include "core/hle/service/audio/audout_u.h"
-#include "core/hle/service/audio/audrec_a.h"
-#include "core/hle/service/audio/audrec_u.h"
-#include "core/hle/service/audio/audren_u.h"
-#include "core/hle/service/audio/hwopus.h"
+#include "core/hle/service/audio/audio_in_manager.h"
+#include "core/hle/service/audio/audio_out_manager.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/hardware_opus_decoder_manager.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
@@ -19,12 +19,16 @@ void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
- server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
- server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
- server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
- server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system));
- server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
- server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
+ server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
+ server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system));
+ server_manager->RegisterNamedService(
+ "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<IAudioRendererManager>(system));
+ server_manager->RegisterNamedService("hwopus",
+ std::make_shared<IHardwareOpusDecoderManager>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp
index a6da66d0f..c9804cf9c 100644
--- a/src/core/hle/service/audio/audio_controller.cpp
+++ b/src/core/hle/service/audio/audio_controller.cpp
@@ -16,27 +16,27 @@ IAudioController::IAudioController(Core::System& system_)
static const FunctionInfo functions[] = {
{0, nullptr, "GetTargetVolume"},
{1, nullptr, "SetTargetVolume"},
- {2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
- {3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
+ {2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
+ {3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
{4, nullptr, "IsTargetMute"},
{5, nullptr, "SetTargetMute"},
{6, nullptr, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"},
- {9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
- {10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
+ {9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
+ {10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"},
- {12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
- {13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
- {14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
+ {12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
+ {13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
+ {14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"},
- {17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
- {18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
+ {17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
+ {18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
{21, nullptr, "GetAudioOutputTargetForPlayReport"},
- {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
+ {22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
{23, nullptr, "SetSystemOutputMasterVolume"},
{24, nullptr, "GetSystemOutputMasterVolume"},
{25, nullptr, "GetAudioVolumeDataForPlayReport"},
@@ -44,11 +44,11 @@ IAudioController::IAudioController(Core::System& system_)
{27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
- {30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
- {31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
+ {30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
+ {31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"},
- {34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
+ {34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
{35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{37, nullptr, "SetHearingProtectionSafeguardEnabled"},
@@ -150,6 +150,11 @@ Result IAudioController::GetHeadphoneOutputLevelMode(
R_SUCCEED();
}
+Result IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent() {
+ LOG_WARNING(Service_Audio, "(STUBBED) called");
+ R_SUCCEED();
+}
+
Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);
diff --git a/src/core/hle/service/audio/audio_controller.h b/src/core/hle/service/audio/audio_controller.h
index 9e8514373..d37c4843e 100644
--- a/src/core/hle/service/audio/audio_controller.h
+++ b/src/core/hle/service/audio/audio_controller.h
@@ -45,6 +45,7 @@ private:
Set::AudioOutputMode output_mode);
Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
+ Result NotifyHeadphoneVolumeWarningDisplayedEvent();
Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);
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 000000000..438f3cccd
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.cpp
@@ -0,0 +1,163 @@
+// 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/cmif_serialization.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, D<&IAudioDevice::ListAudioDeviceName>, "ListAudioDeviceName"},
+ {1, D<&IAudioDevice::SetAudioDeviceOutputVolume>, "SetAudioDeviceOutputVolume"},
+ {2, D<&IAudioDevice::GetAudioDeviceOutputVolume>, "GetAudioDeviceOutputVolume"},
+ {3, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioDeviceName"},
+ {4, D<&IAudioDevice::QueryAudioDeviceSystemEvent>, "QueryAudioDeviceSystemEvent"},
+ {5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"},
+ {6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"},
+ {7, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"},
+ {8, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"},
+ {10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"},
+ {11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"},
+ {12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
+ {13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"},
+ {14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
+ };
+ RegisterHandlers(functions);
+
+ event->Signal();
+}
+
+IAudioDevice::~IAudioDevice() {
+ service_context.CloseEvent(event);
+}
+
+Result IAudioDevice::ListAudioDeviceName(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
+ R_RETURN(this->ListAudioDeviceNameAuto(out_names, out_count));
+}
+
+Result IAudioDevice::SetAudioDeviceOutputVolume(
+ InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume) {
+ R_RETURN(this->SetAudioDeviceOutputVolumeAuto(name, volume));
+}
+
+Result IAudioDevice::GetAudioDeviceOutputVolume(
+ Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name) {
+ R_RETURN(this->GetAudioDeviceOutputVolumeAuto(out_volume, name));
+}
+
+Result IAudioDevice::GetActiveAudioDeviceName(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name) {
+ R_RETURN(this->GetActiveAudioDeviceNameAuto(out_name));
+}
+
+Result IAudioDevice::ListAudioDeviceNameAuto(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
+ Out<s32> out_count) {
+ *out_count = impl->ListAudioDeviceName(out_names);
+
+ std::string out{};
+ for (s32 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);
+ R_SUCCEED();
+}
+
+Result IAudioDevice::SetAudioDeviceOutputVolumeAuto(
+ InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume) {
+ R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);
+
+ const std::string device_name = Common::StringFromBuffer(name[0].name);
+ LOG_DEBUG(Service_Audio, "called. name={}, volume={}", device_name, volume);
+
+ if (device_name == "AudioTvOutput") {
+ impl->SetDeviceVolumes(volume);
+ }
+
+ R_SUCCEED();
+}
+
+Result IAudioDevice::GetAudioDeviceOutputVolumeAuto(
+ Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name) {
+ R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);
+
+ const std::string device_name = Common::StringFromBuffer(name[0].name);
+ LOG_DEBUG(Service_Audio, "called. Name={}", device_name);
+
+ *out_volume = 1.0f;
+ if (device_name == "AudioTvOutput") {
+ *out_volume = impl->GetDeviceVolume(device_name);
+ }
+
+ R_SUCCEED();
+}
+
+Result IAudioDevice::GetActiveAudioDeviceNameAuto(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name) {
+ R_UNLESS(!out_name.empty(), Audio::ResultInsufficientBuffer);
+ out_name[0] = AudioDevice::AudioDeviceName("AudioTvOutput");
+ LOG_DEBUG(Service_Audio, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_Audio, "(STUBBED) called");
+ event->Signal();
+ *out_event = &event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IAudioDevice::QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_Audio, "(STUBBED) called");
+ *out_event = &event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IAudioDevice::QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_event = &event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IAudioDevice::GetActiveChannelCount(Out<u32> out_active_channel_count) {
+ *out_active_channel_count = system.AudioCore().GetOutputSink().GetSystemChannels();
+ LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", *out_active_channel_count);
+ R_SUCCEED();
+}
+
+Result IAudioDevice::ListAudioOutputDeviceName(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
+ *out_count = impl->ListAudioOutputDeviceName(out_names);
+
+ std::string out{};
+ for (s32 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);
+ R_SUCCEED();
+}
+
+} // 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 000000000..752157272
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.h
@@ -0,0 +1,58 @@
+// 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/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Audio {
+
+using AudioCore::Renderer::AudioDevice;
+
+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:
+ Result ListAudioDeviceName(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
+ Out<s32> out_count);
+ Result SetAudioDeviceOutputVolume(
+ InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume);
+ Result GetAudioDeviceOutputVolume(
+ Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name);
+ Result GetActiveAudioDeviceName(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name);
+ Result ListAudioDeviceNameAuto(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
+ Out<s32> out_count);
+ Result SetAudioDeviceOutputVolumeAuto(
+ InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume);
+ Result GetAudioDeviceOutputVolumeAuto(
+ Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name);
+ Result GetActiveAudioDeviceNameAuto(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name);
+ Result QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetActiveChannelCount(Out<u32> out_active_channel_count);
+ Result ListAudioOutputDeviceName(
+ OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
+ Out<s32> out_count);
+
+ 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_in.cpp b/src/core/hle/service/audio/audio_in.cpp
new file mode 100644
index 000000000..416803acc
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in.cpp
@@ -0,0 +1,146 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/audio/audio_in.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+using namespace AudioCore::AudioIn;
+
+IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
+ const std::string& device_name, const AudioInParameter& in_params,
+ Kernel::KProcess* handle, u64 applet_resource_user_id)
+ : ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
+ event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
+ manager, event,
+ session_id)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
+ {1, D<&IAudioIn::Start>, "Start"},
+ {2, D<&IAudioIn::Stop>, "Stop"},
+ {3, D<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"},
+ {4, D<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"},
+ {5, D<&IAudioIn::GetReleasedAudioInBuffers>, "GetReleasedAudioInBuffers"},
+ {6, D<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"},
+ {7, D<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"},
+ {8, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendAudioInBufferAuto"},
+ {9, D<&IAudioIn::GetReleasedAudioInBuffersAuto>, "GetReleasedAudioInBuffersAuto"},
+ {10, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendUacInBufferAuto"},
+ {11, D<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"},
+ {12, D<&IAudioIn::SetDeviceGain>, "SetDeviceGain"},
+ {13, D<&IAudioIn::GetDeviceGain>, "GetDeviceGain"},
+ {14, D<&IAudioIn::FlushAudioInBuffers>, "FlushAudioInBuffers"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ process->Open();
+
+ if (impl->GetSystem()
+ .Initialize(device_name, in_params, handle, applet_resource_user_id)
+ .IsError()) {
+ LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
+ }
+}
+
+IAudioIn::~IAudioIn() {
+ impl->Free();
+ service_context.CloseEvent(event);
+ process->Close();
+}
+
+Result IAudioIn::GetAudioInState(Out<u32> out_state) {
+ *out_state = static_cast<u32>(impl->GetState());
+ LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
+ R_SUCCEED();
+}
+
+Result IAudioIn::Start() {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(impl->StartSystem());
+}
+
+Result IAudioIn::Stop() {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(impl->StopSystem());
+}
+
+Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
+ u64 buffer_client_ptr) {
+ R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
+}
+
+Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
+ u64 buffer_client_ptr) {
+ if (buffer.empty()) {
+ LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
+ R_THROW(Audio::ResultInsufficientBuffer);
+ }
+
+ [[maybe_unused]] const auto session_id{impl->GetSystem().GetSessionId()};
+ LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", session_id,
+ buffer_client_ptr);
+
+ R_RETURN(impl->AppendBuffer(buffer[0], buffer_client_ptr));
+}
+
+Result IAudioIn::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_event = &impl->GetBufferEvent();
+ R_SUCCEED();
+}
+
+Result IAudioIn::GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
+ Out<u32> out_count) {
+ R_RETURN(this->GetReleasedAudioInBuffersAuto(out_audio_buffer, out_count));
+}
+
+Result IAudioIn::GetReleasedAudioInBuffersAuto(
+ OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {
+
+ if (!out_audio_buffer.empty()) {
+ out_audio_buffer[0] = 0;
+ }
+ *out_count = impl->GetReleasedBuffers(out_audio_buffer);
+
+ LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
+ impl->GetSystem().GetSessionId(), *out_count);
+ R_SUCCEED();
+}
+
+Result IAudioIn::ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
+ *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);
+
+ LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
+ *out_contains_buffer);
+ R_SUCCEED();
+}
+
+Result IAudioIn::GetAudioInBufferCount(Out<u32> out_buffer_count) {
+ *out_buffer_count = impl->GetBufferCount();
+ LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
+ R_SUCCEED();
+}
+
+Result IAudioIn::SetDeviceGain(f32 device_gain) {
+ impl->SetVolume(device_gain);
+ LOG_DEBUG(Service_Audio, "called. Gain {}", device_gain);
+ R_SUCCEED();
+}
+
+Result IAudioIn::GetDeviceGain(Out<f32> out_device_gain) {
+ *out_device_gain = impl->GetVolume();
+ LOG_DEBUG(Service_Audio, "called. Gain {}", *out_device_gain);
+ R_SUCCEED();
+}
+
+Result IAudioIn::FlushAudioInBuffers(Out<bool> out_flushed) {
+ *out_flushed = impl->FlushAudioInBuffers();
+ LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_in.h b/src/core/hle/service/audio/audio_in.h
new file mode 100644
index 000000000..3fe1e1e87
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in.h
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/in/audio_in.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IAudioIn final : public ServiceFramework<IAudioIn> {
+public:
+ explicit IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager,
+ size_t session_id, const std::string& device_name,
+ const AudioCore::AudioIn::AudioInParameter& in_params,
+ Kernel::KProcess* handle, u64 applet_resource_user_id);
+ ~IAudioIn() override;
+
+ std::shared_ptr<AudioCore::AudioIn::In> GetImpl() {
+ return impl;
+ }
+
+ Result GetAudioInState(Out<u32> out_state);
+ Result Start();
+ Result Stop();
+ Result AppendAudioInBuffer(
+ InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
+ u64 buffer_client_ptr);
+ Result AppendAudioInBufferAuto(
+ InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
+ u64 buffer_client_ptr);
+ Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
+ Out<u32> out_count);
+ Result GetReleasedAudioInBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
+ Out<u32> out_count);
+ Result ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
+ Result GetAudioInBufferCount(Out<u32> out_buffer_count);
+ Result SetDeviceGain(f32 device_gain);
+ Result GetDeviceGain(Out<f32> out_device_gain);
+ Result FlushAudioInBuffers(Out<bool> out_flushed);
+
+private:
+ Kernel::KProcess* process;
+ KernelHelpers::ServiceContext service_context;
+ Kernel::KEvent* event;
+ std::shared_ptr<AudioCore::AudioIn::In> impl;
+ Common::ScratchBuffer<u64> released_buffer;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_in_manager.cpp b/src/core/hle/service/audio/audio_in_manager.cpp
new file mode 100644
index 000000000..2675a5773
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in_manager.cpp
@@ -0,0 +1,125 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/string_util.h"
+#include "core/hle/service/audio/audio_in.h"
+#include "core/hle/service/audio/audio_in_manager.h"
+#include "core/hle/service/cmif_serialization.h"
+
+namespace Service::Audio {
+using namespace AudioCore::AudioIn;
+
+IAudioInManager::IAudioInManager(Core::System& system_)
+ : ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
+ system_)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
+ {1, D<&IAudioInManager::OpenAudioIn>, "OpenAudioIn"},
+ {2, D<&IAudioInManager::ListAudioIns>, "ListAudioInsAuto"},
+ {3, D<&IAudioInManager::OpenAudioIn>, "OpenAudioInAuto"},
+ {4, D<&IAudioInManager::ListAudioInsAutoFiltered>, "ListAudioInsAutoFiltered"},
+ {5, D<&IAudioInManager::OpenAudioInProtocolSpecified>, "OpenAudioInProtocolSpecified"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAudioInManager::~IAudioInManager() = default;
+
+Result IAudioInManager::ListAudioIns(
+ OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins, Out<u32> out_count) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
+}
+
+Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioIn>> out_audio_in,
+ OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
+ AudioInParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
+ name, {}, parameter, process_handle, aruid));
+}
+
+Result IAudioInManager::ListAudioInsAuto(
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
+}
+
+Result IAudioInManager::OpenAudioInAuto(
+ Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
+ name, {}, parameter, process_handle, aruid));
+}
+
+Result IAudioInManager::ListAudioInsAutoFiltered(
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_count = impl->GetDeviceNames(out_audio_ins, true);
+ R_SUCCEED();
+}
+
+Result IAudioInManager::OpenAudioInProtocolSpecified(
+ Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
+ AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ if (!process_handle) {
+ LOG_ERROR(Service_Audio, "Failed to get process handle");
+ R_THROW(ResultUnknown);
+ }
+ if (name.empty() || out_name.empty()) {
+ LOG_ERROR(Service_Audio, "Invalid buffers");
+ R_THROW(ResultUnknown);
+ }
+
+ std::scoped_lock l{impl->mutex};
+
+ size_t new_session_id{};
+
+ R_TRY(impl->LinkToManager());
+ R_TRY(impl->AcquireSessionId(new_session_id));
+
+ LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
+ impl->num_free_sessions);
+
+ const auto device_name = Common::StringFromBuffer(name[0].name);
+ *out_audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
+ parameter, process_handle.Get(), aruid.pid);
+ impl->sessions[new_session_id] = (*out_audio_in)->GetImpl();
+ impl->applet_resource_user_ids[new_session_id] = aruid.pid;
+
+ auto& out_system = impl->sessions[new_session_id]->GetSystem();
+ *out_parameter_internal =
+ AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
+ .channel_count = out_system.GetChannelCount(),
+ .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
+ .state = static_cast<u32>(out_system.GetState())};
+
+ out_name[0] = AudioDeviceName(out_system.GetName());
+
+ if (protocol == Protocol{}) {
+ if (out_system.IsUac()) {
+ out_name[0] = AudioDeviceName("UacIn");
+ } else {
+ out_name[0] = AudioDeviceName("DeviceIn");
+ }
+ }
+
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_in_manager.h b/src/core/hle/service/audio/audio_in_manager.h
new file mode 100644
index 000000000..2a983bc60
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in_manager.h
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/audio_in_manager.h"
+#include "audio_core/in/audio_in_system.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
+using Protocol = std::array<u32, 2>;
+
+class IAudioIn;
+
+class IAudioInManager final : public ServiceFramework<IAudioInManager> {
+public:
+ explicit IAudioInManager(Core::System& system_);
+ ~IAudioInManager() override;
+
+private:
+ Result ListAudioIns(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins,
+ Out<u32> out_count);
+ Result OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioIn>> out_audio_in,
+ OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
+ AudioCore::AudioIn::AudioInParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid);
+
+ Result ListAudioInsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins,
+ Out<u32> out_count);
+ Result OpenAudioInAuto(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioIn>> out_audio_in,
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
+ AudioCore::AudioIn::AudioInParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid);
+
+ Result ListAudioInsAutoFiltered(
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count);
+ Result OpenAudioInProtocolSpecified(
+ Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioIn>> out_audio_in,
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
+ AudioCore::AudioIn::AudioInParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
+
+ std::unique_ptr<AudioCore::AudioIn::Manager> impl;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_out.cpp b/src/core/hle/service/audio/audio_out.cpp
new file mode 100644
index 000000000..53009d5d7
--- /dev/null
+++ b/src/core/hle/service/audio/audio_out.cpp
@@ -0,0 +1,146 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "audio_core/out/audio_out.h"
+#include "audio_core/out/audio_out_system.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/service/audio/audio_out.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+using namespace AudioCore::AudioOut;
+
+IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
+ const std::string& device_name, const AudioOutParameter& in_params,
+ Kernel::KProcess* handle, u64 applet_resource_user_id)
+ : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
+ event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
+ impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
+
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioOut::GetAudioOutState>, "GetAudioOutState"},
+ {1, D<&IAudioOut::Start>, "Start"},
+ {2, D<&IAudioOut::Stop>, "Stop"},
+ {3, D<&IAudioOut::AppendAudioOutBuffer>, "AppendAudioOutBuffer"},
+ {4, D<&IAudioOut::RegisterBufferEvent>, "RegisterBufferEvent"},
+ {5, D<&IAudioOut::GetReleasedAudioOutBuffers>, "GetReleasedAudioOutBuffers"},
+ {6, D<&IAudioOut::ContainsAudioOutBuffer>, "ContainsAudioOutBuffer"},
+ {7, D<&IAudioOut::AppendAudioOutBufferAuto>, "AppendAudioOutBufferAuto"},
+ {8, D<&IAudioOut::GetReleasedAudioOutBuffersAuto>, "GetReleasedAudioOutBuffersAuto"},
+ {9, D<&IAudioOut::GetAudioOutBufferCount>, "GetAudioOutBufferCount"},
+ {10, D<&IAudioOut::GetAudioOutPlayedSampleCount>, "GetAudioOutPlayedSampleCount"},
+ {11, D<&IAudioOut::FlushAudioOutBuffers>, "FlushAudioOutBuffers"},
+ {12, D<&IAudioOut::SetAudioOutVolume>, "SetAudioOutVolume"},
+ {13, D<&IAudioOut::GetAudioOutVolume>, "GetAudioOutVolume"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+
+ process->Open();
+}
+
+IAudioOut::~IAudioOut() {
+ impl->Free();
+ service_context.CloseEvent(event);
+ process->Close();
+}
+
+Result IAudioOut::GetAudioOutState(Out<u32> out_state) {
+ *out_state = static_cast<u32>(impl->GetState());
+ LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
+ R_SUCCEED();
+}
+
+Result IAudioOut::Start() {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(impl->StartSystem());
+}
+
+Result IAudioOut::Stop() {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(impl->StopSystem());
+}
+
+Result IAudioOut::AppendAudioOutBuffer(
+ InArray<AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) {
+ R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr));
+}
+
+Result IAudioOut::AppendAudioOutBufferAuto(
+ InArray<AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) {
+ if (audio_out_buffer.empty()) {
+ LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
+ R_THROW(Audio::ResultInsufficientBuffer);
+ }
+
+ LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}",
+ impl->GetSystem().GetSessionId(), buffer_client_ptr);
+ R_RETURN(impl->AppendBuffer(audio_out_buffer[0], buffer_client_ptr));
+}
+
+Result IAudioOut::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_event = &impl->GetBufferEvent();
+ R_SUCCEED();
+}
+
+Result IAudioOut::GetReleasedAudioOutBuffers(
+ OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, Out<u32> out_count) {
+ R_RETURN(this->GetReleasedAudioOutBuffersAuto(out_audio_buffer, out_count));
+}
+
+Result IAudioOut::GetReleasedAudioOutBuffersAuto(
+ OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {
+
+ if (!out_audio_buffer.empty()) {
+ out_audio_buffer[0] = 0;
+ }
+ *out_count = impl->GetReleasedBuffers(out_audio_buffer);
+
+ LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
+ impl->GetSystem().GetSessionId(), *out_count);
+ R_SUCCEED();
+}
+
+Result IAudioOut::ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
+ *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);
+
+ LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
+ *out_contains_buffer);
+ R_SUCCEED();
+}
+
+Result IAudioOut::GetAudioOutBufferCount(Out<u32> out_buffer_count) {
+ *out_buffer_count = impl->GetBufferCount();
+ LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
+ R_SUCCEED();
+}
+
+Result IAudioOut::GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count) {
+ *out_played_sample_count = impl->GetPlayedSampleCount();
+ LOG_DEBUG(Service_Audio, "called. Played samples={}", *out_played_sample_count);
+ R_SUCCEED();
+}
+
+Result IAudioOut::FlushAudioOutBuffers(Out<bool> out_flushed) {
+ *out_flushed = impl->FlushAudioOutBuffers();
+ LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
+ R_SUCCEED();
+}
+
+Result IAudioOut::SetAudioOutVolume(f32 volume) {
+ LOG_DEBUG(Service_Audio, "called. Volume={}", volume);
+ impl->SetVolume(volume);
+ R_SUCCEED();
+}
+
+Result IAudioOut::GetAudioOutVolume(Out<f32> out_volume) {
+ *out_volume = impl->GetVolume();
+ LOG_DEBUG(Service_Audio, "called. Volume={}", *out_volume);
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_out.h b/src/core/hle/service/audio/audio_out.h
new file mode 100644
index 000000000..779b213e7
--- /dev/null
+++ b/src/core/hle/service/audio/audio_out.h
@@ -0,0 +1,58 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/audio_out_manager.h"
+#include "audio_core/out/audio_out_system.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Audio {
+
+class IAudioOut : public ServiceFramework<IAudioOut> {
+public:
+ explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
+ size_t session_id, const std::string& device_name,
+ const AudioCore::AudioOut::AudioOutParameter& in_params,
+ Kernel::KProcess* handle, u64 applet_resource_user_id);
+ ~IAudioOut() override;
+
+ std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
+ return impl;
+ }
+
+ Result GetAudioOutState(Out<u32> out_state);
+ Result Start();
+ Result Stop();
+ Result AppendAudioOutBuffer(
+ InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer,
+ u64 buffer_client_ptr);
+ Result AppendAudioOutBufferAuto(
+ InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer,
+ u64 buffer_client_ptr);
+ Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetReleasedAudioOutBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
+ Out<u32> out_count);
+ Result GetReleasedAudioOutBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
+ Out<u32> out_count);
+ Result ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
+ Result GetAudioOutBufferCount(Out<u32> out_buffer_count);
+ Result GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count);
+ Result FlushAudioOutBuffers(Out<bool> out_flushed);
+ Result SetAudioOutVolume(f32 volume);
+ Result GetAudioOutVolume(Out<f32> out_volume);
+
+private:
+ KernelHelpers::ServiceContext service_context;
+ Kernel::KEvent* event;
+ Kernel::KProcess* process;
+ std::shared_ptr<AudioCore::AudioOut::Out> impl;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_out_manager.cpp b/src/core/hle/service/audio/audio_out_manager.cpp
new file mode 100644
index 000000000..153445097
--- /dev/null
+++ b/src/core/hle/service/audio/audio_out_manager.cpp
@@ -0,0 +1,101 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/string_util.h"
+#include "core/hle/service/audio/audio_out.h"
+#include "core/hle/service/audio/audio_out_manager.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/memory.h"
+
+namespace Service::Audio {
+using namespace AudioCore::AudioOut;
+
+IAudioOutManager::IAudioOutManager(Core::System& system_)
+ : ServiceFramework{system_, "audout:u"}, impl{std::make_unique<Manager>(system_)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"},
+ {1, D<&IAudioOutManager::OpenAudioOut>, "OpenAudioOut"},
+ {2, D<&IAudioOutManager::ListAudioOutsAuto>, "ListAudioOutsAuto"},
+ {3, D<&IAudioOutManager::OpenAudioOutAuto>, "OpenAudioOutAuto"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAudioOutManager::~IAudioOutManager() = default;
+
+Result IAudioOutManager::ListAudioOuts(
+ OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs, Out<u32> out_count) {
+ R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count));
+}
+
+Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioOut>> out_audio_out,
+ OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
+ AudioOutParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid) {
+ R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
+ parameter, process_handle, aruid));
+}
+
+Result IAudioOutManager::ListAudioOutsAuto(
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs, Out<u32> out_count) {
+ if (!out_audio_outs.empty()) {
+ out_audio_outs[0] = AudioDeviceName("DeviceOut");
+ *out_count = 1;
+ LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut");
+ } else {
+ *out_count = 0;
+ LOG_DEBUG(Service_Audio, "called. Empty buffer passed in.");
+ }
+
+ R_SUCCEED();
+}
+
+Result IAudioOutManager::OpenAudioOutAuto(
+ Out<AudioOutParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioOut>> out_audio_out,
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
+ if (!process_handle) {
+ LOG_ERROR(Service_Audio, "Failed to get process handle");
+ R_THROW(ResultUnknown);
+ }
+ if (name.empty() || out_name.empty()) {
+ LOG_ERROR(Service_Audio, "Invalid buffers");
+ R_THROW(ResultUnknown);
+ }
+
+ size_t new_session_id{};
+ R_TRY(impl->LinkToManager());
+ R_TRY(impl->AcquireSessionId(new_session_id));
+
+ const auto device_name = Common::StringFromBuffer(name[0].name);
+ LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
+ impl->num_free_sessions);
+
+ auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name,
+ parameter, process_handle.Get(), aruid.pid);
+ R_TRY(audio_out->GetImpl()->GetSystem().Initialize(device_name, parameter, process_handle.Get(),
+ aruid.pid));
+
+ *out_audio_out = audio_out;
+ impl->sessions[new_session_id] = audio_out->GetImpl();
+ impl->applet_resource_user_ids[new_session_id] = aruid.pid;
+
+ auto& out_system = impl->sessions[new_session_id]->GetSystem();
+ *out_parameter_internal =
+ AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
+ .channel_count = out_system.GetChannelCount(),
+ .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
+ .state = static_cast<u32>(out_system.GetState())};
+
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_out_manager.h b/src/core/hle/service/audio/audio_out_manager.h
new file mode 100644
index 000000000..eaa27bc79
--- /dev/null
+++ b/src/core/hle/service/audio/audio_out_manager.h
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/audio_out_manager.h"
+#include "audio_core/out/audio_out.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
+class IAudioOut;
+
+class IAudioOutManager final : public ServiceFramework<IAudioOutManager> {
+public:
+ explicit IAudioOutManager(Core::System& system_);
+ ~IAudioOutManager() override;
+
+private:
+ Result ListAudioOuts(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs,
+ Out<u32> out_count);
+ Result OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioOut>> out_audio_out,
+ OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
+ AudioCore::AudioOut::AudioOutParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid);
+ Result ListAudioOutsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs,
+ Out<u32> out_count);
+ Result OpenAudioOutAuto(
+ Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
+ Out<SharedPointer<IAudioOut>> out_audio_out,
+ OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
+ InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
+ AudioCore::AudioOut::AudioOutParameter parameter,
+ InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
+
+ std::unique_ptr<AudioCore::AudioOut::Manager> impl;
+};
+
+} // 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 000000000..fc4aad233
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.cpp
@@ -0,0 +1,139 @@
+// 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/cmif_serialization.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,
+ Kernel::KProcess* process_handle_, 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_handle{
+ process_handle_} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
+ {1, D<&IAudioRenderer::GetSampleCount>, "GetSampleCount"},
+ {2, D<&IAudioRenderer::GetMixBufferCount>, "GetMixBufferCount"},
+ {3, D<&IAudioRenderer::GetState>, "GetState"},
+ {4, D<&IAudioRenderer::RequestUpdate>, "RequestUpdate"},
+ {5, D<&IAudioRenderer::Start>, "Start"},
+ {6, D<&IAudioRenderer::Stop>, "Stop"},
+ {7, D<&IAudioRenderer::QuerySystemEvent>, "QuerySystemEvent"},
+ {8, D<&IAudioRenderer::SetRenderingTimeLimit>, "SetRenderingTimeLimit"},
+ {9, D<&IAudioRenderer::GetRenderingTimeLimit>, "GetRenderingTimeLimit"},
+ {10, D<&IAudioRenderer::RequestUpdateAuto>, "RequestUpdateAuto"},
+ {11, nullptr, "ExecuteAudioRendererRendering"},
+ {12, D<&IAudioRenderer::SetVoiceDropParameter>, "SetVoiceDropParameter"},
+ {13, D<&IAudioRenderer::GetVoiceDropParameter>, "GetVoiceDropParameter"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+
+ process_handle->Open();
+ impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
+ applet_resource_user_id, session_id);
+}
+
+IAudioRenderer::~IAudioRenderer() {
+ impl->Finalize();
+ service_context.CloseEvent(rendered_event);
+ process_handle->Close();
+}
+
+Result IAudioRenderer::GetSampleRate(Out<u32> out_sample_rate) {
+ *out_sample_rate = impl->GetSystem().GetSampleRate();
+ LOG_DEBUG(Service_Audio, "called. Sample rate {}", *out_sample_rate);
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::GetSampleCount(Out<u32> out_sample_count) {
+ *out_sample_count = impl->GetSystem().GetSampleCount();
+ LOG_DEBUG(Service_Audio, "called. Sample count {}", *out_sample_count);
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::GetState(Out<u32> out_state) {
+ *out_state = !impl->GetSystem().IsActive();
+ LOG_DEBUG(Service_Audio, "called, state {}", *out_state);
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::GetMixBufferCount(Out<u32> out_mix_buffer_count) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_mix_buffer_count = impl->GetSystem().GetMixBufferCount();
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+ OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
+ InBuffer<BufferAttr_HipcMapAlias> input) {
+ R_RETURN(this->RequestUpdateAuto(out_buffer, out_performance_buffer, input));
+}
+
+Result IAudioRenderer::RequestUpdateAuto(
+ OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
+ OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
+ InBuffer<BufferAttr_HipcAutoSelect> input) {
+ LOG_TRACE(Service_Audio, "called");
+
+ const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
+ if (result.IsFailure()) {
+ LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
+ }
+
+ R_RETURN(result);
+}
+
+Result IAudioRenderer::Start() {
+ LOG_DEBUG(Service_Audio, "called");
+ impl->Start();
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::Stop() {
+ LOG_DEBUG(Service_Audio, "called");
+ impl->Stop();
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_UNLESS(impl->GetSystem().GetExecutionMode() != AudioCore::ExecutionMode::Manual,
+ Audio::ResultNotSupported);
+ *out_event = &rendered_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::SetRenderingTimeLimit(u32 rendering_time_limit) {
+ LOG_DEBUG(Service_Audio, "called");
+ impl->GetSystem().SetRenderingTimeLimit(rendering_time_limit);
+ ;
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::GetRenderingTimeLimit(Out<u32> out_rendering_time_limit) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_rendering_time_limit = impl->GetSystem().GetRenderingTimeLimit();
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::SetVoiceDropParameter(f32 voice_drop_parameter) {
+ LOG_DEBUG(Service_Audio, "called");
+ impl->GetSystem().SetVoiceDropParameter(voice_drop_parameter);
+ R_SUCCEED();
+}
+
+Result IAudioRenderer::GetVoiceDropParameter(Out<f32> out_voice_drop_parameter) {
+ LOG_DEBUG(Service_Audio, "called");
+ *out_voice_drop_parameter = impl->GetSystem().GetVoiceDropParameter();
+ R_SUCCEED();
+}
+
+} // 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 000000000..f25c50ce8
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.h
@@ -0,0 +1,54 @@
+// 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/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+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,
+ Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
+ s32 session_id);
+ ~IAudioRenderer() override;
+
+private:
+ Result GetSampleRate(Out<u32> out_sample_rate);
+ Result GetSampleCount(Out<u32> out_sample_count);
+ Result GetState(Out<u32> out_state);
+ Result GetMixBufferCount(Out<u32> out_mix_buffer_count);
+ Result RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+ OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
+ InBuffer<BufferAttr_HipcMapAlias> input);
+ Result RequestUpdateAuto(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
+ OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
+ InBuffer<BufferAttr_HipcAutoSelect> input);
+ Result Start();
+ Result Stop();
+ Result QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result SetRenderingTimeLimit(u32 rendering_time_limit);
+ Result GetRenderingTimeLimit(Out<u32> out_rendering_time_limit);
+ Result SetVoiceDropParameter(f32 voice_drop_parameter);
+ Result GetVoiceDropParameter(Out<f32> out_voice_drop_parameter);
+
+ KernelHelpers::ServiceContext service_context;
+ Kernel::KEvent* rendered_event;
+ AudioCore::Renderer::Manager& manager;
+ std::unique_ptr<AudioCore::Renderer::Renderer> impl;
+ Kernel::KProcess* process_handle;
+ 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 000000000..6a1345c07
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer_manager.cpp
@@ -0,0 +1,104 @@
+// 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/cmif_serialization.h"
+
+namespace Service::Audio {
+
+using namespace AudioCore::Renderer;
+
+IAudioRendererManager::IAudioRendererManager(Core::System& system_)
+ : ServiceFramework{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"},
+ {1, D<&IAudioRendererManager::GetWorkBufferSize>, "GetWorkBufferSize"},
+ {2, D<&IAudioRendererManager::GetAudioDeviceService>, "GetAudioDeviceService"},
+ {3, nullptr, "OpenAudioRendererForManualExecution"},
+ {4, D<&IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo>, "GetAudioDeviceServiceWithRevisionInfo"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAudioRendererManager::~IAudioRendererManager() = default;
+
+Result IAudioRendererManager::OpenAudioRenderer(
+ Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
+ AudioCore::AudioRendererParameterInternal parameter,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
+ InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
+ LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
+ R_THROW(Audio::ResultOutOfSessions);
+ }
+
+ const auto session_id{impl->GetSessionId()};
+ if (session_id == -1) {
+ LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
+ R_THROW(Audio::ResultOutOfSessions);
+ }
+
+ LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
+ impl->GetSessionCount());
+
+ *out_audio_renderer =
+ std::make_shared<IAudioRenderer>(system, *impl, parameter, tmem_handle.Get(), tmem_size,
+ process_handle.Get(), aruid.pid, session_id);
+ R_SUCCEED();
+}
+
+Result IAudioRendererManager::GetWorkBufferSize(Out<u64> out_size,
+ AudioCore::AudioRendererParameterInternal params) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ R_TRY(impl->GetWorkBufferSize(params, *out_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, *out_size);
+ R_SUCCEED();
+}
+
+Result IAudioRendererManager::GetAudioDeviceService(
+ Out<SharedPointer<IAudioDevice>> out_audio_device, ClientAppletResourceUserId aruid) {
+ LOG_DEBUG(Service_Audio, "called, aruid={:#x}", aruid.pid);
+ *out_audio_device = std::make_shared<IAudioDevice>(
+ system, aruid.pid, Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
+ R_SUCCEED();
+}
+
+Result IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(
+ Out<SharedPointer<IAudioDevice>> out_audio_device, u32 revision,
+ ClientAppletResourceUserId aruid) {
+ LOG_DEBUG(Service_Audio, "called, revision={} aruid={:#x}", AudioCore::GetRevisionNum(revision),
+ aruid.pid);
+ *out_audio_device =
+ std::make_shared<IAudioDevice>(system, aruid.pid, revision, num_audio_devices++);
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer_manager.h b/src/core/hle/service/audio/audio_renderer_manager.h
new file mode 100644
index 000000000..69eee664c
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer_manager.h
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/audio_render_manager.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IAudioDevice;
+class IAudioRenderer;
+
+class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
+public:
+ explicit IAudioRendererManager(Core::System& system_);
+ ~IAudioRendererManager() override;
+
+private:
+ Result OpenAudioRenderer(Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
+ AudioCore::AudioRendererParameterInternal parameter,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
+ InCopyHandle<Kernel::KProcess> process_handle,
+ ClientAppletResourceUserId aruid);
+ Result GetWorkBufferSize(Out<u64> out_size,
+ AudioCore::AudioRendererParameterInternal parameter);
+ Result GetAudioDeviceService(Out<SharedPointer<IAudioDevice>> out_audio_device,
+ ClientAppletResourceUserId aruid);
+ Result GetAudioDeviceServiceWithRevisionInfo(Out<SharedPointer<IAudioDevice>> out_audio_device,
+ u32 revision, ClientAppletResourceUserId aruid);
+
+ std::unique_ptr<AudioCore::Renderer::Manager> impl;
+ u32 num_audio_devices{0};
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
deleted file mode 100644
index 8cc7b69f4..000000000
--- a/src/core/hle/service/audio/audout_u.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <array>
-#include <cstring>
-#include <vector>
-
-#include "audio_core/out/audio_out_system.h"
-#include "audio_core/renderer/audio_device.h"
-#include "common/common_funcs.h"
-#include "common/logging/log.h"
-#include "common/scratch_buffer.h"
-#include "common/string_util.h"
-#include "common/swap.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/service/audio/audout_u.h"
-#include "core/hle/service/audio/errors.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/memory.h"
-
-namespace Service::Audio {
-using namespace AudioCore::AudioOut;
-
-class IAudioOut final : public ServiceFramework<IAudioOut> {
-public:
- explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
- size_t session_id, const std::string& device_name,
- const AudioOutParameter& in_params, Kernel::KProcess* handle,
- u64 applet_resource_user_id)
- : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
- event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
- impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
-
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
- {1, &IAudioOut::Start, "Start"},
- {2, &IAudioOut::Stop, "Stop"},
- {3, &IAudioOut::AppendAudioOutBuffer, "AppendAudioOutBuffer"},
- {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
- {5, &IAudioOut::GetReleasedAudioOutBuffers, "GetReleasedAudioOutBuffers"},
- {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"},
- {7, &IAudioOut::AppendAudioOutBuffer, "AppendAudioOutBufferAuto"},
- {8, &IAudioOut::GetReleasedAudioOutBuffers, "GetReleasedAudioOutBuffersAuto"},
- {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
- {10, &IAudioOut::GetAudioOutPlayedSampleCount, "GetAudioOutPlayedSampleCount"},
- {11, &IAudioOut::FlushAudioOutBuffers, "FlushAudioOutBuffers"},
- {12, &IAudioOut::SetAudioOutVolume, "SetAudioOutVolume"},
- {13, &IAudioOut::GetAudioOutVolume, "GetAudioOutVolume"},
- };
- // clang-format on
- RegisterHandlers(functions);
-
- process->Open();
- }
-
- ~IAudioOut() override {
- impl->Free();
- service_context.CloseEvent(event);
- process->Close();
- }
-
- [[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
- return impl;
- }
-
-private:
- void GetAudioOutState(HLERequestContext& ctx) {
- const auto state = static_cast<u32>(impl->GetState());
-
- LOG_DEBUG(Service_Audio, "called. State={}", state);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(state);
- }
-
- void Start(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto result = impl->StartSystem();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void Stop(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto result = impl->StopSystem();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void AppendAudioOutBuffer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- u64 tag = rp.PopRaw<u64>();
-
- const auto in_buffer_size{ctx.GetReadBufferSize()};
- if (in_buffer_size < sizeof(AudioOutBuffer)) {
- LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
- }
-
- const auto& in_buffer = ctx.ReadBuffer();
- AudioOutBuffer buffer{};
- std::memcpy(&buffer, in_buffer.data(), sizeof(AudioOutBuffer));
-
- LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}",
- impl->GetSystem().GetSessionId(), tag);
-
- auto result = impl->AppendBuffer(buffer, tag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void RegisterBufferEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto& buffer_event = impl->GetBufferEvent();
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(buffer_event);
- }
-
- void GetReleasedAudioOutBuffers(HLERequestContext& ctx) {
- const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>();
- released_buffer.resize_destructive(write_buffer_size);
- released_buffer[0] = 0;
-
- const auto count = impl->GetReleasedBuffers(released_buffer);
-
- ctx.WriteBuffer(released_buffer);
-
- LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
- impl->GetSystem().GetSessionId(), count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(count);
- }
-
- void ContainsAudioOutBuffer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const u64 tag{rp.Pop<u64>()};
- const auto buffer_queued{impl->ContainsAudioBuffer(tag)};
-
- LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", tag, buffer_queued);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(buffer_queued);
- }
-
- void GetAudioOutBufferCount(HLERequestContext& ctx) {
- const auto buffer_count = impl->GetBufferCount();
-
- LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(buffer_count);
- }
-
- void GetAudioOutPlayedSampleCount(HLERequestContext& ctx) {
- const auto samples_played = impl->GetPlayedSampleCount();
-
- LOG_DEBUG(Service_Audio, "called. Played samples={}", samples_played);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(samples_played);
- }
-
- void FlushAudioOutBuffers(HLERequestContext& ctx) {
- bool flushed{impl->FlushAudioOutBuffers()};
-
- LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", flushed);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(flushed);
- }
-
- void SetAudioOutVolume(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto volume = rp.Pop<f32>();
-
- LOG_DEBUG(Service_Audio, "called. Volume={}", volume);
-
- impl->SetVolume(volume);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetAudioOutVolume(HLERequestContext& ctx) {
- const auto volume = impl->GetVolume();
-
- LOG_DEBUG(Service_Audio, "called. Volume={}", volume);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(volume);
- }
-
- KernelHelpers::ServiceContext service_context;
- Kernel::KEvent* event;
- Kernel::KProcess* process;
- std::shared_ptr<AudioCore::AudioOut::Out> impl;
- Common::ScratchBuffer<u64> released_buffer;
-};
-
-AudOutU::AudOutU(Core::System& system_)
- : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"},
- impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
- {1, &AudOutU::OpenAudioOut, "OpenAudioOut"},
- {2, &AudOutU::ListAudioOuts, "ListAudioOutsAuto"},
- {3, &AudOutU::OpenAudioOut, "OpenAudioOutAuto"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-AudOutU::~AudOutU() = default;
-
-void AudOutU::ListAudioOuts(HLERequestContext& ctx) {
- using namespace AudioCore::Renderer;
-
- std::scoped_lock l{impl->mutex};
-
- const auto write_count =
- static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
- std::vector<AudioDevice::AudioDeviceName> device_names{};
- if (write_count > 0) {
- device_names.emplace_back("DeviceOut");
- LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut");
- } else {
- LOG_DEBUG(Service_Audio, "called. Empty buffer passed in.");
- }
-
- ctx.WriteBuffer(device_names);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(device_names.size()));
-}
-
-void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- auto in_params{rp.PopRaw<AudioOutParameter>()};
- auto applet_resource_user_id{rp.PopRaw<u64>()};
- const auto device_name_data{ctx.ReadBuffer()};
- auto device_name = Common::StringFromBuffer(device_name_data);
- auto handle{ctx.GetCopyHandle(0)};
-
- auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
- if (process.IsNull()) {
- LOG_ERROR(Service_Audio, "Failed to get process handle");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultUnknown);
- return;
- }
-
- auto link{impl->LinkToManager()};
- if (link.IsError()) {
- LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(link);
- return;
- }
-
- size_t new_session_id{};
- auto result{impl->AcquireSessionId(new_session_id)};
- if (result.IsError()) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
- impl->num_free_sessions);
-
- auto audio_out =
- std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params,
- process.GetPointerUnsafe(), applet_resource_user_id);
- result = audio_out->GetImpl()->GetSystem().Initialize(
- device_name, in_params, process.GetPointerUnsafe(), applet_resource_user_id);
- if (result.IsError()) {
- LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
-
- impl->sessions[new_session_id] = audio_out->GetImpl();
- impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
-
- auto& out_system = impl->sessions[new_session_id]->GetSystem();
- AudioOutParameterInternal out_params{.sample_rate = out_system.GetSampleRate(),
- .channel_count = out_system.GetChannelCount(),
- .sample_format =
- static_cast<u32>(out_system.GetSampleFormat()),
- .state = static_cast<u32>(out_system.GetState())};
-
- IPC::ResponseBuilder rb{ctx, 6, 0, 1};
-
- ctx.WriteBuffer(out_system.GetName());
-
- rb.Push(ResultSuccess);
- rb.PushRaw<AudioOutParameterInternal>(out_params);
- rb.PushIpcInterface<IAudioOut>(audio_out);
-}
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
deleted file mode 100644
index 8f288c6e0..000000000
--- a/src/core/hle/service/audio/audout_u.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "audio_core/audio_out_manager.h"
-#include "audio_core/out/audio_out.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace AudioCore::AudioOut {
-class Manager;
-class Out;
-} // namespace AudioCore::AudioOut
-
-namespace Service::Audio {
-
-class IAudioOut;
-
-class AudOutU final : public ServiceFramework<AudOutU> {
-public:
- explicit AudOutU(Core::System& system_);
- ~AudOutU() override;
-
-private:
- void ListAudioOuts(HLERequestContext& ctx);
- void OpenAudioOut(HLERequestContext& ctx);
-
- KernelHelpers::ServiceContext service_context;
- std::unique_ptr<AudioCore::AudioOut::Manager> impl;
-};
-
-} // namespace Service::Audio
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 10108abc0..000000000
--- 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
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
deleted file mode 100644
index 3d7993a16..000000000
--- a/src/core/hle/service/audio/audren_u.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#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"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Audio {
-class IAudioRenderer;
-
-class AudRenU final : public ServiceFramework<AudRenU> {
-public:
- explicit AudRenU(Core::System& system_);
- ~AudRenU() override;
-
-private:
- void OpenAudioRenderer(HLERequestContext& ctx);
- void GetWorkBufferSize(HLERequestContext& ctx);
- void GetAudioDeviceService(HLERequestContext& ctx);
- void OpenAudioRendererForManualExecution(HLERequestContext& ctx);
- void GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx);
-
- KernelHelpers::ServiceContext service_context;
- std::unique_ptr<AudioCore::Renderer::Manager> impl;
- u32 num_audio_devices{0};
-};
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/final_output_recorder_manager.cpp
index bc55cec17..f70a0e62d 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/final_output_recorder_manager.cpp
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "core/hle/service/audio/audrec_u.h"
+#include "core/hle/service/audio/final_output_recorder_manager.h"
namespace Service::Audio {
@@ -30,13 +30,14 @@ public:
}
};
-AudRecU::AudRecU(Core::System& system_) : ServiceFramework{system_, "audrec:u"} {
+IFinalOutputRecorderManager::IFinalOutputRecorderManager(Core::System& system_)
+ : ServiceFramework{system_, "audrec:u"} {
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFinalOutputRecorder"},
};
RegisterHandlers(functions);
}
-AudRecU::~AudRecU() = default;
+IFinalOutputRecorderManager::~IFinalOutputRecorderManager() = default;
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.h b/src/core/hle/service/audio/final_output_recorder_manager.h
index 9edf89f6c..0663b894e 100644
--- a/src/core/hle/service/audio/audrec_a.h
+++ b/src/core/hle/service/audio/final_output_recorder_manager.h
@@ -11,10 +11,10 @@ class System;
namespace Service::Audio {
-class AudRecA final : public ServiceFramework<AudRecA> {
+class IFinalOutputRecorderManager final : public ServiceFramework<IFinalOutputRecorderManager> {
public:
- explicit AudRecA(Core::System& system_);
- ~AudRecA() override;
+ explicit IFinalOutputRecorderManager(Core::System& system_);
+ ~IFinalOutputRecorderManager() override;
};
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp
index fa82e9ac7..7e2e42bbe 100644
--- a/src/core/hle/service/audio/audrec_a.cpp
+++ b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp
@@ -1,11 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "core/hle/service/audio/audrec_a.h"
+#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
namespace Service::Audio {
-AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} {
+IFinalOutputRecorderManagerForApplet::IFinalOutputRecorderManagerForApplet(Core::System& system_)
+ : ServiceFramework{system_, "audrec:a"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestSuspend"},
@@ -16,6 +17,6 @@ AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"}
RegisterHandlers(functions);
}
-AudRecA::~AudRecA() = default;
+IFinalOutputRecorderManagerForApplet::~IFinalOutputRecorderManagerForApplet() = default;
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_u.h b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.h
index 8b4817884..27940f7e0 100644
--- a/src/core/hle/service/audio/audrec_u.h
+++ b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.h
@@ -11,10 +11,11 @@ class System;
namespace Service::Audio {
-class AudRecU final : public ServiceFramework<AudRecU> {
+class IFinalOutputRecorderManagerForApplet final
+ : public ServiceFramework<IFinalOutputRecorderManagerForApplet> {
public:
- explicit AudRecU(Core::System& system_);
- ~AudRecU() override;
+ explicit IFinalOutputRecorderManagerForApplet(Core::System& system_);
+ ~IFinalOutputRecorderManagerForApplet() override;
};
} // namespace Service::Audio
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..03d3374c1
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder.cpp
@@ -0,0 +1,145 @@
+// 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/cmif_serialization.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, D<&IHardwareOpusDecoder::DecodeInterleavedOld>, "DecodeInterleavedOld"},
+ {1, D<&IHardwareOpusDecoder::SetContext>, "SetContext"},
+ {2, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld>, "DecodeInterleavedForMultiStreamOld"},
+ {3, D<&IHardwareOpusDecoder::SetContextForMultiStream>, "SetContextForMultiStream"},
+ {4, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfOld>, "DecodeInterleavedWithPerfOld"},
+ {5, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld>, "DecodeInterleavedForMultiStreamWithPerfOld"},
+ {6, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld>, "DecodeInterleavedWithPerfAndResetOld"},
+ {7, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld>, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
+ {8, D<&IHardwareOpusDecoder::DecodeInterleaved>, "DecodeInterleaved"},
+ {9, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStream>, "DecodeInterleavedForMultiStream"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IHardwareOpusDecoder::~IHardwareOpusDecoder() = default;
+
+Result IHardwareOpusDecoder::Initialize(const OpusParametersEx& params,
+ Kernel::KTransferMemory* transfer_memory,
+ u64 transfer_memory_size) {
+ return impl->Initialize(params, transfer_memory, transfer_memory_size);
+}
+
+Result IHardwareOpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
+ Kernel::KTransferMemory* transfer_memory,
+ u64 transfer_memory_size) {
+ return impl->Initialize(params, transfer_memory, transfer_memory_size);
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data) {
+ R_TRY(impl->DecodeInterleaved(out_data_size, nullptr, out_sample_count, opus_data, out_pcm_data,
+ false));
+ LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
+ *out_sample_count);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(impl->SetContext(decoder_context));
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld(
+ OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data, Out<u32> out_data_size,
+ Out<u32> out_sample_count, InBuffer<BufferAttr_HipcMapAlias> opus_data) {
+ R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, nullptr, out_sample_count, opus_data,
+ out_pcm_data, false));
+ LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
+ *out_sample_count);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::SetContextForMultiStream(
+ InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
+ LOG_DEBUG(Service_Audio, "called");
+ R_RETURN(impl->SetContext(decoder_context));
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedWithPerfOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data) {
+ R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
+ out_pcm_data, false));
+ LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
+ *out_sample_count, *out_time_taken);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data) {
+ R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
+ opus_data, out_pcm_data, false));
+ LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
+ *out_sample_count, *out_time_taken);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
+ R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
+ out_pcm_data, reset));
+ LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
+ *out_data_size, *out_sample_count, *out_time_taken);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
+ R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
+ opus_data, out_pcm_data, reset));
+ LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
+ *out_data_size, *out_sample_count, *out_time_taken);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::DecodeInterleaved(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
+ bool reset) {
+ R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
+ out_pcm_data, reset));
+ LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
+ *out_data_size, *out_sample_count, *out_time_taken);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoder::DecodeInterleavedForMultiStream(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
+ bool reset) {
+ R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
+ opus_data, out_pcm_data, reset));
+ LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
+ *out_data_size, *out_sample_count, *out_time_taken);
+ R_SUCCEED();
+}
+
+} // 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..511bf46bd
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder.h
@@ -0,0 +1,63 @@
+// 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/cmif_types.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(const AudioCore::OpusDecoder::OpusParametersEx& params,
+ Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
+ Result Initialize(const AudioCore::OpusDecoder::OpusMultiStreamParametersEx& params,
+ Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
+
+private:
+ Result DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data);
+ Result SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context);
+ Result DecodeInterleavedForMultiStreamOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data);
+ Result SetContextForMultiStream(InBuffer<BufferAttr_HipcMapAlias> decoder_context);
+ Result DecodeInterleavedWithPerfOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data);
+ Result DecodeInterleavedForMultiStreamWithPerfOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data);
+ Result DecodeInterleavedWithPerfAndResetOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset);
+ Result DecodeInterleavedForMultiStreamWithPerfAndResetOld(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset);
+ Result DecodeInterleaved(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
+ bool reset);
+ Result DecodeInterleavedForMultiStream(
+ OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
+ Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
+ InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
+ bool reset);
+
+ 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..9de72e30f
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
@@ -0,0 +1,156 @@
+// 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/cmif_serialization.h"
+
+namespace Service::Audio {
+
+using namespace AudioCore::OpusDecoder;
+
+IHardwareOpusDecoderManager::IHardwareOpusDecoderManager(Core::System& system_)
+ : ServiceFramework{system_, "hwopus"}, system{system_}, impl{system} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoder>, "OpenHardwareOpusDecoder"},
+ {1, D<&IHardwareOpusDecoderManager::GetWorkBufferSize>, "GetWorkBufferSize"},
+ {2, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream>, "OpenOpusDecoderForMultiStream"},
+ {3, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream>, "GetWorkBufferSizeForMultiStream"},
+ {4, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx>, "OpenHardwareOpusDecoderEx"},
+ {5, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeEx>, "GetWorkBufferSizeEx"},
+ {6, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx>, "OpenHardwareOpusDecoderForMultiStreamEx"},
+ {7, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx>, "GetWorkBufferSizeForMultiStreamEx"},
+ {8, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeExEx>, "GetWorkBufferSizeExEx"},
+ {9, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx>, "GetWorkBufferSizeForMultiStreamExEx"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+}
+
+IHardwareOpusDecoderManager::~IHardwareOpusDecoderManager() = default;
+
+Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoder(
+ Out<SharedPointer<IHardwareOpusDecoder>> out_decoder, OpusParameters params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
+ LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size {:#x}",
+ params.sample_rate, params.channel_count, tmem_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,
+ };
+ R_TRY(decoder->Initialize(ex, tmem_handle.Get(), tmem_size));
+
+ *out_decoder = decoder;
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::GetWorkBufferSize(Out<u32> out_size, OpusParameters params) {
+ R_TRY(impl.GetWorkBufferSize(params, *out_size));
+ LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} -- returned size {:#x}",
+ params.sample_rate, params.channel_count, *out_size);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream(
+ Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
+ InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
+ LOG_DEBUG(Service_Audio,
+ "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
+ "transfer_memory_size {:#x}",
+ params->sample_rate, params->channel_count, params->total_stream_count,
+ params->stereo_stream_count, tmem_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));
+ R_TRY(decoder->Initialize(ex, tmem_handle.Get(), tmem_size));
+
+ *out_decoder = decoder;
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream(
+ Out<u32> out_size, InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params) {
+ R_TRY(impl.GetWorkBufferSizeForMultiStream(*params, *out_size));
+ LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx(
+ Out<SharedPointer<IHardwareOpusDecoder>> out_decoder, OpusParametersEx params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
+ LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size {:#x}",
+ params.sample_rate, params.channel_count, tmem_size);
+
+ auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
+ R_TRY(decoder->Initialize(params, tmem_handle.Get(), tmem_size));
+
+ *out_decoder = decoder;
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::GetWorkBufferSizeEx(Out<u32> out_size,
+ OpusParametersEx params) {
+ R_TRY(impl.GetWorkBufferSizeEx(params, *out_size));
+ LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx(
+ Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
+ InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
+ LOG_DEBUG(Service_Audio,
+ "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
+ "use_large_frame_size {}"
+ "transfer_memory_size {:#x}",
+ params->sample_rate, params->channel_count, params->total_stream_count,
+ params->stereo_stream_count, params->use_large_frame_size, tmem_size);
+
+ auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
+
+ R_TRY(decoder->Initialize(*params, tmem_handle.Get(), tmem_size));
+
+ *out_decoder = decoder;
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
+ Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params) {
+ R_TRY(impl.GetWorkBufferSizeForMultiStreamEx(*params, *out_size));
+ LOG_DEBUG(Service_Audio,
+ "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
+ "use_large_frame_size {} -- returned size {:#x}",
+ params->sample_rate, params->channel_count, params->total_stream_count,
+ params->stereo_stream_count, params->use_large_frame_size, *out_size);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::GetWorkBufferSizeExEx(Out<u32> out_size,
+ OpusParametersEx params) {
+ R_TRY(impl.GetWorkBufferSizeExEx(params, *out_size));
+ LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
+ R_SUCCEED();
+}
+
+Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
+ Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params) {
+ R_TRY(impl.GetWorkBufferSizeForMultiStreamExEx(*params, *out_size));
+ LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder_manager.h b/src/core/hle/service/audio/hardware_opus_decoder_manager.h
new file mode 100644
index 000000000..4f869c517
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder_manager.h
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/opus/decoder_manager.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IHardwareOpusDecoder;
+
+using AudioCore::OpusDecoder::OpusMultiStreamParameters;
+using AudioCore::OpusDecoder::OpusMultiStreamParametersEx;
+using AudioCore::OpusDecoder::OpusParameters;
+using AudioCore::OpusDecoder::OpusParametersEx;
+
+class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
+public:
+ explicit IHardwareOpusDecoderManager(Core::System& system_);
+ ~IHardwareOpusDecoderManager() override;
+
+private:
+ Result OpenHardwareOpusDecoder(Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
+ OpusParameters params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle);
+ Result GetWorkBufferSize(Out<u32> out_size, OpusParameters params);
+ Result OpenHardwareOpusDecoderForMultiStream(
+ Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
+ InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle);
+ Result GetWorkBufferSizeForMultiStream(
+ Out<u32> out_size, InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params);
+ Result OpenHardwareOpusDecoderEx(Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
+ OpusParametersEx params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle);
+ Result GetWorkBufferSizeEx(Out<u32> out_size, OpusParametersEx params);
+ Result OpenHardwareOpusDecoderForMultiStreamEx(
+ Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
+ InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params, u32 tmem_size,
+ InCopyHandle<Kernel::KTransferMemory> tmem_handle);
+ Result GetWorkBufferSizeForMultiStreamEx(
+ Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params);
+ Result GetWorkBufferSizeExEx(Out<u32> out_size, OpusParametersEx params);
+ Result GetWorkBufferSizeForMultiStreamExEx(
+ Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params);
+
+ Core::System& system;
+ AudioCore::OpusDecoder::OpusDecoderManager impl;
+};
+
+} // namespace Service::Audio
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
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
deleted file mode 100644
index d3960065e..000000000
--- a/src/core/hle/service/audio/hwopus.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "audio_core/opus/decoder_manager.h"
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Audio {
-
-class HwOpus final : public ServiceFramework<HwOpus> {
-public:
- explicit HwOpus(Core::System& system_);
- ~HwOpus() override;
-
-private:
- void OpenHardwareOpusDecoder(HLERequestContext& ctx);
- void GetWorkBufferSize(HLERequestContext& ctx);
- void OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx);
- void GetWorkBufferSizeForMultiStream(HLERequestContext& ctx);
- void OpenHardwareOpusDecoderEx(HLERequestContext& ctx);
- void GetWorkBufferSizeEx(HLERequestContext& ctx);
- void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx);
- void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx);
- void GetWorkBufferSizeExEx(HLERequestContext& ctx);
- void GetWorkBufferSizeForMultiStreamExEx(HLERequestContext& ctx);
-
- Core::System& system;
- AudioCore::OpusDecoder::OpusDecoderManager impl;
-};
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/cmif_serialization.h b/src/core/hle/service/cmif_serialization.h
index f24682c34..5a5f610f3 100644
--- a/src/core/hle/service/cmif_serialization.h
+++ b/src/core/hle/service/cmif_serialization.h
@@ -415,7 +415,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
auto& buffer = temp[OutBufferIndex];
const size_t size = buffer.size();
- if (ctx.CanWriteBuffer(OutBufferIndex)) {
+ if (size > 0 && ctx.CanWriteBuffer(OutBufferIndex)) {
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
ctx.WriteBuffer(buffer.data(), size, OutBufferIndex);
} else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) {