From 3fd6eeaf9fb42c942ffbc2a60a50dd8ebfd8dfee Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 9 Jul 2026 19:02:26 +0200 Subject: Revert #3970 #4177 (#4187) 3970 revert fixes crash caused by scheduler 4177 fix mario galaxy and metroid prime 4 not booting Co-authored-by: CamilleLaVey Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4187 Reviewed-by: MaranBr --- .../adsp/apps/audio_renderer/audio_renderer.cpp | 181 +++++----- .../adsp/apps/audio_renderer/audio_renderer.h | 5 + src/audio_core/adsp/apps/opus/opus_decoder.cpp | 371 +++++++++++---------- src/audio_core/adsp/apps/opus/opus_decoder.h | 4 + 4 files changed, 287 insertions(+), 274 deletions(-) (limited to 'src/audio_core') diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp index af37fb4685..45a69eca03 100644 --- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp @@ -29,96 +29,8 @@ void AudioRenderer::Start() { CreateSinkStreams(); mailbox.Initialize(AppMailboxId::AudioRenderer); - // Main AudioRenderer thread, responsible for processing the command lists. - main_thread = std::jthread([this](std::stop_token stop_token) { - Common::SetCurrentThreadName("DSP_AudioRenderer_Main"); - Common::SetCurrentThreadPriority(Common::ThreadPriority::High); - // TODO: Create buffer map/unmap thread + mailbox - // TODO: Create gMix devices, initialize them here - - if (mailbox.Receive(Direction::DSP) != Message::InitializeOK) { - LOG_ERROR(Service_Audio, "ADSP Audio Renderer -- Failed to receive initialize message from host!"); - return; - } - - mailbox.Send(Direction::Host, Message::InitializeOK); - - // 0.12 seconds (2,304,000 / 19,200,000) - constexpr u64 max_process_time{2'304'000ULL}; - while (!stop_token.stop_requested()) { - auto msg{mailbox.Receive(Direction::DSP)}; - switch (msg) { - case Message::Shutdown: - mailbox.Send(Direction::Host, Message::Shutdown); - return; - - case Message::Render: { - if (system.IsShuttingDown()) { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - mailbox.Send(Direction::Host, Message::RenderResponse); - continue; - } - std::array buffers_reset{}; - std::array render_times_taken{}; - const auto start_time{system.CoreTiming().GetGlobalTimeUs().count()}; - - for (u32 index = 0; index < MaxRendererSessions; index++) { - auto& command_buffer{command_buffers[index]}; - auto& command_list_processor{command_list_processors[index]}; - - // Check this buffer is valid, as it may not be used. - if (command_buffer.buffer != 0) { - // If there are no remaining commands (from the previous list), - // this is a new command list, initialize it. - if (command_buffer.remaining_command_count == 0) { - command_list_processor.Initialize(system, *command_buffer.process, - command_buffer.buffer, - command_buffer.size, streams[index]); - } - - if (command_buffer.reset_buffer && !buffers_reset[index]) { - streams[index]->ClearQueue(); - buffers_reset[index] = true; - } - - u64 max_time{max_process_time}; - if (index == 1 && command_buffer.applet_resource_user_id == - command_buffers[0].applet_resource_user_id) { - max_time = max_process_time - render_times_taken[0]; - if (render_times_taken[0] > max_process_time) { - max_time = 0; - } - } - - max_time = (std::min)(command_buffer.time_limit, max_time); - command_list_processor.SetProcessTimeMax(max_time); - - if (index == 0) { - streams[index]->WaitFreeSpace(stop_token); - } - - // Process the command list - { - render_times_taken[index] = - command_list_processor.Process(index) - start_time; - } - - const auto end_time{system.CoreTiming().GetGlobalTimeUs().count()}; - - command_buffer.remaining_command_count = - command_list_processor.GetRemainingCommandCount(); - command_buffer.render_time_taken_us = end_time - start_time; - } - } - mailbox.Send(Direction::Host, Message::RenderResponse); - } break; - default: - LOG_WARNING(Service_Audio, "ADSP AudioRenderer received an invalid message, msg={:02X}!", msg); - break; - } - } - }); + main_thread = std::jthread([this](std::stop_token stop_token) { Main(stop_token); }); mailbox.Send(Direction::DSP, Message::InitializeOK); if (mailbox.Receive(Direction::Host) != Message::InitializeOK) { @@ -217,4 +129,95 @@ void AudioRenderer::CreateSinkStreams() { } } +void AudioRenderer::Main(std::stop_token stop_token) { + Common::SetCurrentThreadName("DSP_AudioRenderer_Main"); + Common::SetCurrentThreadPriority(Common::ThreadPriority::High); + + // TODO: Create buffer map/unmap thread + mailbox + // TODO: Create gMix devices, initialize them here + + if (mailbox.Receive(Direction::DSP) != Message::InitializeOK) { + LOG_ERROR(Service_Audio, "ADSP Audio Renderer -- Failed to receive initialize message from host!"); + return; + } + + mailbox.Send(Direction::Host, Message::InitializeOK); + + // 0.12 seconds (2,304,000 / 19,200,000) + constexpr u64 max_process_time{2'304'000ULL}; + + while (!stop_token.stop_requested()) { + auto msg{mailbox.Receive(Direction::DSP)}; + switch (msg) { + case Message::Shutdown: + mailbox.Send(Direction::Host, Message::Shutdown); + return; + + case Message::Render: { + if (system.IsShuttingDown()) { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + mailbox.Send(Direction::Host, Message::RenderResponse); + continue; + } + std::array buffers_reset{}; + std::array render_times_taken{}; + const auto start_time{system.CoreTiming().GetGlobalTimeUs().count()}; + + for (u32 index = 0; index < MaxRendererSessions; index++) { + auto& command_buffer{command_buffers[index]}; + auto& command_list_processor{command_list_processors[index]}; + + // Check this buffer is valid, as it may not be used. + if (command_buffer.buffer != 0) { + // If there are no remaining commands (from the previous list), + // this is a new command list, initialize it. + if (command_buffer.remaining_command_count == 0) { + command_list_processor.Initialize(system, *command_buffer.process, + command_buffer.buffer, + command_buffer.size, streams[index]); + } + + if (command_buffer.reset_buffer && !buffers_reset[index]) { + streams[index]->ClearQueue(); + buffers_reset[index] = true; + } + + u64 max_time{max_process_time}; + if (index == 1 && command_buffer.applet_resource_user_id == + command_buffers[0].applet_resource_user_id) { + max_time = max_process_time - render_times_taken[0]; + if (render_times_taken[0] > max_process_time) { + max_time = 0; + } + } + + max_time = (std::min)(command_buffer.time_limit, max_time); + command_list_processor.SetProcessTimeMax(max_time); + + if (index == 0) { + streams[index]->WaitFreeSpace(stop_token); + } + + // Process the command list + { + render_times_taken[index] = + command_list_processor.Process(index) - start_time; + } + + const auto end_time{system.CoreTiming().GetGlobalTimeUs().count()}; + + command_buffer.remaining_command_count = + command_list_processor.GetRemainingCommandCount(); + command_buffer.render_time_taken_us = end_time - start_time; + } + } + mailbox.Send(Direction::Host, Message::RenderResponse); + } break; + default: + LOG_WARNING(Service_Audio, "ADSP AudioRenderer received an invalid message, msg={:02X}!", msg); + break; + } + } +} + } // namespace AudioCore::ADSP::AudioRenderer diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h index a7a21e76af..4e128187a7 100644 --- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.h @@ -82,6 +82,11 @@ public: u64 GetRenderingStartTick(s32 session_id) const noexcept; private: + /** + * Main AudioRenderer thread, responsible for processing the command lists. + */ + void Main(std::stop_token stop_token); + /** * Creates the streams which will receive the processed samples. */ diff --git a/src/audio_core/adsp/apps/opus/opus_decoder.cpp b/src/audio_core/adsp/apps/opus/opus_decoder.cpp index 1ce81d287a..8a009c04c7 100644 --- a/src/audio_core/adsp/apps/opus/opus_decoder.cpp +++ b/src/audio_core/adsp/apps/opus/opus_decoder.cpp @@ -37,9 +37,7 @@ bool IsValidMultiStreamStreamCounts(s32 total_stream_count, s32 stereo_stream_co } // namespace OpusDecoder::OpusDecoder(Core::System& system_) : system{system_} { - init_thread = std::jthread([this](std::stop_token stop_token) { - Init(stop_token); - }); + init_thread = std::jthread([this](std::stop_token stop_token) { Init(stop_token); }); } OpusDecoder::~OpusDecoder() { @@ -66,203 +64,206 @@ u32 OpusDecoder::Receive(Direction dir, std::stop_token stop_token) { return mailbox.Receive(dir, stop_token); } -void OpusDecoder::Init(std::stop_token rc_stop_token) { +void OpusDecoder::Init(std::stop_token stop_token) { Common::SetCurrentThreadName("DSP_OpusDecoder_Init"); - if (Receive(Direction::DSP, rc_stop_token) != Message::Start) { - LOG_ERROR(Service_Audio, "DSP OpusDecoder failed to receive Start message. Opus initialization failed."); + if (Receive(Direction::DSP, stop_token) != Message::Start) { + LOG_ERROR(Service_Audio, + "DSP OpusDecoder failed to receive Start message. Opus initialization failed."); return; } - // Main OpusDecoder thread, responsible for processing the incoming Opus packets. - main_thread = std::jthread([this](std::stop_token stop_token) { - Common::SetCurrentThreadName("DSP_OpusDecoder_Main"); - while (!stop_token.stop_requested()) { - auto msg = Receive(Direction::DSP, stop_token); - switch (msg) { - case Shutdown: - Send(Direction::Host, Message::ShutdownOK); - return; - - case GetWorkBufferSize: { - auto channel_count = static_cast(shared_memory->host_send_data[0]); - - ASSERT(IsValidChannelCount(channel_count)); - - shared_memory->dsp_return_data[0] = OpusDecodeObject::GetWorkBufferSize(channel_count); - Send(Direction::Host, Message::GetWorkBufferSizeOK); - } break; - - case InitializeDecodeObject: { - auto buffer = shared_memory->host_send_data[0]; - auto buffer_size = shared_memory->host_send_data[1]; - auto sample_rate = static_cast(shared_memory->host_send_data[2]); - auto channel_count = static_cast(shared_memory->host_send_data[3]); - - ASSERT(sample_rate >= 0); - ASSERT(IsValidChannelCount(channel_count)); - ASSERT(buffer_size >= OpusDecodeObject::GetWorkBufferSize(channel_count)); - - auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer); - shared_memory->dsp_return_data[0] = - decoder_object.InitializeDecoder(sample_rate, channel_count); - - Send(Direction::Host, Message::InitializeDecodeObjectOK); - } break; - - case ShutdownDecodeObject: { - auto buffer = shared_memory->host_send_data[0]; - [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; - - auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer); - shared_memory->dsp_return_data[0] = decoder_object.Shutdown(); - - Send(Direction::Host, Message::ShutdownDecodeObjectOK); - } break; - - case DecodeInterleaved: { - auto start_time = system.CoreTiming().GetGlobalTimeUs(); - - auto buffer = shared_memory->host_send_data[0]; - auto input_data = shared_memory->host_send_data[1]; - auto input_data_size = shared_memory->host_send_data[2]; - auto output_data = shared_memory->host_send_data[3]; - auto output_data_size = shared_memory->host_send_data[4]; - auto final_range = static_cast(shared_memory->host_send_data[5]); - auto reset_requested = shared_memory->host_send_data[6]; - - u32 decoded_samples{0}; - - auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer); - s32 error_code{OPUS_OK}; - if (reset_requested) { - error_code = decoder_object.ResetDecoder(); - } + main_thread = std::jthread([this](std::stop_token st) { Main(st); }); + running = true; + Send(Direction::Host, Message::StartOK); +} - if (error_code == OPUS_OK) { - error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size, - input_data, input_data_size); - } +void OpusDecoder::Main(std::stop_token stop_token) { + Common::SetCurrentThreadName("DSP_OpusDecoder_Main"); - if (error_code == OPUS_OK) { - if (final_range && decoder_object.GetFinalRange() != final_range) { - error_code = OPUS_INVALID_PACKET; - } - } + while (!stop_token.stop_requested()) { + auto msg = Receive(Direction::DSP, stop_token); + switch (msg) { + case Shutdown: + Send(Direction::Host, Message::ShutdownOK); + return; - auto end_time = system.CoreTiming().GetGlobalTimeUs(); - shared_memory->dsp_return_data[0] = error_code; - shared_memory->dsp_return_data[1] = decoded_samples; - shared_memory->dsp_return_data[2] = (end_time - start_time).count(); - - Send(Direction::Host, Message::DecodeInterleavedOK); - } break; - - case MapMemory: { - [[maybe_unused]] auto buffer = shared_memory->host_send_data[0]; - [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; - Send(Direction::Host, Message::MapMemoryOK); - } break; - - case UnmapMemory: { - [[maybe_unused]] auto buffer = shared_memory->host_send_data[0]; - [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; - Send(Direction::Host, Message::UnmapMemoryOK); - } break; - - case GetWorkBufferSizeForMultiStream: { - auto total_stream_count = static_cast(shared_memory->host_send_data[0]); - auto stereo_stream_count = static_cast(shared_memory->host_send_data[1]); - - ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count)); - - shared_memory->dsp_return_data[0] = OpusMultiStreamDecodeObject::GetWorkBufferSize( - total_stream_count, stereo_stream_count); - Send(Direction::Host, Message::GetWorkBufferSizeForMultiStreamOK); - } break; - - case InitializeMultiStreamDecodeObject: { - auto buffer = shared_memory->host_send_data[0]; - auto buffer_size = shared_memory->host_send_data[1]; - auto sample_rate = static_cast(shared_memory->host_send_data[2]); - auto channel_count = static_cast(shared_memory->host_send_data[3]); - auto total_stream_count = static_cast(shared_memory->host_send_data[4]); - auto stereo_stream_count = static_cast(shared_memory->host_send_data[5]); - // Nintendo seem to have a bug here, they try to use &host_send_data[6] for the channel - // mappings, but [6] is never set, and there is not enough room in the argument data for - // more than 40 channels, when 255 are possible. - // It also means the mapping values are undefined, though likely always 0, - // and the mappings given by the game are ignored. The mappings are copied to this - // dedicated buffer host side, so let's do as intended. - auto mappings = shared_memory->channel_mapping.data(); - - ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count)); - ASSERT(sample_rate >= 0); - ASSERT(buffer_size >= OpusMultiStreamDecodeObject::GetWorkBufferSize( - total_stream_count, stereo_stream_count)); - - auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer); - shared_memory->dsp_return_data[0] = decoder_object.InitializeDecoder( - sample_rate, total_stream_count, channel_count, stereo_stream_count, mappings); - - Send(Direction::Host, Message::InitializeMultiStreamDecodeObjectOK); - } break; - - case ShutdownMultiStreamDecodeObject: { - auto buffer = shared_memory->host_send_data[0]; - [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; - - auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer); - shared_memory->dsp_return_data[0] = decoder_object.Shutdown(); - - Send(Direction::Host, Message::ShutdownMultiStreamDecodeObjectOK); - } break; - - case DecodeInterleavedForMultiStream: { - auto start_time = system.CoreTiming().GetGlobalTimeUs(); - - auto buffer = shared_memory->host_send_data[0]; - auto input_data = shared_memory->host_send_data[1]; - auto input_data_size = shared_memory->host_send_data[2]; - auto output_data = shared_memory->host_send_data[3]; - auto output_data_size = shared_memory->host_send_data[4]; - auto final_range = static_cast(shared_memory->host_send_data[5]); - auto reset_requested = shared_memory->host_send_data[6]; - - u32 decoded_samples{0}; - - auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer); - s32 error_code{OPUS_OK}; - if (reset_requested) { - error_code = decoder_object.ResetDecoder(); - } + case GetWorkBufferSize: { + auto channel_count = static_cast(shared_memory->host_send_data[0]); - if (error_code == OPUS_OK) { - error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size, - input_data, input_data_size); - } + ASSERT(IsValidChannelCount(channel_count)); + + shared_memory->dsp_return_data[0] = OpusDecodeObject::GetWorkBufferSize(channel_count); + Send(Direction::Host, Message::GetWorkBufferSizeOK); + } break; + + case InitializeDecodeObject: { + auto buffer = shared_memory->host_send_data[0]; + auto buffer_size = shared_memory->host_send_data[1]; + auto sample_rate = static_cast(shared_memory->host_send_data[2]); + auto channel_count = static_cast(shared_memory->host_send_data[3]); + + ASSERT(sample_rate >= 0); + ASSERT(IsValidChannelCount(channel_count)); + ASSERT(buffer_size >= OpusDecodeObject::GetWorkBufferSize(channel_count)); + + auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer); + shared_memory->dsp_return_data[0] = + decoder_object.InitializeDecoder(sample_rate, channel_count); + + Send(Direction::Host, Message::InitializeDecodeObjectOK); + } break; + + case ShutdownDecodeObject: { + auto buffer = shared_memory->host_send_data[0]; + [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; + + auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer); + shared_memory->dsp_return_data[0] = decoder_object.Shutdown(); + + Send(Direction::Host, Message::ShutdownDecodeObjectOK); + } break; + + case DecodeInterleaved: { + auto start_time = system.CoreTiming().GetGlobalTimeUs(); - if (error_code == OPUS_OK) { - if (final_range && decoder_object.GetFinalRange() != final_range) { - error_code = OPUS_INVALID_PACKET; - } + auto buffer = shared_memory->host_send_data[0]; + auto input_data = shared_memory->host_send_data[1]; + auto input_data_size = shared_memory->host_send_data[2]; + auto output_data = shared_memory->host_send_data[3]; + auto output_data_size = shared_memory->host_send_data[4]; + auto final_range = static_cast(shared_memory->host_send_data[5]); + auto reset_requested = shared_memory->host_send_data[6]; + + u32 decoded_samples{0}; + + auto& decoder_object = OpusDecodeObject::Initialize(buffer, buffer); + s32 error_code{OPUS_OK}; + if (reset_requested) { + error_code = decoder_object.ResetDecoder(); + } + + if (error_code == OPUS_OK) { + error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size, + input_data, input_data_size); + } + + if (error_code == OPUS_OK) { + if (final_range && decoder_object.GetFinalRange() != final_range) { + error_code = OPUS_INVALID_PACKET; } + } - auto end_time = system.CoreTiming().GetGlobalTimeUs(); - shared_memory->dsp_return_data[0] = error_code; - shared_memory->dsp_return_data[1] = decoded_samples; - shared_memory->dsp_return_data[2] = (end_time - start_time).count(); + auto end_time = system.CoreTiming().GetGlobalTimeUs(); + shared_memory->dsp_return_data[0] = error_code; + shared_memory->dsp_return_data[1] = decoded_samples; + shared_memory->dsp_return_data[2] = (end_time - start_time).count(); + + Send(Direction::Host, Message::DecodeInterleavedOK); + } break; + + case MapMemory: { + [[maybe_unused]] auto buffer = shared_memory->host_send_data[0]; + [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; + Send(Direction::Host, Message::MapMemoryOK); + } break; + + case UnmapMemory: { + [[maybe_unused]] auto buffer = shared_memory->host_send_data[0]; + [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; + Send(Direction::Host, Message::UnmapMemoryOK); + } break; + + case GetWorkBufferSizeForMultiStream: { + auto total_stream_count = static_cast(shared_memory->host_send_data[0]); + auto stereo_stream_count = static_cast(shared_memory->host_send_data[1]); + + ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count)); + + shared_memory->dsp_return_data[0] = OpusMultiStreamDecodeObject::GetWorkBufferSize( + total_stream_count, stereo_stream_count); + Send(Direction::Host, Message::GetWorkBufferSizeForMultiStreamOK); + } break; + + case InitializeMultiStreamDecodeObject: { + auto buffer = shared_memory->host_send_data[0]; + auto buffer_size = shared_memory->host_send_data[1]; + auto sample_rate = static_cast(shared_memory->host_send_data[2]); + auto channel_count = static_cast(shared_memory->host_send_data[3]); + auto total_stream_count = static_cast(shared_memory->host_send_data[4]); + auto stereo_stream_count = static_cast(shared_memory->host_send_data[5]); + // Nintendo seem to have a bug here, they try to use &host_send_data[6] for the channel + // mappings, but [6] is never set, and there is not enough room in the argument data for + // more than 40 channels, when 255 are possible. + // It also means the mapping values are undefined, though likely always 0, + // and the mappings given by the game are ignored. The mappings are copied to this + // dedicated buffer host side, so let's do as intended. + auto mappings = shared_memory->channel_mapping.data(); + + ASSERT(IsValidMultiStreamStreamCounts(total_stream_count, stereo_stream_count)); + ASSERT(sample_rate >= 0); + ASSERT(buffer_size >= OpusMultiStreamDecodeObject::GetWorkBufferSize( + total_stream_count, stereo_stream_count)); + + auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer); + shared_memory->dsp_return_data[0] = decoder_object.InitializeDecoder( + sample_rate, total_stream_count, channel_count, stereo_stream_count, mappings); + + Send(Direction::Host, Message::InitializeMultiStreamDecodeObjectOK); + } break; + + case ShutdownMultiStreamDecodeObject: { + auto buffer = shared_memory->host_send_data[0]; + [[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1]; + + auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer); + shared_memory->dsp_return_data[0] = decoder_object.Shutdown(); + + Send(Direction::Host, Message::ShutdownMultiStreamDecodeObjectOK); + } break; + + case DecodeInterleavedForMultiStream: { + auto start_time = system.CoreTiming().GetGlobalTimeUs(); + + auto buffer = shared_memory->host_send_data[0]; + auto input_data = shared_memory->host_send_data[1]; + auto input_data_size = shared_memory->host_send_data[2]; + auto output_data = shared_memory->host_send_data[3]; + auto output_data_size = shared_memory->host_send_data[4]; + auto final_range = static_cast(shared_memory->host_send_data[5]); + auto reset_requested = shared_memory->host_send_data[6]; + + u32 decoded_samples{0}; + + auto& decoder_object = OpusMultiStreamDecodeObject::Initialize(buffer, buffer); + s32 error_code{OPUS_OK}; + if (reset_requested) { + error_code = decoder_object.ResetDecoder(); + } - Send(Direction::Host, Message::DecodeInterleavedForMultiStreamOK); - } break; + if (error_code == OPUS_OK) { + error_code = decoder_object.Decode(decoded_samples, output_data, output_data_size, + input_data, input_data_size); + } - default: - LOG_ERROR(Service_Audio, "Invalid OpusDecoder command {}", msg); - continue; + if (error_code == OPUS_OK) { + if (final_range && decoder_object.GetFinalRange() != final_range) { + error_code = OPUS_INVALID_PACKET; + } } + + auto end_time = system.CoreTiming().GetGlobalTimeUs(); + shared_memory->dsp_return_data[0] = error_code; + shared_memory->dsp_return_data[1] = decoded_samples; + shared_memory->dsp_return_data[2] = (end_time - start_time).count(); + + Send(Direction::Host, Message::DecodeInterleavedForMultiStreamOK); + } break; + + default: + LOG_ERROR(Service_Audio, "Invalid OpusDecoder command {}", msg); + continue; } - }); - running = true; - Send(Direction::Host, Message::StartOK); + } } } // namespace AudioCore::ADSP::OpusDecoder diff --git a/src/audio_core/adsp/apps/opus/opus_decoder.h b/src/audio_core/adsp/apps/opus/opus_decoder.h index d554586703..5b3f22bf4c 100644 --- a/src/audio_core/adsp/apps/opus/opus_decoder.h +++ b/src/audio_core/adsp/apps/opus/opus_decoder.h @@ -72,6 +72,10 @@ private: * Initializing thread, launched at audio_core boot to avoid blocking the main emu boot thread. */ void Init(std::stop_token stop_token); + /** + * Main OpusDecoder thread, responsible for processing the incoming Opus packets. + */ + void Main(std::stop_token stop_token); /// Core system Core::System& system; -- cgit v1.2.3