From 0471e54e5a74e3171da77ca95f0420142d675947 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 20 Feb 2024 20:16:41 -0500 Subject: [PATCH] audio: rewrite IAudioRenderer --- src/core/hle/service/audio/audio_renderer.cpp | 200 ++++++------------ src/core/hle/service/audio/audio_renderer.h | 35 +-- src/core/hle/service/cmif_serialization.h | 2 +- 3 files changed, 87 insertions(+), 150 deletions(-) diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp index a408fc3cf..fc20054b4 100644 --- a/src/core/hle/service/audio/audio_renderer.cpp +++ b/src/core/hle/service/audio/audio_renderer.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/audio/audio_renderer.h" -#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/cmif_serialization.h" namespace Service::Audio { using namespace AudioCore::Renderer; @@ -18,20 +18,20 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_, process_handle{process_handle_} { // 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"}, + {0, C<&IAudioRenderer::GetSampleRate>, "GetSampleRate"}, + {1, C<&IAudioRenderer::GetSampleCount>, "GetSampleCount"}, + {2, C<&IAudioRenderer::GetMixBufferCount>, "GetMixBufferCount"}, + {3, C<&IAudioRenderer::GetState>, "GetState"}, + {4, C<&IAudioRenderer::RequestUpdate>, "RequestUpdate"}, + {5, C<&IAudioRenderer::Start>, "Start"}, + {6, C<&IAudioRenderer::Stop>, "Stop"}, + {7, C<&IAudioRenderer::QuerySystemEvent>, "QuerySystemEvent"}, + {8, C<&IAudioRenderer::SetRenderingTimeLimit>, "SetRenderingTimeLimit"}, + {9, C<&IAudioRenderer::GetRenderingTimeLimit>, "GetRenderingTimeLimit"}, + {10, C<&IAudioRenderer::RequestUpdateAuto>, "RequestUpdateAuto"}, {11, nullptr, "ExecuteAudioRendererRendering"}, - {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"}, - {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"}, + {12, C<&IAudioRenderer::SetVoiceDropParameter>, "SetVoiceDropParameter"}, + {13, C<&IAudioRenderer::GetVoiceDropParameter>, "GetVoiceDropParameter"}, }; // clang-format on RegisterHandlers(functions); @@ -47,165 +47,93 @@ IAudioRenderer::~IAudioRenderer() { process_handle->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); +Result IAudioRenderer::GetSampleRate(Out out_sample_rate) { + *out_sample_rate = impl->GetSystem().GetSampleRate(); + LOG_DEBUG(Service_Audio, "called. Sample rate {}", *out_sample_rate); + R_SUCCEED(); } -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); +Result IAudioRenderer::GetSampleCount(Out out_sample_count) { + *out_sample_count = impl->GetSystem().GetSampleCount(); + LOG_DEBUG(Service_Audio, "called. Sample count {}", *out_sample_count); + R_SUCCEED(); } -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); +Result IAudioRenderer::GetState(Out out_state) { + *out_state = !impl->GetSystem().IsActive(); + LOG_DEBUG(Service_Audio, "called, state {}", *out_state); + R_SUCCEED(); } -void IAudioRenderer::GetMixBufferCount(HLERequestContext& ctx) { +Result IAudioRenderer::GetMixBufferCount(Out out_mix_buffer_count) { LOG_DEBUG(Service_Audio, "called"); - - const auto buffer_count{impl->GetSystem().GetMixBufferCount()}; - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(buffer_count); + *out_mix_buffer_count = impl->GetSystem().GetMixBufferCount(); + R_SUCCEED(); } -void IAudioRenderer::RequestUpdate(HLERequestContext& ctx) { +Result IAudioRenderer::RequestUpdate(OutBuffer out_buffer, + OutBuffer out_performance_buffer, + InBuffer input) { + R_RETURN(this->RequestUpdateAuto(out_buffer, out_performance_buffer, input)); +} + +Result IAudioRenderer::RequestUpdateAuto( + OutBuffer out_buffer, + OutBuffer out_performance_buffer, + InBuffer input) { 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 { + 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()); } - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + R_RETURN(result); } -void IAudioRenderer::Start(HLERequestContext& ctx) { +Result IAudioRenderer::Start() { LOG_DEBUG(Service_Audio, "called"); - impl->Start(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void IAudioRenderer::Stop(HLERequestContext& ctx) { +Result IAudioRenderer::Stop() { LOG_DEBUG(Service_Audio, "called"); - impl->Stop(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void IAudioRenderer::QuerySystemEvent(HLERequestContext& ctx) { +Result IAudioRenderer::QuerySystemEvent(OutCopyHandle out_event) { 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()); + R_UNLESS(impl->GetSystem().GetExecutionMode() != AudioCore::ExecutionMode::Manual, + Audio::ResultNotSupported); + *out_event = &rendered_event->GetReadableEvent(); + R_SUCCEED(); } -void IAudioRenderer::SetRenderingTimeLimit(HLERequestContext& ctx) { +Result IAudioRenderer::SetRenderingTimeLimit(u32 rendering_time_limit) { LOG_DEBUG(Service_Audio, "called"); - - IPC::RequestParser rp{ctx}; - auto limit = rp.PopRaw(); - - auto& system_ = impl->GetSystem(); - system_.SetRenderingTimeLimit(limit); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + impl->GetSystem().SetRenderingTimeLimit(rendering_time_limit); + ; + R_SUCCEED(); } -void IAudioRenderer::GetRenderingTimeLimit(HLERequestContext& ctx) { +Result IAudioRenderer::GetRenderingTimeLimit(Out out_rendering_time_limit) { LOG_DEBUG(Service_Audio, "called"); - - auto& system_ = impl->GetSystem(); - auto time = system_.GetRenderingTimeLimit(); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(time); + *out_rendering_time_limit = impl->GetSystem().GetRenderingTimeLimit(); + R_SUCCEED(); } -void IAudioRenderer::ExecuteAudioRendererRendering(HLERequestContext& ctx) { +Result IAudioRenderer::SetVoiceDropParameter(f32 voice_drop_parameter) { LOG_DEBUG(Service_Audio, "called"); + impl->GetSystem().SetVoiceDropParameter(voice_drop_parameter); + R_SUCCEED(); } -void IAudioRenderer::SetVoiceDropParameter(HLERequestContext& ctx) { +Result IAudioRenderer::GetVoiceDropParameter(Out out_voice_drop_parameter) { LOG_DEBUG(Service_Audio, "called"); - - IPC::RequestParser rp{ctx}; - auto voice_drop_param{rp.Pop()}; - - 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); + *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 index d3e7461ef..f25c50ce8 100644 --- a/src/core/hle/service/audio/audio_renderer.h +++ b/src/core/hle/service/audio/audio_renderer.h @@ -4,9 +4,14 @@ #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 { @@ -19,19 +24,23 @@ public: ~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); + Result GetSampleRate(Out out_sample_rate); + Result GetSampleCount(Out out_sample_count); + Result GetState(Out out_state); + Result GetMixBufferCount(Out out_mix_buffer_count); + Result RequestUpdate(OutBuffer out_buffer, + OutBuffer out_performance_buffer, + InBuffer input); + Result RequestUpdateAuto(OutBuffer out_buffer, + OutBuffer out_performance_buffer, + InBuffer input); + Result Start(); + Result Stop(); + Result QuerySystemEvent(OutCopyHandle out_event); + Result SetRenderingTimeLimit(u32 rendering_time_limit); + Result GetRenderingTimeLimit(Out out_rendering_time_limit); + Result SetVoiceDropParameter(f32 voice_drop_parameter); + Result GetVoiceDropParameter(Out out_voice_drop_parameter); KernelHelpers::ServiceContext service_context; Kernel::KEvent* rendered_event; 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) {