Compare commits

..

2 Commits

Author SHA1 Message Date
FengChen
20139f8a55 Address feedback 2022-10-17 09:40:44 +08:00
FengChen
d4cb0eac87 video_core: Fix legacy to generic location unpaired 2022-09-20 12:03:31 +08:00
404 changed files with 17207 additions and 26306 deletions

View File

@@ -33,14 +33,16 @@ DESTDIR="$PWD/AppDir" ninja install
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
# Download tools needed to build an AppImage
wget -nc https://raw.githubusercontent.com/yuzu-emu/ext-linux-bin/main/gcc/deploy-linux.sh
wget -nc https://raw.githubusercontent.com/yuzu-emu/AppImageKit-checkrt/old/AppRun.sh
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
# Set executable bit
chmod 755 \
deploy-linux.sh \
AppRun.sh \
AppRun-patched-x86_64 \
exec-x86_64.so \
linuxdeploy-x86_64.AppImage \
linuxdeploy-plugin-qt-x86_64.AppImage
# Workaround for https://github.com/AppImage/AppImageKit/issues/828
export APPIMAGE_EXTRACT_AND_RUN=1
@@ -50,7 +52,7 @@ mkdir -p AppDir/usr/optional/libstdc++
mkdir -p AppDir/usr/optional/libgcc_s
# Deploy yuzu's needed dependencies
DEPLOY_QT=1 ./deploy-linux.sh AppDir/usr/bin/yuzu AppDir
./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt
# Workaround for libQt5MultimediaGstTools indirectly requiring libwayland-client and breaking Vulkan usage on end-user systems
find AppDir -type f -regex '.*libwayland-client\.so.*' -delete -print
@@ -58,6 +60,6 @@ find AppDir -type f -regex '.*libwayland-client\.so.*' -delete -print
# Workaround for building yuzu with GCC 10 but also trying to distribute it to Ubuntu 18.04 et al.
# See https://github.com/darealshinji/AppImageKit-checkrt
cp exec-x86_64.so AppDir/usr/optional/exec.so
cp AppRun.sh AppDir/AppRun
cp AppRun-patched-x86_64 AppDir/AppRun
cp --dereference /usr/lib/x86_64-linux-gnu/libstdc++.so.6 AppDir/usr/optional/libstdc++/libstdc++.so.6
cp --dereference /lib/x86_64-linux-gnu/libgcc_s.so.1 AppDir/usr/optional/libgcc_s/libgcc_s.so.1

View File

@@ -5,24 +5,21 @@
. .ci/scripts/common/pre-upload.sh
APPIMAGE_NAME="yuzu-${RELEASE_NAME}-${GITDATE}-${GITREV}.AppImage"
BASE_NAME="yuzu-linux"
REV_NAME="${BASE_NAME}-${GITDATE}-${GITREV}"
APPIMAGE_NAME="yuzu-${GITDATE}-${GITREV}.AppImage"
REV_NAME="yuzu-linux-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.xz"
COMPRESSION_FLAGS="-cJvf"
if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; then
DIR_NAME="${BASE_NAME}-${RELEASE_NAME}"
if [ "${RELEASE_NAME}" = "mainline" ]; then
DIR_NAME="${REV_NAME}"
else
DIR_NAME="${REV_NAME}-${RELEASE_NAME}"
DIR_NAME="${REV_NAME}_${RELEASE_NAME}"
fi
mkdir "$DIR_NAME"
cp build/bin/yuzu-cmd "$DIR_NAME"
if [ "${RELEASE_NAME}" != "early-access" ] && [ "${RELEASE_NAME}" != "mainline" ]; then
cp build/bin/yuzu "$DIR_NAME"
fi
cp build/bin/yuzu "$DIR_NAME"
# Build an AppImage
cd build
@@ -35,11 +32,6 @@ if ! ./appimagetool-x86_64.AppImage --version; then
export APPIMAGE_EXTRACT_AND_RUN=1
fi
# Don't let AppImageLauncher ask to integrate EA
if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; then
echo "X-AppImage-Integrate=false" >> AppDir/org.yuzu_emu.yuzu.desktop
fi
if [ "${RELEASE_NAME}" = "mainline" ]; then
# Generate update information if releasing to mainline
./appimagetool-x86_64.AppImage -u "gh-releases-zsync|yuzu-emu|yuzu-${RELEASE_NAME}|latest|yuzu-*.AppImage.zsync" AppDir "${APPIMAGE_NAME}"
@@ -54,9 +46,4 @@ if [ -f "build/${APPIMAGE_NAME}.zsync" ]; then
cp "build/${APPIMAGE_NAME}.zsync" "${ARTIFACTS_DIR}/"
fi
# Copy the AppImage to the general release directory and remove git revision info
if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ]; then
cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage"
fi
. .ci/scripts/common/post-upload.sh

View File

@@ -21,7 +21,6 @@ cmake .. \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DENABLE_QT_TRANSLATION=ON \
-DUSE_CCACHE=ON \
-DYUZU_CRASH_DUMPS=ON \
-DYUZU_USE_BUNDLED_SDL2=OFF \
-DYUZU_USE_EXTERNAL_SDL2=OFF \
-DYUZU_TESTS=OFF \

View File

@@ -65,8 +65,8 @@ if ("$env:GITHUB_ACTIONS" -eq "true") {
# None of the other GHA builds are including source, so commenting out today
#Copy-Item $MSVC_SOURCE_TARXZ -Destination "artifacts"
# Debugging symbols
cp .\build\bin\yuzu*.pdb .\artifacts\
# Are debug symbols important?
# cp .\build\bin\yuzu*.pdb .\pdb\
# Write out a tag BUILD_TAG to environment for the Upload step
# We're getting ${{ github.event.number }} as $env:PR_NUMBER"

View File

@@ -9,7 +9,7 @@ parameters:
steps:
- script: choco install vulkan-sdk
displayName: 'Install vulkan-sdk'
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
displayName: 'Configure CMake'
- task: MSBuild@1
displayName: 'Build'

View File

@@ -11,30 +11,9 @@ stages:
- stage: build
displayName: 'build'
jobs:
- job: linux
- job: build
timeoutInMinutes: 120
displayName: 'linux'
pool:
vmImage: ubuntu-latest
strategy:
maxParallel: 10
matrix:
linux:
BuildSuffix: 'linux'
ScriptFolder: 'linux'
steps:
- template: ./templates/sync-source.yml
parameters:
artifactSource: $(parameters.artifactSource)
needSubmodules: 'true'
- template: ./templates/build-single.yml
parameters:
artifactSource: 'false'
cache: $(parameters.cache)
version: $(DisplayVersion)
- job: msvc
timeoutInMinutes: 120
displayName: 'windows'
displayName: 'windows-msvc'
pool:
vmImage: windows-2022
steps:

View File

@@ -104,7 +104,7 @@ jobs:
run: |
glslangValidator --version
mkdir build
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DYUZU_CRASH_DUMPS=ON
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify
- name: Build
run: cmake --build build
- name: Cache Summary

2
.gitignore vendored
View File

@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Build directory
[Bb]uild*/
[Bb]uild/
doc-build/
# Generated source files

View File

@@ -6,7 +6,6 @@ Files: dist/english_plurals/*
dist/icons/controller/*.png
dist/icons/overlay/*.png
dist/languages/*
dist/qt_themes/*/icons/48x48/sd_card.png
dist/qt_themes/*/icons/index.theme
dist/qt_themes/default/style.qss
Copyright: yuzu Emulator Project
@@ -52,8 +51,6 @@ Files: dist/qt_themes/colorful/icons/16x16/lock.png
dist/qt_themes/colorful/icons/48x48/chip.png
dist/qt_themes/colorful/icons/48x48/folder.png
dist/qt_themes/colorful_dark/icons/16x16/lock.png
dist/qt_themes/colorful/icons/16x16/info.png
dist/qt_themes/colorful/icons/16x16/sync.png
Copyright: Icons8
License: MIT
Comment: https://github.com/icons8/flat-color-icons
@@ -69,9 +66,11 @@ Files: dist/qt_themes/*/icons/48x48/no_avatar.png
Copyright: Ionic (http://ionic.io/)
License: MIT
Files: dist/qt_themes/colorful/icons/48x48/star.png
dist/qt_themes/colorful/icons/16x16/checked.png
dist/qt_themes/colorful/icons/16x16/failed.png
Files: dist/qt_themes/*/icons/48x48/sd_card.png
dist/qt_themes/colorful/icons/48x48/star.png
dist/qt_themes/default/icons/16x16/checked.png
dist/qt_themes/default/icons/16x16/failed.png
Copyright: SVG Repo
License: CC0-1.0

View File

@@ -38,8 +38,6 @@ option(YUZU_USE_BUNDLED_OPUS "Compile bundled opus" ON)
option(YUZU_TESTS "Compile tests" ON)
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF)
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ON)
@@ -48,9 +46,6 @@ if (YUZU_USE_BUNDLED_VCPKG)
if (YUZU_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
endif()
if (YUZU_CRASH_DUMPS)
list(APPEND VCPKG_MANIFEST_FEATURES "dbghelp")
endif()
include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
@@ -452,13 +447,6 @@ elseif (WIN32)
# PSAPI is the Process Status API
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
endif()
if (YUZU_CRASH_DUMPS)
find_library(DBGHELP_LIBRARY dbghelp)
if ("${DBGHELP_LIBRARY}" STREQUAL "DBGHELP_LIBRARY-NOTFOUND")
message(FATAL_ERROR "YUZU_CRASH_DUMPS enabled but dbghelp library not found")
endif()
endif()
elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
set(PLATFORM_LIBRARIES rt)
endif()

View File

@@ -7,6 +7,11 @@ function(get_timestamp _var)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
# Find the package here with the known path so that the GetGit commands can find it as well
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
# generate git/build information
include(GetGitRevisionDescription)
if(NOT GIT_REF_SPEC)
@@ -24,7 +29,6 @@ get_timestamp(BUILD_DATE)
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
set(BUILD_ID ${DISPLAY_VERSION})
if (BUILD_REPOSITORY)
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY})
@@ -53,4 +57,6 @@ if (BUILD_REPOSITORY)
endif()
endif()
configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY)
# The variable SRC_DIR must be passed into the script
# (since it uses the current build directory for all values of CMAKE_*_DIR)
configure_file("${SRC_DIR}/src/common/scm_rev.cpp.in" "scm_rev.cpp" @ONLY)

964
dist/languages/ca.ts vendored

File diff suppressed because it is too large Load Diff

964
dist/languages/cs.ts vendored

File diff suppressed because it is too large Load Diff

968
dist/languages/da.ts vendored

File diff suppressed because it is too large Load Diff

1096
dist/languages/de.ts vendored

File diff suppressed because it is too large Load Diff

1019
dist/languages/el.ts vendored

File diff suppressed because it is too large Load Diff

1015
dist/languages/es.ts vendored

File diff suppressed because it is too large Load Diff

1222
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load Diff

964
dist/languages/id.ts vendored

File diff suppressed because it is too large Load Diff

1030
dist/languages/it.ts vendored

File diff suppressed because it is too large Load Diff

1016
dist/languages/ja_JP.ts vendored

File diff suppressed because it is too large Load Diff

1235
dist/languages/ko_KR.ts vendored

File diff suppressed because it is too large Load Diff

964
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load Diff

964
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load Diff

964
dist/languages/pl.ts vendored

File diff suppressed because it is too large Load Diff

1058
dist/languages/pt_BR.ts vendored

File diff suppressed because it is too large Load Diff

1058
dist/languages/pt_PT.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

964
dist/languages/sv.ts vendored

File diff suppressed because it is too large Load Diff

1216
dist/languages/tr_TR.ts vendored

File diff suppressed because it is too large Load Diff

964
dist/languages/vi.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 981 B

View File

@@ -1,6 +1,7 @@
[Icon Theme]
Name=colorful
Comment=Colorful theme
Inherits=default
Directories=16x16,48x48,256x256
[16x16]

View File

@@ -6,20 +6,14 @@ SPDX-License-Identifier: GPL-2.0-or-later
<RCC>
<qresource prefix="icons/colorful">
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/checked.png">icons/16x16/checked.png</file>
<file alias="16x16/connected.png">icons/16x16/connected.png</file>
<file alias="16x16/connected_notification.png">icons/16x16/connected_notification.png</file>
<file alias="16x16/disconnected.png">icons/16x16/disconnected.png</file>
<file alias="16x16/failed.png">icons/16x16/failed.png</file>
<file alias="16x16/info.png">icons/16x16/info.png</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/sync.png">icons/16x16/sync.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>

View File

@@ -5,9 +5,19 @@ SPDX-License-Identifier: GPL-2.0-or-later
<RCC>
<qresource prefix="icons/colorful_dark">
<file alias="16x16/connected.png">../colorful/icons/16x16/connected.png</file>
<file alias="16x16/connected_notification.png">../colorful/icons/16x16/connected_notification.png</file>
<file alias="16x16/disconnected.png">../colorful/icons/16x16/disconnected.png</file>
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
<file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
</qresource>
<qresource prefix="qss_icons">

View File

@@ -5,20 +5,23 @@ SPDX-License-Identifier: GPL-2.0-or-later
<RCC>
<qresource prefix="icons/default">
<!-- "colorful" is now the default theme, add new icons there -->
<file alias="index.theme">icons/index.theme</file>
<file alias="16x16/connected.png">icons/16x16/connected.png</file>
<file alias="16x16/connected_notification.png">icons/16x16/connected_notification.png</file>
<file alias="16x16/disconnected.png">icons/16x16/disconnected.png</file>
<file alias="16x16/checked.png">icons/16x16/checked.png</file>
<file alias="16x16/failed.png">icons/16x16/failed.png</file>
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
<file alias="16x16/connected.png">icons/16x16/connected.png</file>
<file alias="16x16/disconnected.png">icons/16x16/disconnected.png</file>
<file alias="16x16/connected_notification.png">icons/16x16/connected_notification.png</file>
<file alias="16x16/view-refresh.png">icons/16x16/view-refresh.png</file>
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
<file alias="48x48/star.png">icons/48x48/star.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
</qresource>
<qresource prefix="default">
<file>style.qss</file>

View File

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 414 B

View File

Before

Width:  |  Height:  |  Size: 431 B

After

Width:  |  Height:  |  Size: 431 B

View File

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 349 B

View File

Before

Width:  |  Height:  |  Size: 678 B

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 561 B

View File

@@ -1,7 +1,6 @@
[Icon Theme]
Name=default
Comment=default theme
Inherits=colorful
Directories=16x16,48x48,256x256
[16x16]
@@ -11,4 +10,4 @@ Size=16
Size=48
[256x256]
Size=256
Size=256

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 B

After

Width:  |  Height:  |  Size: 587 B

View File

@@ -1,7 +1,7 @@
[Icon Theme]
Name=qdarkstyle
Comment=dark theme
Inherits=colorful
Inherits=default
Directories=16x16,48x48,256x256
[16x16]
@@ -11,4 +11,4 @@ Size=16
Size=48
[256x256]
Size=256
Size=256

View File

@@ -1,7 +1,7 @@
[Icon Theme]
Name=qdarkstyle_midnight_blue
Comment=dark theme
Inherits=colorful
Inherits=default
Directories=16x16,48x48,256x256
[16x16]

View File

@@ -121,7 +121,6 @@ else()
if (ARCHITECTURE_x86_64)
add_compile_options("-mcx16")
add_compile_options("-fwrapv")
endif()
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)

View File

@@ -194,7 +194,6 @@ add_library(audio_core STATIC
sink/sink.h
sink/sink_details.cpp
sink/sink_details.h
sink/sink_stream.cpp
sink/sink_stream.h
)

View File

@@ -8,7 +8,7 @@
namespace AudioCore {
AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>()} {
AudioCore::AudioCore(Core::System& system) : audio_manager{std::make_unique<AudioManager>(system)} {
CreateSinks();
// Must be created after the sinks
adsp = std::make_unique<AudioRenderer::ADSP::ADSP>(system, *output_sink);
@@ -47,12 +47,22 @@ AudioRenderer::ADSP::ADSP& AudioCore::GetADSP() {
return *adsp;
}
void AudioCore::SetNVDECActive(bool active) {
nvdec_active = active;
void AudioCore::PauseSinks(const bool pausing) const {
if (pausing) {
output_sink->PauseStreams();
input_sink->PauseStreams();
} else {
output_sink->UnpauseStreams();
input_sink->UnpauseStreams();
}
}
bool AudioCore::IsNVDECActive() const {
return nvdec_active;
u32 AudioCore::GetStreamQueue() const {
return estimated_queue.load();
}
void AudioCore::SetStreamQueue(u32 size) {
estimated_queue.store(size);
}
} // namespace AudioCore

View File

@@ -17,7 +17,7 @@ namespace AudioCore {
class AudioManager;
/**
* Main audio class, stored inside the core, and holding the audio manager, all sinks, and the ADSP.
* Main audio class, sotred inside the core, and holding the audio manager, all sinks, and the ADSP.
*/
class AudioCore {
public:
@@ -58,16 +58,26 @@ public:
AudioRenderer::ADSP::ADSP& GetADSP();
/**
* Toggle NVDEC state, used to avoid stall in playback.
* Pause the sink. Called from the core.
*
* @param active - Set true if nvdec is active, otherwise false.
* @param pausing - Is this pause due to an actual pause, or shutdown?
* Unfortunately, shutdown also pauses streams, which can cause issues.
*/
void SetNVDECActive(bool active);
void PauseSinks(bool pausing) const;
/**
* Get NVDEC state.
* Get the size of the current stream queue.
*
* @return Current stream queue size.
*/
bool IsNVDECActive() const;
u32 GetStreamQueue() const;
/**
* Get the size of the current stream queue.
*
* @param size - New stream size.
*/
void SetStreamQueue(u32 size);
private:
/**
@@ -83,8 +93,8 @@ private:
std::unique_ptr<Sink::Sink> input_sink;
/// The ADSP in the sysmodule
std::unique_ptr<AudioRenderer::ADSP::ADSP> adsp;
/// Is NVDec currently active?
bool nvdec_active{false};
/// Current size of the stream queue
std::atomic<u32> estimated_queue{0};
};
} // namespace AudioCore

View File

@@ -14,7 +14,7 @@ namespace AudioCore {
* Responsible for the input/output events, set by the stream backend when buffers are consumed, and
* waited on by the audio manager. These callbacks signal the game's events to keep the audio buffer
* recycling going.
* In a real Switch this is not a separate class, and exists entirely within the audio manager.
* In a real Switch this is not a seprate class, and exists entirely within the audio manager.
* On the Switch it's implemented more simply through a MultiWaitEventHolder, where it can
* wait on multiple events at once, and the events are not needed by the backend.
*/
@@ -81,7 +81,7 @@ public:
void ClearEvents();
private:
/// Lock, used by the audio manager
/// Lock, used bythe audio manager
std::mutex event_lock;
/// Array of events, one per system type (see Type), last event is used to terminate
std::array<std::atomic<bool>, 4> events_signalled;

View File

@@ -82,7 +82,7 @@ u32 Manager::GetDeviceNames(std::vector<AudioRenderer::AudioDevice::AudioDeviceN
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
if (input_devices.size() > 1) {
names.emplace_back("Uac");
names.push_back(AudioRenderer::AudioDevice::AudioDeviceName("Uac"));
return 1;
}
return 0;

View File

@@ -59,10 +59,9 @@ public:
/**
* Get a list of audio in device names.
*
* @param names - Output container to write names to.
* @param max_count - Maximum number of device names to write. Unused
* @oaram names - Output container to write names to.
* @param max_count - Maximum numebr of deivce names to write. Unused
* @param filter - Should the list be filtered? Unused.
*
* @return Number of names written.
*/
u32 GetDeviceNames(std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names,

View File

@@ -1,13 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/audio_in_manager.h"
#include "audio_core/audio_manager.h"
#include "audio_core/audio_out_manager.h"
#include "core/core.h"
#include "core/hle/service/audio/errors.h"
namespace AudioCore {
AudioManager::AudioManager() {
AudioManager::AudioManager(Core::System& system_) : system{system_} {
thread = std::jthread([this]() { ThreadFunc(); });
}
@@ -26,7 +27,7 @@ Result AudioManager::SetOutManager(BufferEventFunc buffer_func) {
const auto index{events.GetManagerIndex(Event::Type::AudioOutManager)};
if (buffer_events[index] == nullptr) {
buffer_events[index] = std::move(buffer_func);
buffer_events[index] = buffer_func;
needs_update = true;
events.SetAudioEvent(Event::Type::AudioOutManager, true);
}
@@ -42,7 +43,7 @@ Result AudioManager::SetInManager(BufferEventFunc buffer_func) {
const auto index{events.GetManagerIndex(Event::Type::AudioInManager)};
if (buffer_events[index] == nullptr) {
buffer_events[index] = std::move(buffer_func);
buffer_events[index] = buffer_func;
needs_update = true;
events.SetAudioEvent(Event::Type::AudioInManager, true);
}
@@ -59,21 +60,19 @@ void AudioManager::ThreadFunc() {
running = true;
while (running) {
const auto timed_out{events.Wait(l, std::chrono::seconds(2))};
auto timed_out{events.Wait(l, std::chrono::seconds(2))};
if (events.CheckAudioEventSet(Event::Type::Max)) {
break;
}
for (size_t i = 0; i < buffer_events.size(); i++) {
const auto event_type = static_cast<Event::Type>(i);
if (events.CheckAudioEventSet(event_type) || timed_out) {
if (events.CheckAudioEventSet(Event::Type(i)) || timed_out) {
if (buffer_events[i]) {
buffer_events[i]();
}
}
events.SetAudioEvent(event_type, false);
events.SetAudioEvent(Event::Type(i), false);
}
}
}

View File

@@ -10,11 +10,22 @@
#include <thread>
#include "audio_core/audio_event.h"
#include "core/hle/service/audio/errors.h"
union Result;
namespace Core {
class System;
}
namespace AudioCore {
namespace AudioOut {
class Manager;
}
namespace AudioIn {
class Manager;
}
/**
* The AudioManager's main purpose is to wait for buffer events for the audio in and out managers,
* and call an associated callback to release buffers.
@@ -32,7 +43,7 @@ class AudioManager {
using BufferEventFunc = std::function<void()>;
public:
explicit AudioManager();
explicit AudioManager(Core::System& system);
/**
* Shutdown the audio manager.
@@ -65,10 +76,14 @@ public:
private:
/**
* Main thread, waiting on a manager signal and calling the registered function.
* Main thread, waiting on a manager signal and calling the registered fucntion.
*/
void ThreadFunc();
/// Core system
Core::System& system;
/// Have sessions started palying?
bool sessions_started{};
/// Is the main thread running?
std::atomic<bool> running{};
/// Unused

View File

@@ -74,7 +74,7 @@ void Manager::BufferReleaseAndRegister() {
u32 Manager::GetAudioOutDeviceNames(
std::vector<AudioRenderer::AudioDevice::AudioDeviceName>& names) const {
names.emplace_back("DeviceOut");
names.push_back({"DeviceOut"});
return 1;
}

View File

@@ -25,8 +25,8 @@ SystemManager& Manager::GetSystemManager() {
return *system_manager;
}
Result Manager::GetWorkBufferSize(const AudioRendererParameterInternal& params,
u64& out_count) const {
auto Manager::GetWorkBufferSize(const AudioRendererParameterInternal& params, u64& out_count)
-> Result {
if (!CheckValidRevision(params.revision)) {
return Service::Audio::ERR_INVALID_REVISION;
}
@@ -54,7 +54,7 @@ void Manager::ReleaseSessionId(const s32 session_id) {
session_ids[--session_count] = session_id;
}
u32 Manager::GetSessionCount() const {
u32 Manager::GetSessionCount() {
std::scoped_lock l{session_lock};
return session_count;
}

View File

@@ -46,7 +46,7 @@ public:
* @param out_count - Output size of the required workbuffer.
* @return Result code.
*/
Result GetWorkBufferSize(const AudioRendererParameterInternal& params, u64& out_count) const;
Result GetWorkBufferSize(const AudioRendererParameterInternal& params, u64& out_count);
/**
* Get a new session id.
@@ -60,14 +60,14 @@ public:
*
* @return The number of active sessions.
*/
u32 GetSessionCount() const;
u32 GetSessionCount();
/**
* Add a renderer system to the manager.
* The system will be regularly called to generate commands for the AudioRenderer.
* The system will be reguarly called to generate commands for the AudioRenderer.
*
* @param system - The system to add.
* @return True if the system was successfully added, otherwise false.
* @return True if the system was sucessfully added, otherwise false.
*/
bool AddSystem(System& system);
@@ -75,7 +75,7 @@ public:
* Remove a renderer system from the manager.
*
* @param system - The system to remove.
* @return True if the system was successfully removed, otherwise false.
* @return True if the system was sucessfully removed, otherwise false.
*/
bool RemoveSystem(System& system);
@@ -94,7 +94,7 @@ private:
/// Number of active renderers
u32 session_count{};
/// Lock for interacting with the sessions
mutable std::mutex session_lock{};
std::mutex session_lock{};
/// Regularly generates commands from the registered systems for the AudioRenderer
std::unique_ptr<SystemManager> system_manager{};
};

View File

@@ -8,10 +8,6 @@
namespace AudioCore {
struct AudioBuffer {
/// Timestamp this buffer started playing.
u64 start_timestamp;
/// Timestamp this buffer should finish playing.
u64 end_timestamp;
/// Timestamp this buffer completed playing.
s64 played_timestamp;
/// Game memory address for these samples.

View File

@@ -36,7 +36,7 @@ public:
*
* @param buffer - The new buffer.
*/
void AppendBuffer(const AudioBuffer& buffer) {
void AppendBuffer(AudioBuffer& buffer) {
std::scoped_lock l{lock};
buffers[appended_index] = buffer;
appended_count++;
@@ -58,7 +58,6 @@ public:
if (index < 0) {
index += N;
}
out_buffers.push_back(buffers[index]);
registered_count++;
registered_index = (registered_index + 1) % append_limit;
@@ -88,12 +87,10 @@ public:
/**
* Release all registered buffers.
*
* @param core_timing - The CoreTiming instance
* @param session - The device session
*
* @param timestamp - The released timestamp for this buffer.
* @return Is the buffer was released.
*/
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session) {
bool ReleaseBuffers(Core::Timing::CoreTiming& core_timing, DeviceSession& session) {
std::scoped_lock l{lock};
bool buffer_released{false};
while (registered_count > 0) {
@@ -103,7 +100,7 @@ public:
}
// Check with the backend if this buffer can be released yet.
if (!session.IsBufferConsumed(buffers[index])) {
if (!session.IsBufferConsumed(buffers[index].tag)) {
break;
}
@@ -283,16 +280,6 @@ public:
return true;
}
u64 GetNextTimestamp() const {
// Iterate backwards through the buffer queue, and take the most recent buffer's end
std::scoped_lock l{lock};
auto index{appended_index - 1};
if (index < 0) {
index += append_limit;
}
return buffers[index].end_timestamp;
}
private:
/// Buffer lock
mutable std::recursive_mutex lock{};

View File

@@ -7,20 +7,11 @@
#include "audio_core/device/device_session.h"
#include "audio_core/sink/sink_stream.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/memory.h"
namespace AudioCore {
using namespace std::literals;
constexpr auto INCREMENT_TIME{5ms};
DeviceSession::DeviceSession(Core::System& system_)
: system{system_}, thread_event{Core::Timing::CreateEvent(
"AudioOutSampleTick",
[this](std::uintptr_t, s64 time, std::chrono::nanoseconds) {
return ThreadFunc();
})} {}
DeviceSession::DeviceSession(Core::System& system_) : system{system_} {}
DeviceSession::~DeviceSession() {
Finalize();
@@ -59,26 +50,25 @@ void DeviceSession::Finalize() {
}
void DeviceSession::Start() {
if (stream) {
stream->Start();
system.CoreTiming().ScheduleLoopingEvent(std::chrono::nanoseconds::zero(), INCREMENT_TIME,
thread_event);
}
stream->SetPlayedSampleCount(played_sample_count);
stream->Start();
}
void DeviceSession::Stop() {
if (stream) {
played_sample_count = stream->GetPlayedSampleCount();
stream->Stop();
system.CoreTiming().UnscheduleEvent(thread_event, {});
}
}
void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
for (const auto& buffer : buffers) {
void DeviceSession::AppendBuffers(std::span<AudioBuffer> buffers) const {
auto& memory{system.Memory()};
for (size_t i = 0; i < buffers.size(); i++) {
Sink::SinkBuffer new_buffer{
.frames = buffer.size / (channel_count * sizeof(s16)),
.frames = buffers[i].size / (channel_count * sizeof(s16)),
.frames_played = 0,
.tag = buffer.tag,
.tag = buffers[i].tag,
.consumed = false,
};
@@ -86,22 +76,26 @@ void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
std::vector<s16> samples{};
stream->AppendBuffer(new_buffer, samples);
} else {
std::vector<s16> samples(buffer.size / sizeof(s16));
system.Memory().ReadBlockUnsafe(buffer.samples, samples.data(), buffer.size);
std::vector<s16> samples(buffers[i].size / sizeof(s16));
memory.ReadBlockUnsafe(buffers[i].samples, samples.data(), buffers[i].size);
stream->AppendBuffer(new_buffer, samples);
}
}
}
void DeviceSession::ReleaseBuffer(const AudioBuffer& buffer) const {
void DeviceSession::ReleaseBuffer(AudioBuffer& buffer) const {
if (type == Sink::StreamType::In) {
auto& memory{system.Memory()};
auto samples{stream->ReleaseBuffer(buffer.size / sizeof(s16))};
system.Memory().WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
memory.WriteBlockUnsafe(buffer.samples, samples.data(), buffer.size);
}
}
bool DeviceSession::IsBufferConsumed(const AudioBuffer& buffer) const {
return played_sample_count >= buffer.end_timestamp;
bool DeviceSession::IsBufferConsumed(u64 tag) const {
if (stream) {
return stream->IsBufferConsumed(tag);
}
return true;
}
void DeviceSession::SetVolume(f32 volume) const {
@@ -111,22 +105,10 @@ void DeviceSession::SetVolume(f32 volume) const {
}
u64 DeviceSession::GetPlayedSampleCount() const {
return played_sample_count;
}
std::optional<std::chrono::nanoseconds> DeviceSession::ThreadFunc() {
// Add 5ms of samples at a 48K sample rate.
played_sample_count += 48'000 * INCREMENT_TIME / 1s;
if (type == Sink::StreamType::Out) {
system.AudioCore().GetAudioManager().SetEvent(Event::Type::AudioOutManager, true);
} else {
system.AudioCore().GetAudioManager().SetEvent(Event::Type::AudioInManager, true);
if (stream) {
return stream->GetPlayedSampleCount();
}
return std::nullopt;
}
void DeviceSession::SetRingSize(u32 ring_size) {
stream->SetRingSize(ring_size);
return 0;
}
} // namespace AudioCore

View File

@@ -3,9 +3,6 @@
#pragma once
#include <chrono>
#include <memory>
#include <optional>
#include <span>
#include "audio_core/common/common.h"
@@ -14,13 +11,9 @@
namespace Core {
class System;
namespace Timing {
struct EventType;
} // namespace Timing
} // namespace Core
}
namespace AudioCore {
namespace Sink {
class SinkStream;
struct SinkBuffer;
@@ -62,23 +55,22 @@ public:
*
* @param buffers - The buffers to play.
*/
void AppendBuffers(std::span<const AudioBuffer> buffers) const;
void AppendBuffers(std::span<AudioBuffer> buffers) const;
/**
* (Audio In only) Pop samples from the backend, and write them back to this buffer's address.
*
* @param buffer - The buffer to write to.
*/
void ReleaseBuffer(const AudioBuffer& buffer) const;
void ReleaseBuffer(AudioBuffer& buffer) const;
/**
* Check if the buffer for the given tag has been consumed by the backend.
*
* @param buffer - the buffer to check.
*
* @param tag - Unqiue tag of the buffer to check.
* @return true if the buffer has been consumed, otherwise false.
*/
bool IsBufferConsumed(const AudioBuffer& buffer) const;
bool IsBufferConsumed(u64 tag) const;
/**
* Start this device session, starting the backend stream.
@@ -104,16 +96,6 @@ public:
*/
u64 GetPlayedSampleCount() const;
/*
* CoreTiming callback to increment played_sample_count over time.
*/
std::optional<std::chrono::nanoseconds> ThreadFunc();
/*
* Set the size of the ring buffer.
*/
void SetRingSize(u32 ring_size);
private:
/// System
Core::System& system;
@@ -136,13 +118,9 @@ private:
/// Applet resource user id of this device session
u64 applet_resource_user_id{};
/// Total number of samples played by this device session
std::atomic<u64> played_sample_count{};
/// Event increasing the played sample count every 5ms
std::shared_ptr<Core::Timing::EventType> thread_event;
u64 played_sample_count{};
/// Is this session initialised?
bool initialized{};
/// Buffer queue
std::vector<AudioBuffer> buffer_queue{};
};
} // namespace AudioCore

View File

@@ -72,7 +72,7 @@ Kernel::KReadableEvent& In::GetBufferEvent() {
return event->GetReadableEvent();
}
f32 In::GetVolume() const {
f32 In::GetVolume() {
std::scoped_lock l{parent_mutex};
return system.GetVolume();
}
@@ -82,17 +82,17 @@ void In::SetVolume(f32 volume) {
system.SetVolume(volume);
}
bool In::ContainsAudioBuffer(u64 tag) const {
bool In::ContainsAudioBuffer(u64 tag) {
std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag);
}
u32 In::GetBufferCount() const {
u32 In::GetBufferCount() {
std::scoped_lock l{parent_mutex};
return system.GetBufferCount();
}
u64 In::GetPlayedSampleCount() const {
u64 In::GetPlayedSampleCount() {
std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount();
}

View File

@@ -102,7 +102,7 @@ public:
*
* @return The current volume.
*/
f32 GetVolume() const;
f32 GetVolume();
/**
* Set the system volume.
@@ -117,21 +117,21 @@ public:
* @param tag - The tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag) const;
bool ContainsAudioBuffer(u64 tag);
/**
* Get the maximum number of buffers.
*
* @return The maximum number of buffers.
*/
u32 GetBufferCount() const;
u32 GetBufferCount();
/**
* Get the total played sample count for this audio in.
*
* @return The played sample count.
*/
u64 GetPlayedSampleCount() const;
u64 GetPlayedSampleCount();
private:
/// The AudioIn::Manager this audio in is registered with

View File

@@ -34,16 +34,16 @@ size_t System::GetSessionId() const {
return session_id;
}
std::string_view System::GetDefaultDeviceName() const {
std::string_view System::GetDefaultDeviceName() {
return "BuiltInHeadset";
}
std::string_view System::GetDefaultUacDeviceName() const {
std::string_view System::GetDefaultUacDeviceName() {
return "Uac";
}
Result System::IsConfigValid(const std::string_view device_name,
const AudioInParameter& in_params) const {
const AudioInParameter& in_params) {
if ((device_name.size() > 0) &&
(device_name != GetDefaultDeviceName() && device_name != GetDefaultUacDeviceName())) {
return Service::Audio::ERR_INVALID_DEVICE_NAME;
@@ -93,7 +93,6 @@ Result System::Start() {
std::vector<AudioBuffer> buffers_to_flush{};
buffers.RegisterBuffers(buffers_to_flush);
session->AppendBuffers(buffers_to_flush);
session->SetRingSize(static_cast<u32>(buffers_to_flush.size()));
return ResultSuccess;
}
@@ -113,15 +112,8 @@ bool System::AppendBuffer(const AudioInBuffer& buffer, const u64 tag) {
return false;
}
const auto timestamp{buffers.GetNextTimestamp()};
const AudioBuffer new_buffer{
.start_timestamp = timestamp,
.end_timestamp = timestamp + buffer.size / (channel_count * sizeof(s16)),
.played_timestamp = 0,
.samples = buffer.samples,
.tag = tag,
.size = buffer.size,
};
AudioBuffer new_buffer{
.played_timestamp = 0, .samples = buffer.samples, .tag = tag, .size = buffer.size};
buffers.AppendBuffer(new_buffer);
RegisterBuffers();
@@ -202,11 +194,11 @@ void System::SetVolume(const f32 volume_) {
session->SetVolume(volume_);
}
bool System::ContainsAudioBuffer(const u64 tag) const {
bool System::ContainsAudioBuffer(const u64 tag) {
return buffers.ContainsBuffer(tag);
}
u32 System::GetBufferCount() const {
u32 System::GetBufferCount() {
return buffers.GetAppendedRegisteredCount();
}

View File

@@ -68,7 +68,7 @@ public:
*
* @return The default audio input device name.
*/
std::string_view GetDefaultDeviceName() const;
std::string_view GetDefaultDeviceName();
/**
* Get the default USB audio input device name.
@@ -77,7 +77,7 @@ public:
*
* @return The default USB audio input device name.
*/
std::string_view GetDefaultUacDeviceName() const;
std::string_view GetDefaultUacDeviceName();
/**
* Is the given initialize config valid?
@@ -86,7 +86,7 @@ public:
* @param in_params - Input parameters, see AudioInParameter.
* @return Result code.
*/
Result IsConfigValid(std::string_view device_name, const AudioInParameter& in_params) const;
Result IsConfigValid(std::string_view device_name, const AudioInParameter& in_params);
/**
* Initialize this system.
@@ -208,7 +208,7 @@ public:
/**
* Set this system's current volume.
*
* @param volume The new volume.
* @param The new volume.
*/
void SetVolume(f32 volume);
@@ -218,14 +218,14 @@ public:
* @param tag - Unique tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag) const;
bool ContainsAudioBuffer(u64 tag);
/**
* Get the maximum number of usable buffers (default 32).
*
* @return The number of buffers.
*/
u32 GetBufferCount() const;
u32 GetBufferCount();
/**
* Get the total number of samples played by this system.

View File

@@ -72,7 +72,7 @@ Kernel::KReadableEvent& Out::GetBufferEvent() {
return event->GetReadableEvent();
}
f32 Out::GetVolume() const {
f32 Out::GetVolume() {
std::scoped_lock l{parent_mutex};
return system.GetVolume();
}
@@ -82,17 +82,17 @@ void Out::SetVolume(const f32 volume) {
system.SetVolume(volume);
}
bool Out::ContainsAudioBuffer(const u64 tag) const {
bool Out::ContainsAudioBuffer(const u64 tag) {
std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag);
}
u32 Out::GetBufferCount() const {
u32 Out::GetBufferCount() {
std::scoped_lock l{parent_mutex};
return system.GetBufferCount();
}
u64 Out::GetPlayedSampleCount() const {
u64 Out::GetPlayedSampleCount() {
std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount();
}

View File

@@ -102,7 +102,7 @@ public:
*
* @return The current volume.
*/
f32 GetVolume() const;
f32 GetVolume();
/**
* Set the system volume.
@@ -117,21 +117,21 @@ public:
* @param tag - The tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag) const;
bool ContainsAudioBuffer(u64 tag);
/**
* Get the maximum number of buffers.
*
* @return The maximum number of buffers.
*/
u32 GetBufferCount() const;
u32 GetBufferCount();
/**
* Get the total played sample count for this audio out.
*
* @return The played sample count.
*/
u64 GetPlayedSampleCount() const;
u64 GetPlayedSampleCount();
private:
/// The AudioOut::Manager this audio out is registered with

View File

@@ -27,12 +27,11 @@ void System::Finalize() {
buffer_event->GetWritableEvent().Signal();
}
std::string_view System::GetDefaultOutputDeviceName() const {
std::string_view System::GetDefaultOutputDeviceName() {
return "DeviceOut";
}
Result System::IsConfigValid(std::string_view device_name,
const AudioOutParameter& in_params) const {
Result System::IsConfigValid(std::string_view device_name, const AudioOutParameter& in_params) {
if ((device_name.size() > 0) && (device_name != GetDefaultOutputDeviceName())) {
return Service::Audio::ERR_INVALID_DEVICE_NAME;
}
@@ -93,7 +92,6 @@ Result System::Start() {
std::vector<AudioBuffer> buffers_to_flush{};
buffers.RegisterBuffers(buffers_to_flush);
session->AppendBuffers(buffers_to_flush);
session->SetRingSize(static_cast<u32>(buffers_to_flush.size()));
return ResultSuccess;
}
@@ -113,15 +111,8 @@ bool System::AppendBuffer(const AudioOutBuffer& buffer, u64 tag) {
return false;
}
const auto timestamp{buffers.GetNextTimestamp()};
const AudioBuffer new_buffer{
.start_timestamp = timestamp,
.end_timestamp = timestamp + buffer.size / (channel_count * sizeof(s16)),
.played_timestamp = 0,
.samples = buffer.samples,
.tag = tag,
.size = buffer.size,
};
AudioBuffer new_buffer{
.played_timestamp = 0, .samples = buffer.samples, .tag = tag, .size = buffer.size};
buffers.AppendBuffer(new_buffer);
RegisterBuffers();
@@ -201,11 +192,11 @@ void System::SetVolume(const f32 volume_) {
session->SetVolume(volume_);
}
bool System::ContainsAudioBuffer(const u64 tag) const {
bool System::ContainsAudioBuffer(const u64 tag) {
return buffers.ContainsBuffer(tag);
}
u32 System::GetBufferCount() const {
u32 System::GetBufferCount() {
return buffers.GetAppendedRegisteredCount();
}

View File

@@ -68,7 +68,7 @@ public:
*
* @return The default audio output device name.
*/
std::string_view GetDefaultOutputDeviceName() const;
std::string_view GetDefaultOutputDeviceName();
/**
* Is the given initialize config valid?
@@ -77,7 +77,7 @@ public:
* @param in_params - Input parameters, see AudioOutParameter.
* @return Result code.
*/
Result IsConfigValid(std::string_view device_name, const AudioOutParameter& in_params) const;
Result IsConfigValid(std::string_view device_name, const AudioOutParameter& in_params);
/**
* Initialize this system.
@@ -199,7 +199,7 @@ public:
/**
* Set this system's current volume.
*
* @param volume The new volume.
* @param The new volume.
*/
void SetVolume(f32 volume);
@@ -209,14 +209,14 @@ public:
* @param tag - Unique tag to search for.
* @return True if the buffer is in the system, otherwise false.
*/
bool ContainsAudioBuffer(u64 tag) const;
bool ContainsAudioBuffer(u64 tag);
/**
* Get the maximum number of usable buffers (default 32).
*
* @return The number of buffers.
*/
u32 GetBufferCount() const;
u32 GetBufferCount();
/**
* Get the total number of samples played by this system.

View File

@@ -50,7 +50,7 @@ u32 ADSP::GetRemainCommandCount(const u32 session_id) const {
return render_mailbox.GetRemainCommandCount(session_id);
}
void ADSP::SendCommandBuffer(const u32 session_id, const CommandBuffer& command_buffer) {
void ADSP::SendCommandBuffer(const u32 session_id, CommandBuffer& command_buffer) {
render_mailbox.SetCommandBuffer(session_id, command_buffer);
}

View File

@@ -63,6 +63,8 @@ public:
/**
* Stop the ADSP.
*
* @return True if started or already running, otherwise false.
*/
void Stop();
@@ -131,7 +133,7 @@ public:
* @param session_id - The session id to check (0 or 1).
* @param command_buffer - The command buffer to process.
*/
void SendCommandBuffer(u32 session_id, const CommandBuffer& command_buffer);
void SendCommandBuffer(u32 session_id, CommandBuffer& command_buffer);
/**
* Clear the command buffers (does not clear the time taken or the remaining command count)

View File

@@ -47,11 +47,11 @@ RenderMessage AudioRenderer_Mailbox::ADSPWaitMessage() {
return msg;
}
CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const u32 session_id) {
CommandBuffer& AudioRenderer_Mailbox::GetCommandBuffer(const s32 session_id) {
return command_buffers[session_id];
}
void AudioRenderer_Mailbox::SetCommandBuffer(const u32 session_id, const CommandBuffer& buffer) {
void AudioRenderer_Mailbox::SetCommandBuffer(const u32 session_id, CommandBuffer& buffer) {
command_buffers[session_id] = buffer;
}
@@ -106,6 +106,9 @@ void AudioRenderer::Start(AudioRenderer_Mailbox* mailbox_) {
mailbox = mailbox_;
thread = std::thread(&AudioRenderer::ThreadFunc, this);
for (auto& stream : streams) {
stream->Start();
}
running = true;
}
@@ -127,12 +130,11 @@ void AudioRenderer::CreateSinkStreams() {
std::string name{fmt::format("ADSP_RenderStream-{}", i)};
streams[i] =
sink.AcquireSinkStream(system, channels, name, ::AudioCore::Sink::StreamType::Render);
streams[i]->SetRingSize(4);
}
}
void AudioRenderer::ThreadFunc() {
constexpr char name[]{"AudioRenderer"};
constexpr char name[]{"yuzu:AudioRenderer"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);
@@ -196,6 +198,11 @@ void AudioRenderer::ThreadFunc() {
command_list_processor.Process(index) - start_time;
}
if (index == 0) {
auto stream{command_list_processor.GetOutputSinkStream()};
system.AudioCore().SetStreamQueue(stream->GetQueueSize());
}
const auto end_time{system.CoreTiming().GetClockTicks()};
command_buffer.remaining_command_count =

View File

@@ -52,7 +52,7 @@ public:
/**
* Send a message from the host to the AudioRenderer.
*
* @param message - The message to send to the AudioRenderer.
* @param message_ - The message to send to the AudioRenderer.
*/
void HostSendMessage(RenderMessage message);
@@ -66,7 +66,7 @@ public:
/**
* Send a message from the AudioRenderer to the host.
*
* @param message - The message to send to the host.
* @param message_ - The message to send to the host.
*/
void ADSPSendMessage(RenderMessage message);
@@ -83,7 +83,7 @@ public:
* @param session_id - The session id to get (0 or 1).
* @return The command buffer.
*/
CommandBuffer& GetCommandBuffer(u32 session_id);
CommandBuffer& GetCommandBuffer(s32 session_id);
/**
* Set the command buffer with the given session id (0 or 1).
@@ -91,7 +91,7 @@ public:
* @param session_id - The session id to get (0 or 1).
* @param buffer - The command buffer to set.
*/
void SetCommandBuffer(u32 session_id, const CommandBuffer& buffer);
void SetCommandBuffer(u32 session_id, CommandBuffer& buffer);
/**
* Get the total render time taken for the last command lists sent.
@@ -163,7 +163,7 @@ public:
/**
* Start the AudioRenderer.
*
* @param mailbox The mailbox to use for this session.
* @param The mailbox to use for this session.
*/
void Start(AudioRenderer_Mailbox* mailbox);

View File

@@ -33,10 +33,10 @@ public:
/**
* Initialize the processor.
*
* @param system - The core system.
* @param buffer - The command buffer to process.
* @param size - The size of the buffer.
* @param stream - The stream to be used for sending the samples.
* @param system_ - The core system.
* @param buffer - The command buffer to process.
* @param size - The size of the buffer.
* @param stream_ - The stream to be used for sending the samples.
*/
void Initialize(Core::System& system, CpuAddr buffer, u64 size, Sink::SinkStream* stream);
@@ -72,8 +72,7 @@ public:
/**
* Process the command list.
*
* @param session_id - Session ID for the commands being processed.
*
* @param index - Index of the current command list.
* @return The time taken to process.
*/
u64 Process(u32 session_id);
@@ -90,7 +89,7 @@ public:
u8* commands{};
/// The command buffer size
u64 commands_buffer_size{};
/// The maximum processing time allotted
/// The maximum processing time alloted
u64 max_process_time{};
/// The number of commands in the buffer
u32 command_count{};

View File

@@ -1,9 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <span>
#include "audio_core/audio_core.h"
#include "audio_core/common/feature_support.h"
#include "audio_core/renderer/audio_device.h"
@@ -12,33 +9,14 @@
namespace AudioCore::AudioRenderer {
constexpr std::array usb_device_names{
AudioDevice::AudioDeviceName{"AudioStereoJackOutput"},
AudioDevice::AudioDeviceName{"AudioBuiltInSpeakerOutput"},
AudioDevice::AudioDeviceName{"AudioTvOutput"},
AudioDevice::AudioDeviceName{"AudioUsbDeviceOutput"},
};
constexpr std::array device_names{
AudioDevice::AudioDeviceName{"AudioStereoJackOutput"},
AudioDevice::AudioDeviceName{"AudioBuiltInSpeakerOutput"},
AudioDevice::AudioDeviceName{"AudioTvOutput"},
};
constexpr std::array output_device_names{
AudioDevice::AudioDeviceName{"AudioBuiltInSpeakerOutput"},
AudioDevice::AudioDeviceName{"AudioTvOutput"},
AudioDevice::AudioDeviceName{"AudioExternalOutput"},
};
AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id_,
const u32 revision)
: output_sink{system.AudioCore().GetOutputSink()},
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
const size_t max_count) const {
std::span<const AudioDeviceName> names{};
const size_t max_count) {
std::span<AudioDeviceName> names{};
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
names = usb_device_names;
@@ -46,7 +24,7 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
names = device_names;
}
const u32 out_count{static_cast<u32>(std::min(max_count, names.size()))};
u32 out_count{static_cast<u32>(std::min(max_count, names.size()))};
for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(names[i]);
}
@@ -54,8 +32,8 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
}
u32 AudioDevice::ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer,
const size_t max_count) const {
const u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
const size_t max_count) {
u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(output_device_names[i]);
@@ -67,7 +45,7 @@ void AudioDevice::SetDeviceVolumes(const f32 volume) {
output_sink.SetDeviceVolume(volume);
}
f32 AudioDevice::GetDeviceVolume([[maybe_unused]] std::string_view name) const {
f32 AudioDevice::GetDeviceVolume([[maybe_unused]] std::string_view name) {
return output_sink.GetDeviceVolume();
}

View File

@@ -3,7 +3,7 @@
#pragma once
#include <string_view>
#include <span>
#include "audio_core/audio_render_manager.h"
@@ -23,13 +23,21 @@ namespace AudioRenderer {
class AudioDevice {
public:
struct AudioDeviceName {
std::array<char, 0x100> name{};
std::array<char, 0x100> name;
constexpr AudioDeviceName(std::string_view name_) {
name_.copy(name.data(), name.size() - 1);
AudioDeviceName(const char* name_) {
std::strncpy(name.data(), name_, name.size());
}
};
std::array<AudioDeviceName, 4> usb_device_names{"AudioStereoJackOutput",
"AudioBuiltInSpeakerOutput", "AudioTvOutput",
"AudioUsbDeviceOutput"};
std::array<AudioDeviceName, 3> device_names{"AudioStereoJackOutput",
"AudioBuiltInSpeakerOutput", "AudioTvOutput"};
std::array<AudioDeviceName, 3> output_device_names{"AudioBuiltInSpeakerOutput", "AudioTvOutput",
"AudioExternalOutput"};
explicit AudioDevice(Core::System& system, u64 applet_resource_user_id, u32 revision);
/**
@@ -39,7 +47,7 @@ public:
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written.
*/
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count);
/**
* Get a list of the available output devices.
@@ -49,7 +57,7 @@ public:
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written.
*/
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const;
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count);
/**
* Set the volume of all streams in the backend sink.
@@ -65,7 +73,7 @@ public:
* @param name - Name of the device to check. Unused.
* @return Volume of the device.
*/
f32 GetDeviceVolume(std::string_view name) const;
f32 GetDeviceVolume(std::string_view name);
private:
/// Backend output sink for the device

View File

@@ -34,7 +34,7 @@ void BehaviorInfo::ClearError() {
error_count = 0;
}
void BehaviorInfo::AppendError(const ErrorInfo& error) {
void BehaviorInfo::AppendError(ErrorInfo& error) {
LOG_ERROR(Service_Audio, "Error during RequestUpdate, reporting code {:04X} address {:08X}",
error.error_code.raw, error.address);
if (error_count < MaxErrors) {
@@ -42,16 +42,14 @@ void BehaviorInfo::AppendError(const ErrorInfo& error) {
}
}
void BehaviorInfo::CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count) const {
out_count = std::min(error_count, MaxErrors);
void BehaviorInfo::CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count) {
auto error_count_{std::min(error_count, MaxErrors)};
std::memset(out_errors.data(), 0, MaxErrors * sizeof(ErrorInfo));
for (size_t i = 0; i < MaxErrors; i++) {
if (i < out_count) {
out_errors[i] = errors[i];
} else {
out_errors[i] = {};
}
for (size_t i = 0; i < error_count_; i++) {
out_errors[i] = errors[i];
}
out_count = error_count_;
}
void BehaviorInfo::UpdateFlags(const Flags flags_) {

View File

@@ -94,7 +94,7 @@ public:
*
* @param error - The new error.
*/
void AppendError(const ErrorInfo& error);
void AppendError(ErrorInfo& error);
/**
* Copy errors to the given output container.
@@ -102,7 +102,7 @@ public:
* @param out_errors - Output container to receive the errors.
* @param out_count - The number of errors written.
*/
void CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count) const;
void CopyErrorInfo(std::span<ErrorInfo> out_errors, u32& out_count);
/**
* Update the behaviour flags.

View File

@@ -485,7 +485,7 @@ Result InfoUpdater::UpdateBehaviorInfo(BehaviorInfo& behaviour_) {
return ResultSuccess;
}
Result InfoUpdater::UpdateErrorInfo(const BehaviorInfo& behaviour_) {
Result InfoUpdater::UpdateErrorInfo(BehaviorInfo& behaviour_) {
auto out_params{reinterpret_cast<BehaviorInfo::OutStatus*>(output)};
behaviour_.CopyErrorInfo(out_params->errors, out_params->error_count);

View File

@@ -130,7 +130,7 @@ public:
* @param behaviour - Behaviour to update.
* @return Result code.
*/
Result UpdateErrorInfo(const BehaviorInfo& behaviour);
Result UpdateErrorInfo(BehaviorInfo& behaviour);
/**
* Update splitter.

View File

@@ -191,7 +191,6 @@ public:
* @param volume - Current mix volume used for calculating the ramp.
* @param prev_volume - Previous mix volume, used for calculating the ramp,
* also applied to the input.
* @param prev_samples - Previous sample buffer. Used for depopping.
* @param precision - Number of decimal bits for fixed point operations.
*/
void GenerateMixRampCommand(s32 node_id, s16 buffer_count, s16 input_index, s16 output_index,
@@ -209,7 +208,6 @@ public:
* @param volumes - Current mix volumes used for calculating the ramp.
* @param prev_volumes - Previous mix volumes, used for calculating the ramp,
* also applied to the input.
* @param prev_samples - Previous sample buffer. Used for depopping.
* @param precision - Number of decimal bits for fixed point operations.
*/
void GenerateMixRampGroupedCommand(s32 node_id, s16 buffer_count, s16 input_index,
@@ -299,11 +297,11 @@ public:
/**
* Generate a device sink command, adding it to the command list.
*
* @param node_id - Node id of the voice this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param sink_info - The sink_info to generate this command from.
* @param session_id - System session id this command is generated from.
* @param samples_buffer - The buffer to be sent to the sink if upsampling is not used.
* @param node_id - Node id of the voice this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param sink_info - The sink_info to generate this command from.
* @session_id - System session id this command is generated from.
* @samples_buffer - The buffer to be sent to the sink if upsampling is not used.
*/
void GenerateDeviceSinkCommand(s32 node_id, s16 buffer_offset, SinkInfoBase& sink_info,
u32 session_id, std::span<s32> samples_buffer);

View File

@@ -197,9 +197,9 @@ public:
/**
* Generate an I3DL2 reverb effect command.
*
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info - I3DL2Reverb effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info_base - I3DL2Reverb effect info.
* @param node_id - Node id of the mix this command is generated for.
*/
void GenerateI3dl2ReverbEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info,
s32 node_id);
@@ -207,18 +207,18 @@ public:
/**
* Generate an aux effect command.
*
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info - Aux effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info_base - Aux effect info.
* @param node_id - Node id of the mix this command is generated for.
*/
void GenerateAuxCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id);
/**
* Generate a biquad filter effect command.
*
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info - Aux effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info_base - Aux effect info.
* @param node_id - Node id of the mix this command is generated for.
*/
void GenerateBiquadFilterEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info,
s32 node_id);
@@ -226,10 +226,10 @@ public:
/**
* Generate a light limiter effect command.
*
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info - Limiter effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param effect_index - Index for the statistics state.
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info_base - Limiter effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param effect_index - Index for the statistics state.
*/
void GenerateLightLimiterEffectCommand(s16 buffer_offset, EffectInfoBase& effect_info,
s32 node_id, u32 effect_index);
@@ -238,20 +238,21 @@ public:
* Generate a capture effect command.
* Writes a mix buffer back to game memory.
*
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info - Capture effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info_base - Capture effect info.
* @param node_id - Node id of the mix this command is generated for.
*/
void GenerateCaptureCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id);
/**
* Generate a compressor effect command.
*
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info - Compressor effect info.
* @param node_id - Node id of the mix this command is generated for.
* @param buffer_offset - Base mix buffer offset to use.
* @param effect_info_base - Compressor effect info.
* @param node_id - Node id of the mix this command is generated for.
*/
void GenerateCompressorCommand(s16 buffer_offset, EffectInfoBase& effect_info, s32 node_id);
void GenerateCompressorCommand(const s16 buffer_offset, EffectInfoBase& effect_info,
const s32 node_id);
/**
* Generate all effect commands for a mix.
@@ -317,9 +318,8 @@ public:
* Generate a performance command.
* Used to report performance metrics of the AudioRenderer back to the game.
*
* @param node_id - Node ID of the mix this command is generated for
* @param state - Output state of the generated performance command
* @param entry_addresses - Addresses to be written
* @param buffer_offset - Base mix buffer offset to use.
* @param sink_info - Sink info to generate the commands from.
*/
void GeneratePerformanceCommand(s32 node_id, PerformanceState state,
const PerformanceEntryAddresses& entry_addresses);

View File

@@ -11,7 +11,7 @@
namespace AudioCore::AudioRenderer {
static void SetCompressorEffectParameter(const CompressorInfo::ParameterVersion2& params,
static void SetCompressorEffectParameter(CompressorInfo::ParameterVersion2& params,
CompressorInfo::State& state) {
const auto ratio{1.0f / params.compressor_ratio};
auto makeup_gain{0.0f};
@@ -31,9 +31,9 @@ static void SetCompressorEffectParameter(const CompressorInfo::ParameterVersion2
state.unk_20 = c;
}
static void InitializeCompressorEffect(const CompressorInfo::ParameterVersion2& params,
static void InitializeCompressorEffect(CompressorInfo::ParameterVersion2& params,
CompressorInfo::State& state) {
state = {};
std::memset(&state, 0, sizeof(CompressorInfo::State));
state.unk_00 = 0;
state.unk_04 = 1.0f;
@@ -42,7 +42,7 @@ static void InitializeCompressorEffect(const CompressorInfo::ParameterVersion2&
SetCompressorEffectParameter(params, state);
}
static void ApplyCompressorEffect(const CompressorInfo::ParameterVersion2& params,
static void ApplyCompressorEffect(CompressorInfo::ParameterVersion2& params,
CompressorInfo::State& state, bool enabled,
std::vector<std::span<const s32>> input_buffers,
std::vector<std::span<s32>> output_buffers, u32 sample_count) {
@@ -103,7 +103,8 @@ static void ApplyCompressorEffect(const CompressorInfo::ParameterVersion2& param
} else {
for (s16 channel = 0; channel < params.channel_count; channel++) {
if (params.inputs[channel] != params.outputs[channel]) {
std::memcpy(output_buffers[channel].data(), input_buffers[channel].data(),
std::memcpy((char*)output_buffers[channel].data(),
(char*)input_buffers[channel].data(),
output_buffers[channel].size_bytes());
}
}

View File

@@ -7,7 +7,17 @@
#include "common/logging/log.h"
namespace AudioCore::AudioRenderer {
/**
* Mix input mix buffer into output mix buffer, with volume applied to the input.
*
* @tparam Q - Number of bits for fixed point operations.
* @param output - Output mix buffer.
* @param input - Input mix buffer.
* @param volume - Volume applied to the input.
* @param ramp - Ramp applied to volume every sample.
* @param sample_count - Number of samples to process.
* @return The final gained input sample, used for depopping.
*/
template <size_t Q>
s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, const f32 volume_,
const f32 ramp_, const u32 sample_count) {
@@ -30,8 +40,10 @@ s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, const f32 vo
return sample.to_int();
}
template s32 ApplyMixRamp<15>(std::span<s32>, std::span<const s32>, f32, f32, u32);
template s32 ApplyMixRamp<23>(std::span<s32>, std::span<const s32>, f32, f32, u32);
template s32 ApplyMixRamp<15>(std::span<s32>, std::span<const s32>, const f32, const f32,
const u32);
template s32 ApplyMixRamp<23>(std::span<s32>, std::span<const s32>, const f32, const f32,
const u32);
void MixRampCommand::Dump(const ADSP::CommandListProcessor& processor, std::string& string) {
const auto ramp{(volume - prev_volume) / static_cast<f32>(processor.sample_count)};

View File

@@ -61,13 +61,13 @@ struct MixRampCommand : ICommand {
* @tparam Q - Number of bits for fixed point operations.
* @param output - Output mix buffer.
* @param input - Input mix buffer.
* @param volume_ - Volume applied to the input.
* @param ramp_ - Ramp applied to volume every sample.
* @param volume - Volume applied to the input.
* @param ramp - Ramp applied to volume every sample.
* @param sample_count - Number of samples to process.
* @return The final gained input sample, used for depopping.
*/
template <size_t Q>
s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, f32 volume_, f32 ramp_,
u32 sample_count);
s32 ApplyMixRamp(std::span<s32> output, std::span<const s32> input, const f32 volume_,
const f32 ramp_, const u32 sample_count);
} // namespace AudioCore::AudioRenderer

View File

@@ -50,9 +50,9 @@ struct MixRampGroupedCommand : ICommand {
std::array<s16, MaxMixBuffers> inputs;
/// Output mix buffer indexes for each mix buffer
std::array<s16, MaxMixBuffers> outputs;
/// Previous mix volumes for each mix buffer
/// Previous mix vloumes for each mix buffer
std::array<f32, MaxMixBuffers> prev_volumes;
/// Current mix volumes for each mix buffer
/// Current mix vloumes for each mix buffer
std::array<f32, MaxMixBuffers> volumes;
/// Pointer to the previous sample buffer, used for depop
CpuAddr previous_samples;

View File

@@ -46,10 +46,6 @@ void DeviceSinkCommand::Process(const ADSP::CommandListProcessor& processor) {
out_buffer.tag = reinterpret_cast<u64>(samples.data());
stream->AppendBuffer(out_buffer, samples);
if (stream->IsPaused()) {
stream->Start();
}
}
bool DeviceSinkCommand::Verify(const ADSP::CommandListProcessor& processor) {

View File

@@ -15,15 +15,15 @@ class EffectContext {
public:
/**
* Initialize the effect context
* @param effect_infos_ - List of effect infos for this context
* @param effect_count_ - The number of effects in the list
* @param result_states_cpu_ - The workbuffer of result states for the CPU for this context
* @param result_states_dsp_ - The workbuffer of result states for the DSP for this context
* @param dsp_state_count - The number of result states
* @param effect_infos List of effect infos for this context
* @param effect_count The number of effects in the list
* @param result_states_cpu The workbuffer of result states for the CPU for this context
* @param result_states_dsp The workbuffer of result states for the DSP for this context
* @param state_count The number of result states
*/
void Initialize(std::span<EffectInfoBase> effect_infos_, u32 effect_count_,
void Initialize(std::span<EffectInfoBase> effect_infos_, const u32 effect_count_,
std::span<EffectResultState> result_states_cpu_,
std::span<EffectResultState> result_states_dsp_, size_t dsp_state_count);
std::span<EffectResultState> result_states_dsp_, const size_t dsp_state_count);
/**
* Get the EffectInfo for a given index

View File

@@ -291,7 +291,7 @@ public:
* Update the info with new parameters, version 1.
*
* @param error_info - Used to write call result code.
* @param params - New parameters to update the info with.
* @param in_params - New parameters to update the info with.
* @param pool_mapper - Pool for mapping buffers.
*/
virtual void Update(BehaviorInfo::ErrorInfo& error_info,
@@ -305,7 +305,7 @@ public:
* Update the info with new parameters, version 2.
*
* @param error_info - Used to write call result code.
* @param params - New parameters to update the info with.
* @param in_params - New parameters to update the info with.
* @param pool_mapper - Pool for mapping buffers.
*/
virtual void Update(BehaviorInfo::ErrorInfo& error_info,

View File

@@ -99,7 +99,7 @@ public:
return out_sample;
}
Common::FixedPoint<50, 14> Read() const {
Common::FixedPoint<50, 14> Read() {
return *output;
}
@@ -110,7 +110,7 @@ public:
}
}
Common::FixedPoint<50, 14> TapOut(const s32 index) const {
Common::FixedPoint<50, 14> TapOut(const s32 index) {
auto out{input - (index + 1)};
if (out < buffer.data()) {
out += max_delay + 1;

View File

@@ -95,7 +95,7 @@ public:
return out_sample;
}
Common::FixedPoint<50, 14> Read() const {
Common::FixedPoint<50, 14> Read() {
return *output;
}
@@ -106,7 +106,7 @@ public:
}
}
Common::FixedPoint<50, 14> TapOut(const s32 index) const {
Common::FixedPoint<50, 14> TapOut(const s32 index) {
auto out{input - (index + 1)};
if (out < buffer.data()) {
out += sample_count;

View File

@@ -19,8 +19,8 @@ public:
/**
* Setup a new AddressInfo.
*
* @param cpu_address_ - The CPU address of this region.
* @param size_ - The size of this region.
* @param cpu_address - The CPU address of this region.
* @param size - The size of this region.
*/
void Setup(CpuAddr cpu_address_, u64 size_) {
cpu_address = cpu_address_;
@@ -42,6 +42,7 @@ public:
* Assign this region to a memory pool.
*
* @param memory_pool_ - Memory pool to assign.
* @return The CpuAddr address of this region.
*/
void SetPool(MemoryPoolInfo* memory_pool_) {
memory_pool = memory_pool_;

View File

@@ -56,7 +56,7 @@ class NodeStates {
*
* @return The current stack position.
*/
u32 Count() const {
u32 Count() {
return pos;
}
@@ -83,7 +83,7 @@ class NodeStates {
*
* @return The node on the top of the stack.
*/
u32 top() const {
u32 top() {
return stack[pos - 1];
}
@@ -112,11 +112,11 @@ public:
/**
* Initialize the node states.
*
* @param buffer_ - The workbuffer to use. Unused.
* @param buffer - The workbuffer to use. Unused.
* @param node_buffer_size - The size of the workbuffer. Unused.
* @param count - The number of nodes in the graph.
*/
void Initialize(std::span<u8> buffer_, u64 node_buffer_size, u32 count);
void Initialize(std::span<u8> nodes, u64 node_buffer_size, u32 count);
/**
* Sort the graph. Only calls DepthFirstSearch.

View File

@@ -73,8 +73,7 @@ public:
* Calculate the required size for the performance workbuffer.
*
* @param behavior - Check which version is supported.
* @param params - Input parameters.
*
* @param params - Input parameters.
* @return Required workbuffer size.
*/
static u64 GetRequiredBufferSizeForPerformanceMetricsPerFrame(
@@ -105,7 +104,7 @@ public:
* @param workbuffer - Workbuffer to use for performance frames.
* @param workbuffer_size - Size of the workbuffer.
* @param params - Input parameters.
* @param behavior - Behaviour to check version and data format.
* @param behavior - Behaviour to check version and data format.
* @param memory_pool - Used to translate the workbuffer address for the DSP.
*/
virtual void Initialize(std::span<u8> workbuffer, u64 workbuffer_size,
@@ -161,8 +160,7 @@ public:
* workbuffer, to be written by the AudioRenderer.
*
* @param addresses - Filled with pointers to the new detail, which should be passed
* to the AudioRenderer with Performance commands to be written.
* @param detail_type - Performance detail type.
* to the AudioRenderer with Performance commands to be written.
* @param entry_type - The type of this detail. See PerformanceEntryType
* @param node_id - Node id for this detail.
* @return True if a new detail was created and the offsets are valid, otherwise false.

View File

@@ -15,14 +15,17 @@ MICROPROFILE_DEFINE(Audio_RenderSystemManager, "Audio", "Render System Manager",
MP_RGB(60, 19, 97));
namespace AudioCore::AudioRenderer {
constexpr std::chrono::nanoseconds RENDER_TIME{5'000'000UL};
constexpr std::chrono::nanoseconds BaseRenderTime{5'000'000UL};
constexpr std::chrono::nanoseconds RenderTimeOffset{400'000UL};
SystemManager::SystemManager(Core::System& core_)
: core{core_}, adsp{core.AudioCore().GetADSP()}, mailbox{adsp.GetRenderMailbox()},
thread_event{Core::Timing::CreateEvent(
"AudioRendererSystemManager", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) {
return ThreadFunc2(time);
})} {}
})} {
core.CoreTiming().RegisterPauseCallback([this](bool paused) { PauseCallback(paused); });
}
SystemManager::~SystemManager() {
Stop();
@@ -33,8 +36,8 @@ bool SystemManager::InitializeUnsafe() {
if (adsp.Start()) {
active = true;
thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(); });
core.CoreTiming().ScheduleLoopingEvent(std::chrono::nanoseconds(0), RENDER_TIME,
thread_event);
core.CoreTiming().ScheduleLoopingEvent(std::chrono::nanoseconds(0),
BaseRenderTime - RenderTimeOffset, thread_event);
}
}
@@ -94,7 +97,7 @@ bool SystemManager::Remove(System& system_) {
}
void SystemManager::ThreadFunc() {
constexpr char name[]{"AudioRenderSystemManager"};
constexpr char name[]{"yuzu:AudioRenderSystemManager"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
@@ -118,9 +121,42 @@ void SystemManager::ThreadFunc() {
}
std::optional<std::chrono::nanoseconds> SystemManager::ThreadFunc2(s64 time) {
std::optional<std::chrono::nanoseconds> new_schedule_time{std::nullopt};
const auto queue_size{core.AudioCore().GetStreamQueue()};
switch (state) {
case StreamState::Filling:
if (queue_size >= 5) {
new_schedule_time = BaseRenderTime;
state = StreamState::Steady;
}
break;
case StreamState::Steady:
if (queue_size <= 2) {
new_schedule_time = BaseRenderTime - RenderTimeOffset;
state = StreamState::Filling;
} else if (queue_size > 5) {
new_schedule_time = BaseRenderTime + RenderTimeOffset;
state = StreamState::Draining;
}
break;
case StreamState::Draining:
if (queue_size <= 5) {
new_schedule_time = BaseRenderTime;
state = StreamState::Steady;
}
break;
}
update.store(true);
update.notify_all();
return std::nullopt;
return new_schedule_time;
}
void SystemManager::PauseCallback(bool paused) {
if (paused && core.IsPoweredOn() && core.IsShuttingDown()) {
update.store(true);
update.notify_all();
}
}
} // namespace AudioCore::AudioRenderer

Some files were not shown because too many files have changed in this diff Show More