diff options
| author | 2024-02-19 23:13:19 -0500 | |
|---|---|---|
| committer | 2024-02-20 22:15:37 -0500 | |
| commit | a05bd3c47ef4d77411c150e5bdbd1efacc5bde68 (patch) | |
| tree | 554bce7aa1cceb4d5ae8c00a6b6629e9c14dd6c1 | |
| parent | audio: rewrite IAudioInManager (diff) | |
| download | yuzu-a05bd3c47ef4d77411c150e5bdbd1efacc5bde68.tar.gz yuzu-a05bd3c47ef4d77411c150e5bdbd1efacc5bde68.tar.xz yuzu-a05bd3c47ef4d77411c150e5bdbd1efacc5bde68.zip | |
audio: rewrite IAudioOut
| -rw-r--r-- | src/audio_core/device/audio_buffers.h | 4 | ||||
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audio_in.cpp | 26 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audio_in.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audio_out.cpp | 146 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audio_out.h | 58 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audout_u.cpp | 207 |
7 files changed, 236 insertions, 216 deletions
diff --git a/src/audio_core/device/audio_buffers.h b/src/audio_core/device/audio_buffers.h index 5d8ed0ef7..25da4c8a2 100644 --- a/src/audio_core/device/audio_buffers.h +++ b/src/audio_core/device/audio_buffers.h | |||
| @@ -146,11 +146,11 @@ public: | |||
| 146 | break; | 146 | break; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | tags[released++] = tag; | ||
| 150 | |||
| 151 | if (released >= tags.size()) { | 149 | if (released >= tags.size()) { |
| 152 | break; | 150 | break; |
| 153 | } | 151 | } |
| 152 | |||
| 153 | tags[released++] = tag; | ||
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | return released; | 156 | return released; |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 51fe8c500..1255ee6bf 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -493,6 +493,8 @@ add_library(core STATIC | |||
| 493 | hle/service/audio/audio_in_manager.h | 493 | hle/service/audio/audio_in_manager.h |
| 494 | hle/service/audio/audio_in.cpp | 494 | hle/service/audio/audio_in.cpp |
| 495 | hle/service/audio/audio_in.h | 495 | hle/service/audio/audio_in.h |
| 496 | hle/service/audio/audio_out.cpp | ||
| 497 | hle/service/audio/audio_out.h | ||
| 496 | hle/service/audio/audio.cpp | 498 | hle/service/audio/audio.cpp |
| 497 | hle/service/audio/audio.h | 499 | hle/service/audio/audio.h |
| 498 | hle/service/audio/audio_controller.cpp | 500 | hle/service/audio/audio_controller.cpp |
diff --git a/src/core/hle/service/audio/audio_in.cpp b/src/core/hle/service/audio/audio_in.cpp index d847e0fc8..31d136077 100644 --- a/src/core/hle/service/audio/audio_in.cpp +++ b/src/core/hle/service/audio/audio_in.cpp | |||
| @@ -21,12 +21,12 @@ IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id, | |||
| 21 | {2, C<&IAudioIn::Stop>, "Stop"}, | 21 | {2, C<&IAudioIn::Stop>, "Stop"}, |
| 22 | {3, C<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"}, | 22 | {3, C<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"}, |
| 23 | {4, C<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"}, | 23 | {4, C<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"}, |
| 24 | {5, C<&IAudioIn::GetReleasedAudioInBuffer>, "GetReleasedAudioInBuffer"}, | 24 | {5, C<&IAudioIn::GetReleasedAudioInBuffers>, "GetReleasedAudioInBuffers"}, |
| 25 | {6, C<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"}, | 25 | {6, C<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"}, |
| 26 | {7, C<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"}, | 26 | {7, C<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"}, |
| 27 | {8, C<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBufferAuto"}, | 27 | {8, C<&IAudioIn::AppendAudioInBufferAuto>, "AppendAudioInBufferAuto"}, |
| 28 | {9, C<&IAudioIn::GetReleasedAudioInBuffer>, "GetReleasedAudioInBuffersAuto"}, | 28 | {9, C<&IAudioIn::GetReleasedAudioInBuffersAuto>, "GetReleasedAudioInBuffersAuto"}, |
| 29 | {10, C<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBufferAuto"}, | 29 | {10, C<&IAudioIn::AppendAudioInBufferAuto>, "AppendUacInBufferAuto"}, |
| 30 | {11, C<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"}, | 30 | {11, C<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"}, |
| 31 | {12, C<&IAudioIn::SetDeviceGain>, "SetDeviceGain"}, | 31 | {12, C<&IAudioIn::SetDeviceGain>, "SetDeviceGain"}, |
| 32 | {13, C<&IAudioIn::GetDeviceGain>, "GetDeviceGain"}, | 32 | {13, C<&IAudioIn::GetDeviceGain>, "GetDeviceGain"}, |
| @@ -69,6 +69,11 @@ Result IAudioIn::Stop() { | |||
| 69 | 69 | ||
| 70 | Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer, | 70 | Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer, |
| 71 | u64 buffer_client_ptr) { | 71 | u64 buffer_client_ptr) { |
| 72 | R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr)); | ||
| 73 | } | ||
| 74 | |||
| 75 | Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer, | ||
| 76 | u64 buffer_client_ptr) { | ||
| 72 | if (buffer.empty()) { | 77 | if (buffer.empty()) { |
| 73 | LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!"); | 78 | LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!"); |
| 74 | R_THROW(Audio::ResultInsufficientBuffer); | 79 | R_THROW(Audio::ResultInsufficientBuffer); |
| @@ -87,8 +92,17 @@ Result IAudioIn::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_e | |||
| 87 | R_SUCCEED(); | 92 | R_SUCCEED(); |
| 88 | } | 93 | } |
| 89 | 94 | ||
| 90 | Result IAudioIn::GetReleasedAudioInBuffer(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, | 95 | Result IAudioIn::GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, |
| 91 | Out<u32> out_count) { | 96 | Out<u32> out_count) { |
| 97 | R_RETURN(this->GetReleasedAudioInBuffersAuto(out_audio_buffer, out_count)); | ||
| 98 | } | ||
| 99 | |||
| 100 | Result IAudioIn::GetReleasedAudioInBuffersAuto( | ||
| 101 | OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) { | ||
| 102 | |||
| 103 | if (!out_audio_buffer.empty()) { | ||
| 104 | out_audio_buffer[0] = 0; | ||
| 105 | } | ||
| 92 | *out_count = impl->GetReleasedBuffers(out_audio_buffer); | 106 | *out_count = impl->GetReleasedBuffers(out_audio_buffer); |
| 93 | 107 | ||
| 94 | LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", | 108 | LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", |
diff --git a/src/core/hle/service/audio/audio_in.h b/src/core/hle/service/audio/audio_in.h index 8d6398ef6..3fe1e1e87 100644 --- a/src/core/hle/service/audio/audio_in.h +++ b/src/core/hle/service/audio/audio_in.h | |||
| @@ -28,9 +28,14 @@ public: | |||
| 28 | Result AppendAudioInBuffer( | 28 | Result AppendAudioInBuffer( |
| 29 | InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer, | 29 | InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer, |
| 30 | u64 buffer_client_ptr); | 30 | u64 buffer_client_ptr); |
| 31 | Result AppendAudioInBufferAuto( | ||
| 32 | InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer, | ||
| 33 | u64 buffer_client_ptr); | ||
| 31 | Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); | 34 | Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); |
| 32 | Result GetReleasedAudioInBuffer(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, | 35 | Result GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, |
| 33 | Out<u32> out_count); | 36 | Out<u32> out_count); |
| 37 | Result GetReleasedAudioInBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, | ||
| 38 | Out<u32> out_count); | ||
| 34 | Result ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr); | 39 | Result ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr); |
| 35 | Result GetAudioInBufferCount(Out<u32> out_buffer_count); | 40 | Result GetAudioInBufferCount(Out<u32> out_buffer_count); |
| 36 | Result SetDeviceGain(f32 device_gain); | 41 | Result SetDeviceGain(f32 device_gain); |
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..cd2dc1f6f --- /dev/null +++ b/src/core/hle/service/audio/audio_out.cpp | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "audio_core/out/audio_out.h" | ||
| 5 | #include "audio_core/out/audio_out_system.h" | ||
| 6 | #include "core/hle/kernel/k_process.h" | ||
| 7 | #include "core/hle/service/audio/audio_out.h" | ||
| 8 | #include "core/hle/service/cmif_serialization.h" | ||
| 9 | #include "core/hle/service/kernel_helpers.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | |||
| 12 | namespace Service::Audio { | ||
| 13 | using namespace AudioCore::AudioOut; | ||
| 14 | |||
| 15 | IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id, | ||
| 16 | const std::string& device_name, const AudioOutParameter& in_params, | ||
| 17 | Kernel::KProcess* handle, u64 applet_resource_user_id) | ||
| 18 | : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, | ||
| 19 | event{service_context.CreateEvent("AudioOutEvent")}, process{handle}, | ||
| 20 | impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { | ||
| 21 | |||
| 22 | // clang-format off | ||
| 23 | static const FunctionInfo functions[] = { | ||
| 24 | {0, C<&IAudioOut::GetAudioOutState>, "GetAudioOutState"}, | ||
| 25 | {1, C<&IAudioOut::Start>, "Start"}, | ||
| 26 | {2, C<&IAudioOut::Stop>, "Stop"}, | ||
| 27 | {3, C<&IAudioOut::AppendAudioOutBuffer>, "AppendAudioOutBuffer"}, | ||
| 28 | {4, C<&IAudioOut::RegisterBufferEvent>, "RegisterBufferEvent"}, | ||
| 29 | {5, C<&IAudioOut::GetReleasedAudioOutBuffers>, "GetReleasedAudioOutBuffers"}, | ||
| 30 | {6, C<&IAudioOut::ContainsAudioOutBuffer>, "ContainsAudioOutBuffer"}, | ||
| 31 | {7, C<&IAudioOut::AppendAudioOutBufferAuto>, "AppendAudioOutBufferAuto"}, | ||
| 32 | {8, C<&IAudioOut::GetReleasedAudioOutBuffersAuto>, "GetReleasedAudioOutBuffersAuto"}, | ||
| 33 | {9, C<&IAudioOut::GetAudioOutBufferCount>, "GetAudioOutBufferCount"}, | ||
| 34 | {10, C<&IAudioOut::GetAudioOutPlayedSampleCount>, "GetAudioOutPlayedSampleCount"}, | ||
| 35 | {11, C<&IAudioOut::FlushAudioOutBuffers>, "FlushAudioOutBuffers"}, | ||
| 36 | {12, C<&IAudioOut::SetAudioOutVolume>, "SetAudioOutVolume"}, | ||
| 37 | {13, C<&IAudioOut::GetAudioOutVolume>, "GetAudioOutVolume"}, | ||
| 38 | }; | ||
| 39 | // clang-format on | ||
| 40 | RegisterHandlers(functions); | ||
| 41 | |||
| 42 | process->Open(); | ||
| 43 | } | ||
| 44 | |||
| 45 | IAudioOut::~IAudioOut() { | ||
| 46 | impl->Free(); | ||
| 47 | service_context.CloseEvent(event); | ||
| 48 | process->Close(); | ||
| 49 | } | ||
| 50 | |||
| 51 | Result IAudioOut::GetAudioOutState(Out<u32> out_state) { | ||
| 52 | *out_state = static_cast<u32>(impl->GetState()); | ||
| 53 | LOG_DEBUG(Service_Audio, "called. state={}", *out_state); | ||
| 54 | R_SUCCEED(); | ||
| 55 | } | ||
| 56 | |||
| 57 | Result IAudioOut::Start() { | ||
| 58 | LOG_DEBUG(Service_Audio, "called"); | ||
| 59 | R_RETURN(impl->StartSystem()); | ||
| 60 | } | ||
| 61 | |||
| 62 | Result IAudioOut::Stop() { | ||
| 63 | LOG_DEBUG(Service_Audio, "called"); | ||
| 64 | R_RETURN(impl->StopSystem()); | ||
| 65 | } | ||
| 66 | |||
| 67 | Result IAudioOut::AppendAudioOutBuffer( | ||
| 68 | InArray<AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) { | ||
| 69 | R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr)); | ||
| 70 | } | ||
| 71 | |||
| 72 | Result IAudioOut::AppendAudioOutBufferAuto( | ||
| 73 | InArray<AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) { | ||
| 74 | if (audio_out_buffer.empty()) { | ||
| 75 | LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!"); | ||
| 76 | R_THROW(Audio::ResultInsufficientBuffer); | ||
| 77 | } | ||
| 78 | |||
| 79 | LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", | ||
| 80 | impl->GetSystem().GetSessionId(), buffer_client_ptr); | ||
| 81 | R_RETURN(impl->AppendBuffer(audio_out_buffer[0], buffer_client_ptr)); | ||
| 82 | } | ||
| 83 | |||
| 84 | Result IAudioOut::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||
| 85 | LOG_DEBUG(Service_Audio, "called"); | ||
| 86 | *out_event = &impl->GetBufferEvent(); | ||
| 87 | R_SUCCEED(); | ||
| 88 | } | ||
| 89 | |||
| 90 | Result IAudioOut::GetReleasedAudioOutBuffers( | ||
| 91 | OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, Out<u32> out_count) { | ||
| 92 | R_RETURN(this->GetReleasedAudioOutBuffersAuto(out_audio_buffer, out_count)); | ||
| 93 | } | ||
| 94 | |||
| 95 | Result IAudioOut::GetReleasedAudioOutBuffersAuto( | ||
| 96 | OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) { | ||
| 97 | |||
| 98 | if (!out_audio_buffer.empty()) { | ||
| 99 | out_audio_buffer[0] = 0; | ||
| 100 | } | ||
| 101 | *out_count = impl->GetReleasedBuffers(out_audio_buffer); | ||
| 102 | |||
| 103 | LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", | ||
| 104 | impl->GetSystem().GetSessionId(), *out_count); | ||
| 105 | R_SUCCEED(); | ||
| 106 | } | ||
| 107 | |||
| 108 | Result IAudioOut::ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) { | ||
| 109 | *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr); | ||
| 110 | |||
| 111 | LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr, | ||
| 112 | *out_contains_buffer); | ||
| 113 | R_SUCCEED(); | ||
| 114 | } | ||
| 115 | |||
| 116 | Result IAudioOut::GetAudioOutBufferCount(Out<u32> out_buffer_count) { | ||
| 117 | *out_buffer_count = impl->GetBufferCount(); | ||
| 118 | LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count); | ||
| 119 | R_SUCCEED(); | ||
| 120 | } | ||
| 121 | |||
| 122 | Result IAudioOut::GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count) { | ||
| 123 | *out_played_sample_count = impl->GetPlayedSampleCount(); | ||
| 124 | LOG_DEBUG(Service_Audio, "called. Played samples={}", *out_played_sample_count); | ||
| 125 | R_SUCCEED(); | ||
| 126 | } | ||
| 127 | |||
| 128 | Result IAudioOut::FlushAudioOutBuffers(Out<bool> out_flushed) { | ||
| 129 | *out_flushed = impl->FlushAudioOutBuffers(); | ||
| 130 | LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed); | ||
| 131 | R_SUCCEED(); | ||
| 132 | } | ||
| 133 | |||
| 134 | Result IAudioOut::SetAudioOutVolume(f32 volume) { | ||
| 135 | LOG_DEBUG(Service_Audio, "called. Volume={}", volume); | ||
| 136 | impl->SetVolume(volume); | ||
| 137 | R_SUCCEED(); | ||
| 138 | } | ||
| 139 | |||
| 140 | Result IAudioOut::GetAudioOutVolume(Out<f32> out_volume) { | ||
| 141 | *out_volume = impl->GetVolume(); | ||
| 142 | LOG_DEBUG(Service_Audio, "called. Volume={}", *out_volume); | ||
| 143 | R_SUCCEED(); | ||
| 144 | } | ||
| 145 | |||
| 146 | } // 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 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "audio_core/audio_out_manager.h" | ||
| 7 | #include "audio_core/out/audio_out_system.h" | ||
| 8 | #include "core/hle/service/cmif_types.h" | ||
| 9 | #include "core/hle/service/kernel_helpers.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | class KReadableEvent; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Service::Audio { | ||
| 17 | |||
| 18 | class IAudioOut : public ServiceFramework<IAudioOut> { | ||
| 19 | public: | ||
| 20 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, | ||
| 21 | size_t session_id, const std::string& device_name, | ||
| 22 | const AudioCore::AudioOut::AudioOutParameter& in_params, | ||
| 23 | Kernel::KProcess* handle, u64 applet_resource_user_id); | ||
| 24 | ~IAudioOut() override; | ||
| 25 | |||
| 26 | std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() { | ||
| 27 | return impl; | ||
| 28 | } | ||
| 29 | |||
| 30 | Result GetAudioOutState(Out<u32> out_state); | ||
| 31 | Result Start(); | ||
| 32 | Result Stop(); | ||
| 33 | Result AppendAudioOutBuffer( | ||
| 34 | InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, | ||
| 35 | u64 buffer_client_ptr); | ||
| 36 | Result AppendAudioOutBufferAuto( | ||
| 37 | InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, | ||
| 38 | u64 buffer_client_ptr); | ||
| 39 | Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); | ||
| 40 | Result GetReleasedAudioOutBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, | ||
| 41 | Out<u32> out_count); | ||
| 42 | Result GetReleasedAudioOutBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, | ||
| 43 | Out<u32> out_count); | ||
| 44 | Result ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr); | ||
| 45 | Result GetAudioOutBufferCount(Out<u32> out_buffer_count); | ||
| 46 | Result GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count); | ||
| 47 | Result FlushAudioOutBuffers(Out<bool> out_flushed); | ||
| 48 | Result SetAudioOutVolume(f32 volume); | ||
| 49 | Result GetAudioOutVolume(Out<f32> out_volume); | ||
| 50 | |||
| 51 | private: | ||
| 52 | KernelHelpers::ServiceContext service_context; | ||
| 53 | Kernel::KEvent* event; | ||
| 54 | Kernel::KProcess* process; | ||
| 55 | std::shared_ptr<AudioCore::AudioOut::Out> impl; | ||
| 56 | }; | ||
| 57 | |||
| 58 | } // namespace Service::Audio | ||
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 8cc7b69f4..5364177ba 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -1,220 +1,15 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <array> | ||
| 5 | #include <cstring> | ||
| 6 | #include <vector> | ||
| 7 | |||
| 8 | #include "audio_core/out/audio_out_system.h" | ||
| 9 | #include "audio_core/renderer/audio_device.h" | ||
| 10 | #include "common/common_funcs.h" | ||
| 11 | #include "common/logging/log.h" | ||
| 12 | #include "common/scratch_buffer.h" | ||
| 13 | #include "common/string_util.h" | 4 | #include "common/string_util.h" |
| 14 | #include "common/swap.h" | 5 | #include "core/hle/service/audio/audio_out.h" |
| 15 | #include "core/core.h" | ||
| 16 | #include "core/hle/kernel/k_event.h" | ||
| 17 | #include "core/hle/service/audio/audout_u.h" | 6 | #include "core/hle/service/audio/audout_u.h" |
| 18 | #include "core/hle/service/audio/errors.h" | ||
| 19 | #include "core/hle/service/ipc_helpers.h" | 7 | #include "core/hle/service/ipc_helpers.h" |
| 20 | #include "core/memory.h" | 8 | #include "core/memory.h" |
| 21 | 9 | ||
| 22 | namespace Service::Audio { | 10 | namespace Service::Audio { |
| 23 | using namespace AudioCore::AudioOut; | 11 | using namespace AudioCore::AudioOut; |
| 24 | 12 | ||
| 25 | class IAudioOut final : public ServiceFramework<IAudioOut> { | ||
| 26 | public: | ||
| 27 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, | ||
| 28 | size_t session_id, const std::string& device_name, | ||
| 29 | const AudioOutParameter& in_params, Kernel::KProcess* handle, | ||
| 30 | u64 applet_resource_user_id) | ||
| 31 | : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, | ||
| 32 | event{service_context.CreateEvent("AudioOutEvent")}, process{handle}, | ||
| 33 | impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { | ||
| 34 | |||
| 35 | // clang-format off | ||
| 36 | static const FunctionInfo functions[] = { | ||
| 37 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | ||
| 38 | {1, &IAudioOut::Start, "Start"}, | ||
| 39 | {2, &IAudioOut::Stop, "Stop"}, | ||
| 40 | {3, &IAudioOut::AppendAudioOutBuffer, "AppendAudioOutBuffer"}, | ||
| 41 | {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"}, | ||
| 42 | {5, &IAudioOut::GetReleasedAudioOutBuffers, "GetReleasedAudioOutBuffers"}, | ||
| 43 | {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"}, | ||
| 44 | {7, &IAudioOut::AppendAudioOutBuffer, "AppendAudioOutBufferAuto"}, | ||
| 45 | {8, &IAudioOut::GetReleasedAudioOutBuffers, "GetReleasedAudioOutBuffersAuto"}, | ||
| 46 | {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"}, | ||
| 47 | {10, &IAudioOut::GetAudioOutPlayedSampleCount, "GetAudioOutPlayedSampleCount"}, | ||
| 48 | {11, &IAudioOut::FlushAudioOutBuffers, "FlushAudioOutBuffers"}, | ||
| 49 | {12, &IAudioOut::SetAudioOutVolume, "SetAudioOutVolume"}, | ||
| 50 | {13, &IAudioOut::GetAudioOutVolume, "GetAudioOutVolume"}, | ||
| 51 | }; | ||
| 52 | // clang-format on | ||
| 53 | RegisterHandlers(functions); | ||
| 54 | |||
| 55 | process->Open(); | ||
| 56 | } | ||
| 57 | |||
| 58 | ~IAudioOut() override { | ||
| 59 | impl->Free(); | ||
| 60 | service_context.CloseEvent(event); | ||
| 61 | process->Close(); | ||
| 62 | } | ||
| 63 | |||
| 64 | [[nodiscard]] std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() { | ||
| 65 | return impl; | ||
| 66 | } | ||
| 67 | |||
| 68 | private: | ||
| 69 | void GetAudioOutState(HLERequestContext& ctx) { | ||
| 70 | const auto state = static_cast<u32>(impl->GetState()); | ||
| 71 | |||
| 72 | LOG_DEBUG(Service_Audio, "called. State={}", state); | ||
| 73 | |||
| 74 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 75 | rb.Push(ResultSuccess); | ||
| 76 | rb.Push(state); | ||
| 77 | } | ||
| 78 | |||
| 79 | void Start(HLERequestContext& ctx) { | ||
| 80 | LOG_DEBUG(Service_Audio, "called"); | ||
| 81 | |||
| 82 | auto result = impl->StartSystem(); | ||
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 85 | rb.Push(result); | ||
| 86 | } | ||
| 87 | |||
| 88 | void Stop(HLERequestContext& ctx) { | ||
| 89 | LOG_DEBUG(Service_Audio, "called"); | ||
| 90 | |||
| 91 | auto result = impl->StopSystem(); | ||
| 92 | |||
| 93 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 94 | rb.Push(result); | ||
| 95 | } | ||
| 96 | |||
| 97 | void AppendAudioOutBuffer(HLERequestContext& ctx) { | ||
| 98 | IPC::RequestParser rp{ctx}; | ||
| 99 | u64 tag = rp.PopRaw<u64>(); | ||
| 100 | |||
| 101 | const auto in_buffer_size{ctx.GetReadBufferSize()}; | ||
| 102 | if (in_buffer_size < sizeof(AudioOutBuffer)) { | ||
| 103 | LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!"); | ||
| 104 | } | ||
| 105 | |||
| 106 | const auto& in_buffer = ctx.ReadBuffer(); | ||
| 107 | AudioOutBuffer buffer{}; | ||
| 108 | std::memcpy(&buffer, in_buffer.data(), sizeof(AudioOutBuffer)); | ||
| 109 | |||
| 110 | LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", | ||
| 111 | impl->GetSystem().GetSessionId(), tag); | ||
| 112 | |||
| 113 | auto result = impl->AppendBuffer(buffer, tag); | ||
| 114 | |||
| 115 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 116 | rb.Push(result); | ||
| 117 | } | ||
| 118 | |||
| 119 | void RegisterBufferEvent(HLERequestContext& ctx) { | ||
| 120 | LOG_DEBUG(Service_Audio, "called"); | ||
| 121 | |||
| 122 | auto& buffer_event = impl->GetBufferEvent(); | ||
| 123 | |||
| 124 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 125 | rb.Push(ResultSuccess); | ||
| 126 | rb.PushCopyObjects(buffer_event); | ||
| 127 | } | ||
| 128 | |||
| 129 | void GetReleasedAudioOutBuffers(HLERequestContext& ctx) { | ||
| 130 | const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>(); | ||
| 131 | released_buffer.resize_destructive(write_buffer_size); | ||
| 132 | released_buffer[0] = 0; | ||
| 133 | |||
| 134 | const auto count = impl->GetReleasedBuffers(released_buffer); | ||
| 135 | |||
| 136 | ctx.WriteBuffer(released_buffer); | ||
| 137 | |||
| 138 | LOG_TRACE(Service_Audio, "called. Session {} released {} buffers", | ||
| 139 | impl->GetSystem().GetSessionId(), count); | ||
| 140 | |||
| 141 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 142 | rb.Push(ResultSuccess); | ||
| 143 | rb.Push(count); | ||
| 144 | } | ||
| 145 | |||
| 146 | void ContainsAudioOutBuffer(HLERequestContext& ctx) { | ||
| 147 | IPC::RequestParser rp{ctx}; | ||
| 148 | |||
| 149 | const u64 tag{rp.Pop<u64>()}; | ||
| 150 | const auto buffer_queued{impl->ContainsAudioBuffer(tag)}; | ||
| 151 | |||
| 152 | LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", tag, buffer_queued); | ||
| 153 | |||
| 154 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 155 | rb.Push(ResultSuccess); | ||
| 156 | rb.Push(buffer_queued); | ||
| 157 | } | ||
| 158 | |||
| 159 | void GetAudioOutBufferCount(HLERequestContext& ctx) { | ||
| 160 | const auto buffer_count = impl->GetBufferCount(); | ||
| 161 | |||
| 162 | LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count); | ||
| 163 | |||
| 164 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 165 | rb.Push(ResultSuccess); | ||
| 166 | rb.Push(buffer_count); | ||
| 167 | } | ||
| 168 | |||
| 169 | void GetAudioOutPlayedSampleCount(HLERequestContext& ctx) { | ||
| 170 | const auto samples_played = impl->GetPlayedSampleCount(); | ||
| 171 | |||
| 172 | LOG_DEBUG(Service_Audio, "called. Played samples={}", samples_played); | ||
| 173 | |||
| 174 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 175 | rb.Push(ResultSuccess); | ||
| 176 | rb.Push(samples_played); | ||
| 177 | } | ||
| 178 | |||
| 179 | void FlushAudioOutBuffers(HLERequestContext& ctx) { | ||
| 180 | bool flushed{impl->FlushAudioOutBuffers()}; | ||
| 181 | |||
| 182 | LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", flushed); | ||
| 183 | |||
| 184 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 185 | rb.Push(ResultSuccess); | ||
| 186 | rb.Push(flushed); | ||
| 187 | } | ||
| 188 | |||
| 189 | void SetAudioOutVolume(HLERequestContext& ctx) { | ||
| 190 | IPC::RequestParser rp{ctx}; | ||
| 191 | const auto volume = rp.Pop<f32>(); | ||
| 192 | |||
| 193 | LOG_DEBUG(Service_Audio, "called. Volume={}", volume); | ||
| 194 | |||
| 195 | impl->SetVolume(volume); | ||
| 196 | |||
| 197 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 198 | rb.Push(ResultSuccess); | ||
| 199 | } | ||
| 200 | |||
| 201 | void GetAudioOutVolume(HLERequestContext& ctx) { | ||
| 202 | const auto volume = impl->GetVolume(); | ||
| 203 | |||
| 204 | LOG_DEBUG(Service_Audio, "called. Volume={}", volume); | ||
| 205 | |||
| 206 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 207 | rb.Push(ResultSuccess); | ||
| 208 | rb.Push(volume); | ||
| 209 | } | ||
| 210 | |||
| 211 | KernelHelpers::ServiceContext service_context; | ||
| 212 | Kernel::KEvent* event; | ||
| 213 | Kernel::KProcess* process; | ||
| 214 | std::shared_ptr<AudioCore::AudioOut::Out> impl; | ||
| 215 | Common::ScratchBuffer<u64> released_buffer; | ||
| 216 | }; | ||
| 217 | |||
| 218 | AudOutU::AudOutU(Core::System& system_) | 13 | AudOutU::AudOutU(Core::System& system_) |
| 219 | : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"}, | 14 | : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"}, |
| 220 | impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} { | 15 | impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} { |