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>
xbzk/reconfigure-controllers-disconnect-fix
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