1
0
Fork 0
forked from suyu/suyu

audio: rewrite IAudioRenderer

This commit is contained in:
Liam 2024-02-20 20:16:41 -05:00
parent 6012c9fe3a
commit 0471e54e5a
3 changed files with 87 additions and 150 deletions

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/audio_renderer.h" #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 { namespace Service::Audio {
using namespace AudioCore::Renderer; using namespace AudioCore::Renderer;
@ -18,20 +18,20 @@ IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
process_handle{process_handle_} { process_handle{process_handle_} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, {0, C<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
{1, &IAudioRenderer::GetSampleCount, "GetSampleCount"}, {1, C<&IAudioRenderer::GetSampleCount>, "GetSampleCount"},
{2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"}, {2, C<&IAudioRenderer::GetMixBufferCount>, "GetMixBufferCount"},
{3, &IAudioRenderer::GetState, "GetState"}, {3, C<&IAudioRenderer::GetState>, "GetState"},
{4, &IAudioRenderer::RequestUpdate, "RequestUpdate"}, {4, C<&IAudioRenderer::RequestUpdate>, "RequestUpdate"},
{5, &IAudioRenderer::Start, "Start"}, {5, C<&IAudioRenderer::Start>, "Start"},
{6, &IAudioRenderer::Stop, "Stop"}, {6, C<&IAudioRenderer::Stop>, "Stop"},
{7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"}, {7, C<&IAudioRenderer::QuerySystemEvent>, "QuerySystemEvent"},
{8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, {8, C<&IAudioRenderer::SetRenderingTimeLimit>, "SetRenderingTimeLimit"},
{9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, {9, C<&IAudioRenderer::GetRenderingTimeLimit>, "GetRenderingTimeLimit"},
{10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"}, {10, C<&IAudioRenderer::RequestUpdateAuto>, "RequestUpdateAuto"},
{11, nullptr, "ExecuteAudioRendererRendering"}, {11, nullptr, "ExecuteAudioRendererRendering"},
{12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"}, {12, C<&IAudioRenderer::SetVoiceDropParameter>, "SetVoiceDropParameter"},
{13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"}, {13, C<&IAudioRenderer::GetVoiceDropParameter>, "GetVoiceDropParameter"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
@ -47,165 +47,93 @@ IAudioRenderer::~IAudioRenderer() {
process_handle->Close(); process_handle->Close();
} }
void IAudioRenderer::GetSampleRate(HLERequestContext& ctx) { Result IAudioRenderer::GetSampleRate(Out<u32> out_sample_rate) {
const auto sample_rate{impl->GetSystem().GetSampleRate()}; *out_sample_rate = impl->GetSystem().GetSampleRate();
LOG_DEBUG(Service_Audio, "called. Sample rate {}", *out_sample_rate);
LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate); R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(sample_rate);
} }
void IAudioRenderer::GetSampleCount(HLERequestContext& ctx) { Result IAudioRenderer::GetSampleCount(Out<u32> out_sample_count) {
const auto sample_count{impl->GetSystem().GetSampleCount()}; *out_sample_count = impl->GetSystem().GetSampleCount();
LOG_DEBUG(Service_Audio, "called. Sample count {}", *out_sample_count);
LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count); R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(sample_count);
} }
void IAudioRenderer::GetState(HLERequestContext& ctx) { Result IAudioRenderer::GetState(Out<u32> out_state) {
const u32 state{!impl->GetSystem().IsActive()}; *out_state = !impl->GetSystem().IsActive();
LOG_DEBUG(Service_Audio, "called, state {}", *out_state);
LOG_DEBUG(Service_Audio, "called, state {}", state); R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(state);
} }
void IAudioRenderer::GetMixBufferCount(HLERequestContext& ctx) { Result IAudioRenderer::GetMixBufferCount(Out<u32> out_mix_buffer_count) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
*out_mix_buffer_count = impl->GetSystem().GetMixBufferCount();
const auto buffer_count{impl->GetSystem().GetMixBufferCount()}; R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(buffer_count);
} }
void IAudioRenderer::RequestUpdate(HLERequestContext& ctx) { 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"); LOG_TRACE(Service_Audio, "called");
const auto input{ctx.ReadBuffer(0)}; const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
if (result.IsFailure()) {
// 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()); LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
} }
IPC::ResponseBuilder rb{ctx, 2}; R_RETURN(result);
rb.Push(result);
} }
void IAudioRenderer::Start(HLERequestContext& ctx) { Result IAudioRenderer::Start() {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
impl->Start(); impl->Start();
R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} }
void IAudioRenderer::Stop(HLERequestContext& ctx) { Result IAudioRenderer::Stop() {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
impl->Stop(); impl->Stop();
R_SUCCEED();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} }
void IAudioRenderer::QuerySystemEvent(HLERequestContext& ctx) { Result IAudioRenderer::QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
R_UNLESS(impl->GetSystem().GetExecutionMode() != AudioCore::ExecutionMode::Manual,
if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) { Audio::ResultNotSupported);
IPC::ResponseBuilder rb{ctx, 2}; *out_event = &rendered_event->GetReadableEvent();
rb.Push(Audio::ResultNotSupported); R_SUCCEED();
return;
}
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(rendered_event->GetReadableEvent());
} }
void IAudioRenderer::SetRenderingTimeLimit(HLERequestContext& ctx) { Result IAudioRenderer::SetRenderingTimeLimit(u32 rendering_time_limit) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
impl->GetSystem().SetRenderingTimeLimit(rendering_time_limit);
IPC::RequestParser rp{ctx}; ;
auto limit = rp.PopRaw<u32>(); R_SUCCEED();
auto& system_ = impl->GetSystem();
system_.SetRenderingTimeLimit(limit);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} }
void IAudioRenderer::GetRenderingTimeLimit(HLERequestContext& ctx) { Result IAudioRenderer::GetRenderingTimeLimit(Out<u32> out_rendering_time_limit) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
*out_rendering_time_limit = impl->GetSystem().GetRenderingTimeLimit();
auto& system_ = impl->GetSystem(); R_SUCCEED();
auto time = system_.GetRenderingTimeLimit();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(time);
} }
void IAudioRenderer::ExecuteAudioRendererRendering(HLERequestContext& ctx) { Result IAudioRenderer::SetVoiceDropParameter(f32 voice_drop_parameter) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
impl->GetSystem().SetVoiceDropParameter(voice_drop_parameter);
R_SUCCEED();
} }
void IAudioRenderer::SetVoiceDropParameter(HLERequestContext& ctx) { Result IAudioRenderer::GetVoiceDropParameter(Out<f32> out_voice_drop_parameter) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
*out_voice_drop_parameter = impl->GetSystem().GetVoiceDropParameter();
IPC::RequestParser rp{ctx}; R_SUCCEED();
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 } // namespace Service::Audio

View file

@ -4,9 +4,14 @@
#pragma once #pragma once
#include "audio_core/renderer/audio_renderer.h" #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/kernel_helpers.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Kernel {
class KReadableEvent;
}
namespace Service::Audio { namespace Service::Audio {
class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
@ -19,19 +24,23 @@ public:
~IAudioRenderer() override; ~IAudioRenderer() override;
private: private:
void GetSampleRate(HLERequestContext& ctx); Result GetSampleRate(Out<u32> out_sample_rate);
void GetSampleCount(HLERequestContext& ctx); Result GetSampleCount(Out<u32> out_sample_count);
void GetState(HLERequestContext& ctx); Result GetState(Out<u32> out_state);
void GetMixBufferCount(HLERequestContext& ctx); Result GetMixBufferCount(Out<u32> out_mix_buffer_count);
void RequestUpdate(HLERequestContext& ctx); Result RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
void Start(HLERequestContext& ctx); OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
void Stop(HLERequestContext& ctx); InBuffer<BufferAttr_HipcMapAlias> input);
void QuerySystemEvent(HLERequestContext& ctx); Result RequestUpdateAuto(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
void SetRenderingTimeLimit(HLERequestContext& ctx); OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
void GetRenderingTimeLimit(HLERequestContext& ctx); InBuffer<BufferAttr_HipcAutoSelect> input);
void ExecuteAudioRendererRendering(HLERequestContext& ctx); Result Start();
void SetVoiceDropParameter(HLERequestContext& ctx); Result Stop();
void GetVoiceDropParameter(HLERequestContext& ctx); 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; KernelHelpers::ServiceContext service_context;
Kernel::KEvent* rendered_event; Kernel::KEvent* rendered_event;

View file

@ -415,7 +415,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
auto& buffer = temp[OutBufferIndex]; auto& buffer = temp[OutBufferIndex];
const size_t size = buffer.size(); const size_t size = buffer.size();
if (ctx.CanWriteBuffer(OutBufferIndex)) { if (size > 0 && ctx.CanWriteBuffer(OutBufferIndex)) {
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
ctx.WriteBuffer(buffer.data(), size, OutBufferIndex); ctx.WriteBuffer(buffer.data(), size, OutBufferIndex);
} else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) { } else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) {