From 90aa937593e53a5d5e070fb623b228578b0b225f Mon Sep 17 00:00:00 2001 From: Kelebek1 Date: Sat, 4 Nov 2023 18:25:40 +0000 Subject: Convert files to LF eol --- src/audio_core/opus/decoder.cpp | 358 ++++++++++++------------ src/audio_core/opus/decoder.h | 106 +++---- src/audio_core/opus/decoder_manager.cpp | 204 +++++++------- src/audio_core/opus/decoder_manager.h | 76 ++--- src/audio_core/opus/hardware_opus.cpp | 482 ++++++++++++++++---------------- src/audio_core/opus/hardware_opus.h | 90 +++--- 6 files changed, 658 insertions(+), 658 deletions(-) (limited to 'src/audio_core/opus') diff --git a/src/audio_core/opus/decoder.cpp b/src/audio_core/opus/decoder.cpp index 5b23fce14..c6fd45f47 100644 --- a/src/audio_core/opus/decoder.cpp +++ b/src/audio_core/opus/decoder.cpp @@ -1,179 +1,179 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "audio_core/opus/decoder.h" -#include "audio_core/opus/hardware_opus.h" -#include "audio_core/opus/parameters.h" -#include "common/alignment.h" -#include "common/swap.h" -#include "core/core.h" - -namespace AudioCore::OpusDecoder { -using namespace Service::Audio; -namespace { -OpusPacketHeader ReverseHeader(OpusPacketHeader header) { - OpusPacketHeader out; - out.size = Common::swap32(header.size); - out.final_range = Common::swap32(header.final_range); - return out; -} -} // namespace - -OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_) - : system{system_}, hardware_opus{hardware_opus_} {} - -OpusDecoder::~OpusDecoder() { - if (decode_object_initialized) { - hardware_opus.ShutdownDecodeObject(shared_buffer.get(), shared_buffer_size); - } -} - -Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, - u64 transfer_memory_size) { - auto frame_size{params.use_large_frame_size ? 5760 : 1920}; - shared_buffer_size = transfer_memory_size; - shared_buffer = std::make_unique(shared_buffer_size); - shared_memory_mapped = true; - - buffer_size = - Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); - - out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; - size_t in_data_size{0x600u}; - in_data = {out_data.data() - in_data_size, in_data_size}; - - ON_RESULT_FAILURE { - if (shared_memory_mapped) { - shared_memory_mapped = false; - ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); - } - }; - - R_TRY(hardware_opus.InitializeDecodeObject(params.sample_rate, params.channel_count, - shared_buffer.get(), shared_buffer_size)); - - sample_rate = params.sample_rate; - channel_count = params.channel_count; - use_large_frame_size = params.use_large_frame_size; - decode_object_initialized = true; - R_SUCCEED(); -} - -Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, - Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) { - auto frame_size{params.use_large_frame_size ? 5760 : 1920}; - shared_buffer_size = transfer_memory_size; - shared_buffer = std::make_unique(shared_buffer_size); - shared_memory_mapped = true; - - buffer_size = - Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); - - out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; - size_t in_data_size{Common::AlignUp(1500ull * params.total_stream_count, 64u)}; - in_data = {out_data.data() - in_data_size, in_data_size}; - - ON_RESULT_FAILURE { - if (shared_memory_mapped) { - shared_memory_mapped = false; - ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); - } - }; - - R_TRY(hardware_opus.InitializeMultiStreamDecodeObject( - params.sample_rate, params.channel_count, params.total_stream_count, - params.stereo_stream_count, params.mappings.data(), shared_buffer.get(), - shared_buffer_size)); - - sample_rate = params.sample_rate; - channel_count = params.channel_count; - total_stream_count = params.total_stream_count; - stereo_stream_count = params.stereo_stream_count; - use_large_frame_size = params.use_large_frame_size; - decode_object_initialized = true; - R_SUCCEED(); -} - -Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken, - u32* out_sample_count, std::span input_data, - std::span output_data, bool reset) { - u32 out_samples; - u64 time_taken{}; - - R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); - - auto* header_p{reinterpret_cast(input_data.data())}; - OpusPacketHeader header{ReverseHeader(*header_p)}; - - R_UNLESS(in_data.size_bytes() >= header.size && - header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), - ResultBufferTooSmall); - - if (!shared_memory_mapped) { - R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); - shared_memory_mapped = true; - } - - std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); - - R_TRY(hardware_opus.DecodeInterleaved(out_samples, out_data.data(), out_data.size_bytes(), - channel_count, in_data.data(), header.size, - shared_buffer.get(), time_taken, reset)); - - std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); - - *out_data_size = header.size + sizeof(OpusPacketHeader); - *out_sample_count = out_samples; - if (out_time_taken) { - *out_time_taken = time_taken / 1000; - } - R_SUCCEED(); -} - -Result OpusDecoder::SetContext([[maybe_unused]] std::span context) { - R_SUCCEED_IF(shared_memory_mapped); - shared_memory_mapped = true; - R_RETURN(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); -} - -Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, - u32* out_sample_count, - std::span input_data, - std::span output_data, bool reset) { - u32 out_samples; - u64 time_taken{}; - - R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); - - auto* header_p{reinterpret_cast(input_data.data())}; - OpusPacketHeader header{ReverseHeader(*header_p)}; - - LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", - header.size, input_data.size_bytes(), in_data.size_bytes()); - - R_UNLESS(in_data.size_bytes() >= header.size && - header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), - ResultBufferTooSmall); - - if (!shared_memory_mapped) { - R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); - shared_memory_mapped = true; - } - - std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); - - R_TRY(hardware_opus.DecodeInterleavedForMultiStream( - out_samples, out_data.data(), out_data.size_bytes(), channel_count, in_data.data(), - header.size, shared_buffer.get(), time_taken, reset)); - - std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); - - *out_data_size = header.size + sizeof(OpusPacketHeader); - *out_sample_count = out_samples; - if (out_time_taken) { - *out_time_taken = time_taken / 1000; - } - R_SUCCEED(); -} - -} // namespace AudioCore::OpusDecoder +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "audio_core/opus/decoder.h" +#include "audio_core/opus/hardware_opus.h" +#include "audio_core/opus/parameters.h" +#include "common/alignment.h" +#include "common/swap.h" +#include "core/core.h" + +namespace AudioCore::OpusDecoder { +using namespace Service::Audio; +namespace { +OpusPacketHeader ReverseHeader(OpusPacketHeader header) { + OpusPacketHeader out; + out.size = Common::swap32(header.size); + out.final_range = Common::swap32(header.final_range); + return out; +} +} // namespace + +OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_) + : system{system_}, hardware_opus{hardware_opus_} {} + +OpusDecoder::~OpusDecoder() { + if (decode_object_initialized) { + hardware_opus.ShutdownDecodeObject(shared_buffer.get(), shared_buffer_size); + } +} + +Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, + u64 transfer_memory_size) { + auto frame_size{params.use_large_frame_size ? 5760 : 1920}; + shared_buffer_size = transfer_memory_size; + shared_buffer = std::make_unique(shared_buffer_size); + shared_memory_mapped = true; + + buffer_size = + Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); + + out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; + size_t in_data_size{0x600u}; + in_data = {out_data.data() - in_data_size, in_data_size}; + + ON_RESULT_FAILURE { + if (shared_memory_mapped) { + shared_memory_mapped = false; + ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); + } + }; + + R_TRY(hardware_opus.InitializeDecodeObject(params.sample_rate, params.channel_count, + shared_buffer.get(), shared_buffer_size)); + + sample_rate = params.sample_rate; + channel_count = params.channel_count; + use_large_frame_size = params.use_large_frame_size; + decode_object_initialized = true; + R_SUCCEED(); +} + +Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, + Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) { + auto frame_size{params.use_large_frame_size ? 5760 : 1920}; + shared_buffer_size = transfer_memory_size; + shared_buffer = std::make_unique(shared_buffer_size); + shared_memory_mapped = true; + + buffer_size = + Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); + + out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; + size_t in_data_size{Common::AlignUp(1500ull * params.total_stream_count, 64u)}; + in_data = {out_data.data() - in_data_size, in_data_size}; + + ON_RESULT_FAILURE { + if (shared_memory_mapped) { + shared_memory_mapped = false; + ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); + } + }; + + R_TRY(hardware_opus.InitializeMultiStreamDecodeObject( + params.sample_rate, params.channel_count, params.total_stream_count, + params.stereo_stream_count, params.mappings.data(), shared_buffer.get(), + shared_buffer_size)); + + sample_rate = params.sample_rate; + channel_count = params.channel_count; + total_stream_count = params.total_stream_count; + stereo_stream_count = params.stereo_stream_count; + use_large_frame_size = params.use_large_frame_size; + decode_object_initialized = true; + R_SUCCEED(); +} + +Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken, + u32* out_sample_count, std::span input_data, + std::span output_data, bool reset) { + u32 out_samples; + u64 time_taken{}; + + R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); + + auto* header_p{reinterpret_cast(input_data.data())}; + OpusPacketHeader header{ReverseHeader(*header_p)}; + + R_UNLESS(in_data.size_bytes() >= header.size && + header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), + ResultBufferTooSmall); + + if (!shared_memory_mapped) { + R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); + shared_memory_mapped = true; + } + + std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); + + R_TRY(hardware_opus.DecodeInterleaved(out_samples, out_data.data(), out_data.size_bytes(), + channel_count, in_data.data(), header.size, + shared_buffer.get(), time_taken, reset)); + + std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); + + *out_data_size = header.size + sizeof(OpusPacketHeader); + *out_sample_count = out_samples; + if (out_time_taken) { + *out_time_taken = time_taken / 1000; + } + R_SUCCEED(); +} + +Result OpusDecoder::SetContext([[maybe_unused]] std::span context) { + R_SUCCEED_IF(shared_memory_mapped); + shared_memory_mapped = true; + R_RETURN(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); +} + +Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, + u32* out_sample_count, + std::span input_data, + std::span output_data, bool reset) { + u32 out_samples; + u64 time_taken{}; + + R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); + + auto* header_p{reinterpret_cast(input_data.data())}; + OpusPacketHeader header{ReverseHeader(*header_p)}; + + LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", + header.size, input_data.size_bytes(), in_data.size_bytes()); + + R_UNLESS(in_data.size_bytes() >= header.size && + header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), + ResultBufferTooSmall); + + if (!shared_memory_mapped) { + R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); + shared_memory_mapped = true; + } + + std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); + + R_TRY(hardware_opus.DecodeInterleavedForMultiStream( + out_samples, out_data.data(), out_data.size_bytes(), channel_count, in_data.data(), + header.size, shared_buffer.get(), time_taken, reset)); + + std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); + + *out_data_size = header.size + sizeof(OpusPacketHeader); + *out_sample_count = out_samples; + if (out_time_taken) { + *out_time_taken = time_taken / 1000; + } + R_SUCCEED(); +} + +} // namespace AudioCore::OpusDecoder diff --git a/src/audio_core/opus/decoder.h b/src/audio_core/opus/decoder.h index d08d8a4a4..fd728958a 100644 --- a/src/audio_core/opus/decoder.h +++ b/src/audio_core/opus/decoder.h @@ -1,53 +1,53 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "audio_core/opus/parameters.h" -#include "common/common_types.h" -#include "core/hle/kernel/k_transfer_memory.h" -#include "core/hle/service/audio/errors.h" - -namespace Core { -class System; -} - -namespace AudioCore::OpusDecoder { -class HardwareOpus; - -class OpusDecoder { -public: - explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_); - ~OpusDecoder(); - - Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, - u64 transfer_memory_size); - Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory, - u64 transfer_memory_size); - Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count, - std::span input_data, std::span output_data, bool reset); - Result SetContext([[maybe_unused]] std::span context); - Result DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, - u32* out_sample_count, std::span input_data, - std::span output_data, bool reset); - -private: - Core::System& system; - HardwareOpus& hardware_opus; - std::unique_ptr shared_buffer{}; - u64 shared_buffer_size; - std::span in_data{}; - std::span out_data{}; - u64 buffer_size{}; - s32 sample_rate{}; - s32 channel_count{}; - bool use_large_frame_size{false}; - s32 total_stream_count{}; - s32 stereo_stream_count{}; - bool shared_memory_mapped{false}; - bool decode_object_initialized{false}; -}; - -} // namespace AudioCore::OpusDecoder +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "audio_core/opus/parameters.h" +#include "common/common_types.h" +#include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/audio/errors.h" + +namespace Core { +class System; +} + +namespace AudioCore::OpusDecoder { +class HardwareOpus; + +class OpusDecoder { +public: + explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_); + ~OpusDecoder(); + + Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, + u64 transfer_memory_size); + Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory, + u64 transfer_memory_size); + Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count, + std::span input_data, std::span output_data, bool reset); + Result SetContext([[maybe_unused]] std::span context); + Result DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, + u32* out_sample_count, std::span input_data, + std::span output_data, bool reset); + +private: + Core::System& system; + HardwareOpus& hardware_opus; + std::unique_ptr shared_buffer{}; + u64 shared_buffer_size; + std::span in_data{}; + std::span out_data{}; + u64 buffer_size{}; + s32 sample_rate{}; + s32 channel_count{}; + bool use_large_frame_size{false}; + s32 total_stream_count{}; + s32 stereo_stream_count{}; + bool shared_memory_mapped{false}; + bool decode_object_initialized{false}; +}; + +} // namespace AudioCore::OpusDecoder diff --git a/src/audio_core/opus/decoder_manager.cpp b/src/audio_core/opus/decoder_manager.cpp index fdeccdf50..1464880a1 100644 --- a/src/audio_core/opus/decoder_manager.cpp +++ b/src/audio_core/opus/decoder_manager.cpp @@ -1,102 +1,102 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "audio_core/adsp/apps/opus/opus_decoder.h" -#include "audio_core/opus/decoder_manager.h" -#include "common/alignment.h" -#include "core/core.h" - -namespace AudioCore::OpusDecoder { -using namespace Service::Audio; - -namespace { -bool IsValidChannelCount(u32 channel_count) { - return channel_count == 1 || channel_count == 2; -} - -bool IsValidMultiStreamChannelCount(u32 channel_count) { - return channel_count > 0 && channel_count <= OpusStreamCountMax; -} - -bool IsValidSampleRate(u32 sample_rate) { - return sample_rate == 8'000 || sample_rate == 12'000 || sample_rate == 16'000 || - sample_rate == 24'000 || sample_rate == 48'000; -} - -bool IsValidStreamCount(u32 channel_count, u32 total_stream_count, u32 stereo_stream_count) { - return total_stream_count > 0 && static_cast(stereo_stream_count) >= 0 && - stereo_stream_count <= total_stream_count && - total_stream_count + stereo_stream_count <= channel_count; -} - -} // namespace - -OpusDecoderManager::OpusDecoderManager(Core::System& system_) - : system{system_}, hardware_opus{system} { - for (u32 i = 0; i < MaxChannels; i++) { - required_workbuffer_sizes[i] = hardware_opus.GetWorkBufferSize(1 + i); - } -} - -Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) { - OpusParametersEx ex{ - .sample_rate = params.sample_rate, - .channel_count = params.channel_count, - .use_large_frame_size = false, - }; - R_RETURN(GetWorkBufferSizeExEx(ex, out_size)); -} - -Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) { - R_RETURN(GetWorkBufferSizeExEx(params, out_size)); -} - -Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) { - R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount); - R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); - - auto work_buffer_size{required_workbuffer_sizes[params.channel_count - 1]}; - auto frame_size{params.use_large_frame_size ? 5760 : 1920}; - work_buffer_size += - Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64); - out_size = work_buffer_size + 0x600; - R_SUCCEED(); -} - -Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, - u64& out_size) { - OpusMultiStreamParametersEx ex{ - .sample_rate = params.sample_rate, - .channel_count = params.channel_count, - .total_stream_count = params.total_stream_count, - .stereo_stream_count = params.stereo_stream_count, - .use_large_frame_size = false, - .mappings = {}, - }; - R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size)); -} - -Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, - u64& out_size) { - R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size)); -} - -Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, - u64& out_size) { - R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount); - R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); - R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count, - params.stereo_stream_count), - ResultInvalidOpusSampleRate); - - auto work_buffer_size{hardware_opus.GetWorkBufferSizeForMultiStream( - params.total_stream_count, params.stereo_stream_count)}; - auto frame_size{params.use_large_frame_size ? 5760 : 1920}; - work_buffer_size += Common::AlignUp(1500 * params.total_stream_count, 64); - work_buffer_size += - Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64); - out_size = work_buffer_size; - R_SUCCEED(); -} - -} // namespace AudioCore::OpusDecoder +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "audio_core/adsp/apps/opus/opus_decoder.h" +#include "audio_core/opus/decoder_manager.h" +#include "common/alignment.h" +#include "core/core.h" + +namespace AudioCore::OpusDecoder { +using namespace Service::Audio; + +namespace { +bool IsValidChannelCount(u32 channel_count) { + return channel_count == 1 || channel_count == 2; +} + +bool IsValidMultiStreamChannelCount(u32 channel_count) { + return channel_count > 0 && channel_count <= OpusStreamCountMax; +} + +bool IsValidSampleRate(u32 sample_rate) { + return sample_rate == 8'000 || sample_rate == 12'000 || sample_rate == 16'000 || + sample_rate == 24'000 || sample_rate == 48'000; +} + +bool IsValidStreamCount(u32 channel_count, u32 total_stream_count, u32 stereo_stream_count) { + return total_stream_count > 0 && static_cast(stereo_stream_count) >= 0 && + stereo_stream_count <= total_stream_count && + total_stream_count + stereo_stream_count <= channel_count; +} + +} // namespace + +OpusDecoderManager::OpusDecoderManager(Core::System& system_) + : system{system_}, hardware_opus{system} { + for (u32 i = 0; i < MaxChannels; i++) { + required_workbuffer_sizes[i] = hardware_opus.GetWorkBufferSize(1 + i); + } +} + +Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) { + OpusParametersEx ex{ + .sample_rate = params.sample_rate, + .channel_count = params.channel_count, + .use_large_frame_size = false, + }; + R_RETURN(GetWorkBufferSizeExEx(ex, out_size)); +} + +Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) { + R_RETURN(GetWorkBufferSizeExEx(params, out_size)); +} + +Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) { + R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount); + R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); + + auto work_buffer_size{required_workbuffer_sizes[params.channel_count - 1]}; + auto frame_size{params.use_large_frame_size ? 5760 : 1920}; + work_buffer_size += + Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64); + out_size = work_buffer_size + 0x600; + R_SUCCEED(); +} + +Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, + u64& out_size) { + OpusMultiStreamParametersEx ex{ + .sample_rate = params.sample_rate, + .channel_count = params.channel_count, + .total_stream_count = params.total_stream_count, + .stereo_stream_count = params.stereo_stream_count, + .use_large_frame_size = false, + .mappings = {}, + }; + R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size)); +} + +Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, + u64& out_size) { + R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size)); +} + +Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, + u64& out_size) { + R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount); + R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); + R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count, + params.stereo_stream_count), + ResultInvalidOpusSampleRate); + + auto work_buffer_size{hardware_opus.GetWorkBufferSizeForMultiStream( + params.total_stream_count, params.stereo_stream_count)}; + auto frame_size{params.use_large_frame_size ? 5760 : 1920}; + work_buffer_size += Common::AlignUp(1500 * params.total_stream_count, 64); + work_buffer_size += + Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64); + out_size = work_buffer_size; + R_SUCCEED(); +} + +} // namespace AudioCore::OpusDecoder diff --git a/src/audio_core/opus/decoder_manager.h b/src/audio_core/opus/decoder_manager.h index 466e1967b..70ebc4bab 100644 --- a/src/audio_core/opus/decoder_manager.h +++ b/src/audio_core/opus/decoder_manager.h @@ -1,38 +1,38 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "audio_core/opus/hardware_opus.h" -#include "audio_core/opus/parameters.h" -#include "common/common_types.h" -#include "core/hle/service/audio/errors.h" - -namespace Core { -class System; -} - -namespace AudioCore::OpusDecoder { - -class OpusDecoderManager { -public: - OpusDecoderManager(Core::System& system); - - HardwareOpus& GetHardwareOpus() { - return hardware_opus; - } - - Result GetWorkBufferSize(OpusParameters& params, u64& out_size); - Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size); - Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size); - Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size); - Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size); - Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size); - -private: - Core::System& system; - HardwareOpus hardware_opus; - std::array required_workbuffer_sizes{}; -}; - -} // namespace AudioCore::OpusDecoder +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "audio_core/opus/hardware_opus.h" +#include "audio_core/opus/parameters.h" +#include "common/common_types.h" +#include "core/hle/service/audio/errors.h" + +namespace Core { +class System; +} + +namespace AudioCore::OpusDecoder { + +class OpusDecoderManager { +public: + OpusDecoderManager(Core::System& system); + + HardwareOpus& GetHardwareOpus() { + return hardware_opus; + } + + Result GetWorkBufferSize(OpusParameters& params, u64& out_size); + Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size); + Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size); + Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size); + Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size); + Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size); + +private: + Core::System& system; + HardwareOpus hardware_opus; + std::array required_workbuffer_sizes{}; +}; + +} // namespace AudioCore::OpusDecoder diff --git a/src/audio_core/opus/hardware_opus.cpp b/src/audio_core/opus/hardware_opus.cpp index d6544dcb0..5ff71ab2d 100644 --- a/src/audio_core/opus/hardware_opus.cpp +++ b/src/audio_core/opus/hardware_opus.cpp @@ -1,241 +1,241 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "audio_core/audio_core.h" -#include "audio_core/opus/hardware_opus.h" -#include "core/core.h" - -namespace AudioCore::OpusDecoder { -namespace { -using namespace Service::Audio; - -static constexpr Result ResultCodeFromLibOpusErrorCode(u64 error_code) { - s32 error{static_cast(error_code)}; - ASSERT(error <= OPUS_OK); - switch (error) { - case OPUS_ALLOC_FAIL: - R_THROW(ResultLibOpusAllocFail); - case OPUS_INVALID_STATE: - R_THROW(ResultLibOpusInvalidState); - case OPUS_UNIMPLEMENTED: - R_THROW(ResultLibOpusUnimplemented); - case OPUS_INVALID_PACKET: - R_THROW(ResultLibOpusInvalidPacket); - case OPUS_INTERNAL_ERROR: - R_THROW(ResultLibOpusInternalError); - case OPUS_BUFFER_TOO_SMALL: - R_THROW(ResultBufferTooSmall); - case OPUS_BAD_ARG: - R_THROW(ResultLibOpusBadArg); - case OPUS_OK: - R_RETURN(ResultSuccess); - } - UNREACHABLE(); -} - -} // namespace - -HardwareOpus::HardwareOpus(Core::System& system_) - : system{system_}, opus_decoder{system.AudioCore().ADSP().OpusDecoder()} { - opus_decoder.SetSharedMemory(shared_memory); -} - -u64 HardwareOpus::GetWorkBufferSize(u32 channel) { - if (!opus_decoder.IsRunning()) { - return 0; - } - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = channel; - opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::GetWorkBufferSize); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg); - return 0; - } - return shared_memory.dsp_return_data[0]; -} - -u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = total_stream_count; - shared_memory.host_send_data[1] = stereo_stream_count; - opus_decoder.Send(ADSP::Direction::DSP, - ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStream); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg); - return 0; - } - return shared_memory.dsp_return_data[0]; -} - -Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, - u64 buffer_size) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = buffer_size; - shared_memory.host_send_data[2] = sample_rate; - shared_memory.host_send_data[3] = channel_count; - - opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::InitializeDecodeObject); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::InitializeDecodeObjectOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::InitializeDecodeObjectOK, msg); - R_THROW(ResultInvalidOpusDSPReturnCode); - } - - R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); -} - -Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, - u32 total_stream_count, - u32 stereo_stream_count, void* mappings, - void* buffer, u64 buffer_size) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = buffer_size; - shared_memory.host_send_data[2] = sample_rate; - shared_memory.host_send_data[3] = channel_count; - shared_memory.host_send_data[4] = total_stream_count; - shared_memory.host_send_data[5] = stereo_stream_count; - - ASSERT(channel_count <= MaxChannels); - std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8)); - - opus_decoder.Send(ADSP::Direction::DSP, - ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObject); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK, msg); - R_THROW(ResultInvalidOpusDSPReturnCode); - } - - R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); -} - -Result HardwareOpus::ShutdownDecodeObject(void* buffer, u64 buffer_size) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = buffer_size; - - opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::ShutdownDecodeObject); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, - "Expected Opus shutdown code {}, got {}", - ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, msg); - - R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); -} - -Result HardwareOpus::ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = buffer_size; - - opus_decoder.Send(ADSP::Direction::DSP, - ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObject); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, - "Expected Opus shutdown code {}, got {}", - ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, msg); - - R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); -} - -Result HardwareOpus::DecodeInterleaved(u32& out_sample_count, void* output_data, - u64 output_data_size, u32 channel_count, void* input_data, - u64 input_data_size, void* buffer, u64& out_time_taken, - bool reset) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = (u64)input_data; - shared_memory.host_send_data[2] = input_data_size; - shared_memory.host_send_data[3] = (u64)output_data; - shared_memory.host_send_data[4] = output_data_size; - shared_memory.host_send_data[5] = 0; - shared_memory.host_send_data[6] = reset; - - opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::DecodeInterleaved); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::DecodeInterleavedOK, msg); - R_THROW(ResultInvalidOpusDSPReturnCode); - } - - auto error_code{static_cast(shared_memory.dsp_return_data[0])}; - if (error_code == OPUS_OK) { - out_sample_count = static_cast(shared_memory.dsp_return_data[1]); - out_time_taken = 1000 * shared_memory.dsp_return_data[2]; - } - R_RETURN(ResultCodeFromLibOpusErrorCode(error_code)); -} - -Result HardwareOpus::DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, - u64 output_data_size, u32 channel_count, - void* input_data, u64 input_data_size, - void* buffer, u64& out_time_taken, - bool reset) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = (u64)input_data; - shared_memory.host_send_data[2] = input_data_size; - shared_memory.host_send_data[3] = (u64)output_data; - shared_memory.host_send_data[4] = output_data_size; - shared_memory.host_send_data[5] = 0; - shared_memory.host_send_data[6] = reset; - - opus_decoder.Send(ADSP::Direction::DSP, - ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStream); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK, msg); - R_THROW(ResultInvalidOpusDSPReturnCode); - } - - auto error_code{static_cast(shared_memory.dsp_return_data[0])}; - if (error_code == OPUS_OK) { - out_sample_count = static_cast(shared_memory.dsp_return_data[1]); - out_time_taken = 1000 * shared_memory.dsp_return_data[2]; - } - R_RETURN(ResultCodeFromLibOpusErrorCode(error_code)); -} - -Result HardwareOpus::MapMemory(void* buffer, u64 buffer_size) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = buffer_size; - - opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::MapMemory); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::MapMemoryOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::MapMemoryOK, msg); - R_THROW(ResultInvalidOpusDSPReturnCode); - } - R_SUCCEED(); -} - -Result HardwareOpus::UnmapMemory(void* buffer, u64 buffer_size) { - std::scoped_lock l{mutex}; - shared_memory.host_send_data[0] = (u64)buffer; - shared_memory.host_send_data[1] = buffer_size; - - opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::UnmapMemory); - auto msg = opus_decoder.Receive(ADSP::Direction::Host); - if (msg != ADSP::OpusDecoder::Message::UnmapMemoryOK) { - LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", - ADSP::OpusDecoder::Message::UnmapMemoryOK, msg); - R_THROW(ResultInvalidOpusDSPReturnCode); - } - R_SUCCEED(); -} - -} // namespace AudioCore::OpusDecoder +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "audio_core/audio_core.h" +#include "audio_core/opus/hardware_opus.h" +#include "core/core.h" + +namespace AudioCore::OpusDecoder { +namespace { +using namespace Service::Audio; + +static constexpr Result ResultCodeFromLibOpusErrorCode(u64 error_code) { + s32 error{static_cast(error_code)}; + ASSERT(error <= OPUS_OK); + switch (error) { + case OPUS_ALLOC_FAIL: + R_THROW(ResultLibOpusAllocFail); + case OPUS_INVALID_STATE: + R_THROW(ResultLibOpusInvalidState); + case OPUS_UNIMPLEMENTED: + R_THROW(ResultLibOpusUnimplemented); + case OPUS_INVALID_PACKET: + R_THROW(ResultLibOpusInvalidPacket); + case OPUS_INTERNAL_ERROR: + R_THROW(ResultLibOpusInternalError); + case OPUS_BUFFER_TOO_SMALL: + R_THROW(ResultBufferTooSmall); + case OPUS_BAD_ARG: + R_THROW(ResultLibOpusBadArg); + case OPUS_OK: + R_RETURN(ResultSuccess); + } + UNREACHABLE(); +} + +} // namespace + +HardwareOpus::HardwareOpus(Core::System& system_) + : system{system_}, opus_decoder{system.AudioCore().ADSP().OpusDecoder()} { + opus_decoder.SetSharedMemory(shared_memory); +} + +u64 HardwareOpus::GetWorkBufferSize(u32 channel) { + if (!opus_decoder.IsRunning()) { + return 0; + } + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = channel; + opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::GetWorkBufferSize); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg); + return 0; + } + return shared_memory.dsp_return_data[0]; +} + +u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = total_stream_count; + shared_memory.host_send_data[1] = stereo_stream_count; + opus_decoder.Send(ADSP::Direction::DSP, + ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStream); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg); + return 0; + } + return shared_memory.dsp_return_data[0]; +} + +Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, + u64 buffer_size) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = buffer_size; + shared_memory.host_send_data[2] = sample_rate; + shared_memory.host_send_data[3] = channel_count; + + opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::InitializeDecodeObject); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::InitializeDecodeObjectOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::InitializeDecodeObjectOK, msg); + R_THROW(ResultInvalidOpusDSPReturnCode); + } + + R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); +} + +Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, + u32 total_stream_count, + u32 stereo_stream_count, void* mappings, + void* buffer, u64 buffer_size) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = buffer_size; + shared_memory.host_send_data[2] = sample_rate; + shared_memory.host_send_data[3] = channel_count; + shared_memory.host_send_data[4] = total_stream_count; + shared_memory.host_send_data[5] = stereo_stream_count; + + ASSERT(channel_count <= MaxChannels); + std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8)); + + opus_decoder.Send(ADSP::Direction::DSP, + ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObject); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK, msg); + R_THROW(ResultInvalidOpusDSPReturnCode); + } + + R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); +} + +Result HardwareOpus::ShutdownDecodeObject(void* buffer, u64 buffer_size) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = buffer_size; + + opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::ShutdownDecodeObject); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, + "Expected Opus shutdown code {}, got {}", + ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, msg); + + R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); +} + +Result HardwareOpus::ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = buffer_size; + + opus_decoder.Send(ADSP::Direction::DSP, + ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObject); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, + "Expected Opus shutdown code {}, got {}", + ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, msg); + + R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); +} + +Result HardwareOpus::DecodeInterleaved(u32& out_sample_count, void* output_data, + u64 output_data_size, u32 channel_count, void* input_data, + u64 input_data_size, void* buffer, u64& out_time_taken, + bool reset) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = (u64)input_data; + shared_memory.host_send_data[2] = input_data_size; + shared_memory.host_send_data[3] = (u64)output_data; + shared_memory.host_send_data[4] = output_data_size; + shared_memory.host_send_data[5] = 0; + shared_memory.host_send_data[6] = reset; + + opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::DecodeInterleaved); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::DecodeInterleavedOK, msg); + R_THROW(ResultInvalidOpusDSPReturnCode); + } + + auto error_code{static_cast(shared_memory.dsp_return_data[0])}; + if (error_code == OPUS_OK) { + out_sample_count = static_cast(shared_memory.dsp_return_data[1]); + out_time_taken = 1000 * shared_memory.dsp_return_data[2]; + } + R_RETURN(ResultCodeFromLibOpusErrorCode(error_code)); +} + +Result HardwareOpus::DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, + u64 output_data_size, u32 channel_count, + void* input_data, u64 input_data_size, + void* buffer, u64& out_time_taken, + bool reset) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = (u64)input_data; + shared_memory.host_send_data[2] = input_data_size; + shared_memory.host_send_data[3] = (u64)output_data; + shared_memory.host_send_data[4] = output_data_size; + shared_memory.host_send_data[5] = 0; + shared_memory.host_send_data[6] = reset; + + opus_decoder.Send(ADSP::Direction::DSP, + ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStream); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK, msg); + R_THROW(ResultInvalidOpusDSPReturnCode); + } + + auto error_code{static_cast(shared_memory.dsp_return_data[0])}; + if (error_code == OPUS_OK) { + out_sample_count = static_cast(shared_memory.dsp_return_data[1]); + out_time_taken = 1000 * shared_memory.dsp_return_data[2]; + } + R_RETURN(ResultCodeFromLibOpusErrorCode(error_code)); +} + +Result HardwareOpus::MapMemory(void* buffer, u64 buffer_size) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = buffer_size; + + opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::MapMemory); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::MapMemoryOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::MapMemoryOK, msg); + R_THROW(ResultInvalidOpusDSPReturnCode); + } + R_SUCCEED(); +} + +Result HardwareOpus::UnmapMemory(void* buffer, u64 buffer_size) { + std::scoped_lock l{mutex}; + shared_memory.host_send_data[0] = (u64)buffer; + shared_memory.host_send_data[1] = buffer_size; + + opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::UnmapMemory); + auto msg = opus_decoder.Receive(ADSP::Direction::Host); + if (msg != ADSP::OpusDecoder::Message::UnmapMemoryOK) { + LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", + ADSP::OpusDecoder::Message::UnmapMemoryOK, msg); + R_THROW(ResultInvalidOpusDSPReturnCode); + } + R_SUCCEED(); +} + +} // namespace AudioCore::OpusDecoder diff --git a/src/audio_core/opus/hardware_opus.h b/src/audio_core/opus/hardware_opus.h index 7013a6b40..b10184baa 100644 --- a/src/audio_core/opus/hardware_opus.h +++ b/src/audio_core/opus/hardware_opus.h @@ -1,45 +1,45 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "audio_core/adsp/apps/opus/opus_decoder.h" -#include "audio_core/adsp/apps/opus/shared_memory.h" -#include "audio_core/adsp/mailbox.h" -#include "core/hle/service/audio/errors.h" - -namespace AudioCore::OpusDecoder { -class HardwareOpus { -public: - HardwareOpus(Core::System& system); - - u64 GetWorkBufferSize(u32 channel); - u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count); - - Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, - u64 buffer_size); - Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, - u32 totaL_stream_count, u32 stereo_stream_count, - void* mappings, void* buffer, u64 buffer_size); - Result ShutdownDecodeObject(void* buffer, u64 buffer_size); - Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size); - Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size, - u32 channel_count, void* input_data, u64 input_data_size, void* buffer, - u64& out_time_taken, bool reset); - Result DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, - u64 output_data_size, u32 channel_count, - void* input_data, u64 input_data_size, void* buffer, - u64& out_time_taken, bool reset); - Result MapMemory(void* buffer, u64 buffer_size); - Result UnmapMemory(void* buffer, u64 buffer_size); - -private: - Core::System& system; - std::mutex mutex; - ADSP::OpusDecoder::OpusDecoder& opus_decoder; - ADSP::OpusDecoder::SharedMemory shared_memory; -}; -} // namespace AudioCore::OpusDecoder +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "audio_core/adsp/apps/opus/opus_decoder.h" +#include "audio_core/adsp/apps/opus/shared_memory.h" +#include "audio_core/adsp/mailbox.h" +#include "core/hle/service/audio/errors.h" + +namespace AudioCore::OpusDecoder { +class HardwareOpus { +public: + HardwareOpus(Core::System& system); + + u64 GetWorkBufferSize(u32 channel); + u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count); + + Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, + u64 buffer_size); + Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, + u32 totaL_stream_count, u32 stereo_stream_count, + void* mappings, void* buffer, u64 buffer_size); + Result ShutdownDecodeObject(void* buffer, u64 buffer_size); + Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size); + Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size, + u32 channel_count, void* input_data, u64 input_data_size, void* buffer, + u64& out_time_taken, bool reset); + Result DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, + u64 output_data_size, u32 channel_count, + void* input_data, u64 input_data_size, void* buffer, + u64& out_time_taken, bool reset); + Result MapMemory(void* buffer, u64 buffer_size); + Result UnmapMemory(void* buffer, u64 buffer_size); + +private: + Core::System& system; + std::mutex mutex; + ADSP::OpusDecoder::OpusDecoder& opus_decoder; + ADSP::OpusDecoder::SharedMemory shared_memory; +}; +} // namespace AudioCore::OpusDecoder -- cgit v1.2.3