diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/service/audio/audout_u.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audout_u.h | 10 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 208 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.h | 19 |
4 files changed, 16 insertions, 233 deletions
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index b317027b6..108a7c6eb 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | |||
| 8 | #include "audio_core/codec.h" | ||
| 7 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 8 | #include "core/core.h" | 10 | #include "core/core.h" |
| 9 | #include "core/hle/ipc_helpers.h" | 11 | #include "core/hle/ipc_helpers.h" |
| @@ -48,7 +50,7 @@ public: | |||
| 48 | buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); | 50 | buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); |
| 49 | 51 | ||
| 50 | stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count, | 52 | stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count, |
| 51 | [=]() { buffer_event->Signal(); }); | 53 | "IAudioOut", [=]() { buffer_event->Signal(); }); |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | private: | 56 | private: |
| @@ -111,10 +113,10 @@ private: | |||
| 111 | std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer)); | 113 | std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer)); |
| 112 | const u64 tag{rp.Pop<u64>()}; | 114 | const u64 tag{rp.Pop<u64>()}; |
| 113 | 115 | ||
| 114 | std::vector<u8> data(audio_buffer.buffer_size); | 116 | std::vector<s16> samples(audio_buffer.buffer_size / sizeof(s16)); |
| 115 | Memory::ReadBlock(audio_buffer.buffer, data.data(), data.size()); | 117 | Memory::ReadBlock(audio_buffer.buffer, samples.data(), audio_buffer.buffer_size); |
| 116 | 118 | ||
| 117 | if (!audio_core.QueueBuffer(stream, tag, std::move(data))) { | 119 | if (!audio_core.QueueBuffer(stream, tag, std::move(samples))) { |
| 118 | IPC::ResponseBuilder rb{ctx, 2}; | 120 | IPC::ResponseBuilder rb{ctx, 2}; |
| 119 | rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded)); | 121 | rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded)); |
| 120 | } | 122 | } |
| @@ -200,7 +202,7 @@ void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) { | |||
| 200 | rb.Push(RESULT_SUCCESS); | 202 | rb.Push(RESULT_SUCCESS); |
| 201 | rb.Push<u32>(DefaultSampleRate); | 203 | rb.Push<u32>(DefaultSampleRate); |
| 202 | rb.Push<u32>(params.channel_count); | 204 | rb.Push<u32>(params.channel_count); |
| 203 | rb.Push<u32>(static_cast<u32>(PcmFormat::Int16)); | 205 | rb.Push<u32>(static_cast<u32>(AudioCore::Codec::PcmFormat::Int16)); |
| 204 | rb.Push<u32>(static_cast<u32>(AudioState::Stopped)); | 206 | rb.Push<u32>(static_cast<u32>(AudioState::Stopped)); |
| 205 | rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface); | 207 | rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface); |
| 206 | } | 208 | } |
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h index e5c2184d5..fd491f65d 100644 --- a/src/core/hle/service/audio/audout_u.h +++ b/src/core/hle/service/audio/audout_u.h | |||
| @@ -38,16 +38,6 @@ private: | |||
| 38 | 38 | ||
| 39 | void ListAudioOutsImpl(Kernel::HLERequestContext& ctx); | 39 | void ListAudioOutsImpl(Kernel::HLERequestContext& ctx); |
| 40 | void OpenAudioOutImpl(Kernel::HLERequestContext& ctx); | 40 | void OpenAudioOutImpl(Kernel::HLERequestContext& ctx); |
| 41 | |||
| 42 | enum class PcmFormat : u32 { | ||
| 43 | Invalid = 0, | ||
| 44 | Int8 = 1, | ||
| 45 | Int16 = 2, | ||
| 46 | Int24 = 3, | ||
| 47 | Int32 = 4, | ||
| 48 | PcmFloat = 5, | ||
| 49 | Adpcm = 6, | ||
| 50 | }; | ||
| 51 | }; | 41 | }; |
| 52 | 42 | ||
| 53 | } // namespace Service::Audio | 43 | } // namespace Service::Audio |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 6aed9e2fa..f99304de5 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -15,13 +15,10 @@ | |||
| 15 | 15 | ||
| 16 | namespace Service::Audio { | 16 | namespace Service::Audio { |
| 17 | 17 | ||
| 18 | /// TODO(bunnei): Find a proper value for the audio_ticks | ||
| 19 | constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)}; | ||
| 20 | |||
| 21 | class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { | 18 | class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { |
| 22 | public: | 19 | public: |
| 23 | explicit IAudioRenderer(AudioRendererParameter audren_params) | 20 | explicit IAudioRenderer(AudioCore::AudioRendererParameter audren_params) |
| 24 | : ServiceFramework("IAudioRenderer"), worker_params(audren_params) { | 21 | : ServiceFramework("IAudioRenderer") { |
| 25 | static const FunctionInfo functions[] = { | 22 | static const FunctionInfo functions[] = { |
| 26 | {0, nullptr, "GetAudioRendererSampleRate"}, | 23 | {0, nullptr, "GetAudioRendererSampleRate"}, |
| 27 | {1, nullptr, "GetAudioRendererSampleCount"}, | 24 | {1, nullptr, "GetAudioRendererSampleCount"}, |
| @@ -39,21 +36,8 @@ public: | |||
| 39 | RegisterHandlers(functions); | 36 | RegisterHandlers(functions); |
| 40 | 37 | ||
| 41 | system_event = | 38 | system_event = |
| 42 | Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioRenderer:SystemEvent"); | 39 | Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent"); |
| 43 | 40 | renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event); | |
| 44 | // Register event callback to update the Audio Buffer | ||
| 45 | audio_event = CoreTiming::RegisterEvent( | ||
| 46 | "IAudioRenderer::UpdateAudioCallback", [this](u64 userdata, int cycles_late) { | ||
| 47 | UpdateAudioCallback(); | ||
| 48 | CoreTiming::ScheduleEvent(audio_ticks - cycles_late, audio_event); | ||
| 49 | }); | ||
| 50 | |||
| 51 | // Start the audio event | ||
| 52 | CoreTiming::ScheduleEvent(audio_ticks, audio_event); | ||
| 53 | voice_status_list.resize(worker_params.voice_count); | ||
| 54 | } | ||
| 55 | ~IAudioRenderer() { | ||
| 56 | CoreTiming::UnscheduleEvent(audio_event, 0); | ||
| 57 | } | 41 | } |
| 58 | 42 | ||
| 59 | private: | 43 | private: |
| @@ -62,60 +46,9 @@ private: | |||
| 62 | } | 46 | } |
| 63 | 47 | ||
| 64 | void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) { | 48 | void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) { |
| 65 | UpdateDataHeader config{}; | 49 | ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer())); |
| 66 | auto buf = ctx.ReadBuffer(); | ||
| 67 | std::memcpy(&config, buf.data(), sizeof(UpdateDataHeader)); | ||
| 68 | u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4); | ||
| 69 | |||
| 70 | std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count); | ||
| 71 | std::memcpy(mem_pool_info.data(), | ||
| 72 | buf.data() + sizeof(UpdateDataHeader) + config.behavior_size, | ||
| 73 | memory_pool_count * sizeof(MemoryPoolInfo)); | ||
| 74 | |||
| 75 | std::vector<VoiceInfo> voice_info(worker_params.voice_count); | ||
| 76 | std::memcpy(voice_info.data(), | ||
| 77 | buf.data() + sizeof(UpdateDataHeader) + config.behavior_size + | ||
| 78 | config.memory_pools_size + config.voice_resource_size, | ||
| 79 | worker_params.voice_count * sizeof(VoiceInfo)); | ||
| 80 | |||
| 81 | UpdateDataHeader response_data{worker_params}; | ||
| 82 | |||
| 83 | ASSERT(ctx.GetWriteBufferSize() == response_data.total_size); | ||
| 84 | |||
| 85 | std::vector<u8> output(response_data.total_size); | ||
| 86 | std::memcpy(output.data(), &response_data, sizeof(UpdateDataHeader)); | ||
| 87 | std::vector<MemoryPoolEntry> memory_pool(memory_pool_count); | ||
| 88 | for (unsigned i = 0; i < memory_pool.size(); i++) { | ||
| 89 | if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestAttach) | ||
| 90 | memory_pool[i].state = MemoryPoolStates::Attached; | ||
| 91 | else if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestDetach) | ||
| 92 | memory_pool[i].state = MemoryPoolStates::Detached; | ||
| 93 | } | ||
| 94 | std::memcpy(output.data() + sizeof(UpdateDataHeader), memory_pool.data(), | ||
| 95 | response_data.memory_pools_size); | ||
| 96 | |||
| 97 | for (unsigned i = 0; i < voice_info.size(); i++) { | ||
| 98 | if (voice_info[i].is_new) { | ||
| 99 | voice_status_list[i].played_sample_count = 0; | ||
| 100 | voice_status_list[i].wave_buffer_consumed = 0; | ||
| 101 | } else if (voice_info[i].play_state == (u8)PlayStates::Started) { | ||
| 102 | for (u32 buff_idx = 0; buff_idx < voice_info[i].wave_buffer_count; buff_idx++) { | ||
| 103 | voice_status_list[i].played_sample_count += | ||
| 104 | (voice_info[i].wave_buffer[buff_idx].end_sample_offset - | ||
| 105 | voice_info[i].wave_buffer[buff_idx].start_sample_offset) / | ||
| 106 | 2; | ||
| 107 | voice_status_list[i].wave_buffer_consumed++; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | } | ||
| 111 | std::memcpy(output.data() + sizeof(UpdateDataHeader) + response_data.memory_pools_size, | ||
| 112 | voice_status_list.data(), response_data.voices_size); | ||
| 113 | |||
| 114 | ctx.WriteBuffer(output); | ||
| 115 | |||
| 116 | IPC::ResponseBuilder rb{ctx, 2}; | 50 | IPC::ResponseBuilder rb{ctx, 2}; |
| 117 | rb.Push(RESULT_SUCCESS); | 51 | rb.Push(RESULT_SUCCESS); |
| 118 | |||
| 119 | LOG_WARNING(Service_Audio, "(STUBBED) called"); | 52 | LOG_WARNING(Service_Audio, "(STUBBED) called"); |
| 120 | } | 53 | } |
| 121 | 54 | ||
| @@ -136,8 +69,6 @@ private: | |||
| 136 | } | 69 | } |
| 137 | 70 | ||
| 138 | void QuerySystemEvent(Kernel::HLERequestContext& ctx) { | 71 | void QuerySystemEvent(Kernel::HLERequestContext& ctx) { |
| 139 | // system_event->Signal(); | ||
| 140 | |||
| 141 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 72 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 142 | rb.Push(RESULT_SUCCESS); | 73 | rb.Push(RESULT_SUCCESS); |
| 143 | rb.PushCopyObjects(system_event); | 74 | rb.PushCopyObjects(system_event); |
| @@ -145,131 +76,8 @@ private: | |||
| 145 | LOG_WARNING(Service_Audio, "(STUBBED) called"); | 76 | LOG_WARNING(Service_Audio, "(STUBBED) called"); |
| 146 | } | 77 | } |
| 147 | 78 | ||
| 148 | enum class MemoryPoolStates : u32 { // Should be LE | ||
| 149 | Invalid = 0x0, | ||
| 150 | Unknown = 0x1, | ||
| 151 | RequestDetach = 0x2, | ||
| 152 | Detached = 0x3, | ||
| 153 | RequestAttach = 0x4, | ||
| 154 | Attached = 0x5, | ||
| 155 | Released = 0x6, | ||
| 156 | }; | ||
| 157 | |||
| 158 | enum class PlayStates : u8 { | ||
| 159 | Started = 0, | ||
| 160 | Stopped = 1, | ||
| 161 | }; | ||
| 162 | |||
| 163 | struct MemoryPoolEntry { | ||
| 164 | MemoryPoolStates state; | ||
| 165 | u32_le unknown_4; | ||
| 166 | u32_le unknown_8; | ||
| 167 | u32_le unknown_c; | ||
| 168 | }; | ||
| 169 | static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size"); | ||
| 170 | |||
| 171 | struct MemoryPoolInfo { | ||
| 172 | u64_le pool_address; | ||
| 173 | u64_le pool_size; | ||
| 174 | MemoryPoolStates pool_state; | ||
| 175 | INSERT_PADDING_WORDS(3); // Unknown | ||
| 176 | }; | ||
| 177 | static_assert(sizeof(MemoryPoolInfo) == 0x20, "MemoryPoolInfo has wrong size"); | ||
| 178 | |||
| 179 | struct UpdateDataHeader { | ||
| 180 | UpdateDataHeader() {} | ||
| 181 | |||
| 182 | explicit UpdateDataHeader(const AudioRendererParameter& config) { | ||
| 183 | revision = Common::MakeMagic('R', 'E', 'V', '4'); // 5.1.0 Revision | ||
| 184 | behavior_size = 0xb0; | ||
| 185 | memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10; | ||
| 186 | voices_size = config.voice_count * 0x10; | ||
| 187 | voice_resource_size = 0x0; | ||
| 188 | effects_size = config.effect_count * 0x10; | ||
| 189 | mixes_size = 0x0; | ||
| 190 | sinks_size = config.sink_count * 0x20; | ||
| 191 | performance_manager_size = 0x10; | ||
| 192 | total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size + | ||
| 193 | voices_size + effects_size + sinks_size + performance_manager_size; | ||
| 194 | } | ||
| 195 | |||
| 196 | u32_le revision; | ||
| 197 | u32_le behavior_size; | ||
| 198 | u32_le memory_pools_size; | ||
| 199 | u32_le voices_size; | ||
| 200 | u32_le voice_resource_size; | ||
| 201 | u32_le effects_size; | ||
| 202 | u32_le mixes_size; | ||
| 203 | u32_le sinks_size; | ||
| 204 | u32_le performance_manager_size; | ||
| 205 | INSERT_PADDING_WORDS(6); | ||
| 206 | u32_le total_size; | ||
| 207 | }; | ||
| 208 | static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size"); | ||
| 209 | |||
| 210 | struct BiquadFilter { | ||
| 211 | u8 enable; | ||
| 212 | INSERT_PADDING_BYTES(1); | ||
| 213 | s16_le numerator[3]; | ||
| 214 | s16_le denominator[2]; | ||
| 215 | }; | ||
| 216 | static_assert(sizeof(BiquadFilter) == 0xc, "BiquadFilter has wrong size"); | ||
| 217 | |||
| 218 | struct WaveBuffer { | ||
| 219 | u64_le buffer_addr; | ||
| 220 | u64_le buffer_sz; | ||
| 221 | s32_le start_sample_offset; | ||
| 222 | s32_le end_sample_offset; | ||
| 223 | u8 loop; | ||
| 224 | u8 end_of_stream; | ||
| 225 | u8 sent_to_server; | ||
| 226 | INSERT_PADDING_BYTES(5); | ||
| 227 | u64 context_addr; | ||
| 228 | u64 context_sz; | ||
| 229 | INSERT_PADDING_BYTES(8); | ||
| 230 | }; | ||
| 231 | static_assert(sizeof(WaveBuffer) == 0x38, "WaveBuffer has wrong size"); | ||
| 232 | |||
| 233 | struct VoiceInfo { | ||
| 234 | u32_le id; | ||
| 235 | u32_le node_id; | ||
| 236 | u8 is_new; | ||
| 237 | u8 is_in_use; | ||
| 238 | u8 play_state; | ||
| 239 | u8 sample_format; | ||
| 240 | u32_le sample_rate; | ||
| 241 | u32_le priority; | ||
| 242 | u32_le sorting_order; | ||
| 243 | u32_le channel_count; | ||
| 244 | float_le pitch; | ||
| 245 | float_le volume; | ||
| 246 | BiquadFilter biquad_filter[2]; | ||
| 247 | u32_le wave_buffer_count; | ||
| 248 | u16_le wave_buffer_head; | ||
| 249 | INSERT_PADDING_BYTES(6); | ||
| 250 | u64_le additional_params_addr; | ||
| 251 | u64_le additional_params_sz; | ||
| 252 | u32_le mix_id; | ||
| 253 | u32_le splitter_info_id; | ||
| 254 | WaveBuffer wave_buffer[4]; | ||
| 255 | u32_le voice_channel_resource_ids[6]; | ||
| 256 | INSERT_PADDING_BYTES(24); | ||
| 257 | }; | ||
| 258 | static_assert(sizeof(VoiceInfo) == 0x170, "VoiceInfo is wrong size"); | ||
| 259 | |||
| 260 | struct VoiceOutStatus { | ||
| 261 | u64_le played_sample_count; | ||
| 262 | u32_le wave_buffer_consumed; | ||
| 263 | INSERT_PADDING_WORDS(1); | ||
| 264 | }; | ||
| 265 | static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size"); | ||
| 266 | |||
| 267 | /// This is used to trigger the audio event callback. | ||
| 268 | CoreTiming::EventType* audio_event; | ||
| 269 | |||
| 270 | Kernel::SharedPtr<Kernel::Event> system_event; | 79 | Kernel::SharedPtr<Kernel::Event> system_event; |
| 271 | AudioRendererParameter worker_params; | 80 | std::unique_ptr<AudioCore::AudioRenderer> renderer; |
| 272 | std::vector<VoiceOutStatus> voice_status_list; | ||
| 273 | }; | 81 | }; |
| 274 | 82 | ||
| 275 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { | 83 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { |
| @@ -368,7 +176,7 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") { | |||
| 368 | 176 | ||
| 369 | void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { | 177 | void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { |
| 370 | IPC::RequestParser rp{ctx}; | 178 | IPC::RequestParser rp{ctx}; |
| 371 | auto params = rp.PopRaw<AudioRendererParameter>(); | 179 | auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); |
| 372 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 180 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 373 | 181 | ||
| 374 | rb.Push(RESULT_SUCCESS); | 182 | rb.Push(RESULT_SUCCESS); |
| @@ -379,7 +187,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { | |||
| 379 | 187 | ||
| 380 | void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | 188 | void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { |
| 381 | IPC::RequestParser rp{ctx}; | 189 | IPC::RequestParser rp{ctx}; |
| 382 | auto params = rp.PopRaw<AudioRendererParameter>(); | 190 | auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); |
| 383 | 191 | ||
| 384 | u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40); | 192 | u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40); |
| 385 | buffer_sz += params.unknown_c * 1024; | 193 | buffer_sz += params.unknown_c * 1024; |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index b9b81db4f..14907f8ae 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "audio_core/audio_renderer.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Kernel { | 10 | namespace Kernel { |
| @@ -12,24 +13,6 @@ class HLERequestContext; | |||
| 12 | 13 | ||
| 13 | namespace Service::Audio { | 14 | namespace Service::Audio { |
| 14 | 15 | ||
| 15 | struct AudioRendererParameter { | ||
| 16 | u32_le sample_rate; | ||
| 17 | u32_le sample_count; | ||
| 18 | u32_le unknown_8; | ||
| 19 | u32_le unknown_c; | ||
| 20 | u32_le voice_count; | ||
| 21 | u32_le sink_count; | ||
| 22 | u32_le effect_count; | ||
| 23 | u32_le unknown_1c; | ||
| 24 | u8 unknown_20; | ||
| 25 | INSERT_PADDING_BYTES(3); | ||
| 26 | u32_le splitter_count; | ||
| 27 | u32_le unknown_2c; | ||
| 28 | INSERT_PADDING_WORDS(1); | ||
| 29 | u32_le revision; | ||
| 30 | }; | ||
| 31 | static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size"); | ||
| 32 | |||
| 33 | class AudRenU final : public ServiceFramework<AudRenU> { | 16 | class AudRenU final : public ServiceFramework<AudRenU> { |
| 34 | public: | 17 | public: |
| 35 | explicit AudRenU(); | 18 | explicit AudRenU(); |