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