From f54277364c773e1721028628b44655e71b5685d0 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 19 Feb 2024 21:11:18 -0500 Subject: [PATCH] audio: rewrite IAudioIn --- src/core/CMakeLists.txt | 2 + src/core/hle/service/audio/audin_u.cpp | 197 +----------------------- src/core/hle/service/audio/audio_in.cpp | 131 ++++++++++++++++ src/core/hle/service/audio/audio_in.h | 48 ++++++ 4 files changed, 182 insertions(+), 196 deletions(-) create mode 100644 src/core/hle/service/audio/audio_in.cpp create mode 100644 src/core/hle/service/audio/audio_in.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f67a12f8f7..75a9bcde7f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -491,6 +491,8 @@ add_library(core STATIC hle/service/apm/apm_interface.h hle/service/audio/audin_u.cpp hle/service/audio/audin_u.h + hle/service/audio/audio_in.cpp + hle/service/audio/audio_in.h hle/service/audio/audio.cpp hle/service/audio/audio.h hle/service/audio/audio_controller.cpp diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index de2aa6906a..0937d6d12f 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -1,209 +1,14 @@ // 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/audio/audio_in.h" #include "core/hle/service/ipc_helpers.h" namespace Service::Audio { using namespace AudioCore::AudioIn; -class IAudioIn final : public ServiceFramework { -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(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 GetImpl() { - return impl; - } - -private: - void GetAudioInState(HLERequestContext& ctx) { - const auto state = static_cast(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(); - - 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(); - 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()}; - 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()}; - 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 impl; - Common::ScratchBuffer released_buffer; -}; - AudInU::AudInU(Core::System& system_) : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"}, impl{std::make_unique(system_)} { 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 0000000000..d847e0fc8e --- /dev/null +++ b/src/core/hle/service/audio/audio_in.cpp @@ -0,0 +1,131 @@ +// 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(system_, manager, event, session_id)} { + // clang-format off + static const FunctionInfo functions[] = { + {0, C<&IAudioIn::GetAudioInState>, "GetAudioInState"}, + {1, C<&IAudioIn::Start>, "Start"}, + {2, C<&IAudioIn::Stop>, "Stop"}, + {3, C<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"}, + {4, C<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"}, + {5, C<&IAudioIn::GetReleasedAudioInBuffer>, "GetReleasedAudioInBuffer"}, + {6, C<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"}, + {7, C<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"}, + {8, C<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBufferAuto"}, + {9, C<&IAudioIn::GetReleasedAudioInBuffer>, "GetReleasedAudioInBuffersAuto"}, + {10, C<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBufferAuto"}, + {11, C<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"}, + {12, C<&IAudioIn::SetDeviceGain>, "SetDeviceGain"}, + {13, C<&IAudioIn::GetDeviceGain>, "GetDeviceGain"}, + {14, C<&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 out_state) { + *out_state = static_cast(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 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 out_event) { + LOG_DEBUG(Service_Audio, "called"); + *out_event = &impl->GetBufferEvent(); + R_SUCCEED(); +} + +Result IAudioIn::GetReleasedAudioInBuffer(OutArray out_audio_buffer, + Out out_count) { + *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 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 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 out_device_gain) { + *out_device_gain = impl->GetVolume(); + LOG_DEBUG(Service_Audio, "called. Gain {}", *out_device_gain); + R_SUCCEED(); +} + +Result IAudioIn::FlushAudioInBuffers(Out 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 0000000000..8d6398ef6c --- /dev/null +++ b/src/core/hle/service/audio/audio_in.h @@ -0,0 +1,48 @@ +// 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 { +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 GetImpl() { + return impl; + } + + Result GetAudioInState(Out out_state); + Result Start(); + Result Stop(); + Result AppendAudioInBuffer( + InArray buffer, + u64 buffer_client_ptr); + Result RegisterBufferEvent(OutCopyHandle out_event); + Result GetReleasedAudioInBuffer(OutArray out_audio_buffer, + Out out_count); + Result ContainsAudioInBuffer(Out out_contains_buffer, u64 buffer_client_ptr); + Result GetAudioInBufferCount(Out out_buffer_count); + Result SetDeviceGain(f32 device_gain); + Result GetDeviceGain(Out out_device_gain); + Result FlushAudioInBuffers(Out out_flushed); + +private: + Kernel::KProcess* process; + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* event; + std::shared_ptr impl; + Common::ScratchBuffer released_buffer; +}; + +} // namespace Service::Audio