summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar liamwhite2024-02-23 11:34:21 -0500
committerGravatar GitHub2024-02-23 11:34:21 -0500
commit215e887be088ed572da999e9ec7fd8559198524b (patch)
tree793415b72d36bb07d0174dfcf731f81235008936
parentMerge pull request #13073 from FearlessTobi/fsp-srv-ipc (diff)
parentoboe_sink: handle temporary stream creation failure (diff)
downloadyuzu-215e887be088ed572da999e9ec7fd8559198524b.tar.gz
yuzu-215e887be088ed572da999e9ec7fd8559198524b.tar.xz
yuzu-215e887be088ed572da999e9ec7fd8559198524b.zip
Merge pull request #13100 from liamwhite/audio-ipc
audio: move to new ipc
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/audio_core/audio_in_manager.cpp7
-rw-r--r--src/audio_core/audio_in_manager.h4
-rw-r--r--src/audio_core/device/audio_buffers.h6
-rw-r--r--src/audio_core/opus/decoder.cpp6
-rw-r--r--src/audio_core/opus/decoder.h6
-rw-r--r--src/audio_core/opus/decoder_manager.cpp18
-rw-r--r--src/audio_core/opus/decoder_manager.h16
-rw-r--r--src/audio_core/opus/hardware_opus.cpp13
-rw-r--r--src/audio_core/opus/hardware_opus.h6
-rw-r--r--src/audio_core/opus/parameters.h4
-rw-r--r--src/audio_core/renderer/audio_device.cpp14
-rw-r--r--src/audio_core/renderer/audio_device.h6
-rw-r--r--src/audio_core/renderer/audio_renderer.cpp7
-rw-r--r--src/audio_core/renderer/audio_renderer.h4
-rw-r--r--src/audio_core/renderer/behavior/info_updater.cpp2
-rw-r--r--src/audio_core/renderer/behavior/info_updater.h10
-rw-r--r--src/audio_core/renderer/memory/pool_mapper.cpp18
-rw-r--r--src/audio_core/renderer/memory/pool_mapper.h14
-rw-r--r--src/audio_core/renderer/system.cpp10
-rw-r--r--src/audio_core/renderer/system.h8
-rw-r--r--src/audio_core/sink/oboe_sink.cpp8
-rw-r--r--src/common/string_util.cpp4
-rw-r--r--src/common/string_util.h1
-rw-r--r--src/core/CMakeLists.txt38
-rw-r--r--src/core/hle/service/audio/audin_u.cpp393
-rw-r--r--src/core/hle/service/audio/audin_u.h38
-rw-r--r--src/core/hle/service/audio/audio.cpp28
-rw-r--r--src/core/hle/service/audio/audio_controller.cpp31
-rw-r--r--src/core/hle/service/audio/audio_controller.h1
-rw-r--r--src/core/hle/service/audio/audio_device.cpp163
-rw-r--r--src/core/hle/service/audio/audio_device.h58
-rw-r--r--src/core/hle/service/audio/audio_in.cpp146
-rw-r--r--src/core/hle/service/audio/audio_in.h53
-rw-r--r--src/core/hle/service/audio/audio_in_manager.cpp125
-rw-r--r--src/core/hle/service/audio/audio_in_manager.h57
-rw-r--r--src/core/hle/service/audio/audio_out.cpp146
-rw-r--r--src/core/hle/service/audio/audio_out.h58
-rw-r--r--src/core/hle/service/audio/audio_out_manager.cpp101
-rw-r--r--src/core/hle/service/audio/audio_out_manager.h44
-rw-r--r--src/core/hle/service/audio/audio_renderer.cpp139
-rw-r--r--src/core/hle/service/audio/audio_renderer.h54
-rw-r--r--src/core/hle/service/audio/audio_renderer_manager.cpp104
-rw-r--r--src/core/hle/service/audio/audio_renderer_manager.h37
-rw-r--r--src/core/hle/service/audio/audout_u.cpp323
-rw-r--r--src/core/hle/service/audio/audout_u.h37
-rw-r--r--src/core/hle/service/audio/audren_u.cpp552
-rw-r--r--src/core/hle/service/audio/audren_u.h35
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager.cpp (renamed from src/core/hle/service/audio/audrec_u.cpp)7
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager.h (renamed from src/core/hle/service/audio/audrec_a.h)6
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp (renamed from src/core/hle/service/audio/audrec_a.cpp)7
-rw-r--r--src/core/hle/service/audio/final_output_recorder_manager_for_applet.h (renamed from src/core/hle/service/audio/audrec_u.h)7
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder.cpp145
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder.h63
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder_manager.cpp156
-rw-r--r--src/core/hle/service/audio/hardware_opus_decoder_manager.h53
-rw-r--r--src/core/hle/service/audio/hwopus.cpp502
-rw-r--r--src/core/hle/service/audio/hwopus.h36
-rw-r--r--src/core/hle/service/cmif_serialization.h2
59 files changed, 1882 insertions, 2056 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index edca221b1..cf05a3fe3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -121,6 +121,7 @@ else()
121 -Wno-attributes 121 -Wno-attributes
122 -Wno-invalid-offsetof 122 -Wno-invalid-offsetof
123 -Wno-unused-parameter 123 -Wno-unused-parameter
124 -Wno-missing-field-initializers
124 ) 125 )
125 126
126 if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang 127 if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang
diff --git a/src/audio_core/audio_in_manager.cpp b/src/audio_core/audio_in_manager.cpp
index a3667524f..63b064922 100644
--- a/src/audio_core/audio_in_manager.cpp
+++ b/src/audio_core/audio_in_manager.cpp
@@ -73,16 +73,15 @@ void Manager::BufferReleaseAndRegister() {
73 } 73 }
74} 74}
75 75
76u32 Manager::GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, 76u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names,
77 [[maybe_unused]] const u32 max_count,
78 [[maybe_unused]] const bool filter) { 77 [[maybe_unused]] const bool filter) {
79 std::scoped_lock l{mutex}; 78 std::scoped_lock l{mutex};
80 79
81 LinkToManager(); 80 LinkToManager();
82 81
83 auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)}; 82 auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
84 if (input_devices.size() > 1) { 83 if (!input_devices.empty() && !names.empty()) {
85 names.emplace_back("Uac"); 84 names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
86 return 1; 85 return 1;
87 } 86 }
88 return 0; 87 return 0;
diff --git a/src/audio_core/audio_in_manager.h b/src/audio_core/audio_in_manager.h
index 5c4614cd1..2179990e0 100644
--- a/src/audio_core/audio_in_manager.h
+++ b/src/audio_core/audio_in_manager.h
@@ -60,13 +60,11 @@ public:
60 * Get a list of audio in device names. 60 * Get a list of audio in device names.
61 * 61 *
62 * @param names - Output container to write names to. 62 * @param names - Output container to write names to.
63 * @param max_count - Maximum number of device names to write. Unused
64 * @param filter - Should the list be filtered? Unused. 63 * @param filter - Should the list be filtered? Unused.
65 * 64 *
66 * @return Number of names written. 65 * @return Number of names written.
67 */ 66 */
68 u32 GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 max_count, 67 u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
69 bool filter);
70 68
71 /// Core system 69 /// Core system
72 Core::System& system; 70 Core::System& system;
diff --git a/src/audio_core/device/audio_buffers.h b/src/audio_core/device/audio_buffers.h
index 5d8ed0ef7..9e84a9c05 100644
--- a/src/audio_core/device/audio_buffers.h
+++ b/src/audio_core/device/audio_buffers.h
@@ -146,7 +146,11 @@ public:
146 break; 146 break;
147 } 147 }
148 148
149 tags[released++] = tag; 149 if (released < tags.size()) {
150 tags[released] = tag;
151 }
152
153 released++;
150 154
151 if (released >= tags.size()) { 155 if (released >= tags.size()) {
152 break; 156 break;
diff --git a/src/audio_core/opus/decoder.cpp b/src/audio_core/opus/decoder.cpp
index b7fed5304..0c110cbeb 100644
--- a/src/audio_core/opus/decoder.cpp
+++ b/src/audio_core/opus/decoder.cpp
@@ -28,8 +28,8 @@ OpusDecoder::~OpusDecoder() {
28 } 28 }
29} 29}
30 30
31Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, 31Result OpusDecoder::Initialize(const OpusParametersEx& params,
32 u64 transfer_memory_size) { 32 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
33 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 33 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
34 shared_buffer_size = transfer_memory_size; 34 shared_buffer_size = transfer_memory_size;
35 shared_buffer = std::make_unique<u8[]>(shared_buffer_size); 35 shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
@@ -59,7 +59,7 @@ Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory
59 R_SUCCEED(); 59 R_SUCCEED();
60} 60}
61 61
62Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, 62Result OpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
63 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) { 63 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
64 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 64 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
65 shared_buffer_size = transfer_memory_size; 65 shared_buffer_size = transfer_memory_size;
diff --git a/src/audio_core/opus/decoder.h b/src/audio_core/opus/decoder.h
index fd728958a..1b8c257d4 100644
--- a/src/audio_core/opus/decoder.h
+++ b/src/audio_core/opus/decoder.h
@@ -22,10 +22,10 @@ public:
22 explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_); 22 explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_);
23 ~OpusDecoder(); 23 ~OpusDecoder();
24 24
25 Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, 25 Result Initialize(const OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
26 u64 transfer_memory_size);
27 Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
28 u64 transfer_memory_size); 26 u64 transfer_memory_size);
27 Result Initialize(const OpusMultiStreamParametersEx& params,
28 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
29 Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count, 29 Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count,
30 std::span<const u8> input_data, std::span<u8> output_data, bool reset); 30 std::span<const u8> input_data, std::span<u8> output_data, bool reset);
31 Result SetContext([[maybe_unused]] std::span<const u8> context); 31 Result SetContext([[maybe_unused]] std::span<const u8> context);
diff --git a/src/audio_core/opus/decoder_manager.cpp b/src/audio_core/opus/decoder_manager.cpp
index 1464880a1..89eec1298 100644
--- a/src/audio_core/opus/decoder_manager.cpp
+++ b/src/audio_core/opus/decoder_manager.cpp
@@ -38,7 +38,7 @@ OpusDecoderManager::OpusDecoderManager(Core::System& system_)
38 } 38 }
39} 39}
40 40
41Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) { 41Result OpusDecoderManager::GetWorkBufferSize(const OpusParameters& params, u32& out_size) {
42 OpusParametersEx ex{ 42 OpusParametersEx ex{
43 .sample_rate = params.sample_rate, 43 .sample_rate = params.sample_rate,
44 .channel_count = params.channel_count, 44 .channel_count = params.channel_count,
@@ -47,11 +47,11 @@ Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_si
47 R_RETURN(GetWorkBufferSizeExEx(ex, out_size)); 47 R_RETURN(GetWorkBufferSizeExEx(ex, out_size));
48} 48}
49 49
50Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) { 50Result OpusDecoderManager::GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size) {
51 R_RETURN(GetWorkBufferSizeExEx(params, out_size)); 51 R_RETURN(GetWorkBufferSizeExEx(params, out_size));
52} 52}
53 53
54Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) { 54Result OpusDecoderManager::GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size) {
55 R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount); 55 R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
56 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); 56 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
57 57
@@ -63,8 +63,8 @@ Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64&
63 R_SUCCEED(); 63 R_SUCCEED();
64} 64}
65 65
66Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, 66Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params,
67 u64& out_size) { 67 u32& out_size) {
68 OpusMultiStreamParametersEx ex{ 68 OpusMultiStreamParametersEx ex{
69 .sample_rate = params.sample_rate, 69 .sample_rate = params.sample_rate,
70 .channel_count = params.channel_count, 70 .channel_count = params.channel_count,
@@ -76,13 +76,13 @@ Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParame
76 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size)); 76 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size));
77} 77}
78 78
79Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, 79Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
80 u64& out_size) { 80 const OpusMultiStreamParametersEx& params, u32& out_size) {
81 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size)); 81 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size));
82} 82}
83 83
84Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, 84Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
85 u64& out_size) { 85 const OpusMultiStreamParametersEx& params, u32& out_size) {
86 R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount); 86 R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
87 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); 87 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
88 R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count, 88 R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count,
diff --git a/src/audio_core/opus/decoder_manager.h b/src/audio_core/opus/decoder_manager.h
index 70ebc4bab..8f6876d5c 100644
--- a/src/audio_core/opus/decoder_manager.h
+++ b/src/audio_core/opus/decoder_manager.h
@@ -22,17 +22,19 @@ public:
22 return hardware_opus; 22 return hardware_opus;
23 } 23 }
24 24
25 Result GetWorkBufferSize(OpusParameters& params, u64& out_size); 25 Result GetWorkBufferSize(const OpusParameters& params, u32& out_size);
26 Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size); 26 Result GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size);
27 Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size); 27 Result GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size);
28 Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size); 28 Result GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params, u32& out_size);
29 Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size); 29 Result GetWorkBufferSizeForMultiStreamEx(const OpusMultiStreamParametersEx& params,
30 Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size); 30 u32& out_size);
31 Result GetWorkBufferSizeForMultiStreamExEx(const OpusMultiStreamParametersEx& params,
32 u32& out_size);
31 33
32private: 34private:
33 Core::System& system; 35 Core::System& system;
34 HardwareOpus hardware_opus; 36 HardwareOpus hardware_opus;
35 std::array<u64, MaxChannels> required_workbuffer_sizes{}; 37 std::array<u32, MaxChannels> required_workbuffer_sizes{};
36}; 38};
37 39
38} // namespace AudioCore::OpusDecoder 40} // namespace AudioCore::OpusDecoder
diff --git a/src/audio_core/opus/hardware_opus.cpp b/src/audio_core/opus/hardware_opus.cpp
index 5ff71ab2d..30805f4a3 100644
--- a/src/audio_core/opus/hardware_opus.cpp
+++ b/src/audio_core/opus/hardware_opus.cpp
@@ -42,7 +42,7 @@ HardwareOpus::HardwareOpus(Core::System& system_)
42 opus_decoder.SetSharedMemory(shared_memory); 42 opus_decoder.SetSharedMemory(shared_memory);
43} 43}
44 44
45u64 HardwareOpus::GetWorkBufferSize(u32 channel) { 45u32 HardwareOpus::GetWorkBufferSize(u32 channel) {
46 if (!opus_decoder.IsRunning()) { 46 if (!opus_decoder.IsRunning()) {
47 return 0; 47 return 0;
48 } 48 }
@@ -55,10 +55,10 @@ u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
55 ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg); 55 ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg);
56 return 0; 56 return 0;
57 } 57 }
58 return shared_memory.dsp_return_data[0]; 58 return static_cast<u32>(shared_memory.dsp_return_data[0]);
59} 59}
60 60
61u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) { 61u32 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
62 std::scoped_lock l{mutex}; 62 std::scoped_lock l{mutex};
63 shared_memory.host_send_data[0] = total_stream_count; 63 shared_memory.host_send_data[0] = total_stream_count;
64 shared_memory.host_send_data[1] = stereo_stream_count; 64 shared_memory.host_send_data[1] = stereo_stream_count;
@@ -70,7 +70,7 @@ u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 st
70 ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg); 70 ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg);
71 return 0; 71 return 0;
72 } 72 }
73 return shared_memory.dsp_return_data[0]; 73 return static_cast<u32>(shared_memory.dsp_return_data[0]);
74} 74}
75 75
76Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, 76Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
@@ -94,8 +94,9 @@ Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count,
94 94
95Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, 95Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
96 u32 total_stream_count, 96 u32 total_stream_count,
97 u32 stereo_stream_count, void* mappings, 97 u32 stereo_stream_count,
98 void* buffer, u64 buffer_size) { 98 const void* mappings, void* buffer,
99 u64 buffer_size) {
99 std::scoped_lock l{mutex}; 100 std::scoped_lock l{mutex};
100 shared_memory.host_send_data[0] = (u64)buffer; 101 shared_memory.host_send_data[0] = (u64)buffer;
101 shared_memory.host_send_data[1] = buffer_size; 102 shared_memory.host_send_data[1] = buffer_size;
diff --git a/src/audio_core/opus/hardware_opus.h b/src/audio_core/opus/hardware_opus.h
index b10184baa..caa746840 100644
--- a/src/audio_core/opus/hardware_opus.h
+++ b/src/audio_core/opus/hardware_opus.h
@@ -16,14 +16,14 @@ class HardwareOpus {
16public: 16public:
17 HardwareOpus(Core::System& system); 17 HardwareOpus(Core::System& system);
18 18
19 u64 GetWorkBufferSize(u32 channel); 19 u32 GetWorkBufferSize(u32 channel);
20 u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count); 20 u32 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
21 21
22 Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, 22 Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
23 u64 buffer_size); 23 u64 buffer_size);
24 Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, 24 Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
25 u32 totaL_stream_count, u32 stereo_stream_count, 25 u32 totaL_stream_count, u32 stereo_stream_count,
26 void* mappings, void* buffer, u64 buffer_size); 26 const void* mappings, void* buffer, u64 buffer_size);
27 Result ShutdownDecodeObject(void* buffer, u64 buffer_size); 27 Result ShutdownDecodeObject(void* buffer, u64 buffer_size);
28 Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size); 28 Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size);
29 Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size, 29 Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size,
diff --git a/src/audio_core/opus/parameters.h b/src/audio_core/opus/parameters.h
index 4c54b2825..47c418b9f 100644
--- a/src/audio_core/opus/parameters.h
+++ b/src/audio_core/opus/parameters.h
@@ -20,7 +20,7 @@ struct OpusParametersEx {
20 /* 0x00 */ u32 sample_rate; 20 /* 0x00 */ u32 sample_rate;
21 /* 0x04 */ u32 channel_count; 21 /* 0x04 */ u32 channel_count;
22 /* 0x08 */ bool use_large_frame_size; 22 /* 0x08 */ bool use_large_frame_size;
23 /* 0x09 */ INSERT_PADDING_BYTES(7); 23 /* 0x09 */ INSERT_PADDING_BYTES_NOINIT(7);
24}; // size = 0x10 24}; // size = 0x10
25static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!"); 25static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!");
26 26
@@ -40,7 +40,7 @@ struct OpusMultiStreamParametersEx {
40 /* 0x08 */ u32 total_stream_count; 40 /* 0x08 */ u32 total_stream_count;
41 /* 0x0C */ u32 stereo_stream_count; 41 /* 0x0C */ u32 stereo_stream_count;
42 /* 0x10 */ bool use_large_frame_size; 42 /* 0x10 */ bool use_large_frame_size;
43 /* 0x11 */ INSERT_PADDING_BYTES(7); 43 /* 0x11 */ INSERT_PADDING_BYTES_NOINIT(7);
44 /* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings; 44 /* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings;
45}; // size = 0x118 45}; // size = 0x118
46static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118, 46static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
diff --git a/src/audio_core/renderer/audio_device.cpp b/src/audio_core/renderer/audio_device.cpp
index 2d9bf82bb..5be5594f6 100644
--- a/src/audio_core/renderer/audio_device.cpp
+++ b/src/audio_core/renderer/audio_device.cpp
@@ -36,8 +36,7 @@ AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id
36 : output_sink{system.AudioCore().GetOutputSink()}, 36 : output_sink{system.AudioCore().GetOutputSink()},
37 applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {} 37 applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
38 38
39u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, 39u32 AudioDevice::ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const {
40 const size_t max_count) const {
41 std::span<const AudioDeviceName> names{}; 40 std::span<const AudioDeviceName> names{};
42 41
43 if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) { 42 if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
@@ -46,19 +45,18 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
46 names = device_names; 45 names = device_names;
47 } 46 }
48 47
49 const u32 out_count{static_cast<u32>(std::min(max_count, names.size()))}; 48 const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), names.size()))};
50 for (u32 i = 0; i < out_count; i++) { 49 for (u32 i = 0; i < out_count; i++) {
51 out_buffer.push_back(names[i]); 50 out_buffer[i] = names[i];
52 } 51 }
53 return out_count; 52 return out_count;
54} 53}
55 54
56u32 AudioDevice::ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, 55u32 AudioDevice::ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const {
57 const size_t max_count) const { 56 const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), output_device_names.size()))};
58 const u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
59 57
60 for (u32 i = 0; i < out_count; i++) { 58 for (u32 i = 0; i < out_count; i++) {
61 out_buffer.push_back(output_device_names[i]); 59 out_buffer[i] = output_device_names[i];
62 } 60 }
63 return out_count; 61 return out_count;
64} 62}
diff --git a/src/audio_core/renderer/audio_device.h b/src/audio_core/renderer/audio_device.h
index ca4040add..4242dad30 100644
--- a/src/audio_core/renderer/audio_device.h
+++ b/src/audio_core/renderer/audio_device.h
@@ -36,20 +36,18 @@ public:
36 * Get a list of the available output devices. 36 * Get a list of the available output devices.
37 * 37 *
38 * @param out_buffer - Output buffer to write the available device names. 38 * @param out_buffer - Output buffer to write the available device names.
39 * @param max_count - Maximum number of devices to write (count of out_buffer).
40 * @return Number of device names written. 39 * @return Number of device names written.
41 */ 40 */
42 u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const; 41 u32 ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const;
43 42
44 /** 43 /**
45 * Get a list of the available output devices. 44 * Get a list of the available output devices.
46 * Different to above somehow... 45 * Different to above somehow...
47 * 46 *
48 * @param out_buffer - Output buffer to write the available device names. 47 * @param out_buffer - Output buffer to write the available device names.
49 * @param max_count - Maximum number of devices to write (count of out_buffer).
50 * @return Number of device names written. 48 * @return Number of device names written.
51 */ 49 */
52 u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const; 50 u32 ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const;
53 51
54 /** 52 /**
55 * Set the volume of all streams in the backend sink. 53 * Set the volume of all streams in the backend sink.
diff --git a/src/audio_core/renderer/audio_renderer.cpp b/src/audio_core/renderer/audio_renderer.cpp
index df03d03aa..7c728cb86 100644
--- a/src/audio_core/renderer/audio_renderer.cpp
+++ b/src/audio_core/renderer/audio_renderer.cpp
@@ -17,9 +17,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
17 17
18Result Renderer::Initialize(const AudioRendererParameterInternal& params, 18Result Renderer::Initialize(const AudioRendererParameterInternal& params,
19 Kernel::KTransferMemory* transfer_memory, 19 Kernel::KTransferMemory* transfer_memory,
20 const u64 transfer_memory_size, const u32 process_handle, 20 const u64 transfer_memory_size, Kernel::KProcess* process_handle,
21 Kernel::KProcess& process, const u64 applet_resource_user_id, 21 const u64 applet_resource_user_id, const s32 session_id) {
22 const s32 session_id) {
23 if (params.execution_mode == ExecutionMode::Auto) { 22 if (params.execution_mode == ExecutionMode::Auto) {
24 if (!manager.AddSystem(system)) { 23 if (!manager.AddSystem(system)) {
25 LOG_ERROR(Service_Audio, 24 LOG_ERROR(Service_Audio,
@@ -30,7 +29,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
30 } 29 }
31 30
32 initialized = true; 31 initialized = true;
33 system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process, 32 system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
34 applet_resource_user_id, session_id); 33 applet_resource_user_id, session_id);
35 34
36 return ResultSuccess; 35 return ResultSuccess;
diff --git a/src/audio_core/renderer/audio_renderer.h b/src/audio_core/renderer/audio_renderer.h
index 1219f74ca..f16adeda7 100644
--- a/src/audio_core/renderer/audio_renderer.h
+++ b/src/audio_core/renderer/audio_renderer.h
@@ -38,14 +38,14 @@ public:
38 * @param params - Input parameters to initialize the system with. 38 * @param params - Input parameters to initialize the system with.
39 * @param transfer_memory - Game-supplied memory for all workbuffers. Unused. 39 * @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
40 * @param transfer_memory_size - Size of the transfer memory. Unused. 40 * @param transfer_memory_size - Size of the transfer memory. Unused.
41 * @param process_handle - Process handle, also used for memory. Unused. 41 * @param process_handle - Process handle, also used for memory.
42 * @param applet_resource_user_id - Applet id for this renderer. Unused. 42 * @param applet_resource_user_id - Applet id for this renderer. Unused.
43 * @param session_id - Session id of this renderer. 43 * @param session_id - Session id of this renderer.
44 * @return Result code. 44 * @return Result code.
45 */ 45 */
46 Result Initialize(const AudioRendererParameterInternal& params, 46 Result Initialize(const AudioRendererParameterInternal& params,
47 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 47 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
48 u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, 48 Kernel::KProcess* process_handle, u64 applet_resource_user_id,
49 s32 session_id); 49 s32 session_id);
50 50
51 /** 51 /**
diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp
index 667711e17..3dae6069f 100644
--- a/src/audio_core/renderer/behavior/info_updater.cpp
+++ b/src/audio_core/renderer/behavior/info_updater.cpp
@@ -18,7 +18,7 @@
18namespace AudioCore::Renderer { 18namespace AudioCore::Renderer {
19 19
20InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_, 20InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
21 const u32 process_handle_, BehaviorInfo& behaviour_) 21 Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
22 : input{input_.data() + sizeof(UpdateDataHeader)}, 22 : input{input_.data() + sizeof(UpdateDataHeader)},
23 input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)}, 23 input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
24 output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>( 24 output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(
diff --git a/src/audio_core/renderer/behavior/info_updater.h b/src/audio_core/renderer/behavior/info_updater.h
index fb4b7d25a..4f27a817e 100644
--- a/src/audio_core/renderer/behavior/info_updater.h
+++ b/src/audio_core/renderer/behavior/info_updater.h
@@ -8,6 +8,10 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/hle/service/audio/errors.h" 9#include "core/hle/service/audio/errors.h"
10 10
11namespace Kernel {
12class KProcess;
13}
14
11namespace AudioCore::Renderer { 15namespace AudioCore::Renderer {
12class BehaviorInfo; 16class BehaviorInfo;
13class VoiceContext; 17class VoiceContext;
@@ -39,8 +43,8 @@ class InfoUpdater {
39 static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!"); 43 static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!");
40 44
41public: 45public:
42 explicit InfoUpdater(std::span<const u8> input, std::span<u8> output, u32 process_handle, 46 explicit InfoUpdater(std::span<const u8> input, std::span<u8> output,
43 BehaviorInfo& behaviour); 47 Kernel::KProcess* process_handle, BehaviorInfo& behaviour);
44 48
45 /** 49 /**
46 * Update the voice channel resources. 50 * Update the voice channel resources.
@@ -197,7 +201,7 @@ private:
197 /// Expected output size, see CheckConsumedSize 201 /// Expected output size, see CheckConsumedSize
198 u64 expected_output_size; 202 u64 expected_output_size;
199 /// Unused 203 /// Unused
200 u32 process_handle; 204 Kernel::KProcess* process_handle;
201 /// Behaviour 205 /// Behaviour
202 BehaviorInfo& behaviour; 206 BehaviorInfo& behaviour;
203}; 207};
diff --git a/src/audio_core/renderer/memory/pool_mapper.cpp b/src/audio_core/renderer/memory/pool_mapper.cpp
index 999bb746b..e47eb66d5 100644
--- a/src/audio_core/renderer/memory/pool_mapper.cpp
+++ b/src/audio_core/renderer/memory/pool_mapper.cpp
@@ -8,11 +8,11 @@
8 8
9namespace AudioCore::Renderer { 9namespace AudioCore::Renderer {
10 10
11PoolMapper::PoolMapper(u32 process_handle_, bool force_map_) 11PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, bool force_map_)
12 : process_handle{process_handle_}, force_map{force_map_} {} 12 : process_handle{process_handle_}, force_map{force_map_} {}
13 13
14PoolMapper::PoolMapper(u32 process_handle_, std::span<MemoryPoolInfo> pool_infos_, u32 pool_count_, 14PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
15 bool force_map_) 15 u32 pool_count_, bool force_map_)
16 : process_handle{process_handle_}, pool_infos{pool_infos_.data()}, 16 : process_handle{process_handle_}, pool_infos{pool_infos_.data()},
17 pool_count{pool_count_}, force_map{force_map_} {} 17 pool_count{pool_count_}, force_map{force_map_} {}
18 18
@@ -106,15 +106,17 @@ bool PoolMapper::IsForceMapEnabled() const {
106 return force_map; 106 return force_map;
107} 107}
108 108
109u32 PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const { 109Kernel::KProcess* PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
110 switch (pool->GetLocation()) { 110 switch (pool->GetLocation()) {
111 case MemoryPoolInfo::Location::CPU: 111 case MemoryPoolInfo::Location::CPU:
112 return process_handle; 112 return process_handle;
113 case MemoryPoolInfo::Location::DSP: 113 case MemoryPoolInfo::Location::DSP:
114 return Kernel::Svc::CurrentProcess; 114 // return Kernel::Svc::CurrentProcess;
115 return nullptr;
115 } 116 }
116 LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!"); 117 LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!");
117 return Kernel::Svc::CurrentProcess; 118 // return Kernel::Svc::CurrentProcess;
119 return nullptr;
118} 120}
119 121
120bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr, 122bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
@@ -147,14 +149,14 @@ bool PoolMapper::Unmap([[maybe_unused]] const u32 handle, [[maybe_unused]] const
147} 149}
148 150
149bool PoolMapper::Unmap(MemoryPoolInfo& pool) const { 151bool PoolMapper::Unmap(MemoryPoolInfo& pool) const {
150 [[maybe_unused]] u32 handle{0}; 152 [[maybe_unused]] Kernel::KProcess* handle{};
151 153
152 switch (pool.GetLocation()) { 154 switch (pool.GetLocation()) {
153 case MemoryPoolInfo::Location::CPU: 155 case MemoryPoolInfo::Location::CPU:
154 handle = process_handle; 156 handle = process_handle;
155 break; 157 break;
156 case MemoryPoolInfo::Location::DSP: 158 case MemoryPoolInfo::Location::DSP:
157 handle = Kernel::Svc::CurrentProcess; 159 // handle = Kernel::Svc::CurrentProcess;
158 break; 160 break;
159 } 161 }
160 // nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size); 162 // nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size);
diff --git a/src/audio_core/renderer/memory/pool_mapper.h b/src/audio_core/renderer/memory/pool_mapper.h
index 95ae5d8ea..fb5122b73 100644
--- a/src/audio_core/renderer/memory/pool_mapper.h
+++ b/src/audio_core/renderer/memory/pool_mapper.h
@@ -10,6 +10,10 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/service/audio/errors.h" 11#include "core/hle/service/audio/errors.h"
12 12
13namespace Kernel {
14class KProcess;
15}
16
13namespace AudioCore::Renderer { 17namespace AudioCore::Renderer {
14class AddressInfo; 18class AddressInfo;
15 19
@@ -18,9 +22,9 @@ class AddressInfo;
18 */ 22 */
19class PoolMapper { 23class PoolMapper {
20public: 24public:
21 explicit PoolMapper(u32 process_handle, bool force_map); 25 explicit PoolMapper(Kernel::KProcess* process_handle, bool force_map);
22 explicit PoolMapper(u32 process_handle, std::span<MemoryPoolInfo> pool_infos, u32 pool_count, 26 explicit PoolMapper(Kernel::KProcess* process_handle, std::span<MemoryPoolInfo> pool_infos,
23 bool force_map); 27 u32 pool_count, bool force_map);
24 28
25 /** 29 /**
26 * Clear the usage state for all given pools. 30 * Clear the usage state for all given pools.
@@ -98,7 +102,7 @@ public:
98 * @return CurrentProcessHandle if location == DSP, 102 * @return CurrentProcessHandle if location == DSP,
99 * the PoolMapper's process_handle if location == CPU 103 * the PoolMapper's process_handle if location == CPU
100 */ 104 */
101 u32 GetProcessHandle(const MemoryPoolInfo* pool) const; 105 Kernel::KProcess* GetProcessHandle(const MemoryPoolInfo* pool) const;
102 106
103 /** 107 /**
104 * Map the given region with the given handle. This is a no-op. 108 * Map the given region with the given handle. This is a no-op.
@@ -167,7 +171,7 @@ public:
167 171
168private: 172private:
169 /// Process handle for this mapper, used when location == CPU 173 /// Process handle for this mapper, used when location == CPU
170 u32 process_handle; 174 Kernel::KProcess* process_handle{};
171 /// List of memory pools assigned to this mapper 175 /// List of memory pools assigned to this mapper
172 MemoryPoolInfo* pool_infos{}; 176 MemoryPoolInfo* pool_infos{};
173 /// The number of pools 177 /// The number of pools
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index ca656edae..c30d68426 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -102,8 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
102 102
103Result System::Initialize(const AudioRendererParameterInternal& params, 103Result System::Initialize(const AudioRendererParameterInternal& params,
104 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 104 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
105 u32 process_handle_, Kernel::KProcess& process_, 105 Kernel::KProcess* process_handle_, u64 applet_resource_user_id_,
106 u64 applet_resource_user_id_, s32 session_id_) { 106 s32 session_id_) {
107 if (!CheckValidRevision(params.revision)) { 107 if (!CheckValidRevision(params.revision)) {
108 return Service::Audio::ResultInvalidRevision; 108 return Service::Audio::ResultInvalidRevision;
109 } 109 }
@@ -119,7 +119,6 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
119 behavior.SetUserLibRevision(params.revision); 119 behavior.SetUserLibRevision(params.revision);
120 120
121 process_handle = process_handle_; 121 process_handle = process_handle_;
122 process = &process_;
123 applet_resource_user_id = applet_resource_user_id_; 122 applet_resource_user_id = applet_resource_user_id_;
124 session_id = session_id_; 123 session_id = session_id_;
125 124
@@ -132,7 +131,8 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
132 render_device = params.rendering_device; 131 render_device = params.rendering_device;
133 execution_mode = params.execution_mode; 132 execution_mode = params.execution_mode;
134 133
135 process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size); 134 process_handle->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(),
135 transfer_memory_size);
136 136
137 // Note: We're not actually using the transfer memory because it's a pain to code for. 137 // Note: We're not actually using the transfer memory because it's a pain to code for.
138 // Allocate the memory normally instead and hope the game doesn't try to read anything back 138 // Allocate the memory normally instead and hope the game doesn't try to read anything back
@@ -616,7 +616,7 @@ void System::SendCommandToDsp() {
616 static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 * 616 static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
617 (static_cast<f32>(render_time_limit_percent) / 100.0f))}; 617 (static_cast<f32>(render_time_limit_percent) / 100.0f))};
618 audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit, 618 audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
619 applet_resource_user_id, process, 619 applet_resource_user_id, process_handle,
620 reset_command_buffers); 620 reset_command_buffers);
621 reset_command_buffers = false; 621 reset_command_buffers = false;
622 command_buffer_size = command_size; 622 command_buffer_size = command_size;
diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h
index 753a0b796..3533a74ef 100644
--- a/src/audio_core/renderer/system.h
+++ b/src/audio_core/renderer/system.h
@@ -74,14 +74,14 @@ public:
74 * @param params - Input parameters to initialize the system with. 74 * @param params - Input parameters to initialize the system with.
75 * @param transfer_memory - Game-supplied memory for all workbuffers. Unused. 75 * @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
76 * @param transfer_memory_size - Size of the transfer memory. Unused. 76 * @param transfer_memory_size - Size of the transfer memory. Unused.
77 * @param process_handle - Process handle, also used for memory. Unused. 77 * @param process_handle - Process handle, also used for memory.
78 * @param applet_resource_user_id - Applet id for this renderer. Unused. 78 * @param applet_resource_user_id - Applet id for this renderer. Unused.
79 * @param session_id - Session id of this renderer. 79 * @param session_id - Session id of this renderer.
80 * @return Result code. 80 * @return Result code.
81 */ 81 */
82 Result Initialize(const AudioRendererParameterInternal& params, 82 Result Initialize(const AudioRendererParameterInternal& params,
83 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, 83 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
84 u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, 84 Kernel::KProcess* process_handle, u64 applet_resource_user_id,
85 s32 session_id); 85 s32 session_id);
86 86
87 /** 87 /**
@@ -278,9 +278,7 @@ private:
278 /// Does what locks do 278 /// Does what locks do
279 std::mutex lock{}; 279 std::mutex lock{};
280 /// Process this audio render is operating within, used for memory reads/writes. 280 /// Process this audio render is operating within, used for memory reads/writes.
281 Kernel::KProcess* process{}; 281 Kernel::KProcess* process_handle{};
282 /// Handle for the process for this system, unused
283 u32 process_handle{};
284 /// Applet resource id for this system, unused 282 /// Applet resource id for this system, unused
285 u64 applet_resource_user_id{}; 283 u64 applet_resource_user_id{};
286 /// Controls performance input and output 284 /// Controls performance input and output
diff --git a/src/audio_core/sink/oboe_sink.cpp b/src/audio_core/sink/oboe_sink.cpp
index e61841172..466a9cc8e 100644
--- a/src/audio_core/sink/oboe_sink.cpp
+++ b/src/audio_core/sink/oboe_sink.cpp
@@ -67,9 +67,13 @@ public:
67 oboe::AudioStreamBuilder builder; 67 oboe::AudioStreamBuilder builder;
68 68
69 const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream); 69 const auto result = ConfigureBuilder(builder, direction)->openStream(temp_stream);
70 ASSERT(result == oboe::Result::OK); 70 if (result == oboe::Result::OK) {
71 return temp_stream->getChannelCount() >= 6 ? 6 : 2;
72 }
71 73
72 return temp_stream->getChannelCount() >= 6 ? 6 : 2; 74 LOG_ERROR(Audio_Sink, "Failed to open {} stream. Using default channel count 2",
75 direction == oboe::Direction::Output ? "output" : "input");
76 return 2;
73 } 77 }
74 78
75protected: 79protected:
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 72c481798..1909aced5 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -38,6 +38,10 @@ std::string StringFromBuffer(std::span<const u8> data) {
38 return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); 38 return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
39} 39}
40 40
41std::string StringFromBuffer(std::span<const char> data) {
42 return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
43}
44
41// Turns " hej " into "hej". Also handles tabs. 45// Turns " hej " into "hej". Also handles tabs.
42std::string StripSpaces(const std::string& str) { 46std::string StripSpaces(const std::string& str) {
43 const std::size_t s = str.find_first_not_of(" \t\r\n"); 47 const std::size_t s = str.find_first_not_of(" \t\r\n");
diff --git a/src/common/string_util.h b/src/common/string_util.h
index 9da1ca4e9..53d0549ca 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -19,6 +19,7 @@ namespace Common {
19[[nodiscard]] std::string ToUpper(std::string str); 19[[nodiscard]] std::string ToUpper(std::string str);
20 20
21[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data); 21[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
22[[nodiscard]] std::string StringFromBuffer(std::span<const char> data);
22 23
23[[nodiscard]] std::string StripSpaces(const std::string& s); 24[[nodiscard]] std::string StripSpaces(const std::string& s);
24[[nodiscard]] std::string StripQuotes(const std::string& s); 25[[nodiscard]] std::string StripQuotes(const std::string& s);
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 65bbf4818..3400c512d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -494,23 +494,33 @@ add_library(core STATIC
494 hle/service/apm/apm_controller.h 494 hle/service/apm/apm_controller.h
495 hle/service/apm/apm_interface.cpp 495 hle/service/apm/apm_interface.cpp
496 hle/service/apm/apm_interface.h 496 hle/service/apm/apm_interface.h
497 hle/service/audio/audin_u.cpp
498 hle/service/audio/audin_u.h
499 hle/service/audio/audio.cpp
500 hle/service/audio/audio.h
501 hle/service/audio/audio_controller.cpp 497 hle/service/audio/audio_controller.cpp
502 hle/service/audio/audio_controller.h 498 hle/service/audio/audio_controller.h
503 hle/service/audio/audout_u.cpp 499 hle/service/audio/audio_device.cpp
504 hle/service/audio/audout_u.h 500 hle/service/audio/audio_device.h
505 hle/service/audio/audrec_a.cpp 501 hle/service/audio/audio_in_manager.cpp
506 hle/service/audio/audrec_a.h 502 hle/service/audio/audio_in_manager.h
507 hle/service/audio/audrec_u.cpp 503 hle/service/audio/audio_in.cpp
508 hle/service/audio/audrec_u.h 504 hle/service/audio/audio_in.h
509 hle/service/audio/audren_u.cpp 505 hle/service/audio/audio_out_manager.cpp
510 hle/service/audio/audren_u.h 506 hle/service/audio/audio_out_manager.h
507 hle/service/audio/audio_out.cpp
508 hle/service/audio/audio_out.h
509 hle/service/audio/audio_renderer_manager.cpp
510 hle/service/audio/audio_renderer_manager.h
511 hle/service/audio/audio_renderer.cpp
512 hle/service/audio/audio_renderer.h
513 hle/service/audio/audio.cpp
514 hle/service/audio/audio.h
511 hle/service/audio/errors.h 515 hle/service/audio/errors.h
512 hle/service/audio/hwopus.cpp 516 hle/service/audio/final_output_recorder_manager_for_applet.cpp
513 hle/service/audio/hwopus.h 517 hle/service/audio/final_output_recorder_manager_for_applet.h
518 hle/service/audio/final_output_recorder_manager.cpp
519 hle/service/audio/final_output_recorder_manager.h
520 hle/service/audio/hardware_opus_decoder_manager.cpp
521 hle/service/audio/hardware_opus_decoder_manager.h
522 hle/service/audio/hardware_opus_decoder.cpp
523 hle/service/audio/hardware_opus_decoder.h
514 hle/service/bcat/backend/backend.cpp 524 hle/service/bcat/backend/backend.cpp
515 hle/service/bcat/backend/backend.h 525 hle/service/bcat/backend/backend.h
516 hle/service/bcat/bcat.cpp 526 hle/service/bcat/bcat.cpp
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
deleted file mode 100644
index de2aa6906..000000000
--- a/src/core/hle/service/audio/audin_u.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/in/audio_in_system.h"
5#include "audio_core/renderer/audio_device.h"
6#include "common/common_funcs.h"
7#include "common/logging/log.h"
8#include "common/scratch_buffer.h"
9#include "common/string_util.h"
10#include "core/core.h"
11#include "core/hle/kernel/k_event.h"
12#include "core/hle/service/audio/audin_u.h"
13#include "core/hle/service/ipc_helpers.h"
14
15namespace Service::Audio {
16using namespace AudioCore::AudioIn;
17
18class IAudioIn final : public ServiceFramework<IAudioIn> {
19public:
20 explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
21 const std::string& device_name, const AudioInParameter& in_params,
22 Kernel::KProcess* handle, u64 applet_resource_user_id)
23 : ServiceFramework{system_, "IAudioIn"},
24 service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")},
25 process{handle}, impl{std::make_shared<In>(system_, manager, event, session_id)} {
26 // clang-format off
27 static const FunctionInfo functions[] = {
28 {0, &IAudioIn::GetAudioInState, "GetAudioInState"},
29 {1, &IAudioIn::Start, "Start"},
30 {2, &IAudioIn::Stop, "Stop"},
31 {3, &IAudioIn::AppendAudioInBuffer, "AppendAudioInBuffer"},
32 {4, &IAudioIn::RegisterBufferEvent, "RegisterBufferEvent"},
33 {5, &IAudioIn::GetReleasedAudioInBuffer, "GetReleasedAudioInBuffer"},
34 {6, &IAudioIn::ContainsAudioInBuffer, "ContainsAudioInBuffer"},
35 {7, &IAudioIn::AppendAudioInBuffer, "AppendUacInBuffer"},
36 {8, &IAudioIn::AppendAudioInBuffer, "AppendAudioInBufferAuto"},
37 {9, &IAudioIn::GetReleasedAudioInBuffer, "GetReleasedAudioInBuffersAuto"},
38 {10, &IAudioIn::AppendAudioInBuffer, "AppendUacInBufferAuto"},
39 {11, &IAudioIn::GetAudioInBufferCount, "GetAudioInBufferCount"},
40 {12, &IAudioIn::SetDeviceGain, "SetDeviceGain"},
41 {13, &IAudioIn::GetDeviceGain, "GetDeviceGain"},
42 {14, &IAudioIn::FlushAudioInBuffers, "FlushAudioInBuffers"},
43 };
44 // clang-format on
45
46 RegisterHandlers(functions);
47
48 process->Open();
49
50 if (impl->GetSystem()
51 .Initialize(device_name, in_params, handle, applet_resource_user_id)
52 .IsError()) {
53 LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
54 }
55 }
56
57 ~IAudioIn() override {
58 impl->Free();
59 service_context.CloseEvent(event);
60 process->Close();
61 }
62
63 [[nodiscard]] std::shared_ptr<In> GetImpl() {
64 return impl;
65 }
66
67private:
68 void GetAudioInState(HLERequestContext& ctx) {
69 const auto state = static_cast<u32>(impl->GetState());
70
71 LOG_DEBUG(Service_Audio, "called. State={}", state);
72
73 IPC::ResponseBuilder rb{ctx, 3};
74 rb.Push(ResultSuccess);
75 rb.Push(state);
76 }
77
78 void Start(HLERequestContext& ctx) {
79 LOG_DEBUG(Service_Audio, "called");
80
81 auto result = impl->StartSystem();
82
83 IPC::ResponseBuilder rb{ctx, 2};
84 rb.Push(result);
85 }
86
87 void Stop(HLERequestContext& ctx) {
88 LOG_DEBUG(Service_Audio, "called");
89
90 auto result = impl->StopSystem();
91
92 IPC::ResponseBuilder rb{ctx, 2};
93 rb.Push(result);
94 }
95
96 void AppendAudioInBuffer(HLERequestContext& ctx) {
97 IPC::RequestParser rp{ctx};
98 u64 tag = rp.PopRaw<u64>();
99
100 const auto in_buffer_size{ctx.GetReadBufferSize()};
101 if (in_buffer_size < sizeof(AudioInBuffer)) {
102 LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
103 }
104
105 const auto& in_buffer = ctx.ReadBuffer();
106 AudioInBuffer buffer{};
107 std::memcpy(&buffer, in_buffer.data(), sizeof(AudioInBuffer));
108
109 [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()};
110 LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", sessionid, tag);
111
112 auto result = impl->AppendBuffer(buffer, tag);
113
114 IPC::ResponseBuilder rb{ctx, 2};
115 rb.Push(result);
116 }
117
118 void RegisterBufferEvent(HLERequestContext& ctx) {
119 LOG_DEBUG(Service_Audio, "called");
120
121 auto& buffer_event = impl->GetBufferEvent();
122
123 IPC::ResponseBuilder rb{ctx, 2, 1};
124 rb.Push(ResultSuccess);
125 rb.PushCopyObjects(buffer_event);
126 }
127
128 void GetReleasedAudioInBuffer(HLERequestContext& ctx) {
129 const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>();
130 released_buffer.resize_destructive(write_buffer_size);
131 released_buffer[0] = 0;
132
133 const auto count = impl->GetReleasedBuffers(released_buffer);
134
135 LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
136 impl->GetSystem().GetSessionId(), count);
137
138 ctx.WriteBuffer(released_buffer);
139
140 IPC::ResponseBuilder rb{ctx, 3};
141 rb.Push(ResultSuccess);
142 rb.Push(count);
143 }
144
145 void ContainsAudioInBuffer(HLERequestContext& ctx) {
146 IPC::RequestParser rp{ctx};
147
148 const u64 tag{rp.Pop<u64>()};
149 const auto buffer_queued{impl->ContainsAudioBuffer(tag)};
150
151 LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", tag, buffer_queued);
152
153 IPC::ResponseBuilder rb{ctx, 3};
154 rb.Push(ResultSuccess);
155 rb.Push(buffer_queued);
156 }
157
158 void GetAudioInBufferCount(HLERequestContext& ctx) {
159 const auto buffer_count = impl->GetBufferCount();
160
161 LOG_DEBUG(Service_Audio, "called. Buffer count={}", buffer_count);
162
163 IPC::ResponseBuilder rb{ctx, 3};
164 rb.Push(ResultSuccess);
165 rb.Push(buffer_count);
166 }
167
168 void SetDeviceGain(HLERequestContext& ctx) {
169 IPC::RequestParser rp{ctx};
170
171 const auto volume{rp.Pop<f32>()};
172 LOG_DEBUG(Service_Audio, "called. Gain {}", volume);
173
174 impl->SetVolume(volume);
175
176 IPC::ResponseBuilder rb{ctx, 2};
177 rb.Push(ResultSuccess);
178 }
179
180 void GetDeviceGain(HLERequestContext& ctx) {
181 auto volume{impl->GetVolume()};
182
183 LOG_DEBUG(Service_Audio, "called. Gain {}", volume);
184
185 IPC::ResponseBuilder rb{ctx, 3};
186 rb.Push(ResultSuccess);
187 rb.Push(volume);
188 }
189
190 void FlushAudioInBuffers(HLERequestContext& ctx) {
191 bool flushed{impl->FlushAudioInBuffers()};
192
193 LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", flushed);
194
195 IPC::ResponseBuilder rb{ctx, 3};
196 rb.Push(ResultSuccess);
197 rb.Push(flushed);
198 }
199
200 KernelHelpers::ServiceContext service_context;
201 Kernel::KEvent* event;
202 Kernel::KProcess* process;
203 std::shared_ptr<AudioCore::AudioIn::In> impl;
204 Common::ScratchBuffer<u64> released_buffer;
205};
206
207AudInU::AudInU(Core::System& system_)
208 : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"},
209 impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
210 // clang-format off
211 static const FunctionInfo functions[] = {
212 {0, &AudInU::ListAudioIns, "ListAudioIns"},
213 {1, &AudInU::OpenAudioIn, "OpenAudioIn"},
214 {2, &AudInU::ListAudioIns, "ListAudioInsAuto"},
215 {3, &AudInU::OpenAudioIn, "OpenAudioInAuto"},
216 {4, &AudInU::ListAudioInsAutoFiltered, "ListAudioInsAutoFiltered"},
217 {5, &AudInU::OpenAudioInProtocolSpecified, "OpenAudioInProtocolSpecified"},
218 };
219 // clang-format on
220
221 RegisterHandlers(functions);
222}
223
224AudInU::~AudInU() = default;
225
226void AudInU::ListAudioIns(HLERequestContext& ctx) {
227 using namespace AudioCore::Renderer;
228
229 LOG_DEBUG(Service_Audio, "called");
230
231 const auto write_count =
232 static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
233 std::vector<AudioDevice::AudioDeviceName> device_names{};
234
235 u32 out_count{0};
236 if (write_count > 0) {
237 out_count = impl->GetDeviceNames(device_names, write_count, false);
238 ctx.WriteBuffer(device_names);
239 }
240
241 IPC::ResponseBuilder rb{ctx, 3};
242 rb.Push(ResultSuccess);
243 rb.Push(out_count);
244}
245
246void AudInU::ListAudioInsAutoFiltered(HLERequestContext& ctx) {
247 using namespace AudioCore::Renderer;
248
249 LOG_DEBUG(Service_Audio, "called");
250
251 const auto write_count =
252 static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
253 std::vector<AudioDevice::AudioDeviceName> device_names{};
254
255 u32 out_count{0};
256 if (write_count > 0) {
257 out_count = impl->GetDeviceNames(device_names, write_count, true);
258 ctx.WriteBuffer(device_names);
259 }
260
261 IPC::ResponseBuilder rb{ctx, 3};
262 rb.Push(ResultSuccess);
263 rb.Push(out_count);
264}
265
266void AudInU::OpenAudioIn(HLERequestContext& ctx) {
267 IPC::RequestParser rp{ctx};
268 auto in_params{rp.PopRaw<AudioInParameter>()};
269 auto applet_resource_user_id{rp.PopRaw<u64>()};
270 const auto device_name_data{ctx.ReadBuffer()};
271 auto device_name = Common::StringFromBuffer(device_name_data);
272 auto handle{ctx.GetCopyHandle(0)};
273
274 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
275 if (process.IsNull()) {
276 LOG_ERROR(Service_Audio, "Failed to get process handle");
277 IPC::ResponseBuilder rb{ctx, 2};
278 rb.Push(ResultUnknown);
279 return;
280 }
281
282 std::scoped_lock l{impl->mutex};
283 auto link{impl->LinkToManager()};
284 if (link.IsError()) {
285 LOG_ERROR(Service_Audio, "Failed to link Audio In to Audio Manager");
286 IPC::ResponseBuilder rb{ctx, 2};
287 rb.Push(link);
288 return;
289 }
290
291 size_t new_session_id{};
292 auto result{impl->AcquireSessionId(new_session_id)};
293 if (result.IsError()) {
294 IPC::ResponseBuilder rb{ctx, 2};
295 rb.Push(result);
296 return;
297 }
298
299 LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
300 impl->num_free_sessions);
301
302 auto audio_in =
303 std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
304 process.GetPointerUnsafe(), applet_resource_user_id);
305 impl->sessions[new_session_id] = audio_in->GetImpl();
306 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
307
308 auto& out_system = impl->sessions[new_session_id]->GetSystem();
309 AudioInParameterInternal out_params{.sample_rate = out_system.GetSampleRate(),
310 .channel_count = out_system.GetChannelCount(),
311 .sample_format =
312 static_cast<u32>(out_system.GetSampleFormat()),
313 .state = static_cast<u32>(out_system.GetState())};
314
315 IPC::ResponseBuilder rb{ctx, 6, 0, 1};
316
317 std::string out_name{out_system.GetName()};
318 ctx.WriteBuffer(out_name);
319
320 rb.Push(ResultSuccess);
321 rb.PushRaw<AudioInParameterInternal>(out_params);
322 rb.PushIpcInterface<IAudioIn>(audio_in);
323}
324
325void AudInU::OpenAudioInProtocolSpecified(HLERequestContext& ctx) {
326 IPC::RequestParser rp{ctx};
327 auto protocol_specified{rp.PopRaw<u64>()};
328 auto in_params{rp.PopRaw<AudioInParameter>()};
329 auto applet_resource_user_id{rp.PopRaw<u64>()};
330 const auto device_name_data{ctx.ReadBuffer()};
331 auto device_name = Common::StringFromBuffer(device_name_data);
332 auto handle{ctx.GetCopyHandle(0)};
333
334 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
335 if (process.IsNull()) {
336 LOG_ERROR(Service_Audio, "Failed to get process handle");
337 IPC::ResponseBuilder rb{ctx, 2};
338 rb.Push(ResultUnknown);
339 return;
340 }
341
342 std::scoped_lock l{impl->mutex};
343 auto link{impl->LinkToManager()};
344 if (link.IsError()) {
345 LOG_ERROR(Service_Audio, "Failed to link Audio In to Audio Manager");
346 IPC::ResponseBuilder rb{ctx, 2};
347 rb.Push(link);
348 return;
349 }
350
351 size_t new_session_id{};
352 auto result{impl->AcquireSessionId(new_session_id)};
353 if (result.IsError()) {
354 IPC::ResponseBuilder rb{ctx, 2};
355 rb.Push(result);
356 return;
357 }
358
359 LOG_DEBUG(Service_Audio, "Opening new AudioIn, sessionid={}, free sessions={}", new_session_id,
360 impl->num_free_sessions);
361
362 auto audio_in =
363 std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name, in_params,
364 process.GetPointerUnsafe(), applet_resource_user_id);
365 impl->sessions[new_session_id] = audio_in->GetImpl();
366 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
367
368 auto& out_system = impl->sessions[new_session_id]->GetSystem();
369 AudioInParameterInternal out_params{.sample_rate = out_system.GetSampleRate(),
370 .channel_count = out_system.GetChannelCount(),
371 .sample_format =
372 static_cast<u32>(out_system.GetSampleFormat()),
373 .state = static_cast<u32>(out_system.GetState())};
374
375 IPC::ResponseBuilder rb{ctx, 6, 0, 1};
376
377 std::string out_name{out_system.GetName()};
378 if (protocol_specified == 0) {
379 if (out_system.IsUac()) {
380 out_name = "UacIn";
381 } else {
382 out_name = "DeviceIn";
383 }
384 }
385
386 ctx.WriteBuffer(out_name);
387
388 rb.Push(ResultSuccess);
389 rb.PushRaw<AudioInParameterInternal>(out_params);
390 rb.PushIpcInterface<IAudioIn>(audio_in);
391}
392
393} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h
deleted file mode 100644
index 51e770ff9..000000000
--- a/src/core/hle/service/audio/audin_u.h
+++ /dev/null
@@ -1,38 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/audio_in_manager.h"
7#include "audio_core/in/audio_in.h"
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Core {
12class System;
13}
14
15namespace AudioCore::AudioOut {
16class Manager;
17class In;
18} // namespace AudioCore::AudioOut
19
20namespace Service::Audio {
21
22class AudInU final : public ServiceFramework<AudInU> {
23public:
24 explicit AudInU(Core::System& system_);
25 ~AudInU() override;
26
27private:
28 void ListAudioIns(HLERequestContext& ctx);
29 void ListAudioInsAutoFiltered(HLERequestContext& ctx);
30 void OpenInOutImpl(HLERequestContext& ctx);
31 void OpenAudioIn(HLERequestContext& ctx);
32 void OpenAudioInProtocolSpecified(HLERequestContext& ctx);
33
34 KernelHelpers::ServiceContext service_context;
35 std::unique_ptr<AudioCore::AudioIn::Manager> impl;
36};
37
38} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 44af030eb..331176bf7 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -2,14 +2,14 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/core.h" 4#include "core/core.h"
5#include "core/hle/service/audio/audin_u.h"
6#include "core/hle/service/audio/audio.h" 5#include "core/hle/service/audio/audio.h"
7#include "core/hle/service/audio/audio_controller.h" 6#include "core/hle/service/audio/audio_controller.h"
8#include "core/hle/service/audio/audout_u.h" 7#include "core/hle/service/audio/audio_in_manager.h"
9#include "core/hle/service/audio/audrec_a.h" 8#include "core/hle/service/audio/audio_out_manager.h"
10#include "core/hle/service/audio/audrec_u.h" 9#include "core/hle/service/audio/audio_renderer_manager.h"
11#include "core/hle/service/audio/audren_u.h" 10#include "core/hle/service/audio/final_output_recorder_manager.h"
12#include "core/hle/service/audio/hwopus.h" 11#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
12#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
13#include "core/hle/service/server_manager.h" 13#include "core/hle/service/server_manager.h"
14#include "core/hle/service/service.h" 14#include "core/hle/service/service.h"
15 15
@@ -19,12 +19,16 @@ void LoopProcess(Core::System& system) {
19 auto server_manager = std::make_unique<ServerManager>(system); 19 auto server_manager = std::make_unique<ServerManager>(system);
20 20
21 server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system)); 21 server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
22 server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system)); 22 server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
23 server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system)); 23 server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system));
24 server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system)); 24 server_manager->RegisterNamedService(
25 server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system)); 25 "audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
26 server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system)); 26 server_manager->RegisterNamedService("audrec:u",
27 server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system)); 27 std::make_shared<IFinalOutputRecorderManager>(system));
28 server_manager->RegisterNamedService("audren:u",
29 std::make_shared<IAudioRendererManager>(system));
30 server_manager->RegisterNamedService("hwopus",
31 std::make_shared<IHardwareOpusDecoderManager>(system));
28 ServerManager::RunServer(std::move(server_manager)); 32 ServerManager::RunServer(std::move(server_manager));
29} 33}
30 34
diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp
index a6da66d0f..c9804cf9c 100644
--- a/src/core/hle/service/audio/audio_controller.cpp
+++ b/src/core/hle/service/audio/audio_controller.cpp
@@ -16,27 +16,27 @@ IAudioController::IAudioController(Core::System& system_)
16 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
17 {0, nullptr, "GetTargetVolume"}, 17 {0, nullptr, "GetTargetVolume"},
18 {1, nullptr, "SetTargetVolume"}, 18 {1, nullptr, "SetTargetVolume"},
19 {2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"}, 19 {2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
20 {3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"}, 20 {3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
21 {4, nullptr, "IsTargetMute"}, 21 {4, nullptr, "IsTargetMute"},
22 {5, nullptr, "SetTargetMute"}, 22 {5, nullptr, "SetTargetMute"},
23 {6, nullptr, "IsTargetConnected"}, 23 {6, nullptr, "IsTargetConnected"},
24 {7, nullptr, "SetDefaultTarget"}, 24 {7, nullptr, "SetDefaultTarget"},
25 {8, nullptr, "GetDefaultTarget"}, 25 {8, nullptr, "GetDefaultTarget"},
26 {9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"}, 26 {9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
27 {10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"}, 27 {10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
28 {11, nullptr, "SetForceMutePolicy"}, 28 {11, nullptr, "SetForceMutePolicy"},
29 {12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"}, 29 {12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
30 {13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"}, 30 {13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
31 {14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"}, 31 {14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
32 {15, nullptr, "SetOutputTarget"}, 32 {15, nullptr, "SetOutputTarget"},
33 {16, nullptr, "SetInputTargetForceEnabled"}, 33 {16, nullptr, "SetInputTargetForceEnabled"},
34 {17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"}, 34 {17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
35 {18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"}, 35 {18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
36 {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, 36 {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
37 {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, 37 {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
38 {21, nullptr, "GetAudioOutputTargetForPlayReport"}, 38 {21, nullptr, "GetAudioOutputTargetForPlayReport"},
39 {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"}, 39 {22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
40 {23, nullptr, "SetSystemOutputMasterVolume"}, 40 {23, nullptr, "SetSystemOutputMasterVolume"},
41 {24, nullptr, "GetSystemOutputMasterVolume"}, 41 {24, nullptr, "GetSystemOutputMasterVolume"},
42 {25, nullptr, "GetAudioVolumeDataForPlayReport"}, 42 {25, nullptr, "GetAudioVolumeDataForPlayReport"},
@@ -44,11 +44,11 @@ IAudioController::IAudioController(Core::System& system_)
44 {27, nullptr, "SetVolumeMappingTableForDev"}, 44 {27, nullptr, "SetVolumeMappingTableForDev"},
45 {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, 45 {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
46 {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, 46 {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
47 {30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"}, 47 {30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
48 {31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"}, 48 {31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
49 {32, nullptr, "GetActiveOutputTarget"}, 49 {32, nullptr, "GetActiveOutputTarget"},
50 {33, nullptr, "GetTargetDeviceInfo"}, 50 {33, nullptr, "GetTargetDeviceInfo"},
51 {34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"}, 51 {34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
52 {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, 52 {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
53 {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, 53 {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
54 {37, nullptr, "SetHearingProtectionSafeguardEnabled"}, 54 {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
@@ -150,6 +150,11 @@ Result IAudioController::GetHeadphoneOutputLevelMode(
150 R_SUCCEED(); 150 R_SUCCEED();
151} 151}
152 152
153Result IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent() {
154 LOG_WARNING(Service_Audio, "(STUBBED) called");
155 R_SUCCEED();
156}
157
153Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) { 158Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
154 LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled); 159 LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);
155 160
diff --git a/src/core/hle/service/audio/audio_controller.h b/src/core/hle/service/audio/audio_controller.h
index 9e8514373..d37c4843e 100644
--- a/src/core/hle/service/audio/audio_controller.h
+++ b/src/core/hle/service/audio/audio_controller.h
@@ -45,6 +45,7 @@ private:
45 Set::AudioOutputMode output_mode); 45 Set::AudioOutputMode output_mode);
46 Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode); 46 Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
47 Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode); 47 Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
48 Result NotifyHeadphoneVolumeWarningDisplayedEvent();
48 Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled); 49 Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
49 Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled); 50 Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
50 Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event); 51 Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);
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..438f3cccd
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.cpp
@@ -0,0 +1,163 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/audio_core.h"
5#include "common/string_util.h"
6#include "core/hle/service/audio/audio_device.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::Audio {
10using namespace AudioCore::Renderer;
11
12IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
13 u32 device_num)
14 : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
15 impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
16 event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
17 static const FunctionInfo functions[] = {
18 {0, D<&IAudioDevice::ListAudioDeviceName>, "ListAudioDeviceName"},
19 {1, D<&IAudioDevice::SetAudioDeviceOutputVolume>, "SetAudioDeviceOutputVolume"},
20 {2, D<&IAudioDevice::GetAudioDeviceOutputVolume>, "GetAudioDeviceOutputVolume"},
21 {3, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioDeviceName"},
22 {4, D<&IAudioDevice::QueryAudioDeviceSystemEvent>, "QueryAudioDeviceSystemEvent"},
23 {5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"},
24 {6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"},
25 {7, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"},
26 {8, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"},
27 {10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"},
28 {11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"},
29 {12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
30 {13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"},
31 {14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
32 };
33 RegisterHandlers(functions);
34
35 event->Signal();
36}
37
38IAudioDevice::~IAudioDevice() {
39 service_context.CloseEvent(event);
40}
41
42Result IAudioDevice::ListAudioDeviceName(
43 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
44 R_RETURN(this->ListAudioDeviceNameAuto(out_names, out_count));
45}
46
47Result IAudioDevice::SetAudioDeviceOutputVolume(
48 InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume) {
49 R_RETURN(this->SetAudioDeviceOutputVolumeAuto(name, volume));
50}
51
52Result IAudioDevice::GetAudioDeviceOutputVolume(
53 Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name) {
54 R_RETURN(this->GetAudioDeviceOutputVolumeAuto(out_volume, name));
55}
56
57Result IAudioDevice::GetActiveAudioDeviceName(
58 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name) {
59 R_RETURN(this->GetActiveAudioDeviceNameAuto(out_name));
60}
61
62Result IAudioDevice::ListAudioDeviceNameAuto(
63 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
64 Out<s32> out_count) {
65 *out_count = impl->ListAudioDeviceName(out_names);
66
67 std::string out{};
68 for (s32 i = 0; i < *out_count; i++) {
69 std::string a{};
70 u32 j = 0;
71 while (out_names[i].name[j] != '\0') {
72 a += out_names[i].name[j];
73 j++;
74 }
75 out += "\n\t" + a;
76 }
77
78 LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
79 R_SUCCEED();
80}
81
82Result IAudioDevice::SetAudioDeviceOutputVolumeAuto(
83 InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume) {
84 R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);
85
86 const std::string device_name = Common::StringFromBuffer(name[0].name);
87 LOG_DEBUG(Service_Audio, "called. name={}, volume={}", device_name, volume);
88
89 if (device_name == "AudioTvOutput") {
90 impl->SetDeviceVolumes(volume);
91 }
92
93 R_SUCCEED();
94}
95
96Result IAudioDevice::GetAudioDeviceOutputVolumeAuto(
97 Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name) {
98 R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);
99
100 const std::string device_name = Common::StringFromBuffer(name[0].name);
101 LOG_DEBUG(Service_Audio, "called. Name={}", device_name);
102
103 *out_volume = 1.0f;
104 if (device_name == "AudioTvOutput") {
105 *out_volume = impl->GetDeviceVolume(device_name);
106 }
107
108 R_SUCCEED();
109}
110
111Result IAudioDevice::GetActiveAudioDeviceNameAuto(
112 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name) {
113 R_UNLESS(!out_name.empty(), Audio::ResultInsufficientBuffer);
114 out_name[0] = AudioDevice::AudioDeviceName("AudioTvOutput");
115 LOG_DEBUG(Service_Audio, "(STUBBED) called");
116 R_SUCCEED();
117}
118
119Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
120 LOG_DEBUG(Service_Audio, "(STUBBED) called");
121 event->Signal();
122 *out_event = &event->GetReadableEvent();
123 R_SUCCEED();
124}
125
126Result IAudioDevice::QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
127 LOG_DEBUG(Service_Audio, "(STUBBED) called");
128 *out_event = &event->GetReadableEvent();
129 R_SUCCEED();
130}
131
132Result IAudioDevice::QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
133 LOG_DEBUG(Service_Audio, "called");
134 *out_event = &event->GetReadableEvent();
135 R_SUCCEED();
136}
137
138Result IAudioDevice::GetActiveChannelCount(Out<u32> out_active_channel_count) {
139 *out_active_channel_count = system.AudioCore().GetOutputSink().GetSystemChannels();
140 LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", *out_active_channel_count);
141 R_SUCCEED();
142}
143
144Result IAudioDevice::ListAudioOutputDeviceName(
145 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
146 *out_count = impl->ListAudioOutputDeviceName(out_names);
147
148 std::string out{};
149 for (s32 i = 0; i < *out_count; i++) {
150 std::string a{};
151 u32 j = 0;
152 while (out_names[i].name[j] != '\0') {
153 a += out_names[i].name[j];
154 j++;
155 }
156 out += "\n\t" + a;
157 }
158
159 LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
160 R_SUCCEED();
161}
162
163} // 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..752157272
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.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/renderer/audio_device.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Kernel {
12class KReadableEvent;
13}
14
15namespace Service::Audio {
16
17using AudioCore::Renderer::AudioDevice;
18
19class IAudioDevice final : public ServiceFramework<IAudioDevice> {
20
21public:
22 explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
23 u32 device_num);
24 ~IAudioDevice() override;
25
26private:
27 Result ListAudioDeviceName(
28 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
29 Out<s32> out_count);
30 Result SetAudioDeviceOutputVolume(
31 InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume);
32 Result GetAudioDeviceOutputVolume(
33 Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name);
34 Result GetActiveAudioDeviceName(
35 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name);
36 Result ListAudioDeviceNameAuto(
37 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
38 Out<s32> out_count);
39 Result SetAudioDeviceOutputVolumeAuto(
40 InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume);
41 Result GetAudioDeviceOutputVolumeAuto(
42 Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name);
43 Result GetActiveAudioDeviceNameAuto(
44 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name);
45 Result QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
46 Result QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
47 Result QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
48 Result GetActiveChannelCount(Out<u32> out_active_channel_count);
49 Result ListAudioOutputDeviceName(
50 OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
51 Out<s32> out_count);
52
53 KernelHelpers::ServiceContext service_context;
54 std::unique_ptr<AudioCore::Renderer::AudioDevice> impl;
55 Kernel::KEvent* event;
56};
57
58} // namespace Service::Audio
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 000000000..416803acc
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in.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 "core/hle/service/audio/audio_in.h"
5#include "core/hle/service/cmif_serialization.h"
6#include "core/hle/service/ipc_helpers.h"
7
8namespace Service::Audio {
9using namespace AudioCore::AudioIn;
10
11IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
12 const std::string& device_name, const AudioInParameter& in_params,
13 Kernel::KProcess* handle, u64 applet_resource_user_id)
14 : ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
15 event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
16 manager, event,
17 session_id)} {
18 // clang-format off
19 static const FunctionInfo functions[] = {
20 {0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
21 {1, D<&IAudioIn::Start>, "Start"},
22 {2, D<&IAudioIn::Stop>, "Stop"},
23 {3, D<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"},
24 {4, D<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"},
25 {5, D<&IAudioIn::GetReleasedAudioInBuffers>, "GetReleasedAudioInBuffers"},
26 {6, D<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"},
27 {7, D<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"},
28 {8, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendAudioInBufferAuto"},
29 {9, D<&IAudioIn::GetReleasedAudioInBuffersAuto>, "GetReleasedAudioInBuffersAuto"},
30 {10, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendUacInBufferAuto"},
31 {11, D<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"},
32 {12, D<&IAudioIn::SetDeviceGain>, "SetDeviceGain"},
33 {13, D<&IAudioIn::GetDeviceGain>, "GetDeviceGain"},
34 {14, D<&IAudioIn::FlushAudioInBuffers>, "FlushAudioInBuffers"},
35 };
36 // clang-format on
37
38 RegisterHandlers(functions);
39
40 process->Open();
41
42 if (impl->GetSystem()
43 .Initialize(device_name, in_params, handle, applet_resource_user_id)
44 .IsError()) {
45 LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
46 }
47}
48
49IAudioIn::~IAudioIn() {
50 impl->Free();
51 service_context.CloseEvent(event);
52 process->Close();
53}
54
55Result IAudioIn::GetAudioInState(Out<u32> out_state) {
56 *out_state = static_cast<u32>(impl->GetState());
57 LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
58 R_SUCCEED();
59}
60
61Result IAudioIn::Start() {
62 LOG_DEBUG(Service_Audio, "called");
63 R_RETURN(impl->StartSystem());
64}
65
66Result IAudioIn::Stop() {
67 LOG_DEBUG(Service_Audio, "called");
68 R_RETURN(impl->StopSystem());
69}
70
71Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
72 u64 buffer_client_ptr) {
73 R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
74}
75
76Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
77 u64 buffer_client_ptr) {
78 if (buffer.empty()) {
79 LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
80 R_THROW(Audio::ResultInsufficientBuffer);
81 }
82
83 [[maybe_unused]] const auto session_id{impl->GetSystem().GetSessionId()};
84 LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", session_id,
85 buffer_client_ptr);
86
87 R_RETURN(impl->AppendBuffer(buffer[0], buffer_client_ptr));
88}
89
90Result IAudioIn::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
91 LOG_DEBUG(Service_Audio, "called");
92 *out_event = &impl->GetBufferEvent();
93 R_SUCCEED();
94}
95
96Result IAudioIn::GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
97 Out<u32> out_count) {
98 R_RETURN(this->GetReleasedAudioInBuffersAuto(out_audio_buffer, out_count));
99}
100
101Result IAudioIn::GetReleasedAudioInBuffersAuto(
102 OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {
103
104 if (!out_audio_buffer.empty()) {
105 out_audio_buffer[0] = 0;
106 }
107 *out_count = impl->GetReleasedBuffers(out_audio_buffer);
108
109 LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
110 impl->GetSystem().GetSessionId(), *out_count);
111 R_SUCCEED();
112}
113
114Result IAudioIn::ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
115 *out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);
116
117 LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
118 *out_contains_buffer);
119 R_SUCCEED();
120}
121
122Result IAudioIn::GetAudioInBufferCount(Out<u32> out_buffer_count) {
123 *out_buffer_count = impl->GetBufferCount();
124 LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
125 R_SUCCEED();
126}
127
128Result IAudioIn::SetDeviceGain(f32 device_gain) {
129 impl->SetVolume(device_gain);
130 LOG_DEBUG(Service_Audio, "called. Gain {}", device_gain);
131 R_SUCCEED();
132}
133
134Result IAudioIn::GetDeviceGain(Out<f32> out_device_gain) {
135 *out_device_gain = impl->GetVolume();
136 LOG_DEBUG(Service_Audio, "called. Gain {}", *out_device_gain);
137 R_SUCCEED();
138}
139
140Result IAudioIn::FlushAudioInBuffers(Out<bool> out_flushed) {
141 *out_flushed = impl->FlushAudioInBuffers();
142 LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
143 R_SUCCEED();
144}
145
146} // 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 000000000..3fe1e1e87
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in.h
@@ -0,0 +1,53 @@
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/in/audio_in.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Service::Audio {
12
13class IAudioIn final : public ServiceFramework<IAudioIn> {
14public:
15 explicit IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager,
16 size_t session_id, const std::string& device_name,
17 const AudioCore::AudioIn::AudioInParameter& in_params,
18 Kernel::KProcess* handle, u64 applet_resource_user_id);
19 ~IAudioIn() override;
20
21 std::shared_ptr<AudioCore::AudioIn::In> GetImpl() {
22 return impl;
23 }
24
25 Result GetAudioInState(Out<u32> out_state);
26 Result Start();
27 Result Stop();
28 Result AppendAudioInBuffer(
29 InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
30 u64 buffer_client_ptr);
31 Result AppendAudioInBufferAuto(
32 InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
33 u64 buffer_client_ptr);
34 Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
35 Result GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
36 Out<u32> out_count);
37 Result GetReleasedAudioInBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
38 Out<u32> out_count);
39 Result ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
40 Result GetAudioInBufferCount(Out<u32> out_buffer_count);
41 Result SetDeviceGain(f32 device_gain);
42 Result GetDeviceGain(Out<f32> out_device_gain);
43 Result FlushAudioInBuffers(Out<bool> out_flushed);
44
45private:
46 Kernel::KProcess* process;
47 KernelHelpers::ServiceContext service_context;
48 Kernel::KEvent* event;
49 std::shared_ptr<AudioCore::AudioIn::In> impl;
50 Common::ScratchBuffer<u64> released_buffer;
51};
52
53} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_in_manager.cpp b/src/core/hle/service/audio/audio_in_manager.cpp
new file mode 100644
index 000000000..2675a5773
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in_manager.cpp
@@ -0,0 +1,125 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/string_util.h"
5#include "core/hle/service/audio/audio_in.h"
6#include "core/hle/service/audio/audio_in_manager.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::Audio {
10using namespace AudioCore::AudioIn;
11
12IAudioInManager::IAudioInManager(Core::System& system_)
13 : ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
14 system_)} {
15 // clang-format off
16 static const FunctionInfo functions[] = {
17 {0, D<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
18 {1, D<&IAudioInManager::OpenAudioIn>, "OpenAudioIn"},
19 {2, D<&IAudioInManager::ListAudioIns>, "ListAudioInsAuto"},
20 {3, D<&IAudioInManager::OpenAudioIn>, "OpenAudioInAuto"},
21 {4, D<&IAudioInManager::ListAudioInsAutoFiltered>, "ListAudioInsAutoFiltered"},
22 {5, D<&IAudioInManager::OpenAudioInProtocolSpecified>, "OpenAudioInProtocolSpecified"},
23 };
24 // clang-format on
25
26 RegisterHandlers(functions);
27}
28
29IAudioInManager::~IAudioInManager() = default;
30
31Result IAudioInManager::ListAudioIns(
32 OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins, Out<u32> out_count) {
33 LOG_DEBUG(Service_Audio, "called");
34 R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
35}
36
37Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
38 Out<SharedPointer<IAudioIn>> out_audio_in,
39 OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
40 InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
41 AudioInParameter parameter,
42 InCopyHandle<Kernel::KProcess> process_handle,
43 ClientAppletResourceUserId aruid) {
44 LOG_DEBUG(Service_Audio, "called");
45 R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
46 name, {}, parameter, process_handle, aruid));
47}
48
49Result IAudioInManager::ListAudioInsAuto(
50 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
51 LOG_DEBUG(Service_Audio, "called");
52 R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
53}
54
55Result IAudioInManager::OpenAudioInAuto(
56 Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
57 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
58 InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
59 InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
60 LOG_DEBUG(Service_Audio, "called");
61 R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
62 name, {}, parameter, process_handle, aruid));
63}
64
65Result IAudioInManager::ListAudioInsAutoFiltered(
66 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
67 LOG_DEBUG(Service_Audio, "called");
68 *out_count = impl->GetDeviceNames(out_audio_ins, true);
69 R_SUCCEED();
70}
71
72Result IAudioInManager::OpenAudioInProtocolSpecified(
73 Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
74 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
75 InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
76 AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
77 ClientAppletResourceUserId aruid) {
78 LOG_DEBUG(Service_Audio, "called");
79
80 if (!process_handle) {
81 LOG_ERROR(Service_Audio, "Failed to get process handle");
82 R_THROW(ResultUnknown);
83 }
84 if (name.empty() || out_name.empty()) {
85 LOG_ERROR(Service_Audio, "Invalid buffers");
86 R_THROW(ResultUnknown);
87 }
88
89 std::scoped_lock l{impl->mutex};
90
91 size_t new_session_id{};
92
93 R_TRY(impl->LinkToManager());
94 R_TRY(impl->AcquireSessionId(new_session_id));
95
96 LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
97 impl->num_free_sessions);
98
99 const auto device_name = Common::StringFromBuffer(name[0].name);
100 *out_audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
101 parameter, process_handle.Get(), aruid.pid);
102 impl->sessions[new_session_id] = (*out_audio_in)->GetImpl();
103 impl->applet_resource_user_ids[new_session_id] = aruid.pid;
104
105 auto& out_system = impl->sessions[new_session_id]->GetSystem();
106 *out_parameter_internal =
107 AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
108 .channel_count = out_system.GetChannelCount(),
109 .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
110 .state = static_cast<u32>(out_system.GetState())};
111
112 out_name[0] = AudioDeviceName(out_system.GetName());
113
114 if (protocol == Protocol{}) {
115 if (out_system.IsUac()) {
116 out_name[0] = AudioDeviceName("UacIn");
117 } else {
118 out_name[0] = AudioDeviceName("DeviceIn");
119 }
120 }
121
122 R_SUCCEED();
123}
124
125} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_in_manager.h b/src/core/hle/service/audio/audio_in_manager.h
new file mode 100644
index 000000000..2a983bc60
--- /dev/null
+++ b/src/core/hle/service/audio/audio_in_manager.h
@@ -0,0 +1,57 @@
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_in_manager.h"
7#include "audio_core/in/audio_in_system.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/service.h"
10
11namespace Service::Audio {
12
13using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
14using Protocol = std::array<u32, 2>;
15
16class IAudioIn;
17
18class IAudioInManager final : public ServiceFramework<IAudioInManager> {
19public:
20 explicit IAudioInManager(Core::System& system_);
21 ~IAudioInManager() override;
22
23private:
24 Result ListAudioIns(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins,
25 Out<u32> out_count);
26 Result OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
27 Out<SharedPointer<IAudioIn>> out_audio_in,
28 OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
29 InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
30 AudioCore::AudioIn::AudioInParameter parameter,
31 InCopyHandle<Kernel::KProcess> process_handle,
32 ClientAppletResourceUserId aruid);
33
34 Result ListAudioInsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins,
35 Out<u32> out_count);
36 Result OpenAudioInAuto(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
37 Out<SharedPointer<IAudioIn>> out_audio_in,
38 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
39 InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
40 AudioCore::AudioIn::AudioInParameter parameter,
41 InCopyHandle<Kernel::KProcess> process_handle,
42 ClientAppletResourceUserId aruid);
43
44 Result ListAudioInsAutoFiltered(
45 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count);
46 Result OpenAudioInProtocolSpecified(
47 Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
48 Out<SharedPointer<IAudioIn>> out_audio_in,
49 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
50 InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
51 AudioCore::AudioIn::AudioInParameter parameter,
52 InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
53
54 std::unique_ptr<AudioCore::AudioIn::Manager> impl;
55};
56
57} // namespace Service::Audio
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..53009d5d7
--- /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
12namespace Service::Audio {
13using namespace AudioCore::AudioOut;
14
15IAudioOut::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, D<&IAudioOut::GetAudioOutState>, "GetAudioOutState"},
25 {1, D<&IAudioOut::Start>, "Start"},
26 {2, D<&IAudioOut::Stop>, "Stop"},
27 {3, D<&IAudioOut::AppendAudioOutBuffer>, "AppendAudioOutBuffer"},
28 {4, D<&IAudioOut::RegisterBufferEvent>, "RegisterBufferEvent"},
29 {5, D<&IAudioOut::GetReleasedAudioOutBuffers>, "GetReleasedAudioOutBuffers"},
30 {6, D<&IAudioOut::ContainsAudioOutBuffer>, "ContainsAudioOutBuffer"},
31 {7, D<&IAudioOut::AppendAudioOutBufferAuto>, "AppendAudioOutBufferAuto"},
32 {8, D<&IAudioOut::GetReleasedAudioOutBuffersAuto>, "GetReleasedAudioOutBuffersAuto"},
33 {9, D<&IAudioOut::GetAudioOutBufferCount>, "GetAudioOutBufferCount"},
34 {10, D<&IAudioOut::GetAudioOutPlayedSampleCount>, "GetAudioOutPlayedSampleCount"},
35 {11, D<&IAudioOut::FlushAudioOutBuffers>, "FlushAudioOutBuffers"},
36 {12, D<&IAudioOut::SetAudioOutVolume>, "SetAudioOutVolume"},
37 {13, D<&IAudioOut::GetAudioOutVolume>, "GetAudioOutVolume"},
38 };
39 // clang-format on
40 RegisterHandlers(functions);
41
42 process->Open();
43}
44
45IAudioOut::~IAudioOut() {
46 impl->Free();
47 service_context.CloseEvent(event);
48 process->Close();
49}
50
51Result 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
57Result IAudioOut::Start() {
58 LOG_DEBUG(Service_Audio, "called");
59 R_RETURN(impl->StartSystem());
60}
61
62Result IAudioOut::Stop() {
63 LOG_DEBUG(Service_Audio, "called");
64 R_RETURN(impl->StopSystem());
65}
66
67Result 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
72Result 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
84Result IAudioOut::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
85 LOG_DEBUG(Service_Audio, "called");
86 *out_event = &impl->GetBufferEvent();
87 R_SUCCEED();
88}
89
90Result 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
95Result 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
108Result 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
116Result 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
122Result 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
128Result 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
134Result IAudioOut::SetAudioOutVolume(f32 volume) {
135 LOG_DEBUG(Service_Audio, "called. Volume={}", volume);
136 impl->SetVolume(volume);
137 R_SUCCEED();
138}
139
140Result 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
12namespace Kernel {
13class KReadableEvent;
14}
15
16namespace Service::Audio {
17
18class IAudioOut : public ServiceFramework<IAudioOut> {
19public:
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
51private:
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/audio_out_manager.cpp b/src/core/hle/service/audio/audio_out_manager.cpp
new file mode 100644
index 000000000..153445097
--- /dev/null
+++ b/src/core/hle/service/audio/audio_out_manager.cpp
@@ -0,0 +1,101 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/string_util.h"
5#include "core/hle/service/audio/audio_out.h"
6#include "core/hle/service/audio/audio_out_manager.h"
7#include "core/hle/service/cmif_serialization.h"
8#include "core/memory.h"
9
10namespace Service::Audio {
11using namespace AudioCore::AudioOut;
12
13IAudioOutManager::IAudioOutManager(Core::System& system_)
14 : ServiceFramework{system_, "audout:u"}, impl{std::make_unique<Manager>(system_)} {
15 // clang-format off
16 static const FunctionInfo functions[] = {
17 {0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"},
18 {1, D<&IAudioOutManager::OpenAudioOut>, "OpenAudioOut"},
19 {2, D<&IAudioOutManager::ListAudioOutsAuto>, "ListAudioOutsAuto"},
20 {3, D<&IAudioOutManager::OpenAudioOutAuto>, "OpenAudioOutAuto"},
21 };
22 // clang-format on
23
24 RegisterHandlers(functions);
25}
26
27IAudioOutManager::~IAudioOutManager() = default;
28
29Result IAudioOutManager::ListAudioOuts(
30 OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs, Out<u32> out_count) {
31 R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count));
32}
33
34Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal,
35 Out<SharedPointer<IAudioOut>> out_audio_out,
36 OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
37 InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
38 AudioOutParameter parameter,
39 InCopyHandle<Kernel::KProcess> process_handle,
40 ClientAppletResourceUserId aruid) {
41 R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
42 parameter, process_handle, aruid));
43}
44
45Result IAudioOutManager::ListAudioOutsAuto(
46 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs, Out<u32> out_count) {
47 if (!out_audio_outs.empty()) {
48 out_audio_outs[0] = AudioDeviceName("DeviceOut");
49 *out_count = 1;
50 LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut");
51 } else {
52 *out_count = 0;
53 LOG_DEBUG(Service_Audio, "called. Empty buffer passed in.");
54 }
55
56 R_SUCCEED();
57}
58
59Result IAudioOutManager::OpenAudioOutAuto(
60 Out<AudioOutParameterInternal> out_parameter_internal,
61 Out<SharedPointer<IAudioOut>> out_audio_out,
62 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
63 InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter,
64 InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
65 if (!process_handle) {
66 LOG_ERROR(Service_Audio, "Failed to get process handle");
67 R_THROW(ResultUnknown);
68 }
69 if (name.empty() || out_name.empty()) {
70 LOG_ERROR(Service_Audio, "Invalid buffers");
71 R_THROW(ResultUnknown);
72 }
73
74 size_t new_session_id{};
75 R_TRY(impl->LinkToManager());
76 R_TRY(impl->AcquireSessionId(new_session_id));
77
78 const auto device_name = Common::StringFromBuffer(name[0].name);
79 LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
80 impl->num_free_sessions);
81
82 auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name,
83 parameter, process_handle.Get(), aruid.pid);
84 R_TRY(audio_out->GetImpl()->GetSystem().Initialize(device_name, parameter, process_handle.Get(),
85 aruid.pid));
86
87 *out_audio_out = audio_out;
88 impl->sessions[new_session_id] = audio_out->GetImpl();
89 impl->applet_resource_user_ids[new_session_id] = aruid.pid;
90
91 auto& out_system = impl->sessions[new_session_id]->GetSystem();
92 *out_parameter_internal =
93 AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
94 .channel_count = out_system.GetChannelCount(),
95 .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
96 .state = static_cast<u32>(out_system.GetState())};
97
98 R_SUCCEED();
99}
100
101} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_out_manager.h b/src/core/hle/service/audio/audio_out_manager.h
new file mode 100644
index 000000000..eaa27bc79
--- /dev/null
+++ b/src/core/hle/service/audio/audio_out_manager.h
@@ -0,0 +1,44 @@
1// SPDX-FileCopyrightText: Copyright 2018 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.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/service.h"
10
11namespace Service::Audio {
12
13using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
14class IAudioOut;
15
16class IAudioOutManager final : public ServiceFramework<IAudioOutManager> {
17public:
18 explicit IAudioOutManager(Core::System& system_);
19 ~IAudioOutManager() override;
20
21private:
22 Result ListAudioOuts(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs,
23 Out<u32> out_count);
24 Result OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
25 Out<SharedPointer<IAudioOut>> out_audio_out,
26 OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
27 InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
28 AudioCore::AudioOut::AudioOutParameter parameter,
29 InCopyHandle<Kernel::KProcess> process_handle,
30 ClientAppletResourceUserId aruid);
31 Result ListAudioOutsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs,
32 Out<u32> out_count);
33 Result OpenAudioOutAuto(
34 Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
35 Out<SharedPointer<IAudioOut>> out_audio_out,
36 OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
37 InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
38 AudioCore::AudioOut::AudioOutParameter parameter,
39 InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
40
41 std::unique_ptr<AudioCore::AudioOut::Manager> impl;
42};
43
44} // 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..fc4aad233
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.cpp
@@ -0,0 +1,139 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/audio/audio_renderer.h"
5#include "core/hle/service/cmif_serialization.h"
6
7namespace Service::Audio {
8using namespace AudioCore::Renderer;
9
10IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
11 AudioCore::AudioRendererParameterInternal& params,
12 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
13 Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
14 s32 session_id)
15 : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
16 rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
17 impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process_handle{
18 process_handle_} {
19 // clang-format off
20 static const FunctionInfo functions[] = {
21 {0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
22 {1, D<&IAudioRenderer::GetSampleCount>, "GetSampleCount"},
23 {2, D<&IAudioRenderer::GetMixBufferCount>, "GetMixBufferCount"},
24 {3, D<&IAudioRenderer::GetState>, "GetState"},
25 {4, D<&IAudioRenderer::RequestUpdate>, "RequestUpdate"},
26 {5, D<&IAudioRenderer::Start>, "Start"},
27 {6, D<&IAudioRenderer::Stop>, "Stop"},
28 {7, D<&IAudioRenderer::QuerySystemEvent>, "QuerySystemEvent"},
29 {8, D<&IAudioRenderer::SetRenderingTimeLimit>, "SetRenderingTimeLimit"},
30 {9, D<&IAudioRenderer::GetRenderingTimeLimit>, "GetRenderingTimeLimit"},
31 {10, D<&IAudioRenderer::RequestUpdateAuto>, "RequestUpdateAuto"},
32 {11, nullptr, "ExecuteAudioRendererRendering"},
33 {12, D<&IAudioRenderer::SetVoiceDropParameter>, "SetVoiceDropParameter"},
34 {13, D<&IAudioRenderer::GetVoiceDropParameter>, "GetVoiceDropParameter"},
35 };
36 // clang-format on
37 RegisterHandlers(functions);
38
39 process_handle->Open();
40 impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
41 applet_resource_user_id, session_id);
42}
43
44IAudioRenderer::~IAudioRenderer() {
45 impl->Finalize();
46 service_context.CloseEvent(rendered_event);
47 process_handle->Close();
48}
49
50Result IAudioRenderer::GetSampleRate(Out<u32> out_sample_rate) {
51 *out_sample_rate = impl->GetSystem().GetSampleRate();
52 LOG_DEBUG(Service_Audio, "called. Sample rate {}", *out_sample_rate);
53 R_SUCCEED();
54}
55
56Result IAudioRenderer::GetSampleCount(Out<u32> out_sample_count) {
57 *out_sample_count = impl->GetSystem().GetSampleCount();
58 LOG_DEBUG(Service_Audio, "called. Sample count {}", *out_sample_count);
59 R_SUCCEED();
60}
61
62Result IAudioRenderer::GetState(Out<u32> out_state) {
63 *out_state = !impl->GetSystem().IsActive();
64 LOG_DEBUG(Service_Audio, "called, state {}", *out_state);
65 R_SUCCEED();
66}
67
68Result IAudioRenderer::GetMixBufferCount(Out<u32> out_mix_buffer_count) {
69 LOG_DEBUG(Service_Audio, "called");
70 *out_mix_buffer_count = impl->GetSystem().GetMixBufferCount();
71 R_SUCCEED();
72}
73
74Result IAudioRenderer::RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
75 OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
76 InBuffer<BufferAttr_HipcMapAlias> input) {
77 R_RETURN(this->RequestUpdateAuto(out_buffer, out_performance_buffer, input));
78}
79
80Result IAudioRenderer::RequestUpdateAuto(
81 OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
82 OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
83 InBuffer<BufferAttr_HipcAutoSelect> input) {
84 LOG_TRACE(Service_Audio, "called");
85
86 const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
87 if (result.IsFailure()) {
88 LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
89 }
90
91 R_RETURN(result);
92}
93
94Result IAudioRenderer::Start() {
95 LOG_DEBUG(Service_Audio, "called");
96 impl->Start();
97 R_SUCCEED();
98}
99
100Result IAudioRenderer::Stop() {
101 LOG_DEBUG(Service_Audio, "called");
102 impl->Stop();
103 R_SUCCEED();
104}
105
106Result IAudioRenderer::QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
107 LOG_DEBUG(Service_Audio, "called");
108 R_UNLESS(impl->GetSystem().GetExecutionMode() != AudioCore::ExecutionMode::Manual,
109 Audio::ResultNotSupported);
110 *out_event = &rendered_event->GetReadableEvent();
111 R_SUCCEED();
112}
113
114Result IAudioRenderer::SetRenderingTimeLimit(u32 rendering_time_limit) {
115 LOG_DEBUG(Service_Audio, "called");
116 impl->GetSystem().SetRenderingTimeLimit(rendering_time_limit);
117 ;
118 R_SUCCEED();
119}
120
121Result IAudioRenderer::GetRenderingTimeLimit(Out<u32> out_rendering_time_limit) {
122 LOG_DEBUG(Service_Audio, "called");
123 *out_rendering_time_limit = impl->GetSystem().GetRenderingTimeLimit();
124 R_SUCCEED();
125}
126
127Result IAudioRenderer::SetVoiceDropParameter(f32 voice_drop_parameter) {
128 LOG_DEBUG(Service_Audio, "called");
129 impl->GetSystem().SetVoiceDropParameter(voice_drop_parameter);
130 R_SUCCEED();
131}
132
133Result IAudioRenderer::GetVoiceDropParameter(Out<f32> out_voice_drop_parameter) {
134 LOG_DEBUG(Service_Audio, "called");
135 *out_voice_drop_parameter = impl->GetSystem().GetVoiceDropParameter();
136 R_SUCCEED();
137}
138
139} // 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..f25c50ce8
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.h
@@ -0,0 +1,54 @@
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/renderer/audio_renderer.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Kernel {
12class KReadableEvent;
13}
14
15namespace Service::Audio {
16
17class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
18public:
19 explicit IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
20 AudioCore::AudioRendererParameterInternal& params,
21 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
22 Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
23 s32 session_id);
24 ~IAudioRenderer() override;
25
26private:
27 Result GetSampleRate(Out<u32> out_sample_rate);
28 Result GetSampleCount(Out<u32> out_sample_count);
29 Result GetState(Out<u32> out_state);
30 Result GetMixBufferCount(Out<u32> out_mix_buffer_count);
31 Result RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
32 OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
33 InBuffer<BufferAttr_HipcMapAlias> input);
34 Result RequestUpdateAuto(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
35 OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
36 InBuffer<BufferAttr_HipcAutoSelect> input);
37 Result Start();
38 Result Stop();
39 Result QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
40 Result SetRenderingTimeLimit(u32 rendering_time_limit);
41 Result GetRenderingTimeLimit(Out<u32> out_rendering_time_limit);
42 Result SetVoiceDropParameter(f32 voice_drop_parameter);
43 Result GetVoiceDropParameter(Out<f32> out_voice_drop_parameter);
44
45 KernelHelpers::ServiceContext service_context;
46 Kernel::KEvent* rendered_event;
47 AudioCore::Renderer::Manager& manager;
48 std::unique_ptr<AudioCore::Renderer::Renderer> impl;
49 Kernel::KProcess* process_handle;
50 Common::ScratchBuffer<u8> output_buffer;
51 Common::ScratchBuffer<u8> performance_buffer;
52};
53
54} // 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..6a1345c07
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer_manager.cpp
@@ -0,0 +1,104 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "audio_core/audio_render_manager.h"
5#include "audio_core/common/feature_support.h"
6#include "core/hle/kernel/k_process.h"
7#include "core/hle/kernel/k_transfer_memory.h"
8#include "core/hle/service/audio/audio_device.h"
9#include "core/hle/service/audio/audio_renderer.h"
10#include "core/hle/service/audio/audio_renderer_manager.h"
11#include "core/hle/service/cmif_serialization.h"
12
13namespace Service::Audio {
14
15using namespace AudioCore::Renderer;
16
17IAudioRendererManager::IAudioRendererManager(Core::System& system_)
18 : ServiceFramework{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
19 // clang-format off
20 static const FunctionInfo functions[] = {
21 {0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"},
22 {1, D<&IAudioRendererManager::GetWorkBufferSize>, "GetWorkBufferSize"},
23 {2, D<&IAudioRendererManager::GetAudioDeviceService>, "GetAudioDeviceService"},
24 {3, nullptr, "OpenAudioRendererForManualExecution"},
25 {4, D<&IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo>, "GetAudioDeviceServiceWithRevisionInfo"},
26 };
27 // clang-format on
28
29 RegisterHandlers(functions);
30}
31
32IAudioRendererManager::~IAudioRendererManager() = default;
33
34Result IAudioRendererManager::OpenAudioRenderer(
35 Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
36 AudioCore::AudioRendererParameterInternal parameter,
37 InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
38 InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
39 LOG_DEBUG(Service_Audio, "called");
40
41 if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
42 LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
43 R_THROW(Audio::ResultOutOfSessions);
44 }
45
46 const auto session_id{impl->GetSessionId()};
47 if (session_id == -1) {
48 LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
49 R_THROW(Audio::ResultOutOfSessions);
50 }
51
52 LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
53 impl->GetSessionCount());
54
55 *out_audio_renderer =
56 std::make_shared<IAudioRenderer>(system, *impl, parameter, tmem_handle.Get(), tmem_size,
57 process_handle.Get(), aruid.pid, session_id);
58 R_SUCCEED();
59}
60
61Result IAudioRendererManager::GetWorkBufferSize(Out<u64> out_size,
62 AudioCore::AudioRendererParameterInternal params) {
63 LOG_DEBUG(Service_Audio, "called");
64
65 R_TRY(impl->GetWorkBufferSize(params, *out_size))
66
67 std::string output_info{};
68 output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
69 output_info +=
70 fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
71 output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
72 static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
73 output_info += fmt::format(
74 "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
75 "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
76 "Context {:04X}",
77 params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
78 params.splitter_destinations, params.voices, params.perf_frames,
79 params.external_context_size);
80
81 LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
82 output_info, *out_size);
83 R_SUCCEED();
84}
85
86Result IAudioRendererManager::GetAudioDeviceService(
87 Out<SharedPointer<IAudioDevice>> out_audio_device, ClientAppletResourceUserId aruid) {
88 LOG_DEBUG(Service_Audio, "called, aruid={:#x}", aruid.pid);
89 *out_audio_device = std::make_shared<IAudioDevice>(
90 system, aruid.pid, Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
91 R_SUCCEED();
92}
93
94Result IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(
95 Out<SharedPointer<IAudioDevice>> out_audio_device, u32 revision,
96 ClientAppletResourceUserId aruid) {
97 LOG_DEBUG(Service_Audio, "called, revision={} aruid={:#x}", AudioCore::GetRevisionNum(revision),
98 aruid.pid);
99 *out_audio_device =
100 std::make_shared<IAudioDevice>(system, aruid.pid, revision, num_audio_devices++);
101 R_SUCCEED();
102}
103
104} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer_manager.h b/src/core/hle/service/audio/audio_renderer_manager.h
new file mode 100644
index 000000000..69eee664c
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer_manager.h
@@ -0,0 +1,37 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/audio_render_manager.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Service::Audio {
11
12class IAudioDevice;
13class IAudioRenderer;
14
15class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
16public:
17 explicit IAudioRendererManager(Core::System& system_);
18 ~IAudioRendererManager() override;
19
20private:
21 Result OpenAudioRenderer(Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
22 AudioCore::AudioRendererParameterInternal parameter,
23 InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
24 InCopyHandle<Kernel::KProcess> process_handle,
25 ClientAppletResourceUserId aruid);
26 Result GetWorkBufferSize(Out<u64> out_size,
27 AudioCore::AudioRendererParameterInternal parameter);
28 Result GetAudioDeviceService(Out<SharedPointer<IAudioDevice>> out_audio_device,
29 ClientAppletResourceUserId aruid);
30 Result GetAudioDeviceServiceWithRevisionInfo(Out<SharedPointer<IAudioDevice>> out_audio_device,
31 u32 revision, ClientAppletResourceUserId aruid);
32
33 std::unique_ptr<AudioCore::Renderer::Manager> impl;
34 u32 num_audio_devices{0};
35};
36
37} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
deleted file mode 100644
index 8cc7b69f4..000000000
--- a/src/core/hle/service/audio/audout_u.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
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"
14#include "common/swap.h"
15#include "core/core.h"
16#include "core/hle/kernel/k_event.h"
17#include "core/hle/service/audio/audout_u.h"
18#include "core/hle/service/audio/errors.h"
19#include "core/hle/service/ipc_helpers.h"
20#include "core/memory.h"
21
22namespace Service::Audio {
23using namespace AudioCore::AudioOut;
24
25class IAudioOut final : public ServiceFramework<IAudioOut> {
26public:
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
68private:
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
218AudOutU::AudOutU(Core::System& system_)
219 : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"},
220 impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} {
221 // clang-format off
222 static const FunctionInfo functions[] = {
223 {0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
224 {1, &AudOutU::OpenAudioOut, "OpenAudioOut"},
225 {2, &AudOutU::ListAudioOuts, "ListAudioOutsAuto"},
226 {3, &AudOutU::OpenAudioOut, "OpenAudioOutAuto"},
227 };
228 // clang-format on
229
230 RegisterHandlers(functions);
231}
232
233AudOutU::~AudOutU() = default;
234
235void AudOutU::ListAudioOuts(HLERequestContext& ctx) {
236 using namespace AudioCore::Renderer;
237
238 std::scoped_lock l{impl->mutex};
239
240 const auto write_count =
241 static_cast<u32>(ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>());
242 std::vector<AudioDevice::AudioDeviceName> device_names{};
243 if (write_count > 0) {
244 device_names.emplace_back("DeviceOut");
245 LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut");
246 } else {
247 LOG_DEBUG(Service_Audio, "called. Empty buffer passed in.");
248 }
249
250 ctx.WriteBuffer(device_names);
251
252 IPC::ResponseBuilder rb{ctx, 3};
253 rb.Push(ResultSuccess);
254 rb.Push<u32>(static_cast<u32>(device_names.size()));
255}
256
257void AudOutU::OpenAudioOut(HLERequestContext& ctx) {
258 IPC::RequestParser rp{ctx};
259 auto in_params{rp.PopRaw<AudioOutParameter>()};
260 auto applet_resource_user_id{rp.PopRaw<u64>()};
261 const auto device_name_data{ctx.ReadBuffer()};
262 auto device_name = Common::StringFromBuffer(device_name_data);
263 auto handle{ctx.GetCopyHandle(0)};
264
265 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(handle)};
266 if (process.IsNull()) {
267 LOG_ERROR(Service_Audio, "Failed to get process handle");
268 IPC::ResponseBuilder rb{ctx, 2};
269 rb.Push(ResultUnknown);
270 return;
271 }
272
273 auto link{impl->LinkToManager()};
274 if (link.IsError()) {
275 LOG_ERROR(Service_Audio, "Failed to link Audio Out to Audio Manager");
276 IPC::ResponseBuilder rb{ctx, 2};
277 rb.Push(link);
278 return;
279 }
280
281 size_t new_session_id{};
282 auto result{impl->AcquireSessionId(new_session_id)};
283 if (result.IsError()) {
284 IPC::ResponseBuilder rb{ctx, 2};
285 rb.Push(result);
286 return;
287 }
288
289 LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
290 impl->num_free_sessions);
291
292 auto audio_out =
293 std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name, in_params,
294 process.GetPointerUnsafe(), applet_resource_user_id);
295 result = audio_out->GetImpl()->GetSystem().Initialize(
296 device_name, in_params, process.GetPointerUnsafe(), applet_resource_user_id);
297 if (result.IsError()) {
298 LOG_ERROR(Service_Audio, "Failed to initialize the AudioOut System!");
299 IPC::ResponseBuilder rb{ctx, 2};
300 rb.Push(result);
301 return;
302 }
303
304 impl->sessions[new_session_id] = audio_out->GetImpl();
305 impl->applet_resource_user_ids[new_session_id] = applet_resource_user_id;
306
307 auto& out_system = impl->sessions[new_session_id]->GetSystem();
308 AudioOutParameterInternal out_params{.sample_rate = out_system.GetSampleRate(),
309 .channel_count = out_system.GetChannelCount(),
310 .sample_format =
311 static_cast<u32>(out_system.GetSampleFormat()),
312 .state = static_cast<u32>(out_system.GetState())};
313
314 IPC::ResponseBuilder rb{ctx, 6, 0, 1};
315
316 ctx.WriteBuffer(out_system.GetName());
317
318 rb.Push(ResultSuccess);
319 rb.PushRaw<AudioOutParameterInternal>(out_params);
320 rb.PushIpcInterface<IAudioOut>(audio_out);
321}
322
323} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
deleted file mode 100644
index 8f288c6e0..000000000
--- a/src/core/hle/service/audio/audout_u.h
+++ /dev/null
@@ -1,37 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 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.h"
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Core {
12class System;
13}
14
15namespace AudioCore::AudioOut {
16class Manager;
17class Out;
18} // namespace AudioCore::AudioOut
19
20namespace Service::Audio {
21
22class IAudioOut;
23
24class AudOutU final : public ServiceFramework<AudOutU> {
25public:
26 explicit AudOutU(Core::System& system_);
27 ~AudOutU() override;
28
29private:
30 void ListAudioOuts(HLERequestContext& ctx);
31 void OpenAudioOut(HLERequestContext& ctx);
32
33 KernelHelpers::ServiceContext service_context;
34 std::unique_ptr<AudioCore::AudioOut::Manager> impl;
35};
36
37} // namespace Service::Audio
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 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <array>
5#include <memory>
6
7#include "audio_core/audio_core.h"
8#include "audio_core/common/audio_renderer_parameter.h"
9#include "audio_core/common/feature_support.h"
10#include "audio_core/renderer/audio_device.h"
11#include "audio_core/renderer/audio_renderer.h"
12#include "audio_core/renderer/voice/voice_info.h"
13#include "common/alignment.h"
14#include "common/bit_util.h"
15#include "common/common_funcs.h"
16#include "common/logging/log.h"
17#include "common/polyfill_ranges.h"
18#include "common/scratch_buffer.h"
19#include "common/string_util.h"
20#include "core/core.h"
21#include "core/hle/kernel/k_event.h"
22#include "core/hle/kernel/k_process.h"
23#include "core/hle/kernel/k_transfer_memory.h"
24#include "core/hle/service/audio/audren_u.h"
25#include "core/hle/service/audio/errors.h"
26#include "core/hle/service/ipc_helpers.h"
27#include "core/memory.h"
28
29using namespace AudioCore::Renderer;
30
31namespace Service::Audio {
32
33class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
34public:
35 explicit IAudioRenderer(Core::System& system_, Manager& manager_,
36 AudioCore::AudioRendererParameterInternal& params,
37 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
38 u32 process_handle, Kernel::KProcess& process_,
39 u64 applet_resource_user_id, s32 session_id)
40 : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
41 rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
42 impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
43 // clang-format off
44 static const FunctionInfo functions[] = {
45 {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
46 {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
47 {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
48 {3, &IAudioRenderer::GetState, "GetState"},
49 {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
50 {5, &IAudioRenderer::Start, "Start"},
51 {6, &IAudioRenderer::Stop, "Stop"},
52 {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
53 {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
54 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
55 {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
56 {11, nullptr, "ExecuteAudioRendererRendering"},
57 {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
58 {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
59 };
60 // clang-format on
61 RegisterHandlers(functions);
62
63 process.Open();
64 impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
65 applet_resource_user_id, session_id);
66 }
67
68 ~IAudioRenderer() override {
69 impl->Finalize();
70 service_context.CloseEvent(rendered_event);
71 process.Close();
72 }
73
74private:
75 void GetSampleRate(HLERequestContext& ctx) {
76 const auto sample_rate{impl->GetSystem().GetSampleRate()};
77
78 LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
79
80 IPC::ResponseBuilder rb{ctx, 3};
81 rb.Push(ResultSuccess);
82 rb.Push(sample_rate);
83 }
84
85 void GetSampleCount(HLERequestContext& ctx) {
86 const auto sample_count{impl->GetSystem().GetSampleCount()};
87
88 LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
89
90 IPC::ResponseBuilder rb{ctx, 3};
91 rb.Push(ResultSuccess);
92 rb.Push(sample_count);
93 }
94
95 void GetState(HLERequestContext& ctx) {
96 const u32 state{!impl->GetSystem().IsActive()};
97
98 LOG_DEBUG(Service_Audio, "called, state {}", state);
99
100 IPC::ResponseBuilder rb{ctx, 3};
101 rb.Push(ResultSuccess);
102 rb.Push(state);
103 }
104
105 void GetMixBufferCount(HLERequestContext& ctx) {
106 LOG_DEBUG(Service_Audio, "called");
107
108 const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
109
110 IPC::ResponseBuilder rb{ctx, 3};
111 rb.Push(ResultSuccess);
112 rb.Push(buffer_count);
113 }
114
115 void RequestUpdate(HLERequestContext& ctx) {
116 LOG_TRACE(Service_Audio, "called");
117
118 const auto input{ctx.ReadBuffer(0)};
119
120 // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
121 // checking size 0. Performance size is 0 for most games.
122
123 auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
124 if (is_buffer_b) {
125 const auto buffersB{ctx.BufferDescriptorB()};
126 output_buffer.resize_destructive(buffersB[0].Size());
127 performance_buffer.resize_destructive(buffersB[1].Size());
128 } else {
129 const auto buffersC{ctx.BufferDescriptorC()};
130 output_buffer.resize_destructive(buffersC[0].Size());
131 performance_buffer.resize_destructive(buffersC[1].Size());
132 }
133
134 auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
135
136 if (result.IsSuccess()) {
137 if (is_buffer_b) {
138 ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
139 ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
140 } else {
141 ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
142 ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
143 }
144 } else {
145 LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!",
146 result.GetDescription());
147 }
148
149 IPC::ResponseBuilder rb{ctx, 2};
150 rb.Push(result);
151 }
152
153 void Start(HLERequestContext& ctx) {
154 LOG_DEBUG(Service_Audio, "called");
155
156 impl->Start();
157
158 IPC::ResponseBuilder rb{ctx, 2};
159 rb.Push(ResultSuccess);
160 }
161
162 void Stop(HLERequestContext& ctx) {
163 LOG_DEBUG(Service_Audio, "called");
164
165 impl->Stop();
166
167 IPC::ResponseBuilder rb{ctx, 2};
168 rb.Push(ResultSuccess);
169 }
170
171 void QuerySystemEvent(HLERequestContext& ctx) {
172 LOG_DEBUG(Service_Audio, "called");
173
174 if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
175 IPC::ResponseBuilder rb{ctx, 2};
176 rb.Push(Audio::ResultNotSupported);
177 return;
178 }
179
180 IPC::ResponseBuilder rb{ctx, 2, 1};
181 rb.Push(ResultSuccess);
182 rb.PushCopyObjects(rendered_event->GetReadableEvent());
183 }
184
185 void SetRenderingTimeLimit(HLERequestContext& ctx) {
186 LOG_DEBUG(Service_Audio, "called");
187
188 IPC::RequestParser rp{ctx};
189 auto limit = rp.PopRaw<u32>();
190
191 auto& system_ = impl->GetSystem();
192 system_.SetRenderingTimeLimit(limit);
193
194 IPC::ResponseBuilder rb{ctx, 2};
195 rb.Push(ResultSuccess);
196 }
197
198 void GetRenderingTimeLimit(HLERequestContext& ctx) {
199 LOG_DEBUG(Service_Audio, "called");
200
201 auto& system_ = impl->GetSystem();
202 auto time = system_.GetRenderingTimeLimit();
203
204 IPC::ResponseBuilder rb{ctx, 3};
205 rb.Push(ResultSuccess);
206 rb.Push(time);
207 }
208
209 void ExecuteAudioRendererRendering(HLERequestContext& ctx) {
210 LOG_DEBUG(Service_Audio, "called");
211 }
212
213 void SetVoiceDropParameter(HLERequestContext& ctx) {
214 LOG_DEBUG(Service_Audio, "called");
215
216 IPC::RequestParser rp{ctx};
217 auto voice_drop_param{rp.Pop<f32>()};
218
219 auto& system_ = impl->GetSystem();
220 system_.SetVoiceDropParameter(voice_drop_param);
221
222 IPC::ResponseBuilder rb{ctx, 2};
223 rb.Push(ResultSuccess);
224 }
225
226 void GetVoiceDropParameter(HLERequestContext& ctx) {
227 LOG_DEBUG(Service_Audio, "called");
228
229 auto& system_ = impl->GetSystem();
230 auto voice_drop_param{system_.GetVoiceDropParameter()};
231
232 IPC::ResponseBuilder rb{ctx, 3};
233 rb.Push(ResultSuccess);
234 rb.Push(voice_drop_param);
235 }
236
237 KernelHelpers::ServiceContext service_context;
238 Kernel::KEvent* rendered_event;
239 Manager& manager;
240 std::unique_ptr<Renderer> impl;
241 Kernel::KProcess& process;
242 Common::ScratchBuffer<u8> output_buffer;
243 Common::ScratchBuffer<u8> performance_buffer;
244};
245
246class IAudioDevice final : public ServiceFramework<IAudioDevice> {
247
248public:
249 explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
250 u32 device_num)
251 : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
252 impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
253 event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
254 static const FunctionInfo functions[] = {
255 {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
256 {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
257 {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
258 {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
259 {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
260 {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
261 {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
262 {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
263 {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
264 {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
265 {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
266 {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
267 {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
268 {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
269 };
270 RegisterHandlers(functions);
271
272 event->Signal();
273 }
274
275 ~IAudioDevice() override {
276 service_context.CloseEvent(event);
277 }
278
279private:
280 void ListAudioDeviceName(HLERequestContext& ctx) {
281 const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
282
283 std::vector<AudioDevice::AudioDeviceName> out_names{};
284
285 const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
286
287 std::string out{};
288 for (u32 i = 0; i < out_count; i++) {
289 std::string a{};
290 u32 j = 0;
291 while (out_names[i].name[j] != '\0') {
292 a += out_names[i].name[j];
293 j++;
294 }
295 out += "\n\t" + a;
296 }
297
298 LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
299
300 IPC::ResponseBuilder rb{ctx, 3};
301
302 ctx.WriteBuffer(out_names);
303
304 rb.Push(ResultSuccess);
305 rb.Push(out_count);
306 }
307
308 void SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
309 IPC::RequestParser rp{ctx};
310 const f32 volume = rp.Pop<f32>();
311
312 const auto device_name_buffer = ctx.ReadBuffer();
313 const std::string name = Common::StringFromBuffer(device_name_buffer);
314
315 LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
316
317 if (name == "AudioTvOutput") {
318 impl->SetDeviceVolumes(volume);
319 }
320
321 IPC::ResponseBuilder rb{ctx, 2};
322 rb.Push(ResultSuccess);
323 }
324
325 void GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
326 const auto device_name_buffer = ctx.ReadBuffer();
327 const std::string name = Common::StringFromBuffer(device_name_buffer);
328
329 LOG_DEBUG(Service_Audio, "called. Name={}", name);
330
331 f32 volume{1.0f};
332 if (name == "AudioTvOutput") {
333 volume = impl->GetDeviceVolume(name);
334 }
335
336 IPC::ResponseBuilder rb{ctx, 3};
337 rb.Push(ResultSuccess);
338 rb.Push(volume);
339 }
340
341 void GetActiveAudioDeviceName(HLERequestContext& ctx) {
342 const auto write_size = ctx.GetWriteBufferSize();
343 std::string out_name{"AudioTvOutput"};
344
345 LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
346
347 out_name.resize(write_size);
348
349 ctx.WriteBuffer(out_name);
350
351 IPC::ResponseBuilder rb{ctx, 2};
352 rb.Push(ResultSuccess);
353 }
354
355 void QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
356 LOG_DEBUG(Service_Audio, "(STUBBED) called");
357
358 event->Signal();
359
360 IPC::ResponseBuilder rb{ctx, 2, 1};
361 rb.Push(ResultSuccess);
362 rb.PushCopyObjects(event->GetReadableEvent());
363 }
364
365 void GetActiveChannelCount(HLERequestContext& ctx) {
366 const auto& sink{system.AudioCore().GetOutputSink()};
367 u32 channel_count{sink.GetSystemChannels()};
368
369 LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
370
371 IPC::ResponseBuilder rb{ctx, 3};
372
373 rb.Push(ResultSuccess);
374 rb.Push<u32>(channel_count);
375 }
376
377 void QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
378 LOG_DEBUG(Service_Audio, "(STUBBED) called");
379
380 IPC::ResponseBuilder rb{ctx, 2, 1};
381 rb.Push(ResultSuccess);
382 rb.PushCopyObjects(event->GetReadableEvent());
383 }
384
385 void QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
386 LOG_DEBUG(Service_Audio, "called");
387
388 IPC::ResponseBuilder rb{ctx, 2, 1};
389 rb.Push(ResultSuccess);
390 rb.PushCopyObjects(event->GetReadableEvent());
391 }
392
393 void ListAudioOutputDeviceName(HLERequestContext& ctx) {
394 const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
395
396 std::vector<AudioDevice::AudioDeviceName> out_names{};
397
398 const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
399
400 std::string out{};
401 for (u32 i = 0; i < out_count; i++) {
402 std::string a{};
403 u32 j = 0;
404 while (out_names[i].name[j] != '\0') {
405 a += out_names[i].name[j];
406 j++;
407 }
408 out += "\n\t" + a;
409 }
410
411 LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
412
413 IPC::ResponseBuilder rb{ctx, 3};
414
415 ctx.WriteBuffer(out_names);
416
417 rb.Push(ResultSuccess);
418 rb.Push(out_count);
419 }
420
421 KernelHelpers::ServiceContext service_context;
422 std::unique_ptr<AudioDevice> impl;
423 Kernel::KEvent* event;
424};
425
426AudRenU::AudRenU(Core::System& system_)
427 : ServiceFramework{system_, "audren:u"},
428 service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
429 // clang-format off
430 static const FunctionInfo functions[] = {
431 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
432 {1, &AudRenU::GetWorkBufferSize, "GetWorkBufferSize"},
433 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
434 {3, nullptr, "OpenAudioRendererForManualExecution"},
435 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
436 };
437 // clang-format on
438
439 RegisterHandlers(functions);
440}
441
442AudRenU::~AudRenU() = default;
443
444void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
445 IPC::RequestParser rp{ctx};
446
447 AudioCore::AudioRendererParameterInternal params;
448 rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
449 rp.Skip(1, false);
450 auto transfer_memory_size = rp.Pop<u64>();
451 auto applet_resource_user_id = rp.Pop<u64>();
452 auto transfer_memory_handle = ctx.GetCopyHandle(0);
453 auto process_handle = ctx.GetCopyHandle(1);
454
455 if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
456 LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
457 IPC::ResponseBuilder rb{ctx, 2};
458 rb.Push(Audio::ResultOutOfSessions);
459 return;
460 }
461
462 auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
463 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
464
465 const auto session_id{impl->GetSessionId()};
466 if (session_id == -1) {
467 LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
468 IPC::ResponseBuilder rb{ctx, 2};
469 rb.Push(Audio::ResultOutOfSessions);
470 return;
471 }
472
473 LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
474 impl->GetSessionCount());
475
476 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
477 rb.Push(ResultSuccess);
478 rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
479 transfer_memory_size, process_handle, *process,
480 applet_resource_user_id, session_id);
481}
482
483void AudRenU::GetWorkBufferSize(HLERequestContext& ctx) {
484 AudioCore::AudioRendererParameterInternal params;
485
486 IPC::RequestParser rp{ctx};
487 rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
488
489 u64 size{0};
490 auto result = impl->GetWorkBufferSize(params, size);
491
492 std::string output_info{};
493 output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
494 output_info +=
495 fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
496 output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
497 static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
498 output_info += fmt::format(
499 "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
500 "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
501 "Context {:04X}",
502 params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
503 params.splitter_destinations, params.voices, params.perf_frames,
504 params.external_context_size);
505
506 LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
507 output_info, size);
508
509 IPC::ResponseBuilder rb{ctx, 4};
510 rb.Push(result);
511 rb.Push<u64>(size);
512}
513
514void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
515 IPC::RequestParser rp{ctx};
516
517 const auto applet_resource_user_id = rp.Pop<u64>();
518
519 LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
520
521 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
522
523 rb.Push(ResultSuccess);
524 rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
525 ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
526}
527
528void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
529 LOG_ERROR(Service_Audio, "called. Implement me!");
530}
531
532void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
533 struct Parameters {
534 u32 revision;
535 u64 applet_resource_user_id;
536 };
537
538 IPC::RequestParser rp{ctx};
539
540 const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
541
542 LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
543 AudioCore::GetRevisionNum(revision), applet_resource_user_id);
544
545 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
546
547 rb.Push(ResultSuccess);
548 rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
549 num_audio_devices++);
550}
551
552} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
deleted file mode 100644
index 3d7993a16..000000000
--- a/src/core/hle/service/audio/audren_u.h
+++ /dev/null
@@ -1,35 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/audio_render_manager.h"
7#include "common/scratch_buffer.h"
8#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h"
10
11namespace Core {
12class System;
13}
14
15namespace Service::Audio {
16class IAudioRenderer;
17
18class AudRenU final : public ServiceFramework<AudRenU> {
19public:
20 explicit AudRenU(Core::System& system_);
21 ~AudRenU() override;
22
23private:
24 void OpenAudioRenderer(HLERequestContext& ctx);
25 void GetWorkBufferSize(HLERequestContext& ctx);
26 void GetAudioDeviceService(HLERequestContext& ctx);
27 void OpenAudioRendererForManualExecution(HLERequestContext& ctx);
28 void GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx);
29
30 KernelHelpers::ServiceContext service_context;
31 std::unique_ptr<AudioCore::Renderer::Manager> impl;
32 u32 num_audio_devices{0};
33};
34
35} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/final_output_recorder_manager.cpp
index bc55cec17..f70a0e62d 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/final_output_recorder_manager.cpp
@@ -1,7 +1,7 @@
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 "core/hle/service/audio/audrec_u.h" 4#include "core/hle/service/audio/final_output_recorder_manager.h"
5 5
6namespace Service::Audio { 6namespace Service::Audio {
7 7
@@ -30,13 +30,14 @@ public:
30 } 30 }
31}; 31};
32 32
33AudRecU::AudRecU(Core::System& system_) : ServiceFramework{system_, "audrec:u"} { 33IFinalOutputRecorderManager::IFinalOutputRecorderManager(Core::System& system_)
34 : ServiceFramework{system_, "audrec:u"} {
34 static const FunctionInfo functions[] = { 35 static const FunctionInfo functions[] = {
35 {0, nullptr, "OpenFinalOutputRecorder"}, 36 {0, nullptr, "OpenFinalOutputRecorder"},
36 }; 37 };
37 RegisterHandlers(functions); 38 RegisterHandlers(functions);
38} 39}
39 40
40AudRecU::~AudRecU() = default; 41IFinalOutputRecorderManager::~IFinalOutputRecorderManager() = default;
41 42
42} // namespace Service::Audio 43} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.h b/src/core/hle/service/audio/final_output_recorder_manager.h
index 9edf89f6c..0663b894e 100644
--- a/src/core/hle/service/audio/audrec_a.h
+++ b/src/core/hle/service/audio/final_output_recorder_manager.h
@@ -11,10 +11,10 @@ class System;
11 11
12namespace Service::Audio { 12namespace Service::Audio {
13 13
14class AudRecA final : public ServiceFramework<AudRecA> { 14class IFinalOutputRecorderManager final : public ServiceFramework<IFinalOutputRecorderManager> {
15public: 15public:
16 explicit AudRecA(Core::System& system_); 16 explicit IFinalOutputRecorderManager(Core::System& system_);
17 ~AudRecA() override; 17 ~IFinalOutputRecorderManager() override;
18}; 18};
19 19
20} // namespace Service::Audio 20} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp
index fa82e9ac7..7e2e42bbe 100644
--- a/src/core/hle/service/audio/audrec_a.cpp
+++ b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp
@@ -1,11 +1,12 @@
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 "core/hle/service/audio/audrec_a.h" 4#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
5 5
6namespace Service::Audio { 6namespace Service::Audio {
7 7
8AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} { 8IFinalOutputRecorderManagerForApplet::IFinalOutputRecorderManagerForApplet(Core::System& system_)
9 : ServiceFramework{system_, "audrec:a"} {
9 // clang-format off 10 // clang-format off
10 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
11 {0, nullptr, "RequestSuspend"}, 12 {0, nullptr, "RequestSuspend"},
@@ -16,6 +17,6 @@ AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"}
16 RegisterHandlers(functions); 17 RegisterHandlers(functions);
17} 18}
18 19
19AudRecA::~AudRecA() = default; 20IFinalOutputRecorderManagerForApplet::~IFinalOutputRecorderManagerForApplet() = default;
20 21
21} // namespace Service::Audio 22} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_u.h b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.h
index 8b4817884..27940f7e0 100644
--- a/src/core/hle/service/audio/audrec_u.h
+++ b/src/core/hle/service/audio/final_output_recorder_manager_for_applet.h
@@ -11,10 +11,11 @@ class System;
11 11
12namespace Service::Audio { 12namespace Service::Audio {
13 13
14class AudRecU final : public ServiceFramework<AudRecU> { 14class IFinalOutputRecorderManagerForApplet final
15 : public ServiceFramework<IFinalOutputRecorderManagerForApplet> {
15public: 16public:
16 explicit AudRecU(Core::System& system_); 17 explicit IFinalOutputRecorderManagerForApplet(Core::System& system_);
17 ~AudRecU() override; 18 ~IFinalOutputRecorderManagerForApplet() override;
18}; 19};
19 20
20} // namespace Service::Audio 21} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder.cpp b/src/core/hle/service/audio/hardware_opus_decoder.cpp
new file mode 100644
index 000000000..03d3374c1
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder.cpp
@@ -0,0 +1,145 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/audio/hardware_opus_decoder.h"
5#include "core/hle/service/cmif_serialization.h"
6
7namespace Service::Audio {
8
9using namespace AudioCore::OpusDecoder;
10
11IHardwareOpusDecoder::IHardwareOpusDecoder(Core::System& system_, HardwareOpus& hardware_opus)
12 : ServiceFramework{system_, "IHardwareOpusDecoder"},
13 impl{std::make_unique<AudioCore::OpusDecoder::OpusDecoder>(system_, hardware_opus)} {
14 // clang-format off
15 static const FunctionInfo functions[] = {
16 {0, D<&IHardwareOpusDecoder::DecodeInterleavedOld>, "DecodeInterleavedOld"},
17 {1, D<&IHardwareOpusDecoder::SetContext>, "SetContext"},
18 {2, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld>, "DecodeInterleavedForMultiStreamOld"},
19 {3, D<&IHardwareOpusDecoder::SetContextForMultiStream>, "SetContextForMultiStream"},
20 {4, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfOld>, "DecodeInterleavedWithPerfOld"},
21 {5, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld>, "DecodeInterleavedForMultiStreamWithPerfOld"},
22 {6, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld>, "DecodeInterleavedWithPerfAndResetOld"},
23 {7, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld>, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
24 {8, D<&IHardwareOpusDecoder::DecodeInterleaved>, "DecodeInterleaved"},
25 {9, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStream>, "DecodeInterleavedForMultiStream"},
26 };
27 // clang-format on
28
29 RegisterHandlers(functions);
30}
31
32IHardwareOpusDecoder::~IHardwareOpusDecoder() = default;
33
34Result IHardwareOpusDecoder::Initialize(const OpusParametersEx& params,
35 Kernel::KTransferMemory* transfer_memory,
36 u64 transfer_memory_size) {
37 return impl->Initialize(params, transfer_memory, transfer_memory_size);
38}
39
40Result IHardwareOpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
41 Kernel::KTransferMemory* transfer_memory,
42 u64 transfer_memory_size) {
43 return impl->Initialize(params, transfer_memory, transfer_memory_size);
44}
45
46Result IHardwareOpusDecoder::DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
47 Out<u32> out_data_size, Out<u32> out_sample_count,
48 InBuffer<BufferAttr_HipcMapAlias> opus_data) {
49 R_TRY(impl->DecodeInterleaved(out_data_size, nullptr, out_sample_count, opus_data, out_pcm_data,
50 false));
51 LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
52 *out_sample_count);
53 R_SUCCEED();
54}
55
56Result IHardwareOpusDecoder::SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
57 LOG_DEBUG(Service_Audio, "called");
58 R_RETURN(impl->SetContext(decoder_context));
59}
60
61Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld(
62 OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data, Out<u32> out_data_size,
63 Out<u32> out_sample_count, InBuffer<BufferAttr_HipcMapAlias> opus_data) {
64 R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, nullptr, out_sample_count, opus_data,
65 out_pcm_data, false));
66 LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
67 *out_sample_count);
68 R_SUCCEED();
69}
70
71Result IHardwareOpusDecoder::SetContextForMultiStream(
72 InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
73 LOG_DEBUG(Service_Audio, "called");
74 R_RETURN(impl->SetContext(decoder_context));
75}
76
77Result IHardwareOpusDecoder::DecodeInterleavedWithPerfOld(
78 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
79 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
80 InBuffer<BufferAttr_HipcMapAlias> opus_data) {
81 R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
82 out_pcm_data, false));
83 LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
84 *out_sample_count, *out_time_taken);
85 R_SUCCEED();
86}
87
88Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld(
89 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
90 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
91 InBuffer<BufferAttr_HipcMapAlias> opus_data) {
92 R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
93 opus_data, out_pcm_data, false));
94 LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
95 *out_sample_count, *out_time_taken);
96 R_SUCCEED();
97}
98
99Result IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld(
100 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
101 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
102 InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
103 R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
104 out_pcm_data, reset));
105 LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
106 *out_data_size, *out_sample_count, *out_time_taken);
107 R_SUCCEED();
108}
109
110Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld(
111 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
112 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
113 InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
114 R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
115 opus_data, out_pcm_data, reset));
116 LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
117 *out_data_size, *out_sample_count, *out_time_taken);
118 R_SUCCEED();
119}
120
121Result IHardwareOpusDecoder::DecodeInterleaved(
122 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
123 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
124 InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
125 bool reset) {
126 R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
127 out_pcm_data, reset));
128 LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
129 *out_data_size, *out_sample_count, *out_time_taken);
130 R_SUCCEED();
131}
132
133Result IHardwareOpusDecoder::DecodeInterleavedForMultiStream(
134 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
135 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
136 InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
137 bool reset) {
138 R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
139 opus_data, out_pcm_data, reset));
140 LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
141 *out_data_size, *out_sample_count, *out_time_taken);
142 R_SUCCEED();
143}
144
145} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder.h b/src/core/hle/service/audio/hardware_opus_decoder.h
new file mode 100644
index 000000000..511bf46bd
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder.h
@@ -0,0 +1,63 @@
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/opus/decoder.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Service::Audio {
11
12class IHardwareOpusDecoder final : public ServiceFramework<IHardwareOpusDecoder> {
13public:
14 explicit IHardwareOpusDecoder(Core::System& system_,
15 AudioCore::OpusDecoder::HardwareOpus& hardware_opus);
16 ~IHardwareOpusDecoder() override;
17
18 Result Initialize(const AudioCore::OpusDecoder::OpusParametersEx& params,
19 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
20 Result Initialize(const AudioCore::OpusDecoder::OpusMultiStreamParametersEx& params,
21 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
22
23private:
24 Result DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
25 Out<u32> out_data_size, Out<u32> out_sample_count,
26 InBuffer<BufferAttr_HipcMapAlias> opus_data);
27 Result SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context);
28 Result DecodeInterleavedForMultiStreamOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
29 Out<u32> out_data_size, Out<u32> out_sample_count,
30 InBuffer<BufferAttr_HipcMapAlias> opus_data);
31 Result SetContextForMultiStream(InBuffer<BufferAttr_HipcMapAlias> decoder_context);
32 Result DecodeInterleavedWithPerfOld(
33 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
34 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
35 InBuffer<BufferAttr_HipcMapAlias> opus_data);
36 Result DecodeInterleavedForMultiStreamWithPerfOld(
37 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
38 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
39 InBuffer<BufferAttr_HipcMapAlias> opus_data);
40 Result DecodeInterleavedWithPerfAndResetOld(
41 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
42 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
43 InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset);
44 Result DecodeInterleavedForMultiStreamWithPerfAndResetOld(
45 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
46 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
47 InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset);
48 Result DecodeInterleaved(
49 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
50 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
51 InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
52 bool reset);
53 Result DecodeInterleavedForMultiStream(
54 OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
55 Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
56 InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
57 bool reset);
58
59 std::unique_ptr<AudioCore::OpusDecoder::OpusDecoder> impl;
60 Common::ScratchBuffer<u8> output_data;
61};
62
63} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp b/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
new file mode 100644
index 000000000..9de72e30f
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
@@ -0,0 +1,156 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/audio/hardware_opus_decoder.h"
5#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
6#include "core/hle/service/cmif_serialization.h"
7
8namespace Service::Audio {
9
10using namespace AudioCore::OpusDecoder;
11
12IHardwareOpusDecoderManager::IHardwareOpusDecoderManager(Core::System& system_)
13 : ServiceFramework{system_, "hwopus"}, system{system_}, impl{system} {
14 // clang-format off
15 static const FunctionInfo functions[] = {
16 {0, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoder>, "OpenHardwareOpusDecoder"},
17 {1, D<&IHardwareOpusDecoderManager::GetWorkBufferSize>, "GetWorkBufferSize"},
18 {2, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream>, "OpenOpusDecoderForMultiStream"},
19 {3, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream>, "GetWorkBufferSizeForMultiStream"},
20 {4, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx>, "OpenHardwareOpusDecoderEx"},
21 {5, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeEx>, "GetWorkBufferSizeEx"},
22 {6, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx>, "OpenHardwareOpusDecoderForMultiStreamEx"},
23 {7, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx>, "GetWorkBufferSizeForMultiStreamEx"},
24 {8, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeExEx>, "GetWorkBufferSizeExEx"},
25 {9, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx>, "GetWorkBufferSizeForMultiStreamExEx"},
26 };
27 // clang-format on
28 RegisterHandlers(functions);
29}
30
31IHardwareOpusDecoderManager::~IHardwareOpusDecoderManager() = default;
32
33Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoder(
34 Out<SharedPointer<IHardwareOpusDecoder>> out_decoder, OpusParameters params, u32 tmem_size,
35 InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
36 LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size {:#x}",
37 params.sample_rate, params.channel_count, tmem_size);
38
39 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
40 OpusParametersEx ex{
41 .sample_rate = params.sample_rate,
42 .channel_count = params.channel_count,
43 .use_large_frame_size = false,
44 };
45 R_TRY(decoder->Initialize(ex, tmem_handle.Get(), tmem_size));
46
47 *out_decoder = decoder;
48 R_SUCCEED();
49}
50
51Result IHardwareOpusDecoderManager::GetWorkBufferSize(Out<u32> out_size, OpusParameters params) {
52 R_TRY(impl.GetWorkBufferSize(params, *out_size));
53 LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} -- returned size {:#x}",
54 params.sample_rate, params.channel_count, *out_size);
55 R_SUCCEED();
56}
57
58Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream(
59 Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
60 InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params, u32 tmem_size,
61 InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
62 LOG_DEBUG(Service_Audio,
63 "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
64 "transfer_memory_size {:#x}",
65 params->sample_rate, params->channel_count, params->total_stream_count,
66 params->stereo_stream_count, tmem_size);
67
68 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
69
70 OpusMultiStreamParametersEx ex{
71 .sample_rate = params->sample_rate,
72 .channel_count = params->channel_count,
73 .total_stream_count = params->total_stream_count,
74 .stereo_stream_count = params->stereo_stream_count,
75 .use_large_frame_size = false,
76 .mappings{},
77 };
78 std::memcpy(ex.mappings.data(), params->mappings.data(), sizeof(params->mappings));
79 R_TRY(decoder->Initialize(ex, tmem_handle.Get(), tmem_size));
80
81 *out_decoder = decoder;
82 R_SUCCEED();
83}
84
85Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream(
86 Out<u32> out_size, InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params) {
87 R_TRY(impl.GetWorkBufferSizeForMultiStream(*params, *out_size));
88 LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
89 R_SUCCEED();
90}
91
92Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx(
93 Out<SharedPointer<IHardwareOpusDecoder>> out_decoder, OpusParametersEx params, u32 tmem_size,
94 InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
95 LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size {:#x}",
96 params.sample_rate, params.channel_count, tmem_size);
97
98 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
99 R_TRY(decoder->Initialize(params, tmem_handle.Get(), tmem_size));
100
101 *out_decoder = decoder;
102 R_SUCCEED();
103}
104
105Result IHardwareOpusDecoderManager::GetWorkBufferSizeEx(Out<u32> out_size,
106 OpusParametersEx params) {
107 R_TRY(impl.GetWorkBufferSizeEx(params, *out_size));
108 LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
109 R_SUCCEED();
110}
111
112Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx(
113 Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
114 InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params, u32 tmem_size,
115 InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
116 LOG_DEBUG(Service_Audio,
117 "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
118 "use_large_frame_size {}"
119 "transfer_memory_size {:#x}",
120 params->sample_rate, params->channel_count, params->total_stream_count,
121 params->stereo_stream_count, params->use_large_frame_size, tmem_size);
122
123 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
124
125 R_TRY(decoder->Initialize(*params, tmem_handle.Get(), tmem_size));
126
127 *out_decoder = decoder;
128 R_SUCCEED();
129}
130
131Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
132 Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params) {
133 R_TRY(impl.GetWorkBufferSizeForMultiStreamEx(*params, *out_size));
134 LOG_DEBUG(Service_Audio,
135 "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
136 "use_large_frame_size {} -- returned size {:#x}",
137 params->sample_rate, params->channel_count, params->total_stream_count,
138 params->stereo_stream_count, params->use_large_frame_size, *out_size);
139 R_SUCCEED();
140}
141
142Result IHardwareOpusDecoderManager::GetWorkBufferSizeExEx(Out<u32> out_size,
143 OpusParametersEx params) {
144 R_TRY(impl.GetWorkBufferSizeExEx(params, *out_size));
145 LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
146 R_SUCCEED();
147}
148
149Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
150 Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params) {
151 R_TRY(impl.GetWorkBufferSizeForMultiStreamExEx(*params, *out_size));
152 LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
153 R_SUCCEED();
154}
155
156} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hardware_opus_decoder_manager.h b/src/core/hle/service/audio/hardware_opus_decoder_manager.h
new file mode 100644
index 000000000..4f869c517
--- /dev/null
+++ b/src/core/hle/service/audio/hardware_opus_decoder_manager.h
@@ -0,0 +1,53 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/opus/decoder_manager.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Service::Audio {
11
12class IHardwareOpusDecoder;
13
14using AudioCore::OpusDecoder::OpusMultiStreamParameters;
15using AudioCore::OpusDecoder::OpusMultiStreamParametersEx;
16using AudioCore::OpusDecoder::OpusParameters;
17using AudioCore::OpusDecoder::OpusParametersEx;
18
19class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
20public:
21 explicit IHardwareOpusDecoderManager(Core::System& system_);
22 ~IHardwareOpusDecoderManager() override;
23
24private:
25 Result OpenHardwareOpusDecoder(Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
26 OpusParameters params, u32 tmem_size,
27 InCopyHandle<Kernel::KTransferMemory> tmem_handle);
28 Result GetWorkBufferSize(Out<u32> out_size, OpusParameters params);
29 Result OpenHardwareOpusDecoderForMultiStream(
30 Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
31 InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params, u32 tmem_size,
32 InCopyHandle<Kernel::KTransferMemory> tmem_handle);
33 Result GetWorkBufferSizeForMultiStream(
34 Out<u32> out_size, InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params);
35 Result OpenHardwareOpusDecoderEx(Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
36 OpusParametersEx params, u32 tmem_size,
37 InCopyHandle<Kernel::KTransferMemory> tmem_handle);
38 Result GetWorkBufferSizeEx(Out<u32> out_size, OpusParametersEx params);
39 Result OpenHardwareOpusDecoderForMultiStreamEx(
40 Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
41 InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params, u32 tmem_size,
42 InCopyHandle<Kernel::KTransferMemory> tmem_handle);
43 Result GetWorkBufferSizeForMultiStreamEx(
44 Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params);
45 Result GetWorkBufferSizeExEx(Out<u32> out_size, OpusParametersEx params);
46 Result GetWorkBufferSizeForMultiStreamExEx(
47 Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params);
48
49 Core::System& system;
50 AudioCore::OpusDecoder::OpusDecoderManager impl;
51};
52
53} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
deleted file mode 100644
index 91f33aabd..000000000
--- a/src/core/hle/service/audio/hwopus.cpp
+++ /dev/null
@@ -1,502 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <memory>
5#include <vector>
6
7#include "audio_core/opus/decoder.h"
8#include "audio_core/opus/parameters.h"
9#include "common/assert.h"
10#include "common/logging/log.h"
11#include "common/scratch_buffer.h"
12#include "core/core.h"
13#include "core/hle/service/audio/hwopus.h"
14#include "core/hle/service/ipc_helpers.h"
15
16namespace Service::Audio {
17using namespace AudioCore::OpusDecoder;
18
19class IHardwareOpusDecoder final : public ServiceFramework<IHardwareOpusDecoder> {
20public:
21 explicit IHardwareOpusDecoder(Core::System& system_, HardwareOpus& hardware_opus)
22 : ServiceFramework{system_, "IHardwareOpusDecoder"},
23 impl{std::make_unique<AudioCore::OpusDecoder::OpusDecoder>(system_, hardware_opus)} {
24 // clang-format off
25 static const FunctionInfo functions[] = {
26 {0, &IHardwareOpusDecoder::DecodeInterleavedOld, "DecodeInterleavedOld"},
27 {1, &IHardwareOpusDecoder::SetContext, "SetContext"},
28 {2, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld, "DecodeInterleavedForMultiStreamOld"},
29 {3, &IHardwareOpusDecoder::SetContextForMultiStream, "SetContextForMultiStream"},
30 {4, &IHardwareOpusDecoder::DecodeInterleavedWithPerfOld, "DecodeInterleavedWithPerfOld"},
31 {5, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld, "DecodeInterleavedForMultiStreamWithPerfOld"},
32 {6, &IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld, "DecodeInterleavedWithPerfAndResetOld"},
33 {7, &IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
34 {8, &IHardwareOpusDecoder::DecodeInterleaved, "DecodeInterleaved"},
35 {9, &IHardwareOpusDecoder::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
36 };
37 // clang-format on
38
39 RegisterHandlers(functions);
40 }
41
42 Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
43 u64 transfer_memory_size) {
44 return impl->Initialize(params, transfer_memory, transfer_memory_size);
45 }
46
47 Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
48 u64 transfer_memory_size) {
49 return impl->Initialize(params, transfer_memory, transfer_memory_size);
50 }
51
52private:
53 void DecodeInterleavedOld(HLERequestContext& ctx) {
54 IPC::RequestParser rp{ctx};
55
56 auto input_data{ctx.ReadBuffer(0)};
57 output_data.resize_destructive(ctx.GetWriteBufferSize());
58
59 u32 size{};
60 u32 sample_count{};
61 auto result =
62 impl->DecodeInterleaved(&size, nullptr, &sample_count, input_data, output_data, false);
63
64 LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {}", size, sample_count);
65
66 ctx.WriteBuffer(output_data);
67
68 IPC::ResponseBuilder rb{ctx, 4};
69 rb.Push(result);
70 rb.Push(size);
71 rb.Push(sample_count);
72 }
73
74 void SetContext(HLERequestContext& ctx) {
75 IPC::RequestParser rp{ctx};
76
77 LOG_DEBUG(Service_Audio, "called");
78
79 auto input_data{ctx.ReadBuffer(0)};
80 auto result = impl->SetContext(input_data);
81
82 IPC::ResponseBuilder rb{ctx, 2};
83 rb.Push(result);
84 }
85
86 void DecodeInterleavedForMultiStreamOld(HLERequestContext& ctx) {
87 IPC::RequestParser rp{ctx};
88
89 auto input_data{ctx.ReadBuffer(0)};
90 output_data.resize_destructive(ctx.GetWriteBufferSize());
91
92 u32 size{};
93 u32 sample_count{};
94 auto result = impl->DecodeInterleavedForMultiStream(&size, nullptr, &sample_count,
95 input_data, output_data, false);
96
97 LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {}", size, sample_count);
98
99 ctx.WriteBuffer(output_data);
100
101 IPC::ResponseBuilder rb{ctx, 4};
102 rb.Push(result);
103 rb.Push(size);
104 rb.Push(sample_count);
105 }
106
107 void SetContextForMultiStream(HLERequestContext& ctx) {
108 IPC::RequestParser rp{ctx};
109
110 LOG_DEBUG(Service_Audio, "called");
111
112 auto input_data{ctx.ReadBuffer(0)};
113 auto result = impl->SetContext(input_data);
114
115 IPC::ResponseBuilder rb{ctx, 2};
116 rb.Push(result);
117 }
118
119 void DecodeInterleavedWithPerfOld(HLERequestContext& ctx) {
120 IPC::RequestParser rp{ctx};
121
122 auto input_data{ctx.ReadBuffer(0)};
123 output_data.resize_destructive(ctx.GetWriteBufferSize());
124
125 u32 size{};
126 u32 sample_count{};
127 u64 time_taken{};
128 auto result = impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data,
129 output_data, false);
130
131 LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {} time taken {}", size,
132 sample_count, time_taken);
133
134 ctx.WriteBuffer(output_data);
135
136 IPC::ResponseBuilder rb{ctx, 6};
137 rb.Push(result);
138 rb.Push(size);
139 rb.Push(sample_count);
140 rb.Push(time_taken);
141 }
142
143 void DecodeInterleavedForMultiStreamWithPerfOld(HLERequestContext& ctx) {
144 IPC::RequestParser rp{ctx};
145
146 auto input_data{ctx.ReadBuffer(0)};
147 output_data.resize_destructive(ctx.GetWriteBufferSize());
148
149 u32 size{};
150 u32 sample_count{};
151 u64 time_taken{};
152 auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
153 input_data, output_data, false);
154
155 LOG_DEBUG(Service_Audio, "bytes read 0x{:X} samples generated {} time taken {}", size,
156 sample_count, time_taken);
157
158 ctx.WriteBuffer(output_data);
159
160 IPC::ResponseBuilder rb{ctx, 6};
161 rb.Push(result);
162 rb.Push(size);
163 rb.Push(sample_count);
164 rb.Push(time_taken);
165 }
166
167 void DecodeInterleavedWithPerfAndResetOld(HLERequestContext& ctx) {
168 IPC::RequestParser rp{ctx};
169
170 auto reset{rp.Pop<bool>()};
171
172 auto input_data{ctx.ReadBuffer(0)};
173 output_data.resize_destructive(ctx.GetWriteBufferSize());
174
175 u32 size{};
176 u32 sample_count{};
177 u64 time_taken{};
178 auto result = impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data,
179 output_data, reset);
180
181 LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
182 reset, size, sample_count, time_taken);
183
184 ctx.WriteBuffer(output_data);
185
186 IPC::ResponseBuilder rb{ctx, 6};
187 rb.Push(result);
188 rb.Push(size);
189 rb.Push(sample_count);
190 rb.Push(time_taken);
191 }
192
193 void DecodeInterleavedForMultiStreamWithPerfAndResetOld(HLERequestContext& ctx) {
194 IPC::RequestParser rp{ctx};
195
196 auto reset{rp.Pop<bool>()};
197
198 auto input_data{ctx.ReadBuffer(0)};
199 output_data.resize_destructive(ctx.GetWriteBufferSize());
200
201 u32 size{};
202 u32 sample_count{};
203 u64 time_taken{};
204 auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
205 input_data, output_data, reset);
206
207 LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
208 reset, size, sample_count, time_taken);
209
210 ctx.WriteBuffer(output_data);
211
212 IPC::ResponseBuilder rb{ctx, 6};
213 rb.Push(result);
214 rb.Push(size);
215 rb.Push(sample_count);
216 rb.Push(time_taken);
217 }
218
219 void DecodeInterleaved(HLERequestContext& ctx) {
220 IPC::RequestParser rp{ctx};
221
222 auto reset{rp.Pop<bool>()};
223
224 auto input_data{ctx.ReadBuffer(0)};
225 output_data.resize_destructive(ctx.GetWriteBufferSize());
226
227 u32 size{};
228 u32 sample_count{};
229 u64 time_taken{};
230 auto result = impl->DecodeInterleaved(&size, &time_taken, &sample_count, input_data,
231 output_data, reset);
232
233 LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
234 reset, size, sample_count, time_taken);
235
236 ctx.WriteBuffer(output_data);
237
238 IPC::ResponseBuilder rb{ctx, 6};
239 rb.Push(result);
240 rb.Push(size);
241 rb.Push(sample_count);
242 rb.Push(time_taken);
243 }
244
245 void DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
246 IPC::RequestParser rp{ctx};
247
248 auto reset{rp.Pop<bool>()};
249
250 auto input_data{ctx.ReadBuffer(0)};
251 output_data.resize_destructive(ctx.GetWriteBufferSize());
252
253 u32 size{};
254 u32 sample_count{};
255 u64 time_taken{};
256 auto result = impl->DecodeInterleavedForMultiStream(&size, &time_taken, &sample_count,
257 input_data, output_data, reset);
258
259 LOG_DEBUG(Service_Audio, "reset {} bytes read 0x{:X} samples generated {} time taken {}",
260 reset, size, sample_count, time_taken);
261
262 ctx.WriteBuffer(output_data);
263
264 IPC::ResponseBuilder rb{ctx, 6};
265 rb.Push(result);
266 rb.Push(size);
267 rb.Push(sample_count);
268 rb.Push(time_taken);
269 }
270
271 std::unique_ptr<AudioCore::OpusDecoder::OpusDecoder> impl;
272 Common::ScratchBuffer<u8> output_data;
273};
274
275void HwOpus::OpenHardwareOpusDecoder(HLERequestContext& ctx) {
276 IPC::RequestParser rp{ctx};
277
278 auto params = rp.PopRaw<OpusParameters>();
279 auto transfer_memory_size{rp.Pop<u32>()};
280 auto transfer_memory_handle{ctx.GetCopyHandle(0)};
281 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
282
283 LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
284 params.sample_rate, params.channel_count, transfer_memory_size);
285
286 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
287
288 OpusParametersEx ex{
289 .sample_rate = params.sample_rate,
290 .channel_count = params.channel_count,
291 .use_large_frame_size = false,
292 };
293 auto result = decoder->Initialize(ex, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
294
295 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
296 rb.Push(result);
297 rb.PushIpcInterface(decoder);
298}
299
300void HwOpus::GetWorkBufferSize(HLERequestContext& ctx) {
301 IPC::RequestParser rp{ctx};
302 auto params = rp.PopRaw<OpusParameters>();
303
304 u64 size{};
305 auto result = impl.GetWorkBufferSize(params, size);
306
307 LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} -- returned size 0x{:X}",
308 params.sample_rate, params.channel_count, size);
309
310 IPC::ResponseBuilder rb{ctx, 4};
311 rb.Push(result);
312 rb.Push(size);
313}
314
315void HwOpus::OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx) {
316 IPC::RequestParser rp{ctx};
317
318 auto input{ctx.ReadBuffer()};
319 OpusMultiStreamParameters params;
320 std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParameters));
321
322 auto transfer_memory_size{rp.Pop<u32>()};
323 auto transfer_memory_handle{ctx.GetCopyHandle(0)};
324 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
325
326 LOG_DEBUG(Service_Audio,
327 "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
328 "transfer_memory_size 0x{:X}",
329 params.sample_rate, params.channel_count, params.total_stream_count,
330 params.stereo_stream_count, transfer_memory_size);
331
332 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
333
334 OpusMultiStreamParametersEx ex{
335 .sample_rate = params.sample_rate,
336 .channel_count = params.channel_count,
337 .total_stream_count = params.total_stream_count,
338 .stereo_stream_count = params.stereo_stream_count,
339 .use_large_frame_size = false,
340 .mappings{},
341 };
342 std::memcpy(ex.mappings.data(), params.mappings.data(), sizeof(params.mappings));
343 auto result = decoder->Initialize(ex, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
344
345 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
346 rb.Push(result);
347 rb.PushIpcInterface(decoder);
348}
349
350void HwOpus::GetWorkBufferSizeForMultiStream(HLERequestContext& ctx) {
351 IPC::RequestParser rp{ctx};
352
353 auto input{ctx.ReadBuffer()};
354 OpusMultiStreamParameters params;
355 std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParameters));
356
357 u64 size{};
358 auto result = impl.GetWorkBufferSizeForMultiStream(params, size);
359
360 LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
361
362 IPC::ResponseBuilder rb{ctx, 4};
363 rb.Push(result);
364 rb.Push(size);
365}
366
367void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
368 IPC::RequestParser rp{ctx};
369
370 auto params = rp.PopRaw<OpusParametersEx>();
371 auto transfer_memory_size{rp.Pop<u32>()};
372 auto transfer_memory_handle{ctx.GetCopyHandle(0)};
373 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
374
375 LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}",
376 params.sample_rate, params.channel_count, transfer_memory_size);
377
378 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
379
380 auto result =
381 decoder->Initialize(params, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
382
383 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
384 rb.Push(result);
385 rb.PushIpcInterface(decoder);
386}
387
388void HwOpus::GetWorkBufferSizeEx(HLERequestContext& ctx) {
389 IPC::RequestParser rp{ctx};
390 auto params = rp.PopRaw<OpusParametersEx>();
391
392 u64 size{};
393 auto result = impl.GetWorkBufferSizeEx(params, size);
394
395 LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
396
397 IPC::ResponseBuilder rb{ctx, 4};
398 rb.Push(result);
399 rb.Push(size);
400}
401
402void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
403 IPC::RequestParser rp{ctx};
404
405 auto input{ctx.ReadBuffer()};
406 OpusMultiStreamParametersEx params;
407 std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
408
409 auto transfer_memory_size{rp.Pop<u32>()};
410 auto transfer_memory_handle{ctx.GetCopyHandle(0)};
411 auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
412
413 LOG_DEBUG(Service_Audio,
414 "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
415 "use_large_frame_size {}"
416 "transfer_memory_size 0x{:X}",
417 params.sample_rate, params.channel_count, params.total_stream_count,
418 params.stereo_stream_count, params.use_large_frame_size, transfer_memory_size);
419
420 auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
421
422 auto result =
423 decoder->Initialize(params, transfer_memory.GetPointerUnsafe(), transfer_memory_size);
424
425 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
426 rb.Push(result);
427 rb.PushIpcInterface(decoder);
428}
429
430void HwOpus::GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx) {
431 IPC::RequestParser rp{ctx};
432
433 auto input{ctx.ReadBuffer()};
434 OpusMultiStreamParametersEx params;
435 std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
436
437 u64 size{};
438 auto result = impl.GetWorkBufferSizeForMultiStreamEx(params, size);
439
440 LOG_DEBUG(Service_Audio,
441 "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
442 "use_large_frame_size {} -- returned size 0x{:X}",
443 params.sample_rate, params.channel_count, params.total_stream_count,
444 params.stereo_stream_count, params.use_large_frame_size, size);
445
446 IPC::ResponseBuilder rb{ctx, 4};
447 rb.Push(result);
448 rb.Push(size);
449}
450
451void HwOpus::GetWorkBufferSizeExEx(HLERequestContext& ctx) {
452 IPC::RequestParser rp{ctx};
453 auto params = rp.PopRaw<OpusParametersEx>();
454
455 u64 size{};
456 auto result = impl.GetWorkBufferSizeExEx(params, size);
457
458 LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
459
460 IPC::ResponseBuilder rb{ctx, 4};
461 rb.Push(result);
462 rb.Push(size);
463}
464
465void HwOpus::GetWorkBufferSizeForMultiStreamExEx(HLERequestContext& ctx) {
466 IPC::RequestParser rp{ctx};
467
468 auto input{ctx.ReadBuffer()};
469 OpusMultiStreamParametersEx params;
470 std::memcpy(&params, input.data(), sizeof(OpusMultiStreamParametersEx));
471
472 u64 size{};
473 auto result = impl.GetWorkBufferSizeForMultiStreamExEx(params, size);
474
475 LOG_DEBUG(Service_Audio, "size 0x{:X}", size);
476
477 IPC::ResponseBuilder rb{ctx, 4};
478 rb.Push(result);
479 rb.Push(size);
480}
481
482HwOpus::HwOpus(Core::System& system_)
483 : ServiceFramework{system_, "hwopus"}, system{system_}, impl{system} {
484 static const FunctionInfo functions[] = {
485 {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
486 {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
487 {2, &HwOpus::OpenHardwareOpusDecoderForMultiStream, "OpenOpusDecoderForMultiStream"},
488 {3, &HwOpus::GetWorkBufferSizeForMultiStream, "GetWorkBufferSizeForMultiStream"},
489 {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
490 {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
491 {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx,
492 "OpenHardwareOpusDecoderForMultiStreamEx"},
493 {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
494 {8, &HwOpus::GetWorkBufferSizeExEx, "GetWorkBufferSizeExEx"},
495 {9, &HwOpus::GetWorkBufferSizeForMultiStreamExEx, "GetWorkBufferSizeForMultiStreamExEx"},
496 };
497 RegisterHandlers(functions);
498}
499
500HwOpus::~HwOpus() = default;
501
502} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
deleted file mode 100644
index d3960065e..000000000
--- a/src/core/hle/service/audio/hwopus.h
+++ /dev/null
@@ -1,36 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "audio_core/opus/decoder_manager.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Service::Audio {
14
15class HwOpus final : public ServiceFramework<HwOpus> {
16public:
17 explicit HwOpus(Core::System& system_);
18 ~HwOpus() override;
19
20private:
21 void OpenHardwareOpusDecoder(HLERequestContext& ctx);
22 void GetWorkBufferSize(HLERequestContext& ctx);
23 void OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx);
24 void GetWorkBufferSizeForMultiStream(HLERequestContext& ctx);
25 void OpenHardwareOpusDecoderEx(HLERequestContext& ctx);
26 void GetWorkBufferSizeEx(HLERequestContext& ctx);
27 void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx);
28 void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx);
29 void GetWorkBufferSizeExEx(HLERequestContext& ctx);
30 void GetWorkBufferSizeForMultiStreamExEx(HLERequestContext& ctx);
31
32 Core::System& system;
33 AudioCore::OpusDecoder::OpusDecoderManager impl;
34};
35
36} // namespace Service::Audio
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
415 auto& buffer = temp[OutBufferIndex]; 415 auto& buffer = temp[OutBufferIndex];
416 const size_t size = buffer.size(); 416 const size_t size = buffer.size();
417 417
418 if (ctx.CanWriteBuffer(OutBufferIndex)) { 418 if (size > 0 && ctx.CanWriteBuffer(OutBufferIndex)) {
419 if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { 419 if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
420 ctx.WriteBuffer(buffer.data(), size, OutBufferIndex); 420 ctx.WriteBuffer(buffer.data(), size, OutBufferIndex);
421 } else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) { 421 } else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) {