Browse Source
Revert "[audio] Replace libopus with FFmpeg (#4169)" (#4419)
Revert "[audio] Replace libopus with FFmpeg (#4169)" (#4419)
This reverts commit ff8368c606.
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
-------------------
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4419
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
master
committed by
crueter
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
22 changed files with 904 additions and 429 deletions
-
28.patch/opus/0001-disable-clang-runtime-neon.patch
-
153.patch/opus/0002-no-install.patch
-
15CMakeLists.txt
-
22CMakeModules/find/FindOpus.cmake
-
17cpmfile.json
-
19docs/Deps.md
-
2shell.nix
-
7src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LicensesFragment.kt
-
45src/android/app/src/main/res/values/strings.xml
-
14src/audio_core/CMakeLists.txt
-
110src/audio_core/adsp/apps/opus/opus_decode_object.cpp
-
41src/audio_core/adsp/apps/opus/opus_decode_object.h
-
569src/audio_core/adsp/apps/opus/opus_decoder.cpp
-
27src/audio_core/adsp/apps/opus/opus_decoder.h
-
113src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp
-
42src/audio_core/adsp/apps/opus/opus_multistream_decode_object.h
-
32src/audio_core/adsp/apps/opus/opus_types.h
-
1src/audio_core/adsp/apps/opus/shared_memory.h
-
71src/audio_core/opus/hardware_opus.cpp
-
2src/audio_core/opus/hardware_opus.h
-
1src/core/CMakeLists.txt
-
2src/video_core/CMakeLists.txt
@ -0,0 +1,28 @@ |
|||
From cc15da16e533b2a801934eab2dfeaf3c3949a1dc Mon Sep 17 00:00:00 2001 |
|||
From: crueter <crueter@eden-emu.dev> |
|||
Date: Mon, 8 Sep 2025 12:28:55 -0400 |
|||
Subject: [PATCH] [cmake] disable NEON runtime check on clang-cl |
|||
|
|||
When enabling runtime NEON checking for clang-cl, the linker would error out with `undefined symbol: __emit`, since clang doesn't actually implement this instruction. Therefore it makes sense to disable the runtime check by default on this platform, until either this is fixed or a clang-cl compatible intrinsic check is added (I don't have enough knowledge of MSVC to do this) |
|||
---
|
|||
cmake/OpusConfig.cmake | 7 ++++++- |
|||
1 file changed, 6 insertions(+), 1 deletion(-) |
|||
|
|||
diff --git a/cmake/OpusConfig.cmake b/cmake/OpusConfig.cmake
|
|||
index e9319fbad..d0f459e88 100644
|
|||
--- a/cmake/OpusConfig.cmake
|
|||
+++ b/cmake/OpusConfig.cmake
|
|||
@@ -71,7 +71,12 @@ elseif(OPUS_CPU_ARM AND NOT OPUS_DISABLE_INTRINSICS)
|
|||
opus_detect_neon(COMPILER_SUPPORT_NEON) |
|||
if(COMPILER_SUPPORT_NEON) |
|||
option(OPUS_USE_NEON "Option to enable NEON" ON) |
|||
- option(OPUS_MAY_HAVE_NEON "Does runtime check for neon support" ON)
|
|||
+ if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|||
+ set(NEON_RUNTIME_CHECK_DEFAULT OFF)
|
|||
+ else()
|
|||
+ set(NEON_RUNTIME_CHECK_DEFAULT ON)
|
|||
+ endif()
|
|||
+ option(OPUS_MAY_HAVE_NEON "Does runtime check for neon support" ${NEON_RUNTIME_CHECK_DEFAULT})
|
|||
option(OPUS_PRESUME_NEON "Assume target CPU has NEON support" OFF) |
|||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") |
|||
set(OPUS_PRESUME_NEON ON) |
|||
@ -0,0 +1,153 @@ |
|||
From bf455b67b4eaa446ffae5d25410b141b7b1b1082 Mon Sep 17 00:00:00 2001 |
|||
From: crueter <crueter@eden-emu.dev> |
|||
Date: Mon, 8 Sep 2025 12:08:20 -0400 |
|||
Subject: [PATCH] [cmake] `OPUS_INSTALL` option; only default install if root |
|||
project |
|||
|
|||
Signed-off-by: crueter <crueter@eden-emu.dev> |
|||
---
|
|||
CMakeLists.txt | 112 ++++++++++++++++++++++++++++--------------------- |
|||
1 file changed, 64 insertions(+), 48 deletions(-) |
|||
|
|||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|||
index fcf034b19..08b5e16f8 100644
|
|||
--- a/CMakeLists.txt
|
|||
+++ b/CMakeLists.txt
|
|||
@@ -4,6 +4,13 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|||
include(OpusPackageVersion) |
|||
get_package_version(PACKAGE_VERSION PROJECT_VERSION) |
|||
|
|||
+# root project detection
|
|||
+if(DEFINED PROJECT_NAME)
|
|||
+ set(root_project OFF)
|
|||
+else()
|
|||
+ set(root_project ON)
|
|||
+endif()
|
|||
+
|
|||
project(Opus LANGUAGES C VERSION ${PROJECT_VERSION}) |
|||
|
|||
include(OpusFunctions) |
|||
@@ -83,12 +90,16 @@ set(OPUS_DNN_FLOAT_DEBUG_HELP_STR "Run DNN computations as float for debugging p
|
|||
option(OPUS_DNN_FLOAT_DEBUG ${OPUS_DNN_FLOAT_DEBUG_HELP_STR} OFF) |
|||
add_feature_info(OPUS_DNN_FLOAT_DEBUG OPUS_DNN_FLOAT_DEBUG ${OPUS_DNN_FLOAT_DEBUG_HELP_STR}) |
|||
|
|||
+set(OPUS_INSTALL_HELP_STR "Install Opus targets")
|
|||
+option(OPUS_INSTALL ${OPUS_INSTALL_HELP_STR} ${root_project})
|
|||
+add_feature_info(OPUS_INSTALL OPUS_INSTALL ${OPUS_INSTALL_HELP_STR})
|
|||
+
|
|||
set(OPUS_INSTALL_PKG_CONFIG_MODULE_HELP_STR "install pkg-config module.") |
|||
-option(OPUS_INSTALL_PKG_CONFIG_MODULE ${OPUS_INSTALL_PKG_CONFIG_MODULE_HELP_STR} ON)
|
|||
+option(OPUS_INSTALL_PKG_CONFIG_MODULE ${OPUS_INSTALL_PKG_CONFIG_MODULE_HELP_STR} ${OPUS_INSTALL})
|
|||
add_feature_info(OPUS_INSTALL_PKG_CONFIG_MODULE OPUS_INSTALL_PKG_CONFIG_MODULE ${OPUS_INSTALL_PKG_CONFIG_MODULE_HELP_STR}) |
|||
|
|||
set(OPUS_INSTALL_CMAKE_CONFIG_MODULE_HELP_STR "install CMake package config module.") |
|||
-option(OPUS_INSTALL_CMAKE_CONFIG_MODULE ${OPUS_INSTALL_CMAKE_CONFIG_MODULE_HELP_STR} ON)
|
|||
+option(OPUS_INSTALL_CMAKE_CONFIG_MODULE ${OPUS_INSTALL_CMAKE_CONFIG_MODULE_HELP_STR} ${OPUS_INSTALL})
|
|||
add_feature_info(OPUS_INSTALL_CMAKE_CONFIG_MODULE OPUS_INSTALL_CMAKE_CONFIG_MODULE ${OPUS_INSTALL_CMAKE_CONFIG_MODULE_HELP_STR}) |
|||
|
|||
set(OPUS_DRED_HELP_STR "enable DRED.") |
|||
@@ -613,53 +624,58 @@ if(OPUS_BUILD_FRAMEWORK)
|
|||
OUTPUT_NAME Opus) |
|||
endif() |
|||
|
|||
-install(TARGETS opus
|
|||
- EXPORT OpusTargets
|
|||
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|||
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|||
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|||
- FRAMEWORK DESTINATION ${CMAKE_INSTALL_PREFIX}
|
|||
- PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/opus)
|
|||
-
|
|||
-if(OPUS_INSTALL_PKG_CONFIG_MODULE)
|
|||
- set(prefix ${CMAKE_INSTALL_PREFIX})
|
|||
- set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
|||
- set(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
|
|||
- set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
|
|||
- set(VERSION ${PACKAGE_VERSION})
|
|||
- if(HAVE_LIBM)
|
|||
- set(LIBM "-lm")
|
|||
+if (OPUS_INSTALL)
|
|||
+ install(TARGETS opus
|
|||
+ EXPORT OpusTargets
|
|||
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|||
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|||
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|||
+ FRAMEWORK DESTINATION ${CMAKE_INSTALL_PREFIX}
|
|||
+ PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/opus)
|
|||
+
|
|||
+ if(OPUS_INSTALL_PKG_CONFIG_MODULE)
|
|||
+ set(prefix ${CMAKE_INSTALL_PREFIX})
|
|||
+ set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
|||
+ set(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
|
|||
+ set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
|
|||
+ set(VERSION ${PACKAGE_VERSION})
|
|||
+ if(HAVE_LIBM)
|
|||
+ set(LIBM "-lm")
|
|||
+ endif()
|
|||
+ configure_file(opus.pc.in opus.pc)
|
|||
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/opus.pc
|
|||
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
|||
+ endif()
|
|||
+
|
|||
+ if(OPUS_INSTALL_CMAKE_CONFIG_MODULE)
|
|||
+ set(CPACK_GENERATOR TGZ)
|
|||
+ include(CPack)
|
|||
+ set(CMAKE_INSTALL_PACKAGEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
|||
+ install(EXPORT OpusTargets
|
|||
+ NAMESPACE Opus::
|
|||
+ DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
|
|||
+
|
|||
+ include(CMakePackageConfigHelpers)
|
|||
+
|
|||
+ set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
|||
+ configure_package_config_file(
|
|||
+ ${PROJECT_SOURCE_DIR}/cmake/OpusConfig.cmake.in
|
|||
+ OpusConfig.cmake
|
|||
+ INSTALL_DESTINATION
|
|||
+ ${CMAKE_INSTALL_PACKAGEDIR}
|
|||
+ PATH_VARS
|
|||
+ INCLUDE_INSTALL_DIR
|
|||
+ INSTALL_PREFIX
|
|||
+ ${CMAKE_INSTALL_PREFIX})
|
|||
+
|
|||
+ write_basic_package_version_file(OpusConfigVersion.cmake
|
|||
+ VERSION ${PROJECT_VERSION}
|
|||
+ COMPATIBILITY SameMajorVersion)
|
|||
+
|
|||
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/OpusConfig.cmake
|
|||
+ ${CMAKE_CURRENT_BINARY_DIR}/OpusConfigVersion.cmake
|
|||
+ DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
|
|||
endif() |
|||
- configure_file(opus.pc.in opus.pc)
|
|||
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/opus.pc
|
|||
- DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
|||
-endif()
|
|||
-
|
|||
-if(OPUS_INSTALL_CMAKE_CONFIG_MODULE)
|
|||
- set(CPACK_GENERATOR TGZ)
|
|||
- include(CPack)
|
|||
- set(CMAKE_INSTALL_PACKAGEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
|||
- install(EXPORT OpusTargets
|
|||
- NAMESPACE Opus::
|
|||
- DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
|
|||
-
|
|||
- include(CMakePackageConfigHelpers)
|
|||
-
|
|||
- set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
|||
- configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/OpusConfig.cmake.in
|
|||
- OpusConfig.cmake
|
|||
- INSTALL_DESTINATION
|
|||
- ${CMAKE_INSTALL_PACKAGEDIR}
|
|||
- PATH_VARS
|
|||
- INCLUDE_INSTALL_DIR
|
|||
- INSTALL_PREFIX
|
|||
- ${CMAKE_INSTALL_PREFIX})
|
|||
- write_basic_package_version_file(OpusConfigVersion.cmake
|
|||
- VERSION ${PROJECT_VERSION}
|
|||
- COMPATIBILITY SameMajorVersion)
|
|||
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/OpusConfig.cmake
|
|||
- ${CMAKE_CURRENT_BINARY_DIR}/OpusConfigVersion.cmake
|
|||
- DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
|
|||
endif() |
|||
|
|||
if(OPUS_BUILD_PROGRAMS) |
|||
@ -0,0 +1,22 @@ |
|||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
|||
# SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project |
|||
# SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
find_package(PkgConfig QUIET) |
|||
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus) |
|||
|
|||
include(FindPackageHandleStandardArgs) |
|||
find_package_handle_standard_args(Opus |
|||
REQUIRED_VARS OPUS_LINK_LIBRARIES |
|||
VERSION_VAR OPUS_VERSION |
|||
) |
|||
|
|||
if (MSYS2) |
|||
FixMsysPath(PkgConfig::OPUS) |
|||
endif() |
|||
|
|||
if (Opus_FOUND AND NOT TARGET Opus::opus) |
|||
add_library(Opus::opus ALIAS PkgConfig::OPUS) |
|||
endif() |
|||
@ -0,0 +1,110 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "audio_core/adsp/apps/opus/opus_decode_object.h"
|
|||
#include "common/assert.h"
|
|||
|
|||
namespace AudioCore::ADSP::OpusDecoder { |
|||
namespace { |
|||
bool IsValidChannelCount(u32 channel_count) { |
|||
return channel_count == 1 || channel_count == 2; |
|||
} |
|||
} // namespace
|
|||
|
|||
u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) { |
|||
if (!IsValidChannelCount(channel_count)) { |
|||
return 0; |
|||
} |
|||
return static_cast<u32>(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count); |
|||
} |
|||
|
|||
OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) { |
|||
auto* new_decoder = reinterpret_cast<OpusDecodeObject*>(buffer); |
|||
auto* comparison = reinterpret_cast<OpusDecodeObject*>(buffer2); |
|||
|
|||
if (new_decoder->magic == DecodeObjectMagic) { |
|||
if (!new_decoder->initialized || |
|||
(new_decoder->initialized && new_decoder->self == comparison)) { |
|||
new_decoder->state_valid = true; |
|||
} |
|||
} else { |
|||
new_decoder->initialized = false; |
|||
new_decoder->state_valid = true; |
|||
} |
|||
return *new_decoder; |
|||
} |
|||
|
|||
s32 OpusDecodeObject::InitializeDecoder(u32 sample_rate, u32 channel_count) { |
|||
if (!state_valid) { |
|||
return OPUS_INVALID_STATE; |
|||
} |
|||
|
|||
if (initialized) { |
|||
return OPUS_OK; |
|||
} |
|||
|
|||
// Unfortunately libopus does not expose the OpusDecoder struct publicly, so we can't include
|
|||
// it in this class. Nintendo does not allocate memory, which is why we have a workbuffer
|
|||
// provided.
|
|||
// We could use _create and have libopus allocate it for us, but then we have to separately
|
|||
// track which decoder is being used between this and multistream in order to call the correct
|
|||
// destroy from the host side.
|
|||
// This is a bit cringe, but is safe as these objects are only ever initialized inside the given
|
|||
// workbuffer, and GetWorkBufferSize will guarantee there's enough space to follow.
|
|||
decoder = (LibOpusDecoder*)(this + 1); |
|||
s32 ret = opus_decoder_init(decoder, sample_rate, channel_count); |
|||
if (ret == OPUS_OK) { |
|||
magic = DecodeObjectMagic; |
|||
initialized = true; |
|||
state_valid = true; |
|||
self = this; |
|||
final_range = 0; |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
s32 OpusDecodeObject::Shutdown() { |
|||
if (!state_valid) { |
|||
return OPUS_INVALID_STATE; |
|||
} |
|||
|
|||
if (initialized) { |
|||
magic = 0x0; |
|||
initialized = false; |
|||
state_valid = false; |
|||
self = nullptr; |
|||
final_range = 0; |
|||
decoder = nullptr; |
|||
} |
|||
return OPUS_OK; |
|||
} |
|||
|
|||
s32 OpusDecodeObject::ResetDecoder() { |
|||
return opus_decoder_ctl(decoder, OPUS_RESET_STATE); |
|||
} |
|||
|
|||
s32 OpusDecodeObject::Decode(u32& out_sample_count, u64 output_data, u64 output_data_size, |
|||
u64 input_data, u64 input_data_size) { |
|||
ASSERT(initialized); |
|||
out_sample_count = 0; |
|||
|
|||
if (!state_valid) { |
|||
return OPUS_INVALID_STATE; |
|||
} |
|||
|
|||
auto ret_code_or_samples = opus_decode( |
|||
decoder, reinterpret_cast<const u8*>(input_data), static_cast<opus_int32>(input_data_size), |
|||
reinterpret_cast<opus_int16*>(output_data), static_cast<opus_int32>(output_data_size), 0); |
|||
|
|||
if (ret_code_or_samples < OPUS_OK) { |
|||
return ret_code_or_samples; |
|||
} |
|||
|
|||
out_sample_count = ret_code_or_samples; |
|||
return opus_decoder_ctl(decoder, OPUS_GET_FINAL_RANGE_REQUEST, &final_range); |
|||
} |
|||
|
|||
} // namespace AudioCore::ADSP::OpusDecoder
|
|||
@ -0,0 +1,41 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include <opus.h> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
namespace AudioCore::ADSP::OpusDecoder { |
|||
using LibOpusDecoder = ::OpusDecoder; |
|||
static constexpr u32 DecodeObjectMagic = 0xDEADBEEF; |
|||
|
|||
class OpusDecodeObject { |
|||
public: |
|||
static u32 GetWorkBufferSize(u32 channel_count); |
|||
static OpusDecodeObject& Initialize(u64 buffer, u64 buffer2); |
|||
|
|||
s32 InitializeDecoder(u32 sample_rate, u32 channel_count); |
|||
s32 Shutdown(); |
|||
s32 ResetDecoder(); |
|||
s32 Decode(u32& out_sample_count, u64 output_data, u64 output_data_size, u64 input_data, |
|||
u64 input_data_size); |
|||
u32 GetFinalRange() const noexcept { |
|||
return final_range; |
|||
} |
|||
|
|||
private: |
|||
u32 magic; |
|||
bool initialized; |
|||
bool state_valid; |
|||
OpusDecodeObject* self; |
|||
u32 final_range; |
|||
LibOpusDecoder* decoder; |
|||
}; |
|||
static_assert(std::is_trivially_constructible_v<OpusDecodeObject>); |
|||
|
|||
} // namespace AudioCore::ADSP::OpusDecoder |
|||
@ -0,0 +1,113 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
|||
#include "audio_core/adsp/apps/opus/opus_multistream_decode_object.h"
|
|||
#include "common/assert.h"
|
|||
|
|||
namespace AudioCore::ADSP::OpusDecoder { |
|||
|
|||
namespace { |
|||
constexpr u32 OpusStreamCountMax = 255; |
|||
|
|||
bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { |
|||
return total_stream_count > 0 && total_stream_count <= OpusStreamCountMax && |
|||
static_cast<s32>(stereo_stream_count) >= 0 && |
|||
stereo_stream_count <= total_stream_count; |
|||
} |
|||
} // namespace
|
|||
|
|||
u32 OpusMultiStreamDecodeObject::GetWorkBufferSize(u32 total_stream_count, |
|||
u32 stereo_stream_count) { |
|||
if (IsValidStreamCounts(total_stream_count, stereo_stream_count)) { |
|||
return static_cast<u32>(sizeof(OpusMultiStreamDecodeObject)) + |
|||
opus_multistream_decoder_get_size(total_stream_count, stereo_stream_count); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
OpusMultiStreamDecodeObject& OpusMultiStreamDecodeObject::Initialize(u64 buffer, u64 buffer2) { |
|||
auto* new_decoder = reinterpret_cast<OpusMultiStreamDecodeObject*>(buffer); |
|||
auto* comparison = reinterpret_cast<OpusMultiStreamDecodeObject*>(buffer2); |
|||
|
|||
if (new_decoder->magic == DecodeMultiStreamObjectMagic) { |
|||
if (!new_decoder->initialized || |
|||
(new_decoder->initialized && new_decoder->self == comparison)) { |
|||
new_decoder->state_valid = true; |
|||
} |
|||
} else { |
|||
new_decoder->initialized = false; |
|||
new_decoder->state_valid = true; |
|||
} |
|||
return *new_decoder; |
|||
} |
|||
|
|||
s32 OpusMultiStreamDecodeObject::InitializeDecoder(u32 sample_rate, u32 total_stream_count, |
|||
u32 channel_count, u32 stereo_stream_count, |
|||
u8* mappings) { |
|||
if (!state_valid) { |
|||
return OPUS_INVALID_STATE; |
|||
} |
|||
|
|||
if (initialized) { |
|||
return OPUS_OK; |
|||
} |
|||
|
|||
// See OpusDecodeObject::InitializeDecoder for an explanation of this
|
|||
decoder = (LibOpusMSDecoder*)(this + 1); |
|||
s32 ret = opus_multistream_decoder_init(decoder, sample_rate, channel_count, total_stream_count, |
|||
stereo_stream_count, mappings); |
|||
if (ret == OPUS_OK) { |
|||
magic = DecodeMultiStreamObjectMagic; |
|||
initialized = true; |
|||
state_valid = true; |
|||
self = this; |
|||
final_range = 0; |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
s32 OpusMultiStreamDecodeObject::Shutdown() { |
|||
if (!state_valid) { |
|||
return OPUS_INVALID_STATE; |
|||
} |
|||
|
|||
if (initialized) { |
|||
magic = 0x0; |
|||
initialized = false; |
|||
state_valid = false; |
|||
self = nullptr; |
|||
final_range = 0; |
|||
decoder = nullptr; |
|||
} |
|||
return OPUS_OK; |
|||
} |
|||
|
|||
s32 OpusMultiStreamDecodeObject::ResetDecoder() { |
|||
return opus_multistream_decoder_ctl(decoder, OPUS_RESET_STATE); |
|||
} |
|||
|
|||
s32 OpusMultiStreamDecodeObject::Decode(u32& out_sample_count, u64 output_data, |
|||
u64 output_data_size, u64 input_data, u64 input_data_size) { |
|||
ASSERT(initialized); |
|||
out_sample_count = 0; |
|||
|
|||
if (!state_valid) { |
|||
return OPUS_INVALID_STATE; |
|||
} |
|||
|
|||
auto ret_code_or_samples = opus_multistream_decode( |
|||
decoder, reinterpret_cast<const u8*>(input_data), static_cast<opus_int32>(input_data_size), |
|||
reinterpret_cast<opus_int16*>(output_data), static_cast<opus_int32>(output_data_size), 0); |
|||
|
|||
if (ret_code_or_samples < OPUS_OK) { |
|||
return ret_code_or_samples; |
|||
} |
|||
|
|||
out_sample_count = ret_code_or_samples; |
|||
return opus_multistream_decoder_ctl(decoder, OPUS_GET_FINAL_RANGE_REQUEST, &final_range); |
|||
} |
|||
|
|||
} // namespace AudioCore::ADSP::OpusDecoder
|
|||
@ -0,0 +1,42 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
|||
// SPDX-License-Identifier: GPL-2.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include <opus_multistream.h> |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
namespace AudioCore::ADSP::OpusDecoder { |
|||
using LibOpusMSDecoder = ::OpusMSDecoder; |
|||
static constexpr u32 DecodeMultiStreamObjectMagic = 0xDEADBEEF; |
|||
|
|||
class OpusMultiStreamDecodeObject { |
|||
public: |
|||
static u32 GetWorkBufferSize(u32 total_stream_count, u32 stereo_stream_count); |
|||
static OpusMultiStreamDecodeObject& Initialize(u64 buffer, u64 buffer2); |
|||
|
|||
s32 InitializeDecoder(u32 sample_rate, u32 total_stream_count, u32 channel_count, |
|||
u32 stereo_stream_count, u8* mappings); |
|||
s32 Shutdown(); |
|||
s32 ResetDecoder(); |
|||
s32 Decode(u32& out_sample_count, u64 output_data, u64 output_data_size, u64 input_data, |
|||
u64 input_data_size); |
|||
u32 GetFinalRange() const noexcept { |
|||
return final_range; |
|||
} |
|||
|
|||
private: |
|||
u32 magic; |
|||
bool initialized; |
|||
bool state_valid; |
|||
OpusMultiStreamDecodeObject* self; |
|||
u32 final_range; |
|||
LibOpusMSDecoder* decoder; |
|||
}; |
|||
static_assert(std::is_trivially_constructible_v<OpusMultiStreamDecodeObject>); |
|||
|
|||
} // namespace AudioCore::ADSP::OpusDecoder |
|||
@ -1,32 +0,0 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
namespace AudioCore::ADSP { |
|||
|
|||
static constexpr u32 DECODE_OBJECT_MAGIC = 0xDEADBEEF; |
|||
struct LibOpusDecoder { |
|||
u32 magic; |
|||
bool initialized; |
|||
bool state_valid; |
|||
LibOpusDecoder* self; |
|||
u32 final_range; |
|||
void* decoder; |
|||
}; |
|||
static_assert(sizeof(LibOpusDecoder) == 32); |
|||
|
|||
static constexpr u32 DECODE_MULTISTREAM_OBJECT_MAGIC = 0xDEADBEEF; |
|||
struct LibOpusMultistreamDecoder { |
|||
u32 magic; |
|||
bool initialized; |
|||
bool state_valid; |
|||
LibOpusMultistreamDecoder* self; |
|||
u32 final_range; |
|||
void* decoder; |
|||
}; |
|||
static_assert(sizeof(LibOpusMultistreamDecoder) == 32); |
|||
|
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue