Compare commits
2 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20139f8a55 | ||
|
|
d4cb0eac87 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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:
|
||||
|
||||
2
.github/workflows/verify.yml
vendored
@@ -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
@@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# Build directory
|
||||
[Bb]uild*/
|
||||
[Bb]uild/
|
||||
doc-build/
|
||||
|
||||
# Generated source files
|
||||
|
||||
11
.reuse/dep5
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
964
dist/languages/cs.ts
vendored
968
dist/languages/da.ts
vendored
1096
dist/languages/de.ts
vendored
1019
dist/languages/el.ts
vendored
1015
dist/languages/es.ts
vendored
1222
dist/languages/fr.ts
vendored
964
dist/languages/id.ts
vendored
1030
dist/languages/it.ts
vendored
1016
dist/languages/ja_JP.ts
vendored
1235
dist/languages/ko_KR.ts
vendored
964
dist/languages/nb.ts
vendored
964
dist/languages/nl.ts
vendored
964
dist/languages/pl.ts
vendored
1058
dist/languages/pt_BR.ts
vendored
1058
dist/languages/pt_PT.ts
vendored
972
dist/languages/ru_RU.ts
vendored
964
dist/languages/sv.ts
vendored
1216
dist/languages/tr_TR.ts
vendored
964
dist/languages/vi.ts
vendored
964
dist/languages/vi_VN.ts
vendored
982
dist/languages/zh_CN.ts
vendored
968
dist/languages/zh_TW.ts
vendored
BIN
dist/qt_themes/colorful/icons/16x16/info.png
vendored
|
Before Width: | Height: | Size: 428 B |
BIN
dist/qt_themes/colorful/icons/16x16/sync.png
vendored
|
Before Width: | Height: | Size: 548 B |
BIN
dist/qt_themes/colorful/icons/48x48/sd_card.png
vendored
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 981 B |
1
dist/qt_themes/colorful/icons/index.theme
vendored
@@ -1,6 +1,7 @@
|
||||
[Icon Theme]
|
||||
Name=colorful
|
||||
Comment=Colorful theme
|
||||
Inherits=default
|
||||
Directories=16x16,48x48,256x256
|
||||
|
||||
[16x16]
|
||||
|
||||
6
dist/qt_themes/colorful/style.qrc
vendored
@@ -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>
|
||||
|
||||
10
dist/qt_themes/colorful_dark/style.qrc
vendored
@@ -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">
|
||||
|
||||
13
dist/qt_themes/default/default.qrc
vendored
@@ -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>
|
||||
|
||||
|
Before Width: | Height: | Size: 414 B After Width: | Height: | Size: 414 B |
|
Before Width: | Height: | Size: 431 B After Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
|
Before Width: | Height: | Size: 678 B After Width: | Height: | Size: 678 B |
BIN
dist/qt_themes/default/icons/48x48/sd_card.png
vendored
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 561 B |
3
dist/qt_themes/default/icons/index.theme
vendored
@@ -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
|
||||
BIN
dist/qt_themes/qdarkstyle/icons/48x48/sd_card.png
vendored
|
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 587 B |
4
dist/qt_themes/qdarkstyle/icons/index.theme
vendored
@@ -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
|
||||
@@ -1,7 +1,7 @@
|
||||
[Icon Theme]
|
||||
Name=qdarkstyle_midnight_blue
|
||||
Comment=dark theme
|
||||
Inherits=colorful
|
||||
Inherits=default
|
||||
Directories=16x16,48x48,256x256
|
||||
|
||||
[16x16]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
* @param behaviour - Behaviour to update.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result UpdateErrorInfo(const BehaviorInfo& behaviour);
|
||||
Result UpdateErrorInfo(BehaviorInfo& behaviour);
|
||||
|
||||
/**
|
||||
* Update splitter.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||