diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..53be93577f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,305 @@ +name: CI + +on: [push, pull_request] + +env: + SDL2_VERSION: 2.30.11 + SDL3_VERSION: 3.2.0 + +jobs: + linux-SDL2: + name: Steam Linux Runtime (SDL2) + runs-on: ubuntu-latest + container: + image: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install chrpath + run: apt install -y chrpath + + - name: CMake configure (Debug) + run: cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DBUILD_SDL3=OFF + + - name: Build (Debug) + run: ninja -C debug + + - name: CMake configure (Release) + run: cmake -B release -G Ninja . -DCMAKE_BUILD_TYPE=Release -DBUILD_SDL3=OFF + + - name: Build (Release) + run: | + ninja -C release + + linux: + name: Steam Linux Runtime + runs-on: ubuntu-latest + container: + image: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:beta + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Install chrpath + run: apt install -y chrpath + + - name: CMake configure (Debug) + run: cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug + + - name: Build (Debug) + run: ninja -C debug + + - name: CMake configure (Release) + run: cmake -B release -G Ninja . -DCMAKE_BUILD_TYPE=Release + + - name: Build (Release) + run: | + ninja -C release + chrpath -d release/libFAudio.so.0 + strip -S release/libFAudio.so.0 + + - name: Archive build result + uses: actions/upload-artifact@v4 + with: + name: FAudio-lib64 + path: release/libFAudio.so.0 + + linux-ppc: + name: Debian Linux PPC + runs-on: ubuntu-latest + container: + image: dockcross/linux-ppc:latest + steps: + - name: Install chrpath + run: apt install -y chrpath + + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Clone SDL3 + run: git clone --depth 1 --branch release-$SDL3_VERSION https://github.com/libsdl-org/SDL.git + + - name: Build SDL3 (Debug) + run: | + cd SDL + cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DSDL_UNIX_CONSOLE_BUILD=ON + ninja -C debug + cd .. + + - name: CMake configure (Debug) + run: cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DSDL3_DIR=${GITHUB_WORKSPACE}/SDL/debug + + - name: Build (Debug) + run: ninja -C debug + + - name: CMake configure (Release) + run: cmake -B release -G Ninja . -DCMAKE_BUILD_TYPE=Release -DSDL3_DIR=${GITHUB_WORKSPACE}/SDL/debug + + - name: Build (Release) + run: | + ninja -C release + chrpath -d release/libFAudio.so.0 + + - name: Archive build result + uses: actions/upload-artifact@v4 + with: + name: FAudio-libpowerpc + path: release/libFAudio.so.0 + + linux-mingw: + name: Fedora Linux MinGW + runs-on: ubuntu-latest + container: + image: fedora + steps: + - name: Install toolchain + run: | + dnf update -y + dnf install -y git cmake ninja-build mingw32-gcc mingw64-gcc mingw32-SDL3 mingw64-SDL3 + + - uses: actions/checkout@v4 + with: + submodules: true + + - name: CMake configure 32-bit (Release) + run: mingw32-cmake -B release-x86 -G Ninja . -DCMAKE_BUILD_TYPE=Release + + - name: Build 32-bit (Release) + run: ninja -C release-x86 + + - name: CMake configure 64-bit (Release) + run: mingw64-cmake -B release-x64 -G Ninja . -DCMAKE_BUILD_TYPE=Release + + - name: Build 64-bit (Release) + run: ninja -C release-x64 + + - name: Archive build result 32-bit + uses: actions/upload-artifact@v4 + with: + name: FAudio-x86 + path: release-x86/FAudio.dll + + - name: Archive build result 64-bit + uses: actions/upload-artifact@v4 + with: + name: FAudio-x64 + path: release-x64/FAudio.dll + + macos: + name: macOS (Universal) + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Clone SDL3 + run: git clone --depth 1 --branch release-$SDL3_VERSION https://github.com/libsdl-org/SDL.git + + - name: Install dependencies + run: brew install ninja + + - name: Build SDL3 (Debug) + run: | + cd SDL + cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 + ninja -C debug + cd .. + + - name: CMake configure (Debug) + run: cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DSDL3_DIR=${GITHUB_WORKSPACE}/SDL/debug + + - name: Build (Debug) + run: ninja -C debug + + - name: CMake configure (Release) + run: cmake -B release -G Ninja . -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DSDL3_DIR=${GITHUB_WORKSPACE}/SDL/debug + + - name: Build (Release) + run: ninja -C release + + - name: Archive build result + uses: actions/upload-artifact@v4 + with: + name: FAudio-osx + path: release/libFAudio.0.dylib + + ios-tvos: + name: iOS/tvOS + runs-on: macos-latest + strategy: + matrix: + include: + - platform: iOS + sdk: iphoneos + architectures: arm64 + - platform: iOS + sdk: iphonesimulator + architectures: x86_64;arm64 + - platform: tvOS + sdk: appletvos + architectures: arm64 + - platform: tvOS + sdk: appletvsimulator + architectures: x86_64;arm64 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Clone SDL3 + run: git clone --depth 1 --branch release-$SDL3_VERSION https://github.com/libsdl-org/SDL.git + + - name: Install dependencies + run: brew install ninja + + - name: Build SDL3 (Debug) + run: | + cd SDL + cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_SYSTEM_NAME=${{ matrix.platform }} -DCMAKE_OSX_ARCHITECTURES="${{ matrix.architectures }}" -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 -DCMAKE_OSX_SYSROOT=`xcodebuild -version -sdk ${{ matrix.sdk }} Path` + ninja -C debug + cd .. + + - name: CMake configure (Debug) + run: cmake -B debug -G Ninja . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_SYSTEM_NAME=${{ matrix.platform }} -DCMAKE_OSX_ARCHITECTURES="${{ matrix.architectures }}" -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 -DCMAKE_OSX_SYSROOT=`xcodebuild -version -sdk ${{ matrix.sdk }} Path` -DSDL3_DIR=${GITHUB_WORKSPACE}/SDL/debug -DBUILD_SHARED_LIBS=OFF -DMOJOSHADER_STATIC_SPIRVCROSS=ON + + - name: Build (Debug) + run: ninja -C debug + + - name: CMake configure (Release) + run: cmake -B release -G Ninja . -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=${{ matrix.platform }} -DCMAKE_OSX_ARCHITECTURES="${{ matrix.architectures }}" -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0 -DCMAKE_OSX_SYSROOT=`xcodebuild -version -sdk ${{ matrix.sdk }} Path` -DSDL3_DIR=${GITHUB_WORKSPACE}/SDL/debug -DBUILD_SHARED_LIBS=OFF -DMOJOSHADER_STATIC_SPIRVCROSS=ON + + - name: Build (Release) + run: ninja -C release + + - name: Archive build result + uses: actions/upload-artifact@v4 + with: + name: FAudio-${{ matrix.sdk }} + path: release/*.a + + windows-msvc: + name: Windows MSVC + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Cache SDL + uses: actions/cache@v4 + env: + cache-name: cache-sdl + with: + path: C:\SDL + key: ${{ runner.os }}-build-${{ env.cache-name }} + + - name: Download SDL if not cached + run: | + if (-Not (Test-Path C:\SDL)) + { + Invoke-WebRequest "https://github.com/libsdl-org/SDL/releases/download/release-$env:SDL3_VERSION/SDL3-devel-$env:SDL3_VERSION-VC.zip" -OutFile C:\SDL.zip + Expand-Archive C:\SDL.zip -DestinationPath C:\ + } + + - name: CMake configure (Debug) + run: | + $env:LDFLAGS = "/LIBPATH:C:\SDL3-$env:SDL3_VERSION\lib\x86 " + cmake -B debug -G "Visual Studio 17 2022" . -DCMAKE_BUILD_TYPE=Debug ` + -A Win32 ` + -DSDL3_INCLUDE_DIRS="C:\SDL3-$env:SDL3_VERSION\include" ` + -DSDL3_LIBRARIES="SDL3" + + - name: Build (Debug) + run: cmake --build debug + + - name: CMake configure (Release) + run: | + $env:LDFLAGS = "/LIBPATH:C:\SDL3-$env:SDL3_VERSION\lib\x86 " + cmake -B release -G "Visual Studio 17 2022" . -DCMAKE_BUILD_TYPE=Release ` + -A Win32 ` + -DSDL3_INCLUDE_DIRS="C:\SDL3-$env:SDL3_VERSION\include" ` + -DSDL3_LIBRARIES="SDL3" + + - name: Build (Release) + run: cmake --build release + + freebsd: + name: FreeBSD + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + - name: Build + uses: cross-platform-actions/action@v0.26.0 + with: + operating_system: freebsd + version: '14.2' + run: | + sudo pkg update + sudo pkg install -y cmake ninja sdl3 + cmake -B build -G Ninja . + cmake --build build --verbose -- -j`sysctl -n hw.ncpu` diff --git a/.gitignore b/.gitignore index 495c431652..476e85cb0d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ Release/ .DS_Store xcuserdata/ *.xcworkspace/ +*.xcscheme \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 10acbb6665..a7cb8c8b22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,11 @@ cmake_minimum_required(VERSION 2.8.12) project(FAudio C) # Options -option(GSTREAMER "Enable GStreamer support (WMA, XMA)" OFF) option(BUILD_UTILS "Build utils/ folder" OFF) option(BUILD_TESTS "Build tests/ folder for unit tests to be executed on the host against FAudio" OFF) +option(BUILD_SDL3 "Build against SDL 3.0" ON) if(WIN32) -option(BUILD_CPP "Build cpp/ folder (COM wrapper for XAudio2)" OFF) +option(PLATFORM_WIN32 "Enable native Win32 platform instead of SDL" OFF) endif() option(XNASONG "Build with XNA_Song.c" ON) option(LOG_ASSERTIONS "Bind FAudio_assert to log, instead of platform's assert" OFF) @@ -29,8 +29,8 @@ endif() # Version SET(LIB_MAJOR_VERSION "0") -SET(LIB_MINOR_VERSION "21") -SET(LIB_REVISION "03") +SET(LIB_MINOR_VERSION "25") +SET(LIB_REVISION "02") SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}") # Build Type @@ -64,8 +64,14 @@ if(INSTALL_MINGW_DEPENDENCIES) include(cmake/install_shared_libs.cmake) endif() +set(target FAudio-shared) + +if(NOT BUILD_SHARED_LIBS) + set(target FAudio-static) +endif() + # Source lists -add_library(FAudio +add_library(${target} # Public Headers include/F3DAudio.h include/FACT3D.h @@ -80,6 +86,7 @@ add_library(FAudio src/FAudio_internal.h src/stb.h src/stb_vorbis.h + src/qoa_decoder.h # Source Files src/F3DAudio.c src/FACT3D.c @@ -98,77 +105,103 @@ add_library(FAudio src/FAudio_internal_simd.c src/FAudio_operationset.c src/FAudio_platform_sdl2.c + src/FAudio_platform_sdl3.c + src/FAudio_platform_win32.c # Optional source files src/XNA_Song.c - src/FAudio_gstreamer.c ) +if(PLATFORM_WIN32) + target_link_libraries(${target} PRIVATE dxguid uuid winmm ole32 advapi32 user32 mfplat mfreadwrite mfuuid propsys) + target_compile_definitions(${target} PUBLIC FAUDIO_WIN32_PLATFORM) + target_compile_definitions(${target} PRIVATE HAVE_WMADEC=1) + set(PLATFORM_CFLAGS "-DFAUDIO_WIN32_PLATFORM") + set(XNASONG OFF) +else() + if(BUILD_SDL3) + target_compile_definitions(${target} PUBLIC FAUDIO_SDL3_PLATFORM) + set(PLATFORM_CFLAGS "-DFAUDIO_SDL3_PLATFORM") + else() + set(PLATFORM_CFLAGS) + endif() +endif() + # Only disable DebugConfiguration in release builds if(NOT FORCE_ENABLE_DEBUGCONFIGURATION) - target_compile_definitions(FAudio PRIVATE $<$:FAUDIO_DISABLE_DEBUGCONFIGURATION>) + target_compile_definitions(${target} PRIVATE $<$:FAUDIO_DISABLE_DEBUGCONFIGURATION>) endif() # FAudio_assert Customization if(LOG_ASSERTIONS) - target_compile_definitions(FAudio PUBLIC FAUDIO_LOG_ASSERTIONS) + target_compile_definitions(${target} PUBLIC FAUDIO_LOG_ASSERTIONS) endif() # FAudio folders as includes, for other targets to consume -target_include_directories(FAudio PUBLIC +target_include_directories(${target} PUBLIC $ $ ) # MinGW builds should statically link libgcc if(MINGW) - target_link_libraries(FAudio PRIVATE -static-libgcc) + target_link_libraries(${target} PRIVATE -static-libgcc) endif() # Soname -set_target_properties(FAudio PROPERTIES OUTPUT_NAME "FAudio" +set_target_properties(${target} PROPERTIES OUTPUT_NAME "FAudio" VERSION ${LIB_VERSION} SOVERSION ${LIB_MAJOR_VERSION} ) # XNA_Song Support if(NOT XNASONG) - target_compile_definitions(FAudio PRIVATE DISABLE_XNASONG) + target_compile_definitions(${target} PRIVATE DISABLE_XNASONG) endif() -# GStreamer Support -if(GSTREAMER) - # Add the extra definition... - target_compile_definitions(FAudio PRIVATE HAVE_GSTREAMER=1) - - # Find GStreamer - find_package(PkgConfig) - pkg_check_modules(GST REQUIRED gstreamer-1.0>=1.9.2) - pkg_check_modules(GSTAUDIO REQUIRED gstreamer-audio-1.0>=1.9.2) - pkg_check_modules(GSTAPP REQUIRED gstreamer-app-1.0>=1.9.2) - - # Include/Link GStreamer... - target_include_directories(FAudio PRIVATE - ${GST_INCLUDE_DIRS} - ${GSTAUDIO_INCLUDE_DIRS} - ${GSTAPP_INCLUDE_DIRS} - ) - target_link_libraries(FAudio PRIVATE - ${GST_LDFLAGS} - ${GSTAUDIO_LDFLAGS} - ${GSTAPP_LDFLAGS} - ) -endif(GSTREAMER) - # Dump source voices to RIFF WAVE files if(DUMP_VOICES) - target_compile_definitions(FAudio PRIVATE FAUDIO_DUMP_VOICES) + target_compile_definitions(${target} PRIVATE FAUDIO_DUMP_VOICES) endif() -# SDL2 Dependency -if (DEFINED SDL2_INCLUDE_DIRS AND DEFINED SDL2_LIBRARIES) +# SDL Dependency +if (PLATFORM_WIN32) + message(STATUS "not using SDL") +elseif (BUILD_SDL3) + if (DEFINED SDL3_INCLUDE_DIRS AND DEFINED SDL3_LIBRARIES) + message(STATUS "using pre-defined SDL3 variables SDL3_INCLUDE_DIRS and SDL3_LIBRARIES") + target_include_directories(${target} PUBLIC "$") + target_link_libraries(${target} PUBLIC ${SDL3_LIBRARIES}) + if(INSTALL_MINGW_DEPENDENCIES) + install_shared_libs(${SDL3_LIBRARIES} DESTINATION bin NO_INSTALL_SYMLINKS) + endif() + else() + # Only try to autodetect if both SDL3 variables aren't explicitly set + find_package(SDL3 CONFIG) + if (TARGET SDL3::SDL3) + message(STATUS "using TARGET SDL3::SDL3") + target_link_libraries(${target} PUBLIC SDL3::SDL3) + if(INSTALL_MINGW_DEPENDENCIES) + install_shared_libs(TARGETS SDL3::SDL3 DESTINATION bin NO_INSTALL_SYMLINKS REQUIRED) + endif() + elseif (TARGET SDL3) + message(STATUS "using TARGET SDL3") + target_link_libraries(${target} PUBLIC SDL3) + if(INSTALL_MINGW_DEPENDENCIES) + install_shared_libs(TARGETS SDL3 DESTINATION bin NO_INSTALL_SYMLINKS REQUIRED) + endif() + else() + message(STATUS "no TARGET SDL3::SDL3, or SDL3, using variables") + target_include_directories(${target} PUBLIC "$") + target_link_libraries(${target} PUBLIC ${SDL3_LIBRARIES}) + if(INSTALL_MINGW_DEPENDENCIES) + install_shared_libs(${SDL3_LIBRARIES} DESTINATION bin NO_INSTALL_SYMLINKS) + endif() + endif() + endif() +elseif (DEFINED SDL2_INCLUDE_DIRS AND DEFINED SDL2_LIBRARIES) message(STATUS "using pre-defined SDL2 variables SDL2_INCLUDE_DIRS and SDL2_LIBRARIES") - target_include_directories(FAudio PUBLIC "$") - target_link_libraries(FAudio PUBLIC ${SDL2_LIBRARIES}) + target_include_directories(${target} PUBLIC "$") + target_link_libraries(${target} PUBLIC ${SDL2_LIBRARIES}) if(INSTALL_MINGW_DEPENDENCIES) install_shared_libs(${SDL2_LIBRARIES} DESTINATION bin NO_INSTALL_SYMLINKS) endif() @@ -177,20 +210,20 @@ else() find_package(SDL2 CONFIG) if (TARGET SDL2::SDL2) message(STATUS "using TARGET SDL2::SDL2") - target_link_libraries(FAudio PUBLIC SDL2::SDL2) + target_link_libraries(${target} PUBLIC SDL2::SDL2) if(INSTALL_MINGW_DEPENDENCIES) install_shared_libs(TARGETS SDL2::SDL2 DESTINATION bin NO_INSTALL_SYMLINKS REQUIRED) endif() elseif (TARGET SDL2) message(STATUS "using TARGET SDL2") - target_link_libraries(FAudio PUBLIC SDL2) + target_link_libraries(${target} PUBLIC SDL2) if(INSTALL_MINGW_DEPENDENCIES) install_shared_libs(TARGETS SDL2 DESTINATION bin NO_INSTALL_SYMLINKS REQUIRED) endif() else() message(STATUS "no TARGET SDL2::SDL2, or SDL2, using variables") - target_include_directories(FAudio PUBLIC "$") - target_link_libraries(FAudio PUBLIC ${SDL2_LIBRARIES}) + target_include_directories(${target} PUBLIC "$") + target_link_libraries(${target} PUBLIC ${SDL2_LIBRARIES}) if(INSTALL_MINGW_DEPENDENCIES) install_shared_libs(${SDL2_LIBRARIES} DESTINATION bin NO_INSTALL_SYMLINKS) endif() @@ -204,9 +237,6 @@ if(BUILD_UTILS) # Shared ImGui Framework add_library(uicommon STATIC utils/uicommon/FAudioUI_main.cpp - utils/uicommon/FAudioUI_ui.cpp - utils/uicommon/glfuncs.h - utils/uicommon/glmacros.h utils/uicommon/imconfig.h utils/uicommon/imgui.cpp utils/uicommon/imgui_demo.cpp @@ -218,7 +248,7 @@ if(BUILD_UTILS) utils/uicommon/imstb_textedit.h utils/uicommon/imstb_truetype.h ) - target_link_libraries(uicommon PUBLIC FAudio) + target_link_libraries(uicommon PUBLIC ${target}) # Shared WAV Resources add_library(wavs STATIC utils/wavcommon/wavs.cpp) @@ -228,11 +258,11 @@ if(BUILD_UTILS) # These tools do NOT use uicommon add_executable(testparse utils/testparse/testparse.c) - target_link_libraries(testparse PRIVATE FAudio) + target_link_libraries(testparse PRIVATE ${target}) add_executable(testxwma utils/testxwma/testxwma.cpp) - target_link_libraries(testxwma PRIVATE FAudio) + target_link_libraries(testxwma PRIVATE ${target}) add_executable(showriffheader utils/showriffheader/showriffheader.cpp) - target_link_libraries(showriffheader PRIVATE FAudio) + target_link_libraries(showriffheader PRIVATE ${target}) # These tools use uicommon, but NOT wavs add_executable(facttool utils/facttool/facttool.cpp) @@ -265,6 +295,10 @@ if(BUILD_UTILS) utils/testvolumemeter/testvolumemeter.cpp ) target_link_libraries(testvolumemeter PRIVATE uicommon wavs) + add_executable(voicepool + utils/voicepool/voicepool.cpp + ) + target_link_libraries(voicepool PRIVATE uicommon wavs) endif() # define install directories @@ -281,147 +315,11 @@ else() set(FAudio_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}) endif() -# cpp/ Folder -if(BUILD_CPP) - enable_language(CXX) - - # XAPOBase, used by XAudio2 and XAPOFX - add_library(XAPOBase STATIC - cpp/XAPOBase.cpp - ) - target_compile_definitions(XAPOBase PRIVATE - FAUDIOCPP_EXPORTS - _WIN32_WINNT=0x0600 - ) - target_link_libraries(XAPOBase PRIVATE FAudio) - if(MINGW) - target_link_libraries(XAPOBase PRIVATE - "-Wl,--enable-stdcall-fixup" - ) - # Enable various compiler warnings - target_link_libraries(XAPOBase PRIVATE - -Wall -pedantic - -Wsign-compare - -Wshadow - ) - endif() - - # We're about to make a whole bunch of DLLs... - set(FAudio_CPP_libs "") - - # XAudio2 2.0-2.7 - foreach(lib_version RANGE 0 7) - set(faudio_cpp_target "xaudio2_${lib_version}") - add_library(${faudio_cpp_target} SHARED - cpp/com_utils.cpp - cpp/xaudio2.cpp - cpp/XAudio2fx.cpp - cpp/win_registry.cpp - ) - target_compile_definitions(${faudio_cpp_target} PRIVATE - "XAUDIO2_VERSION=${lib_version}" - ) - target_link_libraries(${faudio_cpp_target} PRIVATE XAPOBase) - list(APPEND FAudio_CPP_libs ${faudio_cpp_target}) - endforeach() - - # XAudio2 2.8-2.9 - foreach(lib_version RANGE 8 9) - set(faudio_cpp_target "xaudio2_${lib_version}") - add_library(${faudio_cpp_target} SHARED - cpp/com_utils.cpp - cpp/xaudio2.cpp - cpp/XAudio2fx.cpp - cpp/win_device.cpp - cpp/X3DAudio.cpp - cpp/XAPOFX.cpp - ) - target_compile_definitions(${faudio_cpp_target} PRIVATE - "XAUDIO2_VERSION=${lib_version}" - UNICODE - ) - target_link_libraries(${faudio_cpp_target} PRIVATE XAPOBase setupapi) - list(APPEND FAudio_CPP_libs ${faudio_cpp_target}) - endforeach() - - # X3DAudio 1.3-1.7 - foreach(lib_version RANGE 3 7) - set(faudio_cpp_target "x3daudio1_${lib_version}") - add_library(${faudio_cpp_target} SHARED cpp/X3DAudio.cpp) - list(APPEND FAudio_CPP_libs ${faudio_cpp_target}) - endforeach() - - # XAPOFX 1.1-1.5 - foreach(lib_version RANGE 1 5) - set(faudio_cpp_target "xapofx1_${lib_version}") - add_library(${faudio_cpp_target} SHARED - cpp/com_utils_xapofx.cpp - cpp/XAPOFX.cpp - ) - target_link_libraries(${faudio_cpp_target} PRIVATE XAPOBase) - list(APPEND FAudio_CPP_libs ${faudio_cpp_target}) - endforeach() - - # XACTEngine3 3.0-3.7 - foreach(lib_version RANGE 0 7) - set(faudio_cpp_target "xactengine3_${lib_version}") - add_library(${faudio_cpp_target} SHARED - cpp/com_utils_xact.cpp - cpp/xact3.cpp - cpp/win_registry.cpp - ) - target_compile_definitions(${faudio_cpp_target} PRIVATE - "XACT3_VERSION=${lib_version}" - ) - list(APPEND FAudio_CPP_libs ${faudio_cpp_target}) - endforeach() - - # Common Libraries/Definitions - foreach(faudio_cpp_target ${FAudio_CPP_libs}) - target_link_libraries(${faudio_cpp_target} PRIVATE - ole32 - FAudio - ) - target_compile_definitions(${faudio_cpp_target} PRIVATE - FAUDIOCPP_EXPORTS - _WIN32_WINNT=0x0600 - ) - - # MinGW builds should statically link libgcc/libstdc++ - if(MINGW) - target_link_libraries(${faudio_cpp_target} PRIVATE - "-Wl,--enable-stdcall-fixup" - "-static-libgcc -static-libstdc++" - ) - # Enable various compiler warnings - target_link_libraries(${faudio_cpp_target} PRIVATE - -Wall -pedantic - -Wsign-compare - -Wshadow - ) - endif() - endforeach() - - # Add libraries to install target - install(TARGETS ${FAudio_CPP_libs} - RUNTIME DESTINATION ${FAudio_INSTALL_BINDIR} - LIBRARY DESTINATION ${FAudio_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${FAudio_INSTALL_LIBDIR} - ) - # Add Wine install script to install target - install(PROGRAMS cpp/scripts/wine_setup_native - DESTINATION ${FAudio_INSTALL_BINDIR} - ) - # Install runtime dependencies - if(INSTALL_MINGW_DEPENDENCIES) - install_shared_libs(-lwinpthread-1 -lwinpthread -liconv DESTINATION bin NO_INSTALL_SYMLINKS) - endif() -endif() - # tests/ Folder if(BUILD_TESTS) add_executable(faudio_tests tests/xaudio2.c) - target_link_libraries(faudio_tests PRIVATE FAudio) + target_compile_definitions(faudio_tests PRIVATE _DEFAULT_SOURCE _BSD_SOURCE) + target_link_libraries(faudio_tests PRIVATE ${target}) endif() # Installation @@ -432,9 +330,15 @@ install( DESTINATION ${FAudio_INSTALL_INCLUDEDIR} ) # Libraries... +set(export ${PROJECT_NAME}-targets-shared) + +if(NOT BUILD_SHARED_LIBS) + set(export ${PROJECT_NAME}-targets-static) +endif() + install( - TARGETS ${PROJECT_NAME} - EXPORT ${PROJECT_NAME}-targets + TARGETS ${target} + EXPORT ${export} INCLUDES DESTINATION ${FAudio_INSTALL_INCLUDEDIR} RUNTIME DESTINATION ${FAudio_INSTALL_BINDIR} LIBRARY DESTINATION ${FAudio_INSTALL_LIBDIR} @@ -445,6 +349,15 @@ install( include(cmake/JoinPaths.cmake) join_paths(FAUDIO_PKGCONF_LIBDIR "\${prefix}" "${CMAKE_INSTALL_LIBDIR}") join_paths(FAUDIO_PKGCONF_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") + +if(NOT PLATFORM_WIN32) + if(BUILD_SDL3) + set(PC_REQUIRES_PRIVATE "Requires.private: sdl3") + else() + set(PC_REQUIRES_PRIVATE "Requires.private: sdl2") + endif() +endif() + configure_file( "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}.pc.in" ${PROJECT_BINARY_DIR}/generated/${PROJECT_NAME}.pc @@ -459,15 +372,16 @@ install( include(CMakePackageConfigHelpers) configure_package_config_file( cmake/config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/generated/${PROJECT_NAME}-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/generated/${PROJECT_NAME}Config.cmake INSTALL_DESTINATION ${FAudio_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/generated/${PROJECT_NAME}-config.cmake + FILES ${CMAKE_CURRENT_BINARY_DIR}/generated/${PROJECT_NAME}Config.cmake DESTINATION ${FAudio_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) + install( - EXPORT ${PROJECT_NAME}-targets + EXPORT ${export} NAMESPACE ${PROJECT_NAME}:: DESTINATION ${FAudio_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) diff --git a/LICENSE b/LICENSE index 4877a26753..e7b10fba79 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/README b/README index 262821ec5a..5fdce024de 100644 --- a/README +++ b/README @@ -15,7 +15,7 @@ library via FAudio#, which you can find in the 'csharp/' directory. Dependencies ------------ -FAudio depends solely on SDL 2.0.9 or newer. +FAudio depends solely on SDL 3.2.0 or newer. FAudio never explicitly uses the C runtime. Building FAudio @@ -29,9 +29,9 @@ For *nix platforms, use cmake. For Windows, see the 'visualc/' directory. -For Xbox One, see the 'visualc-winrt/' directory. +For Xbox GDK, see the 'visualc-gdk/' directory. -For iOS/tvOS, see the 'Xcode-iOS/' directory. +For iOS/tvOS and macOS universal binaries, see the 'Xcode/' directory. Unit tests ---------- diff --git a/README.gstreamer b/README.gstreamer deleted file mode 100644 index a561f8ec22..0000000000 --- a/README.gstreamer +++ /dev/null @@ -1,20 +0,0 @@ -FAudio has optional support for decoding xWMA resources using GStreamer. - -Please note that enabling support for GStreamer means your project has to comply -with the GStreamer license and WMA patent license. For more information: - -https://gstreamer.freedesktop.org/documentation/frequently-asked-questions/legal.html - -https://fluendo.com/en/products/enterprise/fluendo-codec-pack/ - -Building with GStreamer support on *nix platforms -------------------------------------------------- -Enable GStreamer support at cmake configure-time with `-DGSTREAMER=ON`. - -Building with GStreamer support on Windows ------------------------------------------- -You'll need to modify the Visual Studio project for FAudio to enable support: -- Add HAVE_GSTREAMER=1 to preprocessor defines -- Add the correct include and lib paths to the Visual C++ directories. -- Add the GStreamer .lib files to the linker input -- Add FAudio_gstreamer.c to the sources of the project diff --git a/Xcode-iOS/FAudio.xcodeproj/xcshareddata/xcschemes/FAudio.xcscheme b/Xcode-iOS/FAudio.xcodeproj/xcshareddata/xcschemes/FAudio.xcscheme deleted file mode 100644 index 76d67b6068..0000000000 --- a/Xcode-iOS/FAudio.xcodeproj/xcshareddata/xcschemes/FAudio.xcscheme +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Xcode-iOS/FAudio.xcodeproj/project.pbxproj b/Xcode/FAudio.xcodeproj/project.pbxproj similarity index 63% rename from Xcode-iOS/FAudio.xcodeproj/project.pbxproj rename to Xcode/FAudio.xcodeproj/project.pbxproj index 77cbeae8db..72dbcc6e4e 100644 --- a/Xcode-iOS/FAudio.xcodeproj/project.pbxproj +++ b/Xcode/FAudio.xcodeproj/project.pbxproj @@ -42,9 +42,108 @@ 7BD20D892190C8E50020B14B /* FAudio_platform_sdl2.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6C2190C8E50020B14B /* FAudio_platform_sdl2.c */; }; 7BD20D8B2190C8E50020B14B /* FAPOFX_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6D2190C8E50020B14B /* FAPOFX_reverb.c */; }; 7BD20D8D2190C8E50020B14B /* FAudioFX_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6E2190C8E50020B14B /* FAudioFX_reverb.c */; }; + 7BD31FBE2B434349003EEE59 /* FAPOBase.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D642190C8E50020B14B /* FAPOBase.c */; }; + 7BD31FBF2B434349003EEE59 /* FAudio_internal_simd.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D662190C8E50020B14B /* FAudio_internal_simd.c */; }; + 7BD31FC02B434349003EEE59 /* FAudio_operationset.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B80D132227CE0E000AE825D /* FAudio_operationset.c */; }; + 7BD31FC12B434349003EEE59 /* FAPOFX_masteringlimiter.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D632190C8E50020B14B /* FAPOFX_masteringlimiter.c */; }; + 7BD31FC22B434349003EEE59 /* FACT.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6A2190C8E50020B14B /* FACT.c */; }; + 7BD31FC32B434349003EEE59 /* FAudioFX_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6E2190C8E50020B14B /* FAudioFX_reverb.c */; }; + 7BD31FC42B434349003EEE59 /* FAudio_platform_sdl2.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6C2190C8E50020B14B /* FAudio_platform_sdl2.c */; }; + 7BD31FC52B434349003EEE59 /* FAPOFX.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D672190C8E50020B14B /* FAPOFX.c */; }; + 7BD31FC62B434349003EEE59 /* FAPOFX_reverb.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6D2190C8E50020B14B /* FAPOFX_reverb.c */; }; + 7BD31FC72B434349003EEE59 /* FAPOFX_eq.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D6B2190C8E50020B14B /* FAPOFX_eq.c */; }; + 7BD31FC82B434349003EEE59 /* FACT_internal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D602190C8E50020B14B /* FACT_internal.c */; }; + 7BD31FC92B434349003EEE59 /* XNA_Song.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B6908262190EC41003C0941 /* XNA_Song.c */; }; + 7BD31FCA2B434349003EEE59 /* FAudio_internal.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D622190C8E50020B14B /* FAudio_internal.c */; }; + 7BD31FCB2B434349003EEE59 /* FAPOFX_echo.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D682190C8E50020B14B /* FAPOFX_echo.c */; }; + 7BD31FCC2B434349003EEE59 /* FACT3D.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D652190C8E50020B14B /* FACT3D.c */; }; + 7BD31FCD2B434349003EEE59 /* FAudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D692190C8E50020B14B /* FAudio.c */; }; + 7BD31FCE2B434349003EEE59 /* F3DAudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D612190C8E50020B14B /* F3DAudio.c */; }; + 7BD31FCF2B434349003EEE59 /* FAudioFX_volumemeter.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BD20D5F2190C8E50020B14B /* FAudioFX_volumemeter.c */; }; + 7BD31FF52B4344D0003EEE59 /* libSDL2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BD31FED2B4344C1003EEE59 /* libSDL2.dylib */; }; 7BD806B122A0B4F900D9679D /* FAudio_operationset.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B80D132227CE0E000AE825D /* FAudio_operationset.c */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 7BD31FDE2B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = BECDF66C0761BA81005FE872; + remoteInfo = Framework; + }; + 7BD31FE02B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A7D88B5423E2437C00DCD162; + remoteInfo = "Framework-iOS"; + }; + 7BD31FE22B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A7D88D1523E24BED00DCD162; + remoteInfo = "Framework-tvOS"; + }; + 7BD31FE42B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E2D187CF28A5673500D2B4F1; + remoteInfo = "xcFramework-iOS"; + }; + 7BD31FE62B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = BECDF6B30761BA81005FE872; + remoteInfo = "Static Library"; + }; + 7BD31FE82B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A7D88E5423E24D3B00DCD162; + remoteInfo = "Static Library-iOS"; + }; + 7BD31FEA2B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A769B23D23E259AE00872273; + remoteInfo = "Static Library-tvOS"; + }; + 7BD31FEC2B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DB31407717554B71006C0E22; + remoteInfo = "Shared Library"; + }; + 7BD31FEE2B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A75FCEB323E25AB700529352; + remoteInfo = "Shared Library-iOS"; + }; + 7BD31FF02B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A75FD06C23E25AC700529352; + remoteInfo = "Shared Library-tvOS"; + }; + 7BD31FF22B4344C1003EEE59 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = BECDF6BE0761BA81005FE872; + remoteInfo = "Standard DMG"; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ 7B1CDD432190C0A200175C7B /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -68,8 +167,9 @@ /* Begin PBXFileReference section */ 7B1CDD452190C0A200175C7B /* libFAudio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFAudio.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B5EE3122B43428D004061E2 /* libFAudio.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libFAudio.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 7B6908262190EC41003C0941 /* XNA_Song.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = XNA_Song.c; path = ../src/XNA_Song.c; sourceTree = ""; }; - 7B7E140D2190E0CB00616654 /* libFAudio-tv.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libFAudio-tv.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B7E140D2190E0CB00616654 /* libFAudio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFAudio.a; sourceTree = BUILT_PRODUCTS_DIR; }; 7B80D132227CE0E000AE825D /* FAudio_operationset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FAudio_operationset.c; path = ../src/FAudio_operationset.c; sourceTree = ""; }; 7BA5611F21B9C7D800AB0E8C /* F3DAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = F3DAudio.h; path = ../include/F3DAudio.h; sourceTree = ""; }; 7BA5612021B9C7D800AB0E8C /* FAPO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FAPO.h; path = ../include/FAPO.h; sourceTree = ""; }; @@ -97,6 +197,7 @@ 7BD20D6C2190C8E50020B14B /* FAudio_platform_sdl2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FAudio_platform_sdl2.c; path = ../src/FAudio_platform_sdl2.c; sourceTree = ""; }; 7BD20D6D2190C8E50020B14B /* FAPOFX_reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FAPOFX_reverb.c; path = ../src/FAPOFX_reverb.c; sourceTree = ""; }; 7BD20D6E2190C8E50020B14B /* FAudioFX_reverb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FAudioFX_reverb.c; path = ../src/FAudioFX_reverb.c; sourceTree = ""; }; + 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL.xcodeproj; path = ../../SDL2/Xcode/SDL/SDL.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -107,6 +208,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7B5EE3102B43428D004061E2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7BD31FF52B4344D0003EEE59 /* libSDL2.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 7B7E140A2190E0CB00616654 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -120,9 +229,11 @@ 7B1CDD3C2190C0A200175C7B = { isa = PBXGroup; children = ( + 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */, 7B1CDDA72190C52900175C7B /* Public Headers */, 7B1CDDA62190C50300175C7B /* Library Source */, 7B1CDD462190C0A200175C7B /* Products */, + 7BD31FF42B4344D0003EEE59 /* Frameworks */, ); sourceTree = ""; }; @@ -130,7 +241,8 @@ isa = PBXGroup; children = ( 7B1CDD452190C0A200175C7B /* libFAudio.a */, - 7B7E140D2190E0CB00616654 /* libFAudio-tv.a */, + 7B7E140D2190E0CB00616654 /* libFAudio.a */, + 7B5EE3122B43428D004061E2 /* libFAudio.dylib */, ); name = Products; sourceTree = ""; @@ -177,12 +289,47 @@ name = "Public Headers"; sourceTree = ""; }; + 7BD31FD12B4344C0003EEE59 /* Products */ = { + isa = PBXGroup; + children = ( + 7BD31FDF2B4344C1003EEE59 /* SDL2.framework */, + 7BD31FE12B4344C1003EEE59 /* SDL2.framework */, + 7BD31FE32B4344C1003EEE59 /* SDL2.framework */, + 7BD31FE52B4344C1003EEE59 /* SDL2.framework */, + 7BD31FE72B4344C1003EEE59 /* libSDL2.a */, + 7BD31FE92B4344C1003EEE59 /* libSDL2.a */, + 7BD31FEB2B4344C1003EEE59 /* libSDL2.a */, + 7BD31FED2B4344C1003EEE59 /* libSDL2.dylib */, + 7BD31FEF2B4344C1003EEE59 /* libSDL2.dylib */, + 7BD31FF12B4344C1003EEE59 /* libSDL2.dylib */, + 7BD31FF32B4344C1003EEE59 /* SDL2 */, + ); + name = Products; + sourceTree = ""; + }; + 7BD31FF42B4344D0003EEE59 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + 7B5EE30E2B43428D004061E2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ - 7B1CDD442190C0A200175C7B /* FAudio */ = { + 7B1CDD442190C0A200175C7B /* FAudio-iOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 7B1CDD4E2190C0A200175C7B /* Build configuration list for PBXNativeTarget "FAudio" */; + buildConfigurationList = 7B1CDD4E2190C0A200175C7B /* Build configuration list for PBXNativeTarget "FAudio-iOS" */; buildPhases = ( 7B1CDD412190C0A200175C7B /* Sources */, 7B1CDD422190C0A200175C7B /* Frameworks */, @@ -192,14 +339,31 @@ ); dependencies = ( ); - name = FAudio; + name = "FAudio-iOS"; productName = "FAudio-iOS"; productReference = 7B1CDD452190C0A200175C7B /* libFAudio.a */; productType = "com.apple.product-type.library.static"; }; - 7B7E140C2190E0CB00616654 /* FAudio-tv */ = { + 7B5EE3112B43428D004061E2 /* FAudio-macOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 7B7E14132190E0CB00616654 /* Build configuration list for PBXNativeTarget "FAudio-tv" */; + buildConfigurationList = 7B5EE3132B43428D004061E2 /* Build configuration list for PBXNativeTarget "FAudio-macOS" */; + buildPhases = ( + 7B5EE30E2B43428D004061E2 /* Headers */, + 7B5EE30F2B43428D004061E2 /* Sources */, + 7B5EE3102B43428D004061E2 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "FAudio-macOS"; + productName = "FAudio-macOS"; + productReference = 7B5EE3122B43428D004061E2 /* libFAudio.dylib */; + productType = "com.apple.product-type.library.dynamic"; + }; + 7B7E140C2190E0CB00616654 /* FAudio-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B7E14132190E0CB00616654 /* Build configuration list for PBXNativeTarget "FAudio-tvOS" */; buildPhases = ( 7B7E14092190E0CB00616654 /* Sources */, 7B7E140A2190E0CB00616654 /* Frameworks */, @@ -209,9 +373,9 @@ ); dependencies = ( ); - name = "FAudio-tv"; + name = "FAudio-tvOS"; productName = "FAudio-tv"; - productReference = 7B7E140D2190E0CB00616654 /* libFAudio-tv.a */; + productReference = 7B7E140D2190E0CB00616654 /* libFAudio.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -226,6 +390,9 @@ 7B1CDD442190C0A200175C7B = { CreatedOnToolsVersion = 10.1; }; + 7B5EE3112B43428D004061E2 = { + CreatedOnToolsVersion = 15.1; + }; 7B7E140C2190E0CB00616654 = { CreatedOnToolsVersion = 10.1; }; @@ -241,14 +408,101 @@ mainGroup = 7B1CDD3C2190C0A200175C7B; productRefGroup = 7B1CDD462190C0A200175C7B /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 7BD31FD12B4344C0003EEE59 /* Products */; + ProjectRef = 7BD31FD02B4344C0003EEE59 /* SDL.xcodeproj */; + }, + ); projectRoot = ""; targets = ( - 7B1CDD442190C0A200175C7B /* FAudio */, - 7B7E140C2190E0CB00616654 /* FAudio-tv */, + 7B1CDD442190C0A200175C7B /* FAudio-iOS */, + 7B7E140C2190E0CB00616654 /* FAudio-tvOS */, + 7B5EE3112B43428D004061E2 /* FAudio-macOS */, ); }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 7BD31FDF2B4344C1003EEE59 /* SDL2.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SDL2.framework; + remoteRef = 7BD31FDE2B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FE12B4344C1003EEE59 /* SDL2.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SDL2.framework; + remoteRef = 7BD31FE02B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FE32B4344C1003EEE59 /* SDL2.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SDL2.framework; + remoteRef = 7BD31FE22B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FE52B4344C1003EEE59 /* SDL2.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SDL2.framework; + remoteRef = 7BD31FE42B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FE72B4344C1003EEE59 /* libSDL2.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSDL2.a; + remoteRef = 7BD31FE62B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FE92B4344C1003EEE59 /* libSDL2.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSDL2.a; + remoteRef = 7BD31FE82B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FEB2B4344C1003EEE59 /* libSDL2.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSDL2.a; + remoteRef = 7BD31FEA2B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FED2B4344C1003EEE59 /* libSDL2.dylib */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.dylib"; + path = libSDL2.dylib; + remoteRef = 7BD31FEC2B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FEF2B4344C1003EEE59 /* libSDL2.dylib */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.dylib"; + path = libSDL2.dylib; + remoteRef = 7BD31FEE2B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FF12B4344C1003EEE59 /* libSDL2.dylib */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.dylib"; + path = libSDL2.dylib; + remoteRef = 7BD31FF02B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 7BD31FF32B4344C1003EEE59 /* SDL2 */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = SDL2; + remoteRef = 7BD31FF22B4344C1003EEE59 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXSourcesBuildPhase section */ 7B1CDD412190C0A200175C7B /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -275,6 +529,31 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7B5EE30F2B43428D004061E2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7BD31FC42B434349003EEE59 /* FAudio_platform_sdl2.c in Sources */, + 7BD31FCD2B434349003EEE59 /* FAudio.c in Sources */, + 7BD31FCC2B434349003EEE59 /* FACT3D.c in Sources */, + 7BD31FCF2B434349003EEE59 /* FAudioFX_volumemeter.c in Sources */, + 7BD31FC72B434349003EEE59 /* FAPOFX_eq.c in Sources */, + 7BD31FC22B434349003EEE59 /* FACT.c in Sources */, + 7BD31FC82B434349003EEE59 /* FACT_internal.c in Sources */, + 7BD31FCB2B434349003EEE59 /* FAPOFX_echo.c in Sources */, + 7BD31FC92B434349003EEE59 /* XNA_Song.c in Sources */, + 7BD31FCA2B434349003EEE59 /* FAudio_internal.c in Sources */, + 7BD31FC32B434349003EEE59 /* FAudioFX_reverb.c in Sources */, + 7BD31FBE2B434349003EEE59 /* FAPOBase.c in Sources */, + 7BD31FC12B434349003EEE59 /* FAPOFX_masteringlimiter.c in Sources */, + 7BD31FC52B434349003EEE59 /* FAPOFX.c in Sources */, + 7BD31FC62B434349003EEE59 /* FAPOFX_reverb.c in Sources */, + 7BD31FCE2B434349003EEE59 /* F3DAudio.c in Sources */, + 7BD31FC02B434349003EEE59 /* FAudio_operationset.c in Sources */, + 7BD31FBF2B434349003EEE59 /* FAudio_internal_simd.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 7B7E14092190E0CB00616654 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -338,6 +617,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; + DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -356,11 +636,10 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ../../SDL2/include; IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvos appletvsimulator"; + PRODUCT_NAME = FAudio; TVOS_DEPLOYMENT_TARGET = 9.0; }; name = Debug; @@ -400,6 +679,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -416,10 +696,10 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ../../SDL2/include; IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvos appletvsimulator"; + PRODUCT_NAME = FAudio; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; }; @@ -430,7 +710,7 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -442,19 +722,56 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; + 7B5EE3142B43428D004061E2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 78E9RL28VG; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu17; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 7B5EE3152B43428D004061E2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 78E9RL28VG; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu17; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; 7B7E14142190E0CB00616654 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; @@ -467,7 +784,6 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; @@ -487,7 +803,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7B1CDD4E2190C0A200175C7B /* Build configuration list for PBXNativeTarget "FAudio" */ = { + 7B1CDD4E2190C0A200175C7B /* Build configuration list for PBXNativeTarget "FAudio-iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B1CDD4F2190C0A200175C7B /* Debug */, @@ -496,7 +812,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 7B7E14132190E0CB00616654 /* Build configuration list for PBXNativeTarget "FAudio-tv" */ = { + 7B5EE3132B43428D004061E2 /* Build configuration list for PBXNativeTarget "FAudio-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B5EE3142B43428D004061E2 /* Debug */, + 7B5EE3152B43428D004061E2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B7E14132190E0CB00616654 /* Build configuration list for PBXNativeTarget "FAudio-tvOS" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B7E14142190E0CB00616654 /* Debug */, diff --git a/Xcode-iOS/README b/Xcode/README similarity index 61% rename from Xcode-iOS/README rename to Xcode/README index 2f44afade8..70dbe0ecdb 100644 --- a/Xcode-iOS/README +++ b/Xcode/README @@ -1,6 +1,6 @@ -Building FAudio for iOS/tvOS +Building FAudio for macOS/iOS/tvOS ---------------------------- -FAudio uses Xcode to build on iOS and tvOS. +FAudio uses Xcode to build on macOS, iOS, and tvOS. Dependencies ------------ @@ -13,6 +13,6 @@ version number (for example, 'SDL2-2.0.8' should be 'SDL2'). Compiling --------- -1. Build SDL2/Xcode-iOS/SDL/SDL.xcodeproj +1. Build SDL2/Xcode/SDL/SDL.xcodeproj 2. Build FAudio.xcodeproj -3. Grab libFAudio.a and libSDL2.a, ship it! +3. Grab libFAudio.a and libSDL2.a (or libFAudio.dylib and libSDL2.dylib on macOS), ship it! diff --git a/cmake/FAudio.pc.in b/cmake/FAudio.pc.in index 223dc2b8de..6d96dbe68c 100644 --- a/cmake/FAudio.pc.in +++ b/cmake/FAudio.pc.in @@ -7,6 +7,7 @@ Name: @PROJECT_NAME@ URL: https://github.com/FNA-XNA/FAudio Description: Accuracy-focused XAudio reimplementation for open platforms Version: @LIB_VERSION@ +@PC_REQUIRES_PRIVATE@ Libs: -L${libdir} -l@PROJECT_NAME@ -Cflags: -I${includedir} +Cflags: -I${includedir} @PLATFORM_CFLAGS@ diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in index 8bb8c0e83a..39cf03ad44 100644 --- a/cmake/config.cmake.in +++ b/cmake/config.cmake.in @@ -1,5 +1,24 @@ @PACKAGE_INIT@ -include("${CMAKE_CURRENT_LIST_DIR}/@CMAKE_PROJECT_NAME@-targets.cmake") +if(NOT "@PLATFORM_WIN32@") + include(CMakeFindDependencyMacro) + find_dependency(SDL2 CONFIG) +endif() + +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@CMAKE_PROJECT_NAME@-targets-shared.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@CMAKE_PROJECT_NAME@-targets-shared.cmake") + set(shared_target TRUE) +endif() + +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@CMAKE_PROJECT_NAME@-targets-static.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@CMAKE_PROJECT_NAME@-targets-static.cmake") +endif() + +if(shared_target) + add_library(@CMAKE_PROJECT_NAME@::@CMAKE_PROJECT_NAME@ ALIAS @CMAKE_PROJECT_NAME@::@CMAKE_PROJECT_NAME@-shared) +else() + add_library(@CMAKE_PROJECT_NAME@::@CMAKE_PROJECT_NAME@ ALIAS @CMAKE_PROJECT_NAME@::@CMAKE_PROJECT_NAME@-static) +endif() + check_required_components("@CMAKE_PROJECT_NAME@") diff --git a/cpp/README.md b/cpp/README.md deleted file mode 100644 index 78fcf7fb59..0000000000 --- a/cpp/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# C++ / COM Interface for FAudio -Use FAudio as a substitute for XAudio2 without changing or recompiling the host application. -Works on: -- Windows -- Wine on Linux as a native (= Windows binary) DLL - -## Building - -### Building Windows DLLs with Visual Studio -A Visual Studio 2010 solution is included in the `cpp/visualc` directory. - -Newer Visual Studio versions should be able to upgrade the 2010 solution (e.g. Visual Studio 2015: right-click the solution and choose `Retarget solution`). If there are any issues check if the Platform Toolset is set to something reasonable in the general properties of the project. - -The resulting DLLs can also be used as native DLLs with Wine. - -### Building Windows DLLs with MSYS / mingw-w64 on Windows -The included `Makefile` has been tested to work with msys and mingw-w64 for both 32-bit and 64-bit builds. - -### Building native Wine DLLs with mingw-w64 on Linux -Because cross-compiling is fun. - -#### Prerequisites -- mingw-w64 has to be present on your system (the C and C++ compiler) -- install the SDL2 development libraries for mingw (download: [here](http://libsdl.org/download-2.0.php)) - -#### Building -Use your cross compilation cmake toolchain to configure the build. Use `i686-w64-mingw32-cmake` to build 32-bit and `x86_64-w64-mingw32-cmake` to build 64-bit libraries. -``` -x86_64-w64-mingw32-cmake -H. -B_build_mingw64 -DCMAKE_INSTALL_PREFIX="${PWD}/_faudio_mingw64" -DBUILD_CPP=ON -DINSTALL_MINGW_DEPENDENCIES=ON -i686-w64-mingw32-cmake -H. -B_build_mingw32 -DCMAKE_INSTALL_PREFIX="${PWD}/_faudio_mingw32" -DBUILD_CPP=ON -DINSTALL_MINGW_DEPENDENCIES=ON -``` -- `-DBUILD_CPP=ON` enables compilation of the C++/COM wrapper -- `-DINSTALL_MINGW_DEPENDENCIES` adds runtime dynamic libraries like `SDL2.dll` and `winpthread-1.dll` to the install target - -Optional: - -- See README.gstreamer for more information about WMA support. - -After the configuration is done the following command(s) starts the cross-compilation of both FAudio and C++/COM wrapper: -``` -cmake --build _build_mingw64 --target install -- -j -cmake --build _build_mingw32 --target install -- -j -``` - -- `-- -j` passes the `-j` flag to the `make` command to speed up compilation -- the results are installed to the `_install_mingw64/32` subdirectories - - -## Using the wrapper - -### Windows - XAudio version 2.8+ -COM support was dropped in XAudio 2.8, it's still using the same interfaces but they aren't registered any more. Applications link directly with an import library and use a plain function to create an IXAudio2 instance. - -Overriding the system XAudio2 DLLs is just a matter of taking advantage of the search path used by Windows when loading DLLs. Place `XAudio2_(8|9).dll` and its dependencies (FAudio.dll and SDL2.dll) in the same directory as the executable you want to test with FAudio. (This will only work if the application does not load the library with an absolute path.) - -Doing this also enables the XAudio2FX and X3DAudio wrappers because they are included in the main XAudio2 DLL starting from version 2.8. - -### Windows - XAudio version 2.7 or earlier -To use XAudio 2.7 or earlier we'll have to hijack to COM registration in the Windows registry. COM information is stored under `HKEY_CLASSES_ROOT` but in modern (Vista+?) Windows versions this is actually a merged view of `HKEY_LOCAL_MACHINE/Software/Classes` (for system defaults) and `HKEY_CURRENT_USER/Software/Classes` for user specific configuration. We use this to our advantage to register the FAudio wrapper DLLs for the current user. The standard Windows tool regsvr32 can be used to register or unregister the DLLs. Just make sure to specify an absolute path to the wrapper DLLs to prevent regsvr32 from using the standard Windows versions. - -The `cpp/scripts` directory has Windows cmd-scripts to (un)register all the DLLs in one step. Run `windows_register.bat` from the directory containing the wrapper DLLs to register and `windows_unregister.bat` to remove the overrides. - -X3DAudio is not a COM-interface, even in these earlier versions of XAudio2, use the version 2.8+ instructions. - -### Wine - native DLLs -A Wine prefix is a directory that contains a Wine configuration, registry, and native Windows DLLs for compatibility. It's trivial to replace the XAudio2 DLLs in a prefix with the FAudio wrapper DLLs and still use another prefix with the original DLLs. - -The `wine_setup_native` script (in the `cpp/scripts` subdirectory) does just this. Run it from a directory containing the wrapper DLLs (32 or 64 bit) and it will create symbolic links in the Wine prefix and modify the Wine registry to make sure Wine only uses the native DLLs. - -### How can I check if the wrapper DLLs are actually being used? -- Build the wrapper DLLs with tracing enabled (at the top of `xaudio2.cpp`) - - check to see if log entries are added when running the application -- Remove a dependency (e.g. `FAudio.dll`), the application will fail to load the wrapper and hopefully show a nice error message. - - Some applications (e.g. games using Wwise) will just try to use a different version of XAudio2 :-) -- Set `WINEDEBUG=+loaddll` to check which DLLs are loaded by the application -- On Windows, use [Sysinternals Process Monitor](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) to check which DLLs are loaded by the application - -## Redistributing the DLLs -The COM wrapper DLLs depend on both FAudio.dll and SDL2.dll. During the build process they are copied to the output directory. Don't forget to include these DLLs when you want to use the binaries from another directory or on another computer. - -# Known Issues -1. The application hangs when using the wrapper DLLs - - An assertion might have been triggered with the message box hidden behind the fullscreen application - - Alt-Tab until you can access the message box and dismiss it -2. The sound is crackling when using the native DLLs with Wine - - Are you using PulseAudio? Try setting the `PULSE_LATENCY_MSEC` environment variable to 60 to fix this. -3. Wine games are silent after installing the native DLLs - - Some MinGW setups will silently link to libwinpthread-1.dll, resulting in failure to load the DLLs if this is not present. Usually this is quickly solved with a line like `ln -sf /usr/i686-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll $WINEPREFIX/drive_c/windows/system32/libwinpthread-1.dll` -4. Wine audio may sound choppy with the native DLLs - - Set `SDL_AUDIODRIVER=directsound`. For Proton, this is `SDL_AUDIODRIVER=directsound %command%` in the Steam Launch Options. diff --git a/cpp/X3DAudio.cpp b/cpp/X3DAudio.cpp deleted file mode 100644 index 928af17a49..0000000000 --- a/cpp/X3DAudio.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "X3DAudio.h" - -F3DAUDIOCPP_API X3DAudioInitialize( - uint32_t SpeakerChannelMask, - float SpeedOfSound, - X3DAUDIO_HANDLE Instance -) { - F3DAudioInitialize(SpeakerChannelMask, SpeedOfSound, Instance); -} - -F3DAUDIOCPP_API X3DAudioCalculate( - const X3DAUDIO_HANDLE Instance, - const X3DAUDIO_LISTENER* pListener, - const X3DAUDIO_EMITTER* pEmitter, - uint32_t Flags, - X3DAUDIO_DSP_SETTINGS* pDSPSettings -) { - F3DAudioCalculate(Instance, pListener, pEmitter, Flags, pDSPSettings); -} - diff --git a/cpp/X3DAudio.h b/cpp/X3DAudio.h deleted file mode 100644 index b466551889..0000000000 --- a/cpp/X3DAudio.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef FACT_CPP_X3DAUDIO_H -#define FACT_CPP_X3DAUDIO_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#if defined _WIN32 || defined __CYGWIN__ - #define DLLIMPORT __declspec(dllimport) - #define DLLEXPORT __declspec(dllexport) -#else - #if __GNUC__ >= 4 - #define DLLIMPORT __attribute__((visibility ("default"))) - #define DLLEXPORT __attribute__((visibility ("default"))) - #else - #define DLLIMPORT - #define DLLEXPORT - #endif -#endif - -#ifdef FAUDIOCPP_EXPORTS -#define F3DAUDIOCPP_API extern "C" DLLEXPORT void __cdecl -#else -#define F3DAUDIOCPP_API extern "C" DLLIMPORT void __cdecl -#endif - -#ifndef X3DAUDIO_VERSION -#define X3DAUDIO_VERSION 7 -#endif - -#include - -typedef F3DAUDIO_HANDLE X3DAUDIO_HANDLE; -typedef F3DAUDIO_LISTENER X3DAUDIO_LISTENER; -typedef F3DAUDIO_EMITTER X3DAUDIO_EMITTER; -typedef F3DAUDIO_DSP_SETTINGS X3DAUDIO_DSP_SETTINGS; - -F3DAUDIOCPP_API X3DAudioInitialize( - uint32_t SpeakerChannelMask, - float SpeedOfSound, - X3DAUDIO_HANDLE Instance); - -F3DAUDIOCPP_API X3DAudioCalculate( - const X3DAUDIO_HANDLE Instance, - const X3DAUDIO_LISTENER* pListener, - const X3DAUDIO_EMITTER* pEmitter, - uint32_t Flags, - X3DAUDIO_DSP_SETTINGS* pDSPSettings); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif // FACT_CPP_X3DAUDIO_H \ No newline at end of file diff --git a/cpp/XAPO.h b/cpp/XAPO.h deleted file mode 100644 index 28fc0935cd..0000000000 --- a/cpp/XAPO.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef FACT_CPP_XAPO_H -#define FACT_CPP_XAPO_H - -#include "com_utils.h" -#include - -typedef FAPORegistrationProperties XAPO_REGISTRATION_PROPERTIES; -typedef FAPOLockForProcessBufferParameters XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS; -typedef FAPOProcessBufferParameters XAPO_PROCESS_BUFFER_PARAMETERS; -typedef FAudioWaveFormatEx WAVEFORMATEX; - -class IXAPO : public IUnknown -{ -public: - COM_METHOD(HRESULT) GetRegistrationProperties (XAPO_REGISTRATION_PROPERTIES** ppRegistrationProperties) = 0; - COM_METHOD(HRESULT) IsInputFormatSupported( - const WAVEFORMATEX* pOutputFormat, - const WAVEFORMATEX* pRequestedInputFormat, - WAVEFORMATEX** ppSupportedInputFormat) = 0; - COM_METHOD(HRESULT) IsOutputFormatSupported( - const WAVEFORMATEX* pInputFormat, - const WAVEFORMATEX* pRequestedOutputFormat, - WAVEFORMATEX** ppSupportedOutputFormat) = 0; - COM_METHOD(HRESULT) Initialize(const void* pData, UINT32 DataByteSize) = 0; - COM_METHOD(void) Reset() = 0; - COM_METHOD(HRESULT) LockForProcess( - UINT32 InputLockedParameterCount, - const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputLockedParameters, - UINT32 OutputLockedParameterCount, - const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputLockedParameters) = 0; - COM_METHOD(void) UnlockForProcess() = 0; - COM_METHOD(void) Process( - UINT32 InputProcessParameterCount, - const XAPO_PROCESS_BUFFER_PARAMETERS* pInputProcessParameters, - UINT32 OutputProcessParameterCount, - XAPO_PROCESS_BUFFER_PARAMETERS* pOutputProcessParameters, - BOOL IsEnabled) = 0; - COM_METHOD(UINT32) CalcInputFrames(UINT32 OutputFrameCount) = 0; - COM_METHOD(UINT32) CalcOutputFrames(UINT32 InputFrameCount) = 0; -}; - -class IXAPOParameters : public IUnknown -{ -public: - COM_METHOD(void) SetParameters(const void* pParameters, UINT32 ParameterByteSize) = 0; - COM_METHOD(void) GetParameters(void* pParameters, UINT32 ParameterByteSize) = 0; -}; - -#endif // FACT_CPP_XAPO_H \ No newline at end of file diff --git a/cpp/XAPOBase.cpp b/cpp/XAPOBase.cpp deleted file mode 100644 index 20ce8da3ec..0000000000 --- a/cpp/XAPOBase.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#include "XAPOBase.h" -#include - -/////////////////////////////////////////////////////////////////////////////// -// -// CXAPOBase -// - -void* CDECL XAPOBase_INTERNAL_Malloc(size_t size) -{ - return CoTaskMemAlloc(size); -} -void CDECL XAPOBase_INTERNAL_Free(void* ptr) -{ - CoTaskMemFree(ptr); -} -void* CDECL XAPOBase_INTERNAL_Realloc(void* ptr, size_t size) -{ - return CoTaskMemRealloc(ptr, size); -} - -CXAPOBase::CXAPOBase(FAPOBase *base) - : fapo_base(base), - own_fapo_base(false) -{ -} - -CXAPOBase::CXAPOBase(const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties, - BYTE* pParameterBlocks, - UINT32 uParameterBlockByteSize, - BOOL fProducer) - : fapo_base(new FAPOBase()), - own_fapo_base(true) -{ - CreateFAPOBaseWithCustomAllocatorEXT( - fapo_base, - pRegistrationProperties, - pParameterBlocks, - uParameterBlockByteSize, - fProducer, - XAPOBase_INTERNAL_Malloc, - XAPOBase_INTERNAL_Free, - XAPOBase_INTERNAL_Realloc - ); -} - -CXAPOBase::~CXAPOBase() -{ - if (own_fapo_base) - { - delete fapo_base; - } - else if (fapo_base->Destructor) - { - fapo_base->Destructor(fapo_base); - } -} - -HRESULT CXAPOBase::QueryInterface(REFIID riid, void** ppInterface) -{ - if (guid_equals(riid, IID_IXAPO)) - { - *ppInterface = static_cast(this); - } - else if (guid_equals(riid, IID_IUnknown)) - { - *ppInterface = static_cast(this); - } - else - { - *ppInterface = NULL; - return E_NOINTERFACE; - } - - reinterpret_cast(*ppInterface)->AddRef(); - - return S_OK; -} - -ULONG CXAPOBase::AddRef() -{ - return FAPOBase_AddRef(fapo_base); -} - -ULONG CXAPOBase::Release() -{ - ULONG refcount = FAPOBase_Release(fapo_base); - if (refcount == 0) - { - delete this; - } - - return refcount; -} - -HRESULT CXAPOBase::GetRegistrationProperties(XAPO_REGISTRATION_PROPERTIES** ppRegistrationProperties) -{ - assert(fapo_base->base.GetRegistrationProperties != NULL); - return fapo_base->base.GetRegistrationProperties(fapo_base, ppRegistrationProperties); -} - -HRESULT CXAPOBase::IsInputFormatSupported( - const WAVEFORMATEX* pOutputFormat, - const WAVEFORMATEX* pRequestedInputFormat, - WAVEFORMATEX** ppSupportedInputFormat -) { - assert(fapo_base->base.IsInputFormatSupported != NULL); - return fapo_base->base.IsInputFormatSupported( - fapo_base, - pOutputFormat, - pRequestedInputFormat, - ppSupportedInputFormat); -} - -HRESULT CXAPOBase::IsOutputFormatSupported( - const WAVEFORMATEX* pInputFormat, - const WAVEFORMATEX* pRequestedOutputFormat, - WAVEFORMATEX** ppSupportedOutputFormat -) { - assert(fapo_base->base.IsOutputFormatSupported != NULL); - return fapo_base->base.IsOutputFormatSupported( - fapo_base, - pInputFormat, - pRequestedOutputFormat, - ppSupportedOutputFormat); -} - -HRESULT CXAPOBase::Initialize(const void*pData, UINT32 DataByteSize) -{ - assert(fapo_base->base.Initialize != NULL); - return fapo_base->base.Initialize(fapo_base, pData, DataByteSize); -} - -void CXAPOBase::Reset() -{ - assert(fapo_base->base.Reset != NULL); - fapo_base->base.Reset(fapo_base); -} - -HRESULT CXAPOBase::LockForProcess( - UINT32 InputLockedParameterCount, - const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputLockedParameters, - UINT32 OutputLockedParameterCount, - const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputLockedParameters -) { - assert(fapo_base->base.LockForProcess != NULL); - return fapo_base->base.LockForProcess( - fapo_base, - InputLockedParameterCount, - pInputLockedParameters, - OutputLockedParameterCount, - pOutputLockedParameters); -} - -void CXAPOBase::UnlockForProcess() -{ - assert(fapo_base->base.UnlockForProcess != NULL); - fapo_base->base.UnlockForProcess(fapo_base); -} - -UINT32 CXAPOBase::CalcInputFrames(UINT32 OutputFrameCount) -{ - assert(fapo_base->base.CalcInputFrames != NULL); - return fapo_base->base.CalcInputFrames(fapo_base, OutputFrameCount); -} - -UINT32 CXAPOBase::CalcOutputFrames(UINT32 InputFrameCount) -{ - assert(fapo_base->base.CalcOutputFrames != NULL); - return fapo_base->base.CalcOutputFrames(fapo_base, InputFrameCount); -} - -// protected functions -HRESULT CXAPOBase::ValidateFormatDefault(WAVEFORMATEX* pFormat, BOOL fOverwrite) -{ - return FAPOBase_ValidateFormatDefault(fapo_base, pFormat, fOverwrite); -} - -HRESULT CXAPOBase::ValidateFormatPair( - const WAVEFORMATEX* pSupportedFormat, - WAVEFORMATEX* pRequestedFormat, - BOOL fOverwrite -) { - return FAPOBase_ValidateFormatPair( - fapo_base, - pSupportedFormat, - pRequestedFormat, - fOverwrite); -} - -void CXAPOBase::ProcessThru( - void* pInputBuffer, - FLOAT32* pOutputBuffer, - UINT32 FrameCount, - WORD InputChannelCount, - WORD OutputChannelCount, - BOOL MixWithOutput) -{ - FAPOBase_ProcessThru( - fapo_base, - pInputBuffer, - pOutputBuffer, - FrameCount, - InputChannelCount, - OutputChannelCount, - MixWithOutput); -} - -BOOL CXAPOBase::IsLocked() -{ - return fapo_base->m_fIsLocked; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// CXAPOParametersBase -// - -CXAPOParametersBase::CXAPOParametersBase(FAPOBase *base) - : CXAPOBase(base) -{ -} - -CXAPOParametersBase::CXAPOParametersBase( - const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties, - BYTE* pParameterBlocks, - UINT32 uParameterBlockByteSize, - BOOL fProducer) - : CXAPOBase(pRegistrationProperties, pParameterBlocks, - uParameterBlockByteSize, fProducer) -{ -} - -CXAPOParametersBase::~CXAPOParametersBase() -{ -} - -HRESULT CXAPOParametersBase::QueryInterface(REFIID riid, void** ppInterface) -{ - if (guid_equals(riid, IID_IXAPOParameters)) - { - *ppInterface = static_cast(this); - CXAPOBase::AddRef(); - return S_OK; - } - else - { - return CXAPOBase::QueryInterface(riid, ppInterface); - } -} - -ULONG CXAPOParametersBase::AddRef() -{ - return CXAPOBase::AddRef(); -} - -ULONG CXAPOParametersBase::Release() -{ - return CXAPOBase::Release(); -} - -void CXAPOParametersBase::SetParameters(const void* pParameters, UINT32 ParameterByteSize) -{ - assert(fapo_base->base.SetParameters); - fapo_base->base.SetParameters(fapo_base, pParameters, ParameterByteSize); -} - -void CXAPOParametersBase::GetParameters(void* pParameters, UINT32 ParameterByteSize) { - assert(fapo_base->base.GetParameters); - fapo_base->base.GetParameters(fapo_base, pParameters, ParameterByteSize); -} - -void CXAPOParametersBase::OnSetParameters(const void* pParameters, UINT32 ParameterByteSize) -{ - assert(fapo_base->OnSetParameters); - fapo_base->OnSetParameters(fapo_base, pParameters, ParameterByteSize); -} - -BOOL CXAPOParametersBase::ParametersChanged() -{ - return FAPOBase_ParametersChanged(fapo_base); -} - -BYTE* CXAPOParametersBase::BeginProcess() -{ - return FAPOBase_BeginProcess(fapo_base); -} - -void CXAPOParametersBase::EndProcess() -{ - FAPOBase_EndProcess(fapo_base); -} diff --git a/cpp/XAPOBase.h b/cpp/XAPOBase.h deleted file mode 100644 index 72bce874c6..0000000000 --- a/cpp/XAPOBase.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef FACT_CPP_XAPOBASE_H -#define FACT_CPP_XAPOBASE_H - -#include "XAPO.h" -#include - -typedef FAPORegistrationProperties XAPO_REGISTRATION_PROPERTIES; - -class CXAPOBase : public IXAPO -{ -protected: - // for CXAPOParametersBase and other derived classes that wrap FAPO structs - CXAPOBase(FAPOBase *base); - -public: - CXAPOBase( - const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties, - BYTE* pParameterBlocks = NULL, - UINT32 uParameterBlockByteSize = 0, - BOOL fProducer = 0); - virtual ~CXAPOBase(); - - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void** ppInterface); - COM_METHOD(ULONG) AddRef(); - COM_METHOD(ULONG) Release(); - - COM_METHOD(HRESULT) GetRegistrationProperties (XAPO_REGISTRATION_PROPERTIES** ppRegistrationProperties); - COM_METHOD(HRESULT) IsInputFormatSupported ( - const WAVEFORMATEX* pOutputFormat, - const WAVEFORMATEX* pRequestedInputFormat, - WAVEFORMATEX** ppSupportedInputFormat); - COM_METHOD(HRESULT) IsOutputFormatSupported ( - const WAVEFORMATEX* pInputFormat, - const WAVEFORMATEX* pRequestedOutputFormat, - WAVEFORMATEX** ppSupportedOutputFormat); - COM_METHOD(HRESULT) Initialize(const void*pData, UINT32 DataByteSize); - COM_METHOD(void) Reset(); - COM_METHOD(HRESULT) LockForProcess ( - UINT32 InputLockedParameterCount, - const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputLockedParameters, - UINT32 OutputLockedParameterCount, - const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputLockedParameters); - COM_METHOD(void) UnlockForProcess (); - COM_METHOD(UINT32) CalcInputFrames(UINT32 OutputFrameCount); - COM_METHOD(UINT32) CalcOutputFrames(UINT32 InputFrameCount); - -protected: - virtual HRESULT ValidateFormatDefault(WAVEFORMATEX* pFormat, BOOL fOverwrite); - HRESULT ValidateFormatPair( - const WAVEFORMATEX* pSupportedFormat, - WAVEFORMATEX* pRequestedFormat, - BOOL fOverwrite); - void ProcessThru( - void* pInputBuffer, - FLOAT32* pOutputBuffer, - UINT32 FrameCount, - WORD InputChannelCount, - WORD OutputChannelCount, - BOOL MixWithOutput); - - const XAPO_REGISTRATION_PROPERTIES* GetRegistrationPropertiesInternal(); - BOOL IsLocked(); - -protected: - FAPOBase *fapo_base; - bool own_fapo_base; -}; - -class CXAPOParametersBase : public CXAPOBase, public IXAPOParameters -{ -protected: - // for derived classes that wrap FAPO structs - CXAPOParametersBase(FAPOBase *base); -public: - CXAPOParametersBase( - const XAPO_REGISTRATION_PROPERTIES* pRegistrationProperties, - BYTE* pParameterBlocks, - UINT32 uParameterBlockByteSize, - BOOL fProducer); - virtual ~CXAPOParametersBase(); - - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void** ppInterface); - COM_METHOD(ULONG) AddRef(); - COM_METHOD(ULONG) Release(); - - COM_METHOD(void) SetParameters (const void* pParameters, UINT32 ParameterByteSize); - COM_METHOD(void) GetParameters (void* pParameters, UINT32 ParameterByteSize); - - virtual void OnSetParameters(const void*, UINT32); - - BOOL ParametersChanged(); - BYTE* BeginProcess(); - void EndProcess(); -}; - -#endif // FACT_CPP_XAPOBASE_H diff --git a/cpp/XAPOFX.cpp b/cpp/XAPOFX.cpp deleted file mode 100644 index 5c78b6768e..0000000000 --- a/cpp/XAPOFX.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "xaudio2.h" -#include "XAPOBase.h" -#include "XAPOFX.h" - -class XAPOFXWrapper : public CXAPOParametersBase -{ -public: - XAPOFXWrapper(void *object) : - fapo_object(object), - CXAPOParametersBase(reinterpret_cast(object)) - { - } - - COM_METHOD(void) Process( - UINT32 InputProcessParameterCount, - const XAPO_PROCESS_BUFFER_PARAMETERS *pInputProcessParameters, - UINT32 OutputProcessParameterCount, - XAPO_PROCESS_BUFFER_PARAMETERS *pOutputProcessParameters, - BOOL IsEnabled - ) { - reinterpret_cast(fapo_object)->Process( - fapo_object, - InputProcessParameterCount, - pInputProcessParameters, - OutputProcessParameterCount, - pOutputProcessParameters, - IsEnabled - ); - } - -private: - void *fapo_object; -}; - -void* CDECL XAPOFX_INTERNAL_Malloc(size_t size) -{ - return CoTaskMemAlloc(size); -} -void CDECL XAPOFX_INTERNAL_Free(void* ptr) -{ - CoTaskMemFree(ptr); -} -void* CDECL XAPOFX_INTERNAL_Realloc(void* ptr, size_t size) -{ - return CoTaskMemRealloc(ptr, size); -} - -void* CreateFXInternal( - REFCLSID clsid, - const void *pInitData, - uint32_t InitDataByteSize -) { - FAPO *fapo_object = NULL; - FAPOFX_CreateFXWithCustomAllocatorEXT( - &clsid, - &fapo_object, - pInitData, - InitDataByteSize, - XAPOFX_INTERNAL_Malloc, - XAPOFX_INTERNAL_Free, - XAPOFX_INTERNAL_Realloc - ); - return new XAPOFXWrapper(fapo_object); -} - -#if XAUDIO2_VERSION >=8 -FAPOFXCPP_API CreateFX( - REFCLSID clsid, - IUnknown **pEffect, - const void *pInitData, - UINT32 InitDataByteSize -) { - *pEffect = reinterpret_cast(CreateFXInternal( - clsid, - pInitData, - InitDataByteSize - )); - return S_OK; -} -#else -FAPOFXCPP_API CreateFX(REFCLSID clsid, IUnknown **pEffect) -{ - *pEffect = reinterpret_cast(CreateFXInternal( - clsid, - NULL, - 0 - )); - return S_OK; -} -#endif // XAUDIO2_VERSION >=8 diff --git a/cpp/XAPOFX.h b/cpp/XAPOFX.h deleted file mode 100644 index 93f72e4cda..0000000000 --- a/cpp/XAPOFX.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef FAUDIO_CPP_XAPOFX_H -#define FAUDIO_CPP_XAPOFX_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#if defined _WIN32 || defined __CYGWIN__ - #define DLLIMPORT __declspec(dllimport) - #define DLLEXPORT __declspec(dllexport) -#else - #if __GNUC__ >= 4 - #define DLLIMPORT __attribute__((visibility ("default"))) - #define DLLEXPORT __attribute__((visibility ("default"))) - #else - #define DLLIMPORT - #define DLLEXPORT - #endif -#endif - -#ifdef FAUDIOCPP_EXPORTS -#define FAPOFXCPP_API extern "C" DLLEXPORT HRESULT __cdecl -#else -#define FAPOFXCPP_API extern "C" DLLIMPORT HRESULT __cdecl -#endif - -#ifndef XAPOFX_VERSION -#define XAPOFX_VERSION 5 -#endif - -#include - -#if XAUDIO2_VERSION >=8 -FAPOFXCPP_API CreateFX( - REFCLSID clsid, - IUnknown **pEffect, - const void *pInitData, - UINT32 InitDataByteSize -); -#else -FAPOFXCPP_API CreateFX(REFCLSID clsid, IUnknown **pEffect); -#endif // XAUDIO2_VERSION >=8 - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* FAUDIO_CPP_XAPOFX_H */ diff --git a/cpp/XAudio2fx.cpp b/cpp/XAudio2fx.cpp deleted file mode 100644 index cd8a4505fd..0000000000 --- a/cpp/XAudio2fx.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "XAudio2fx.h" -#include "XAPOBase.h" - -#include - - -class XAudio2VolumeMeter : public CXAPOParametersBase -{ -public: - XAudio2VolumeMeter(void *object) : fapo_object(object), - CXAPOParametersBase(reinterpret_cast(object)) - { - } - - COM_METHOD(void) Process( - UINT32 InputProcessParameterCount, - const XAPO_PROCESS_BUFFER_PARAMETERS* pInputProcessParameters, - UINT32 OutputProcessParameterCount, - XAPO_PROCESS_BUFFER_PARAMETERS* pOutputProcessParameters, - BOOL IsEnabled - ) { - reinterpret_cast(fapo_object)->Process( - fapo_object, - InputProcessParameterCount, - pInputProcessParameters, - OutputProcessParameterCount, - pOutputProcessParameters, - IsEnabled); - } - -private: - void *fapo_object; -}; - -class XAudio2Reverb : public CXAPOParametersBase -{ -public: - XAudio2Reverb(void *object) : fapo_object(object), - CXAPOParametersBase(reinterpret_cast(object)) - { - } - - COM_METHOD(void) Process( - UINT32 InputProcessParameterCount, - const XAPO_PROCESS_BUFFER_PARAMETERS* pInputProcessParameters, - UINT32 OutputProcessParameterCount, - XAPO_PROCESS_BUFFER_PARAMETERS* pOutputProcessParameters, - BOOL IsEnabled - ) { - reinterpret_cast(fapo_object)->Process( - fapo_object, - InputProcessParameterCount, - pInputProcessParameters, - OutputProcessParameterCount, - pOutputProcessParameters, - IsEnabled); - } - -private: - void *fapo_object; -}; - - - -/////////////////////////////////////////////////////////////////////////////// -// -// Create functions -// - -void* CDECL XAudio2FX_INTERNAL_Malloc(size_t size) -{ - return CoTaskMemAlloc(size); -} -void CDECL XAudio2FX_INTERNAL_Free(void* ptr) -{ - CoTaskMemFree(ptr); -} -void* CDECL XAudio2FX_INTERNAL_Realloc(void* ptr, size_t size) -{ - return CoTaskMemRealloc(ptr, size); -} - -void *CreateAudioVolumeMeterInternal() -{ - FAPO *fapo_object = NULL; - FAudioCreateVolumeMeterWithCustomAllocatorEXT( - &fapo_object, - 0, - XAudio2FX_INTERNAL_Malloc, - XAudio2FX_INTERNAL_Free, - XAudio2FX_INTERNAL_Realloc - ); - return new XAudio2VolumeMeter(fapo_object); -} - -void *CreateAudioReverbInternal() -{ - FAPO *fapo_object = NULL; - FAudioCreateReverbWithCustomAllocatorEXT( - &fapo_object, - 0, - XAudio2FX_INTERNAL_Malloc, - XAudio2FX_INTERNAL_Free, - XAudio2FX_INTERNAL_Realloc - ); - return new XAudio2Reverb(fapo_object); -} - -#if XAUDIO2_VERSION >=8 - -extern "C" FAUDIOCPP_API CreateAudioVolumeMeter(class IUnknown** ppApo) -{ - *ppApo = reinterpret_cast (CreateAudioVolumeMeterInternal()); - return S_OK; -} - -extern "C" FAUDIOCPP_API CreateAudioReverb(class IUnknown** ppApo) -{ - *ppApo = reinterpret_cast (CreateAudioReverbInternal()); - return S_OK; -} - -#endif // XAUDIO2_VERSION >=8 diff --git a/cpp/XAudio2fx.h b/cpp/XAudio2fx.h deleted file mode 100644 index c4442ac68c..0000000000 --- a/cpp/XAudio2fx.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef FACT_CPP_XAUDIO2FX_H -#define FACT_CPP_XAUDIO2FX_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include - -#ifndef XAUDIO2_VERSION -#define XAUDIO2_VERSION 7 -#endif - -#ifdef FAUDIOCPP_EXPORTS -#define FAUDIOCPP_API uint32_t __stdcall -#else -#define FAUDIOCPP_API __declspec(dllimport) uint32_t __stdcall -#endif - -#if XAUDIO2_VERSION >=8 -FAUDIOCPP_API CreateAudioVolumeMeter(class IUnknown** ppApo); -FAUDIOCPP_API CreateAudioReverb(class IUnknown** ppApo); -#endif // XAUDIO2_VERSION >= 8 - - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif // FACT_CPP_XAUDIO2_H diff --git a/cpp/com_utils.cpp b/cpp/com_utils.cpp deleted file mode 100644 index 37c72d8ed4..0000000000 --- a/cpp/com_utils.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include "com_utils.h" -#include /* memcmp */ - -/* GUIDs */ -const IID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 00, 00, 00, 00, 00, 00, 0x46}}; -const IID IID_IClassFactory = {0x00000001, 0x0000, 0x0000, {0xC0, 00, 00, 00, 00, 00, 00, 0x46}}; - -const IID IID_IXAudio2 = {0x8bcf1f58, 0x9fe7, 0x4583, {0x8a, 0xc6, 0xe2, 0xad, 0xc4, 0x65, 0xc8, 0xbb}}; -const IID IID_IXAPO = {0xA90BC001, 0xE897, 0xE897, {0x55, 0xE4, 0x9E, 0x47, 0x00, 0x00, 0x00, 0x00}}; -const IID IID_IXAPOParameters = {0xA90BC001, 0xE897, 0xE897, {0x55, 0xE4, 0x9E, 0x47, 0x00, 0x00, 0x00, 0x01}}; - -const IID CLSID_XAudio2_0 = {0xfac23f48, 0x31f5, 0x45a8, {0xb4, 0x9b, 0x52, 0x25, 0xd6, 0x14, 0x01, 0xaa}}; -const IID CLSID_XAudio2_1 = {0xe21a7345, 0xeb21, 0x468e, {0xbe, 0x50, 0x80, 0x4d, 0xb9, 0x7c, 0xf7, 0x08}}; -const IID CLSID_XAudio2_2 = {0xb802058a, 0x464a, 0x42db, {0xbc, 0x10, 0xb6, 0x50, 0xd6, 0xf2, 0x58, 0x6a}}; -const IID CLSID_XAudio2_3 = {0x4c5e637a, 0x16c7, 0x4de3, {0x9c, 0x46, 0x5e, 0xd2, 0x21, 0x81, 0x96, 0x2d}}; -const IID CLSID_XAudio2_4 = {0x03219e78, 0x5bc3, 0x44d1, {0xb9, 0x2e, 0xf6, 0x3d, 0x89, 0xcc, 0x65, 0x26}}; -const IID CLSID_XAudio2_5 = {0x4c9b6dde, 0x6809, 0x46e6, {0xa2, 0x78, 0x9b, 0x6a, 0x97, 0x58, 0x86, 0x70}}; -const IID CLSID_XAudio2_6 = {0x3eda9b49, 0x2085, 0x498b, {0x9b, 0xb2, 0x39, 0xa6, 0x77, 0x84, 0x93, 0xde}}; -const IID CLSID_XAudio2_7 = {0x5a508685, 0xa254, 0x4fba, {0x9b, 0x82, 0x9a, 0x24, 0xb0, 0x03, 0x06, 0xaf}}; - -const IID *CLSID_XAudio2[] = -{ - &CLSID_XAudio2_0, &CLSID_XAudio2_1, - &CLSID_XAudio2_2, &CLSID_XAudio2_3, - &CLSID_XAudio2_4, &CLSID_XAudio2_5, - &CLSID_XAudio2_6, &CLSID_XAudio2_7 -}; - -const IID CLSID_AudioVolumeMeter_0 = {0xC0C56F46, 0x29B1, 0x44E9, {0x99, 0x39, 0xA3, 0x2C, 0xE8, 0x68, 0x67, 0xE2}}; -const IID CLSID_AudioVolumeMeter_1 = {0xc1e3f122, 0xa2ea, 0x442c, {0x85, 0x4f, 0x20, 0xd9, 0x8f, 0x83, 0x57, 0xa1}}; -const IID CLSID_AudioVolumeMeter_2 = {0xf5ca7b34, 0x8055, 0x42c0, {0xb8, 0x36, 0x21, 0x61, 0x29, 0xeb, 0x7e, 0x30}}; -const IID CLSID_AudioVolumeMeter_3 = {0xe180344b, 0xac83, 0x4483, {0x95, 0x9e, 0x18, 0xa5, 0xc5, 0x6a, 0x5e, 0x19}}; -const IID CLSID_AudioVolumeMeter_4 = {0xc7338b95, 0x52b8, 0x4542, {0xaa, 0x79, 0x42, 0xeb, 0x01, 0x6c, 0x8c, 0x1c}}; -const IID CLSID_AudioVolumeMeter_5 = {0x2139e6da, 0xc341, 0x4774, {0x9a, 0xc3, 0xb4, 0xe0, 0x26, 0x34, 0x7f, 0x64}}; -const IID CLSID_AudioVolumeMeter_6 = {0xe48c5a3f, 0x93ef, 0x43bb, {0xa0, 0x92, 0x2c, 0x7c, 0xeb, 0x94, 0x6f, 0x27}}; -const IID CLSID_AudioVolumeMeter_7 = {0xcac1105f, 0x619b, 0x4d04, {0x83, 0x1a, 0x44, 0xe1, 0xcb, 0xf1, 0x2d, 0x57}}; - -const IID *CLSID_AudioVolumeMeter[] = -{ - &CLSID_AudioVolumeMeter_0, &CLSID_AudioVolumeMeter_1, - &CLSID_AudioVolumeMeter_2, &CLSID_AudioVolumeMeter_3, - &CLSID_AudioVolumeMeter_4, &CLSID_AudioVolumeMeter_5, - &CLSID_AudioVolumeMeter_6, &CLSID_AudioVolumeMeter_7, -}; - -const IID CLSID_AudioReverb_0 = {0x6F6EA3A9, 0x2CF5, 0x41CF, {0x91, 0xC1, 0x21, 0x70, 0xB1, 0x54, 0x00, 0x63}}; -const IID CLSID_AudioReverb_1 = {0xf4769300, 0xb949, 0x4df9, {0xb3, 0x33, 0x00, 0xd3, 0x39, 0x32, 0xe9, 0xa6}}; -const IID CLSID_AudioReverb_2 = {0x629cf0de, 0x3ecc, 0x41e7, {0x99, 0x26, 0xf7, 0xe4, 0x3e, 0xeb, 0xec, 0x51}}; -const IID CLSID_AudioReverb_3 = {0x9cab402c, 0x1d37, 0x44b4, {0x88, 0x6d, 0xfa, 0x4f, 0x36, 0x17, 0x0a, 0x4c}}; -const IID CLSID_AudioReverb_4 = {0x8bb7778b, 0x645b, 0x4475, {0x9a, 0x73, 0x1d, 0xe3, 0x17, 0x0b, 0xd3, 0xaf}}; -const IID CLSID_AudioReverb_5 = {0xd06df0d0, 0x8518, 0x441e, {0x82, 0x2f, 0x54, 0x51, 0xd5, 0xc5, 0x95, 0xb8}}; -const IID CLSID_AudioReverb_6 = {0xcecec95a, 0xd894, 0x491a, {0xbe, 0xe3, 0x5e, 0x10, 0x6f, 0xb5, 0x9f, 0x2d}}; -const IID CLSID_AudioReverb_7 = {0x6a93130e, 0x1d53, 0x41d1, {0xa9, 0xcf, 0xe7, 0x58, 0x80, 0x0b, 0xb1, 0x79}}; - -const IID *CLSID_AudioReverb[] = { - &CLSID_AudioReverb_0, &CLSID_AudioReverb_1, - &CLSID_AudioReverb_2, &CLSID_AudioReverb_3, - &CLSID_AudioReverb_4, &CLSID_AudioReverb_5, - &CLSID_AudioReverb_6, &CLSID_AudioReverb_7, -}; - -bool guid_equals(REFIID a, REFIID b) -{ - return memcmp(&a, &b, sizeof(IID)) == 0; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Class Factory: fun COM stuff -// - -typedef void *(*FACTORY_FUNC)(void); -void *CreateXAudio2Internal(void); -void *CreateAudioVolumeMeterInternal(void); -void *CreateAudioReverbInternal(void); - -template class ClassFactory : public IClassFactory -{ -public: - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void **ppvInterface) - { - if (guid_equals(riid, IID_IUnknown) || guid_equals(riid, IID_IClassFactory)) - { - *ppvInterface = static_cast(this); - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - - reinterpret_cast(*ppvInterface)->AddRef(); - - return S_OK; - } - - COM_METHOD(ULONG) AddRef() - { - // FIXME: atomics - return ++refcount; - } - - COM_METHOD(ULONG) Release() - { - // FIXME: atomics - long rc = --refcount; - - if (rc == 0) - { - delete this; - } - - return rc; - } - - COM_METHOD(HRESULT) CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) - { - if (pUnkOuter != NULL) - { - return CLASS_E_NOAGGREGATION; - } - - void *obj = NULL; - - if (guid_equals(riid, fact_iid)) - { - obj = fact_creator(); - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - if (obj == NULL) - { - return E_OUTOFMEMORY; - } - - return reinterpret_cast(obj)->QueryInterface(riid, ppvObject); - } - - COM_METHOD(HRESULT) LockServer(BOOL fLock) { return E_NOTIMPL; } - -private: - long refcount; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// COM DLL interface functions -// - -static void *DllHandle = NULL; - -BOOL __stdcall DllMain(void *hinstDLL, DWORD dwReason, LPVOID lpvReserved) -{ - if (dwReason == 1 /*DLL_PROCESS_ATTACH*/) - { - DllHandle = hinstDLL; - } - return 1; -} - -#if XAUDIO2_VERSION <= 7 - -extern "C" HRESULT __stdcall DllCanUnloadNow() -{ - return S_FALSE; -} - -extern "C" HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) -{ - IClassFactory *factory = NULL; - - if (guid_equals(rclsid, *CLSID_XAudio2[XAUDIO2_VERSION])) - { - factory = new ClassFactory(); - } - else if (guid_equals(rclsid, *CLSID_AudioVolumeMeter[XAUDIO2_VERSION])) - { - factory = new ClassFactory(); - } - else if (guid_equals(rclsid, *CLSID_AudioReverb[XAUDIO2_VERSION])) - { - factory = new ClassFactory(); - } - else - { - return CLASS_E_CLASSNOTAVAILABLE; - } - - if (!factory) - { - return E_OUTOFMEMORY; - } - - return factory->QueryInterface(riid, ppv); -} - -extern "C" HRESULT register_faudio_dll(void *, REFIID); -extern "C" HRESULT unregister_faudio_dll(void *, REFIID); - -extern "C" HRESULT __stdcall DllRegisterServer(void) -{ -#if XAUDIO2_VERSION <= 7 - /* Please note: if you want to test the XAudio2Fx wrappers with MS XAudio2 (e.g. by not registering the IXAudio2 interface below), - you also need to change XAPOBase.cpp to make everything work */ - register_faudio_dll(DllHandle, *CLSID_XAudio2[XAUDIO2_VERSION]); - register_faudio_dll(DllHandle, *CLSID_AudioReverb[XAUDIO2_VERSION]); - register_faudio_dll(DllHandle, *CLSID_AudioVolumeMeter[XAUDIO2_VERSION]); -#endif - return S_OK; -} - -extern "C" HRESULT __stdcall DllUnregisterServer(void) -{ -#if XAUDIO2_VERSION <= 7 - unregister_faudio_dll(DllHandle, *CLSID_XAudio2[XAUDIO2_VERSION]); - unregister_faudio_dll(DllHandle, *CLSID_AudioReverb[XAUDIO2_VERSION]); - unregister_faudio_dll(DllHandle, *CLSID_AudioVolumeMeter[XAUDIO2_VERSION]); -#endif - return S_OK; -} - -#endif // XAUDIO2_VERSION <= 7 diff --git a/cpp/com_utils.h b/cpp/com_utils.h deleted file mode 100644 index 4e90a333c0..0000000000 --- a/cpp/com_utils.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef FACT_CPP_FAUDIO_COM_H -#define FACT_CPP_FAUDIO_COM_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include - -// CoTaskMem functionality, needed for XAudio2 compat -#if defined _WIN32 || defined __CYGWIN__ - #define DLLIMPORT __declspec(dllimport) -#else - #if __GNUC__ >= 4 - #define DLLIMPORT __attribute__((visibility ("default"))) - #else - #define DLLIMPORT - #endif -#endif -extern "C" DLLIMPORT void * __stdcall CoTaskMemAlloc(size_t cb); -extern "C" DLLIMPORT void __stdcall CoTaskMemFree(void* ptr); -extern "C" DLLIMPORT void * __stdcall CoTaskMemRealloc(void* ptr, size_t cb); - -#define CDECL __cdecl - -// common windows types -#ifndef FAUDIO_USE_STD_TYPES - -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint32_t HRESULT; -typedef uint32_t UINT32; -typedef long LONG; -typedef unsigned long ULONG; -typedef wchar_t WHCAR; -typedef const WHCAR *LPCWSTR; -typedef int BOOL; -typedef unsigned long DWORD; -typedef void *LPVOID; -typedef float FLOAT32; - -#endif - -// HRESULT stuff -#define S_OK 0 -#define S_FALSE 1 -#define E_NOTIMPL 80004001 -#define E_NOINTERFACE 80004002 -#define E_OUTOFMEMORY 0x8007000E -#define CLASS_E_NOAGGREGATION 0x80040110 -#define CLASS_E_CLASSNOTAVAILABLE 0x80040111 - -// GUID, IID stuff -typedef FAudioGUID GUID; -typedef GUID IID; -#define REFIID const IID & -#define REFCLSID const IID & -bool guid_equals(REFIID a, REFIID b); - -extern const IID IID_IUnknown; -extern const IID IID_IClassFactory; -extern const IID IID_IXAudio2; - -extern const IID IID_IXAPO; -extern const IID IID_IXAPOParameters; - -extern const IID CLSID_XAudio2_0; -extern const IID CLSID_XAudio2_1; -extern const IID CLSID_XAudio2_2; -extern const IID CLSID_XAudio2_3; -extern const IID CLSID_XAudio2_4; -extern const IID CLSID_XAudio2_5; -extern const IID CLSID_XAudio2_6; -extern const IID CLSID_XAudio2_7; -extern const IID *CLSID_XAudio2[]; - -extern const IID CLSID_AudioVolumeMeter_0; -extern const IID CLSID_AudioVolumeMeter_1; -extern const IID CLSID_AudioVolumeMeter_2; -extern const IID CLSID_AudioVolumeMeter_3; -extern const IID CLSID_AudioVolumeMeter_4; -extern const IID CLSID_AudioVolumeMeter_5; -extern const IID CLSID_AudioVolumeMeter_6; -extern const IID CLSID_AudioVolumeMeter_7; -extern const IID *CLSID_AudioVolumeMeter[]; - -extern const IID CLSID_AudioReverb_0; -extern const IID CLSID_AudioReverb_1; -extern const IID CLSID_AudioReverb_2; -extern const IID CLSID_AudioReverb_3; -extern const IID CLSID_AudioReverb_4; -extern const IID CLSID_AudioReverb_5; -extern const IID CLSID_AudioReverb_6; -extern const IID CLSID_AudioReverb_7; -extern const IID *CLSID_AudioReverb[]; - -extern const IID IID_IXACT3Engine3_0; -extern const IID IID_IXACT3Engine3_1; -extern const IID IID_IXACT3Engine3_2; -extern const IID IID_IXACT3Engine3_3; -extern const IID IID_IXACT3Engine3_4; -extern const IID IID_IXACT3Engine3_5; -extern const IID IID_IXACT3Engine3_6; -extern const IID IID_IXACT3Engine3_7; - -#define JOIN_IID_VERSION(x, y) JOIN_IID_VERSION2(x, y) -#define JOIN_IID_VERSION2(x, y) x ## y -#define IID_IXACT3Engine JOIN_IID_VERSION(IID_IXACT3Engine3_, XACT3_VERSION) - -extern const IID CLSID_XACTEngine3_0; -extern const IID CLSID_XACTEngine3_1; -extern const IID CLSID_XACTEngine3_2; -extern const IID CLSID_XACTEngine3_3; -extern const IID CLSID_XACTEngine3_4; -extern const IID CLSID_XACTEngine3_5; -extern const IID CLSID_XACTEngine3_6; -extern const IID CLSID_XACTEngine3_7; -extern const IID *CLSID_XACTEngine[]; - -// quality of life macro's -#define COM_METHOD(rtype) virtual rtype __stdcall - -// common interfaces -class IUnknown { -public: - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void** ppvInterface) = 0; - COM_METHOD(ULONG) AddRef() = 0; - COM_METHOD(ULONG) Release() = 0; -}; - -class IClassFactory : public IUnknown { -public: - COM_METHOD(HRESULT) CreateInstance( - IUnknown *pUnkOuter, - REFIID riid, - void **ppvObject) = 0; - - COM_METHOD(HRESULT) LockServer(BOOL fLock) = 0; -}; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif // FACT_CPP_FAUDIO_COM_H diff --git a/cpp/com_utils_xact.cpp b/cpp/com_utils_xact.cpp deleted file mode 100644 index f4bb6e4422..0000000000 --- a/cpp/com_utils_xact.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "com_utils.h" -#include /* memcmp */ - -/* GUIDs */ -const IID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 00, 00, 00, 00, 00, 00, 0x46}}; -const IID IID_IClassFactory = {0x00000001, 0x0000, 0x0000, {0xC0, 00, 00, 00, 00, 00, 00, 0x46}}; - -const IID IID_IXACT3Engine3_0 = {0x9e33f661, 0x2d07, 0x43ec, {0x97, 0x04, 0xbb, 0xcb, 0x71, 0xa5, 0x49, 0x72}}; -const IID IID_IXACT3Engine3_1 = {0xe72c1b9a, 0xd717, 0x41c0, {0x81, 0xa6, 0x50, 0xeb, 0x56, 0xe8, 0x06, 0x49}}; -const IID IID_IXACT3Engine3_2 = {0xe72c1b9a, 0xd717, 0x41c0, {0x81, 0xa6, 0x50, 0xeb, 0x56, 0xe8, 0x06, 0x49}}; -const IID IID_IXACT3Engine3_3 = {0xe72c1b9a, 0xd717, 0x41c0, {0x81, 0xa6, 0x50, 0xeb, 0x56, 0xe8, 0x06, 0x49}}; -const IID IID_IXACT3Engine3_4 = {0xe72c1b9a, 0xd717, 0x41c0, {0x81, 0xa6, 0x50, 0xeb, 0x56, 0xe8, 0x06, 0x49}}; -const IID IID_IXACT3Engine3_5 = {0xb1ee676a, 0xd9cd, 0x4d2a, {0x89, 0xa8, 0xfa, 0x53, 0xeb, 0x9e, 0x48, 0x0b}}; -const IID IID_IXACT3Engine3_6 = {0xb1ee676a, 0xd9cd, 0x4d2a, {0x89, 0xa8, 0xfa, 0x53, 0xeb, 0x9e, 0x48, 0x0b}}; -const IID IID_IXACT3Engine3_7 = {0xb1ee676a, 0xd9cd, 0x4d2a, {0x89, 0xa8, 0xfa, 0x53, 0xeb, 0x9e, 0x48, 0x0b}}; - -const IID CLSID_XACTEngine3_0 = {0x3b80ee2a, 0xb0f5, 0x4780, {0x9e, 0x30, 0x90, 0xcb, 0x39, 0x68, 0x5b, 0x03}}; -const IID CLSID_XACTEngine3_1 = {0x962f5027, 0x99be, 0x4692, {0xa4, 0x68, 0x85, 0x80, 0x2c, 0xf8, 0xde, 0x61}}; -const IID CLSID_XACTEngine3_2 = {0xd3332f02, 0x3dd0, 0x4de9, {0x9a, 0xec, 0x20, 0xd8, 0x5c, 0x41, 0x11, 0xb6}}; -const IID CLSID_XACTEngine3_3 = {0x94c1affa, 0x66e7, 0x4961, {0x95, 0x21, 0xcf, 0xde, 0xf3, 0x12, 0x8d, 0x4f}}; -const IID CLSID_XACTEngine3_4 = {0x0977d092, 0x2d95, 0x4e43, {0x8d, 0x42, 0x9d, 0xdc, 0xc2, 0x54, 0x5e, 0xd5}}; -const IID CLSID_XACTEngine3_5 = {0x074b110f, 0x7f58, 0x4743, {0xae, 0xa5, 0x12, 0xf1, 0x5b, 0x50, 0x74, 0xed}}; -const IID CLSID_XACTEngine3_6 = {0x248d8a3b, 0x6256, 0x44d3, {0xa0, 0x18, 0x2a, 0xc9, 0x6c, 0x45, 0x9f, 0x47}}; -const IID CLSID_XACTEngine3_7 = {0xbcc782bc, 0x6492, 0x4c22, {0x8c, 0x35, 0xf5, 0xd7, 0x2f, 0xe7, 0x3c, 0x6e}}; - -const IID *CLSID_XACTEngine[] = -{ - &CLSID_XACTEngine3_0, - &CLSID_XACTEngine3_1, - &CLSID_XACTEngine3_2, - &CLSID_XACTEngine3_3, - &CLSID_XACTEngine3_4, - &CLSID_XACTEngine3_5, - &CLSID_XACTEngine3_6, - &CLSID_XACTEngine3_7, -}; - -bool guid_equals(REFIID a, REFIID b) -{ - return memcmp(&a, &b, sizeof(IID)) == 0; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// Class Factory: fun COM stuff -// - -typedef void *(*FACTORY_FUNC)(void); -void *CreateXACT3EngineInternal(void); - -template class ClassFactory : public IClassFactory -{ -public: - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void **ppvInterface) - { - if (guid_equals(riid, IID_IUnknown) || guid_equals(riid, IID_IClassFactory)) - { - *ppvInterface = static_cast(this); - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - - reinterpret_cast(*ppvInterface)->AddRef(); - - return S_OK; - } - - COM_METHOD(ULONG) AddRef() - { - // FIXME: atomics - return ++refcount; - } - - COM_METHOD(ULONG) Release() - { - // FIXME: atomics - long rc = --refcount; - - if (rc == 0) - { - delete this; - } - - return rc; - } - - COM_METHOD(HRESULT) CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) - { - if (pUnkOuter != NULL) - { - return CLASS_E_NOAGGREGATION; - } - - void *obj = NULL; - - if (guid_equals(riid, fact_iid)) - { - obj = fact_creator(); - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } - - if (obj == NULL) - { - return E_OUTOFMEMORY; - } - - return reinterpret_cast(obj)->QueryInterface(riid, ppvObject); - } - - COM_METHOD(HRESULT) LockServer(BOOL fLock) { return E_NOTIMPL; } - -private: - long refcount; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// COM DLL interface functions -// - -static void *DllHandle = NULL; - -BOOL __stdcall DllMain(void *hinstDLL, DWORD dwReason, LPVOID lpvReserved) -{ - if (dwReason == 1 /*DLL_PROCESS_ATTACH*/) - { - DllHandle = hinstDLL; - } - return 1; -} - -extern "C" HRESULT __stdcall DllCanUnloadNow() -{ - return S_FALSE; -} - -extern "C" HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) -{ - IClassFactory *factory = NULL; - - if (guid_equals(rclsid, *CLSID_XACTEngine[XACT3_VERSION])) - { - factory = new ClassFactory(); - } - else - { - return CLASS_E_CLASSNOTAVAILABLE; - } - - if (!factory) - { - return E_OUTOFMEMORY; - } - - return factory->QueryInterface(riid, ppv); -} - -extern "C" HRESULT register_faudio_dll(void *, REFIID); -extern "C" HRESULT unregister_faudio_dll(void *, REFIID); - -extern "C" HRESULT __stdcall DllRegisterServer(void) -{ - register_faudio_dll(DllHandle, *CLSID_XACTEngine[XACT3_VERSION]); - return S_OK; -} - -extern "C" HRESULT __stdcall DllUnregisterServer(void) -{ - unregister_faudio_dll(DllHandle, *CLSID_XACTEngine[XACT3_VERSION]); - return S_OK; -} diff --git a/cpp/com_utils_xapofx.cpp b/cpp/com_utils_xapofx.cpp deleted file mode 100644 index a2500f94ec..0000000000 --- a/cpp/com_utils_xapofx.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "com_utils.h" -#include /* memcmp */ - -/* GUIDs */ -const IID IID_IUnknown = {0x00000000, 0x0000, 0x0000, {0xC0, 00, 00, 00, 00, 00, 00, 0x46}}; - -const IID IID_IXAudio2 = {0x8bcf1f58, 0x9fe7, 0x4583, {0x8a, 0xc6, 0xe2, 0xad, 0xc4, 0x65, 0xc8, 0xbb}}; -const IID IID_IXAPO = {0xA90BC001, 0xE897, 0xE897, {0x55, 0xE4, 0x9E, 0x47, 0x00, 0x00, 0x00, 0x00}}; -const IID IID_IXAPOParameters = {0xA90BC001, 0xE897, 0xE897, {0x55, 0xE4, 0x9E, 0x47, 0x00, 0x00, 0x00, 0x01}}; - -bool guid_equals(REFIID a, REFIID b) -{ - return memcmp(&a, &b, sizeof(IID)) == 0; -} diff --git a/cpp/scripts/windows_register.bat b/cpp/scripts/windows_register.bat deleted file mode 100644 index b180524cd7..0000000000 --- a/cpp/scripts/windows_register.bat +++ /dev/null @@ -1,30 +0,0 @@ -@echo off - -CALL :register XAudio2_0.dll -CALL :register XAudio2_1.dll -CALL :register XAudio2_2.dll -CALL :register XAudio2_3.dll -CALL :register XAudio2_4.dll -CALL :register XAudio2_5.dll -CALL :register XAudio2_6.dll -CALL :register XAudio2_7.dll -CALL :register XACTEngine3_0.dll -CALL :register XACTEngine3_1.dll -CALL :register XACTEngine3_2.dll -CALL :register XACTEngine3_3.dll -CALL :register XACTEngine3_4.dll -CALL :register XACTEngine3_5.dll -CALL :register XACTEngine3_6.dll -CALL :register XACTEngine3_7.dll - -EXIT /B %ERRORLEVEL% - -:: a function to register a DLL -:register -regsvr32 /s "%CD%"\%* && goto :register_ok -echo %* failed -goto :register_end -:register_ok -echo %* OK -:register_end -EXIT /B 0 diff --git a/cpp/scripts/windows_unregister.bat b/cpp/scripts/windows_unregister.bat deleted file mode 100644 index c225748837..0000000000 --- a/cpp/scripts/windows_unregister.bat +++ /dev/null @@ -1,30 +0,0 @@ -@echo off - -CALL :register XAudio2_0.dll -CALL :register XAudio2_1.dll -CALL :register XAudio2_2.dll -CALL :register XAudio2_3.dll -CALL :register XAudio2_4.dll -CALL :register XAudio2_5.dll -CALL :register XAudio2_6.dll -CALL :register XAudio2_7.dll -CALL :register XACTEngine3_0.dll -CALL :register XACTEngine3_1.dll -CALL :register XACTEngine3_2.dll -CALL :register XACTEngine3_3.dll -CALL :register XACTEngine3_4.dll -CALL :register XACTEngine3_5.dll -CALL :register XACTEngine3_6.dll -CALL :register XACTEngine3_7.dll - -EXIT /B %ERRORLEVEL% - -:: a function to register a DLL -:register -regsvr32 /u /s "%CD%"\%* && goto :register_ok -echo %* failed -goto :register_end -:register_ok -echo %* OK -:register_end -EXIT /B 0 diff --git a/cpp/scripts/wine_setup_native b/cpp/scripts/wine_setup_native deleted file mode 100755 index ea3a011213..0000000000 --- a/cpp/scripts/wine_setup_native +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash - -if [ -z "$WINEPREFIX" ]; then - echo "Please set WINEPREFIX before running this script" - exit 1 -fi - -if [ ! -f $WINEPREFIX/system.reg ]; then - echo "$WINEPREFIX does not seem like a valid Wine Prefix" - exit 1 -fi - -winedump xaudio2_0.dll | grep 32BIT_MACHINE >> /dev/null 2>&1 - -if [ $? -eq 0 ]; then - wine_exe=wine -else - wine_exe=wine64 -fi - -wine_path=$(${wine_exe} winepath -u 'C:\windows\system32' 2>>/dev/null) -if [ $? -ne 0 ]; then - echo "Failed to get winepath for c:\windows\system32 (64-bit vs 32-bit mismatch?)" - exit 1; -fi - -dll_path=$(pwd) - -function install_dll { - name=$1 - - # update registry - log=$(${wine_exe} reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $name /d native /f 2>>/dev/null) - - if [ $? -ne 0 ]; then - echo "Failed to update registry for $name" - exit 1 - fi - - # link dll - ln -sf "$dll_path/$name.dll" "$wine_path/$name.dll" - - if [ $? -ne 0 ]; then - echo "Failed to create link for $name" - exit 1 - fi - - echo "$name: done" -} - -install_dll xaudio2_0 -install_dll xaudio2_1 -install_dll xaudio2_2 -install_dll xaudio2_3 -install_dll xaudio2_4 -install_dll xaudio2_5 -install_dll xaudio2_6 -install_dll xaudio2_7 -install_dll xaudio2_8 -install_dll xaudio2_9 - -install_dll x3daudio1_3 -install_dll x3daudio1_4 -install_dll x3daudio1_5 -install_dll x3daudio1_6 -install_dll x3daudio1_7 - -install_dll xactengine3_0 -install_dll xactengine3_1 -install_dll xactengine3_2 -install_dll xactengine3_3 -install_dll xactengine3_4 -install_dll xactengine3_5 -install_dll xactengine3_6 -install_dll xactengine3_7 - -install_dll xapofx1_1 -install_dll xapofx1_2 -install_dll xapofx1_3 -install_dll xapofx1_4 -install_dll xapofx1_5 - -ln -sf "$dll_path/FAudio.dll" "$wine_path/FAudio.dll" -ln -sf "$dll_path/SDL2.dll" "$wine_path/SDL2.dll" -ln -sf "$dll_path/libwinpthread-1.dll" "$wine_path/libwinpthread-1.dll" - -if [ -f "$dll_path/iconv.dll" ];then - ln -sf "$dll_path/iconv.dll" "$wine_path/iconv.dll" -fi - -if [ -f "$dll_path/libiconv-2.dll" ];then - ln -sf "$dll_path/libiconv-2.dll" "$wine_path/libiconv-2.dll" -fi - -if [ -f "$dll_path/avcodec-58.dll" ];then - ln -sf "$dll_path/avcodec-58.dll" "$wine_path/avcodec-58.dll" -fi - -if [ -f "$dll_path/avutil-56.dll" ];then - ln -sf "$dll_path/avutil-56.dll" "$wine_path/avutil-56.dll" -fi - -if [ -f "$dll_path/swresample-3.dll" ];then - ln -sf "$dll_path/swresample-3.dll" "$wine_path/swresample-3.dll" -fi - diff --git a/cpp/visualc/FAudio-CPP.sln b/cpp/visualc/FAudio-CPP.sln deleted file mode 100644 index e2f60cb0a8..0000000000 --- a/cpp/visualc/FAudio-CPP.sln +++ /dev/null @@ -1,209 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_7", "XAudio2_7.vcxproj", "{9F5164EA-DC2B-4370-8C3C-DF449413A625}" - ProjectSection(ProjectDependencies) = postProject - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} = {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudio", "FAudio.vcxproj", "{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_9", "XAudio2_9.vcxproj", "{C4BE973A-0412-44D2-A5DB-F9B05EAB6EED}" - ProjectSection(ProjectDependencies) = postProject - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} = {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "X3DAudio1_7", "X3DAudio1_7.vcxproj", "{EAC29019-EB87-434C-9E41-75A499941AD5}" - ProjectSection(ProjectDependencies) = postProject - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} = {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAPOBase", "XAPOBase.vcxproj", "{D1E0EB55-2B90-40A1-B864-0B7A36BF79B7}" - ProjectSection(ProjectDependencies) = postProject - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} = {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_6", "XAudio2_6.vcxproj", "{F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_5", "XAudio2_5.vcxproj", "{841595D8-2B91-49D4-A6D8-D4B8B142137A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_4", "XAudio2_4.vcxproj", "{D000E079-A315-4F06-B2D7-7C319EC286FF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_3", "XAudio2_3.vcxproj", "{71A4644C-3289-4A33-82E8-6949DF25AB8B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_2", "XAudio2_2.vcxproj", "{17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_1", "XAudio2_1.vcxproj", "{18A02609-C3DC-4253-9653-CC00AB1A18C5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_0", "XAudio2_0.vcxproj", "{03853D47-0A08-44FB-92B5-6390B3B15B8D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio2_8", "XAudio2_8.vcxproj", "{E5E99434-57FA-4386-BC10-A72C2CE6B6C4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "X3DAudio1_6", "X3DAudio1_6.vcxproj", "{8FD33503-EA67-41DD-A61F-A76F41B6CCC7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "X3DAudio1_5", "X3DAudio1_5.vcxproj", "{BE261501-F148-4AA1-A8CE-B0E05E05771A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "X3DAudio1_4", "X3DAudio1_4.vcxproj", "{45409D4F-BEB5-44D5-A454-36268F37ED8E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "X3DAudio1_3", "X3DAudio1_3.vcxproj", "{2EFC3682-2141-4E21-B0DA-C34169CD826C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_0", "XACTEngine3_0.vcxproj", "{C91C7EC9-ADC2-43B2-A598-7BB54EA46143}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_1", "XACTEngine3_1.vcxproj", "{4CFD19E3-8DCA-4988-8740-F4C2036F6C0E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_2", "XACTEngine3_2.vcxproj", "{ECEB1BD5-8809-4DBD-9206-DB9F47C0C514}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_3", "XACTEngine3_3.vcxproj", "{EB247C6E-E77D-467B-B0F4-4CA5F24E347B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_4", "XACTEngine3_4.vcxproj", "{CB5573A1-1424-4F10-8566-C325417125B0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_5", "XACTEngine3_5.vcxproj", "{F9D8152D-539E-4D47-9340-6CA134FFD44E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_6", "XACTEngine3_6.vcxproj", "{9C4EDE36-39DC-4FC7-84C8-E3BD422787A9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XACTEngine3_7", "XACTEngine3_7.vcxproj", "{CE69C349-4025-413E-8D7E-3846C90054CD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegisterDLLs", "RegisterDLLs.vcxproj", "{F6E7BB44-39C4-4936-BADB-90010011BFCE}" - ProjectSection(ProjectDependencies) = postProject - {BE261501-F148-4AA1-A8CE-B0E05E05771A} = {BE261501-F148-4AA1-A8CE-B0E05E05771A} - {8FD33503-EA67-41DD-A61F-A76F41B6CCC7} = {8FD33503-EA67-41DD-A61F-A76F41B6CCC7} - {18A02609-C3DC-4253-9653-CC00AB1A18C5} = {18A02609-C3DC-4253-9653-CC00AB1A18C5} - {EAC29019-EB87-434C-9E41-75A499941AD5} = {EAC29019-EB87-434C-9E41-75A499941AD5} - {E5E99434-57FA-4386-BC10-A72C2CE6B6C4} = {E5E99434-57FA-4386-BC10-A72C2CE6B6C4} - {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED} = {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED} - {03853D47-0A08-44FB-92B5-6390B3B15B8D} = {03853D47-0A08-44FB-92B5-6390B3B15B8D} - {71A4644C-3289-4A33-82E8-6949DF25AB8B} = {71A4644C-3289-4A33-82E8-6949DF25AB8B} - {45409D4F-BEB5-44D5-A454-36268F37ED8E} = {45409D4F-BEB5-44D5-A454-36268F37ED8E} - {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7} = {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7} - {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE} = {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE} - {D000E079-A315-4F06-B2D7-7C319EC286FF} = {D000E079-A315-4F06-B2D7-7C319EC286FF} - {2EFC3682-2141-4E21-B0DA-C34169CD826C} = {2EFC3682-2141-4E21-B0DA-C34169CD826C} - {841595D8-2B91-49D4-A6D8-D4B8B142137A} = {841595D8-2B91-49D4-A6D8-D4B8B142137A} - {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5} = {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5} - {9F5164EA-DC2B-4370-8C3C-DF449413A625} = {9F5164EA-DC2B-4370-8C3C-DF449413A625} - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} = {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} - {C91C7EC9-ADC2-43B2-A598-7BB54EA46143} = {C91C7EC9-ADC2-43B2-A598-7BB54EA46143} - {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E} = {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E} - {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514} = {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514} - {EB247C6E-E77D-467B-B0F4-4CA5F24E347B} = {EB247C6E-E77D-467B-B0F4-4CA5F24E347B} - {CB5573A1-1424-4F10-8566-C325417125B0} = {CB5573A1-1424-4F10-8566-C325417125B0} - {F9D8152D-539E-4D47-9340-6CA134FFD44E} = {F9D8152D-539E-4D47-9340-6CA134FFD44E} - {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9} = {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9} - {CE69C349-4025-413E-8D7E-3846C90054CD} = {CE69C349-4025-413E-8D7E-3846C90054CD} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x86 = Debug|x86 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9F5164EA-DC2B-4370-8C3C-DF449413A625}.Debug|x86.ActiveCfg = Debug|Win32 - {9F5164EA-DC2B-4370-8C3C-DF449413A625}.Debug|x86.Build.0 = Debug|Win32 - {9F5164EA-DC2B-4370-8C3C-DF449413A625}.Release|x86.ActiveCfg = Release|Win32 - {9F5164EA-DC2B-4370-8C3C-DF449413A625}.Release|x86.Build.0 = Release|Win32 - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.Debug|x86.ActiveCfg = Debug|Win32 - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.Debug|x86.Build.0 = Debug|Win32 - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.Release|x86.ActiveCfg = Release|Win32 - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.Release|x86.Build.0 = Release|Win32 - {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED}.Debug|x86.ActiveCfg = Debug|Win32 - {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED}.Debug|x86.Build.0 = Debug|Win32 - {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED}.Release|x86.ActiveCfg = Release|Win32 - {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED}.Release|x86.Build.0 = Release|Win32 - {EAC29019-EB87-434C-9E41-75A499941AD5}.Debug|x86.ActiveCfg = Debug|Win32 - {EAC29019-EB87-434C-9E41-75A499941AD5}.Debug|x86.Build.0 = Debug|Win32 - {EAC29019-EB87-434C-9E41-75A499941AD5}.Release|x86.ActiveCfg = Release|Win32 - {EAC29019-EB87-434C-9E41-75A499941AD5}.Release|x86.Build.0 = Release|Win32 - {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7}.Debug|x86.ActiveCfg = Debug|Win32 - {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7}.Debug|x86.Build.0 = Debug|Win32 - {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7}.Release|x86.ActiveCfg = Release|Win32 - {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7}.Release|x86.Build.0 = Release|Win32 - {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE}.Debug|x86.ActiveCfg = Debug|Win32 - {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE}.Debug|x86.Build.0 = Debug|Win32 - {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE}.Release|x86.ActiveCfg = Release|Win32 - {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE}.Release|x86.Build.0 = Release|Win32 - {841595D8-2B91-49D4-A6D8-D4B8B142137A}.Debug|x86.ActiveCfg = Debug|Win32 - {841595D8-2B91-49D4-A6D8-D4B8B142137A}.Debug|x86.Build.0 = Debug|Win32 - {841595D8-2B91-49D4-A6D8-D4B8B142137A}.Release|x86.ActiveCfg = Release|Win32 - {841595D8-2B91-49D4-A6D8-D4B8B142137A}.Release|x86.Build.0 = Release|Win32 - {D000E079-A315-4F06-B2D7-7C319EC286FF}.Debug|x86.ActiveCfg = Debug|Win32 - {D000E079-A315-4F06-B2D7-7C319EC286FF}.Debug|x86.Build.0 = Debug|Win32 - {D000E079-A315-4F06-B2D7-7C319EC286FF}.Release|x86.ActiveCfg = Release|Win32 - {D000E079-A315-4F06-B2D7-7C319EC286FF}.Release|x86.Build.0 = Release|Win32 - {71A4644C-3289-4A33-82E8-6949DF25AB8B}.Debug|x86.ActiveCfg = Debug|Win32 - {71A4644C-3289-4A33-82E8-6949DF25AB8B}.Debug|x86.Build.0 = Debug|Win32 - {71A4644C-3289-4A33-82E8-6949DF25AB8B}.Release|x86.ActiveCfg = Release|Win32 - {71A4644C-3289-4A33-82E8-6949DF25AB8B}.Release|x86.Build.0 = Release|Win32 - {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5}.Debug|x86.ActiveCfg = Debug|Win32 - {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5}.Debug|x86.Build.0 = Debug|Win32 - {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5}.Release|x86.ActiveCfg = Release|Win32 - {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5}.Release|x86.Build.0 = Release|Win32 - {18A02609-C3DC-4253-9653-CC00AB1A18C5}.Debug|x86.ActiveCfg = Debug|Win32 - {18A02609-C3DC-4253-9653-CC00AB1A18C5}.Debug|x86.Build.0 = Debug|Win32 - {18A02609-C3DC-4253-9653-CC00AB1A18C5}.Release|x86.ActiveCfg = Release|Win32 - {18A02609-C3DC-4253-9653-CC00AB1A18C5}.Release|x86.Build.0 = Release|Win32 - {03853D47-0A08-44FB-92B5-6390B3B15B8D}.Debug|x86.ActiveCfg = Debug|Win32 - {03853D47-0A08-44FB-92B5-6390B3B15B8D}.Debug|x86.Build.0 = Debug|Win32 - {03853D47-0A08-44FB-92B5-6390B3B15B8D}.Release|x86.ActiveCfg = Release|Win32 - {03853D47-0A08-44FB-92B5-6390B3B15B8D}.Release|x86.Build.0 = Release|Win32 - {E5E99434-57FA-4386-BC10-A72C2CE6B6C4}.Debug|x86.ActiveCfg = Debug|Win32 - {E5E99434-57FA-4386-BC10-A72C2CE6B6C4}.Debug|x86.Build.0 = Debug|Win32 - {E5E99434-57FA-4386-BC10-A72C2CE6B6C4}.Release|x86.ActiveCfg = Release|Win32 - {E5E99434-57FA-4386-BC10-A72C2CE6B6C4}.Release|x86.Build.0 = Release|Win32 - {8FD33503-EA67-41DD-A61F-A76F41B6CCC7}.Debug|x86.ActiveCfg = Debug|Win32 - {8FD33503-EA67-41DD-A61F-A76F41B6CCC7}.Debug|x86.Build.0 = Debug|Win32 - {8FD33503-EA67-41DD-A61F-A76F41B6CCC7}.Release|x86.ActiveCfg = Release|Win32 - {8FD33503-EA67-41DD-A61F-A76F41B6CCC7}.Release|x86.Build.0 = Release|Win32 - {BE261501-F148-4AA1-A8CE-B0E05E05771A}.Debug|x86.ActiveCfg = Debug|Win32 - {BE261501-F148-4AA1-A8CE-B0E05E05771A}.Debug|x86.Build.0 = Debug|Win32 - {BE261501-F148-4AA1-A8CE-B0E05E05771A}.Release|x86.ActiveCfg = Release|Win32 - {BE261501-F148-4AA1-A8CE-B0E05E05771A}.Release|x86.Build.0 = Release|Win32 - {45409D4F-BEB5-44D5-A454-36268F37ED8E}.Debug|x86.ActiveCfg = Debug|Win32 - {45409D4F-BEB5-44D5-A454-36268F37ED8E}.Debug|x86.Build.0 = Debug|Win32 - {45409D4F-BEB5-44D5-A454-36268F37ED8E}.Release|x86.ActiveCfg = Release|Win32 - {45409D4F-BEB5-44D5-A454-36268F37ED8E}.Release|x86.Build.0 = Release|Win32 - {2EFC3682-2141-4E21-B0DA-C34169CD826C}.Debug|x86.ActiveCfg = Debug|Win32 - {2EFC3682-2141-4E21-B0DA-C34169CD826C}.Debug|x86.Build.0 = Debug|Win32 - {2EFC3682-2141-4E21-B0DA-C34169CD826C}.Release|x86.ActiveCfg = Release|Win32 - {2EFC3682-2141-4E21-B0DA-C34169CD826C}.Release|x86.Build.0 = Release|Win32 - {F6E7BB44-39C4-4936-BADB-90010011BFCE}.Debug|x86.ActiveCfg = Debug|Win32 - {F6E7BB44-39C4-4936-BADB-90010011BFCE}.Debug|x86.Build.0 = Debug|Win32 - {F6E7BB44-39C4-4936-BADB-90010011BFCE}.Release|x86.ActiveCfg = Release|Win32 - {F6E7BB44-39C4-4936-BADB-90010011BFCE}.Release|x86.Build.0 = Release|Win32 - {C91C7EC9-ADC2-43B2-A598-7BB54EA46143}.Debug|x86.ActiveCfg = Debug|Win32 - {C91C7EC9-ADC2-43B2-A598-7BB54EA46143}.Debug|x86.Build.0 = Debug|Win32 - {C91C7EC9-ADC2-43B2-A598-7BB54EA46143}.Release|x86.ActiveCfg = Release|Win32 - {C91C7EC9-ADC2-43B2-A598-7BB54EA46143}.Release|x86.Build.0 = Release|Win32 - {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E}.Debug|x86.ActiveCfg = Debug|Win32 - {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E}.Debug|x86.Build.0 = Debug|Win32 - {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E}.Release|x86.ActiveCfg = Release|Win32 - {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E}.Release|x86.Build.0 = Release|Win32 - {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514}.Debug|x86.ActiveCfg = Debug|Win32 - {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514}.Debug|x86.Build.0 = Debug|Win32 - {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514}.Release|x86.ActiveCfg = Release|Win32 - {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514}.Release|x86.Build.0 = Release|Win32 - {EB247C6E-E77D-467B-B0F4-4CA5F24E347B}.Debug|x86.ActiveCfg = Debug|Win32 - {EB247C6E-E77D-467B-B0F4-4CA5F24E347B}.Debug|x86.Build.0 = Debug|Win32 - {EB247C6E-E77D-467B-B0F4-4CA5F24E347B}.Release|x86.ActiveCfg = Release|Win32 - {EB247C6E-E77D-467B-B0F4-4CA5F24E347B}.Release|x86.Build.0 = Release|Win32 - {CB5573A1-1424-4F10-8566-C325417125B0}.Debug|x86.ActiveCfg = Debug|Win32 - {CB5573A1-1424-4F10-8566-C325417125B0}.Debug|x86.Build.0 = Debug|Win32 - {CB5573A1-1424-4F10-8566-C325417125B0}.Release|x86.ActiveCfg = Release|Win32 - {CB5573A1-1424-4F10-8566-C325417125B0}.Release|x86.Build.0 = Release|Win32 - {F9D8152D-539E-4D47-9340-6CA134FFD44E}.Debug|x86.ActiveCfg = Debug|Win32 - {F9D8152D-539E-4D47-9340-6CA134FFD44E}.Debug|x86.Build.0 = Debug|Win32 - {F9D8152D-539E-4D47-9340-6CA134FFD44E}.Release|x86.ActiveCfg = Release|Win32 - {F9D8152D-539E-4D47-9340-6CA134FFD44E}.Release|x86.Build.0 = Release|Win32 - {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9}.Debug|x86.ActiveCfg = Debug|Win32 - {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9}.Debug|x86.Build.0 = Debug|Win32 - {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9}.Release|x86.ActiveCfg = Release|Win32 - {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9}.Release|x86.Build.0 = Release|Win32 - {CE69C349-4025-413E-8D7E-3846C90054CD}.Debug|x86.ActiveCfg = Debug|Win32 - {CE69C349-4025-413E-8D7E-3846C90054CD}.Debug|x86.Build.0 = Debug|Win32 - {CE69C349-4025-413E-8D7E-3846C90054CD}.Release|x86.ActiveCfg = Release|Win32 - {CE69C349-4025-413E-8D7E-3846C90054CD}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/cpp/visualc/FAudio.vcxproj b/cpp/visualc/FAudio.vcxproj deleted file mode 100644 index 4bb70faf10..0000000000 --- a/cpp/visualc/FAudio.vcxproj +++ /dev/null @@ -1,106 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {90A103EF-E403-47D4-BBBB-0F206B9FA7F2} - FAudio - - - - DynamicLibrary - true - MultiByte - - - DynamicLibrary - false - true - MultiByte - - - - - - - - - - - - - ..\..\..\SDL2\include;..\..\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - - - ..\..\..\SDL2\include;..\..\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - - - - Level3 - Disabled - - - true - SDL2.lib;%(AdditionalDependencies) - - - - - Level3 - MaxSpeed - FAUDIO_DISABLE_DEBUGCONFIGURATION;%(PreprocessorDefinitions) - true - true - - - true - true - true - SDL2.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cpp/visualc/RegisterDLLs.vcxproj b/cpp/visualc/RegisterDLLs.vcxproj deleted file mode 100644 index 1a9ddfa524..0000000000 --- a/cpp/visualc/RegisterDLLs.vcxproj +++ /dev/null @@ -1,153 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - {F6E7BB44-39C4-4936-BADB-90010011BFCE} - RegisterDLLs - 8.1 - - - - Application - true - v140 - MultiByte - - - Application - false - v140 - true - MultiByte - - - Application - true - v140 - MultiByte - - - Application - false - v140 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - true - - - copy $(SolutionDir)..\..\..\SDL2\lib\x86\SDL2.dll $(SolutionDir)$(Configuration) -cd $(SolutionDir)$(Configuration) -..\..\scripts\windows_register.bat - - - Register DLLs - - - - - Level3 - Disabled - true - - - copy $(SolutionDir)..\..\..\SDL2\lib\x64\SDL2.dll $(SolutionDir)$(Platform)\$(Configuration) -cd $(SolutionDir)$(Platform)\$(Configuration) -..\..\scripts\windows_register.bat - - - - Register DLLs - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - copy $(SolutionDir)..\..\..\SDL2\lib\x86\SDL2.dll $(SolutionDir)$(Configuration) -cd $(SolutionDir)$(Configuration) -..\..\scripts\windows_register.bat - - - Register DLLs - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - - - copy $(SolutionDir)..\..\..\SDL2\lib\x64\SDL2.dll $(SolutionDir)$(Platform)\$(Configuration) -cd $(SolutionDir)$(Platform)\$(Configuration) -..\..\scripts\windows_register.bat - - - - Register DLLs - - - - - - - - - - \ No newline at end of file diff --git a/cpp/visualc/X3DAudio1_3.vcxproj b/cpp/visualc/X3DAudio1_3.vcxproj deleted file mode 100644 index ba89ebf089..0000000000 --- a/cpp/visualc/X3DAudio1_3.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {2EFC3682-2141-4E21-B0DA-C34169CD826C} - Win32Proj - FAudioCPP - 8.1 - X3DAudio1_3 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - X3DAUDIO_VERSION=3;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - X3DAUDIO_VERSION=3;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/X3DAudio1_4.vcxproj b/cpp/visualc/X3DAudio1_4.vcxproj deleted file mode 100644 index b85c24b9a3..0000000000 --- a/cpp/visualc/X3DAudio1_4.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {45409D4F-BEB5-44D5-A454-36268F37ED8E} - Win32Proj - FAudioCPP - 8.1 - X3DAudio1_4 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - X3DAUDIO_VERSION=4;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - X3DAUDIO_VERSION=4;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/X3DAudio1_5.vcxproj b/cpp/visualc/X3DAudio1_5.vcxproj deleted file mode 100644 index e58e9e5439..0000000000 --- a/cpp/visualc/X3DAudio1_5.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {BE261501-F148-4AA1-A8CE-B0E05E05771A} - Win32Proj - FAudioCPP - 8.1 - X3DAudio1_5 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - X3DAUDIO_VERSION=5;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - X3DAUDIO_VERSION=5;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/X3DAudio1_6.vcxproj b/cpp/visualc/X3DAudio1_6.vcxproj deleted file mode 100644 index 6e21230f1c..0000000000 --- a/cpp/visualc/X3DAudio1_6.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {8FD33503-EA67-41DD-A61F-A76F41B6CCC7} - Win32Proj - FAudioCPP - 8.1 - X3DAudio1_6 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - X3DAUDIO_VERSION=6;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - X3DAUDIO_VERSION=6;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/X3DAudio1_7.vcxproj b/cpp/visualc/X3DAudio1_7.vcxproj deleted file mode 100644 index 60eb35574c..0000000000 --- a/cpp/visualc/X3DAudio1_7.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {EAC29019-EB87-434C-9E41-75A499941AD5} - Win32Proj - FAudioCPP - 8.1 - X3DAudio1_7 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - X3DAUDIO_VERSION=7;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - X3DAUDIO_VERSION=7;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_0.vcxproj b/cpp/visualc/XACTEngine3_0.vcxproj deleted file mode 100644 index 30f436a931..0000000000 --- a/cpp/visualc/XACTEngine3_0.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {C91C7EC9-ADC2-43B2-A598-7BB54EA46143} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_0 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=0;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=0;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_1.vcxproj b/cpp/visualc/XACTEngine3_1.vcxproj deleted file mode 100644 index 49a3e999ac..0000000000 --- a/cpp/visualc/XACTEngine3_1.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {4CFD19E3-8DCA-4988-8740-F4C2036F6C0E} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_1 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=1;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=1;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_2.vcxproj b/cpp/visualc/XACTEngine3_2.vcxproj deleted file mode 100644 index 8a13d72e21..0000000000 --- a/cpp/visualc/XACTEngine3_2.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {ECEB1BD5-8809-4DBD-9206-DB9F47C0C514} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_2 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=2;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=2;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_3.vcxproj b/cpp/visualc/XACTEngine3_3.vcxproj deleted file mode 100644 index ca36479455..0000000000 --- a/cpp/visualc/XACTEngine3_3.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {EB247C6E-E77D-467B-B0F4-4CA5F24E347B} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_3 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=3;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=3;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_4.vcxproj b/cpp/visualc/XACTEngine3_4.vcxproj deleted file mode 100644 index 56127b768a..0000000000 --- a/cpp/visualc/XACTEngine3_4.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {CB5573A1-1424-4F10-8566-C325417125B0} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_4 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=4;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=4;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_5.vcxproj b/cpp/visualc/XACTEngine3_5.vcxproj deleted file mode 100644 index 9957500978..0000000000 --- a/cpp/visualc/XACTEngine3_5.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {F9D8152D-539E-4D47-9340-6CA134FFD44E} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_5 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=5;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=5;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_6.vcxproj b/cpp/visualc/XACTEngine3_6.vcxproj deleted file mode 100644 index 8b79cdc806..0000000000 --- a/cpp/visualc/XACTEngine3_6.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {9C4EDE36-39DC-4FC7-84C8-E3BD422787A9} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_6 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=6;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=6;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XACTEngine3_7.vcxproj b/cpp/visualc/XACTEngine3_7.vcxproj deleted file mode 100644 index 2fbca09039..0000000000 --- a/cpp/visualc/XACTEngine3_7.vcxproj +++ /dev/null @@ -1,117 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {CE69C349-4025-413E-8D7E-3846C90054CD} - Win32Proj - FAudioCPP - 8.1 - XACTEngine3_7 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XACT3_VERSION=7;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xact3_7.def - - - - - Level3 - - - MaxSpeed - true - true - XACT3_VERSION=7;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xact3_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAPOBase.vcxproj b/cpp/visualc/XAPOBase.vcxproj deleted file mode 100644 index c5d08eab66..0000000000 --- a/cpp/visualc/XAPOBase.vcxproj +++ /dev/null @@ -1,110 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - - {D1E0EB55-2B90-40A1-B864-0B7A36BF79B7} - Win32Proj - FAudioCPP - 8.1 - XAPOBase - - - - StaticLibrary - true - v100 - Unicode - - - StaticLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - FAudio.lib; SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - FAudio.lib; SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_0.vcxproj b/cpp/visualc/XAudio2_0.vcxproj deleted file mode 100644 index c004188f53..0000000000 --- a/cpp/visualc/XAudio2_0.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {03853D47-0A08-44FB-92B5-6390B3B15B8D} - Win32Proj - FAudioCPP - 8.1 - XAudio2_0 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=0;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=0;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_1.vcxproj b/cpp/visualc/XAudio2_1.vcxproj deleted file mode 100644 index dcfe201d1d..0000000000 --- a/cpp/visualc/XAudio2_1.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {18A02609-C3DC-4253-9653-CC00AB1A18C5} - Win32Proj - FAudioCPP - 8.1 - XAudio2_1 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=1;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=1;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_2.vcxproj b/cpp/visualc/XAudio2_2.vcxproj deleted file mode 100644 index 0155f95139..0000000000 --- a/cpp/visualc/XAudio2_2.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {17CFD3E2-E811-45B2-9ACE-75CDFC9D5FE5} - Win32Proj - FAudioCPP - 8.1 - XAudio2_2 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=2;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=2;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_3.vcxproj b/cpp/visualc/XAudio2_3.vcxproj deleted file mode 100644 index 6883ad6ed5..0000000000 --- a/cpp/visualc/XAudio2_3.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {71A4644C-3289-4A33-82E8-6949DF25AB8B} - Win32Proj - FAudioCPP - 8.1 - XAudio2_3 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=3;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=3;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_4.vcxproj b/cpp/visualc/XAudio2_4.vcxproj deleted file mode 100644 index e6d7da57e5..0000000000 --- a/cpp/visualc/XAudio2_4.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {D000E079-A315-4F06-B2D7-7C319EC286FF} - Win32Proj - FAudioCPP - 8.1 - XAudio2_4 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=4;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=4;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_5.vcxproj b/cpp/visualc/XAudio2_5.vcxproj deleted file mode 100644 index acc70d8863..0000000000 --- a/cpp/visualc/XAudio2_5.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {841595D8-2B91-49D4-A6D8-D4B8B142137A} - Win32Proj - FAudioCPP - 8.1 - XAudio2_5 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=5;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=5;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_6.vcxproj b/cpp/visualc/XAudio2_6.vcxproj deleted file mode 100644 index 479c8fa6fa..0000000000 --- a/cpp/visualc/XAudio2_6.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {F84C835D-08F1-4C3C-AEE9-D8E3CFBC29DE} - Win32Proj - FAudioCPP - 8.1 - XAudio2_6 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=6;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=6;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_7.vcxproj b/cpp/visualc/XAudio2_7.vcxproj deleted file mode 100644 index 709ffad623..0000000000 --- a/cpp/visualc/XAudio2_7.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {9F5164EA-DC2B-4370-8C3C-DF449413A625} - Win32Proj - FAudioCPP - 8.1 - XAudio2_7 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=7;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_7.def - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_7.def - SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_8.vcxproj b/cpp/visualc/XAudio2_8.vcxproj deleted file mode 100644 index 1ab417d3e4..0000000000 --- a/cpp/visualc/XAudio2_8.vcxproj +++ /dev/null @@ -1,125 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {E5E99434-57FA-4386-BC10-A72C2CE6B6C4} - Win32Proj - FAudioCPP - 8.1 - XAudio2_8 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=8;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - setupapi.lib; SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_9.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=8;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_9.def - setupapi.lib; SDL2.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/visualc/XAudio2_9.vcxproj b/cpp/visualc/XAudio2_9.vcxproj deleted file mode 100644 index 3e747ceee1..0000000000 --- a/cpp/visualc/XAudio2_9.vcxproj +++ /dev/null @@ -1,125 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - - - - - - - {90a103ef-e403-47d4-bbbb-0f206b9fa7f2} - - - {d1e0eb55-2b90-40a1-b864-0b7a36bf79b7} - - - - {C4BE973A-0412-44D2-A5DB-F9B05EAB6EED} - Win32Proj - FAudioCPP - 8.1 - XAudio2_9 - - - - DynamicLibrary - true - v100 - Unicode - - - DynamicLibrary - false - v100 - true - Unicode - - - - - - - - - - - - - - - true - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(ProjectName) - $(Configuration)\$(ProjectName)\ - - - false - $(ProjectName) - ..\..\src;..\..\include;..\..\..\SDL2\include;$(IncludePath) - ..\..\..\SDL2\lib\x86;$(LibraryPath) - $(Configuration)\$(ProjectName)\ - - - - - - Level3 - Disabled - XAUDIO2_VERSION=9;WIN32;_DEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - SDL2.lib; setupapi.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - ../xaudio2_9.def - - - - - Level3 - - - MaxSpeed - true - true - XAUDIO2_VERSION=9;WIN32;NDEBUG;_WINDOWS;_USRDLL;FAUDIOCPP_EXPORTS;%(PreprocessorDefinitions) - 4200 - - - Windows - true - true - true - false - ../xaudio2_9.def - SDL2.lib; setupapi.lib; kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - - diff --git a/cpp/win_device.cpp b/cpp/win_device.cpp deleted file mode 100644 index 85774b4d95..0000000000 --- a/cpp/win_device.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include - -const IID DEVINTERFACE_AUDIO_RENDER = { 0xe6327cad, 0xdcec, 0x4949, {0xae, 0x8a, 0x99, 0x1e, 0x97, 0x6a, 0x79, 0xd2 } }; - -const DWORD MAX_FRIENDLY_NAME = 2048; -static wchar_t friendlyName[MAX_FRIENDLY_NAME]; - -LPCWSTR win_device_id_to_friendly_name(LPCWSTR deviceId) -{ - LPCWSTR result = NULL; - HDEVINFO devInfoSet = SetupDiGetClassDevs(&DEVINTERFACE_AUDIO_RENDER, 0, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); - - if (devInfoSet == INVALID_HANDLE_VALUE) - { - return NULL; - } - - SP_DEVINFO_DATA devInfo; - devInfo.cbSize = sizeof(SP_DEVINFO_DATA); - - SP_DEVICE_INTERFACE_DATA devInterface; - devInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - DWORD deviceIndex = 0; - - for (;;) - { - if (!SetupDiEnumDeviceInterfaces(devInfoSet, 0, &DEVINTERFACE_AUDIO_RENDER, deviceIndex, &devInterface)) - { - break; - } - deviceIndex++; - - DWORD reqSize = 0; - - SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, NULL, 0, &reqSize, NULL); - SP_DEVICE_INTERFACE_DETAIL_DATA *interfaceDetail = reinterpret_cast(new uint8_t[reqSize]); - - if (!interfaceDetail) - { - break; - } - - interfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - - if (!SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterface, interfaceDetail, reqSize, NULL, &devInfo)) - { - delete[] interfaceDetail; - continue; - } - - if (_wcsicmp(deviceId, interfaceDetail->DevicePath) != 0) - { - delete[] interfaceDetail; - continue; - } - - delete[] interfaceDetail; - - if (!SetupDiGetDeviceRegistryProperty(devInfoSet, &devInfo, SPDRP_FRIENDLYNAME, NULL, (LPBYTE) friendlyName, MAX_FRIENDLY_NAME * sizeof(wchar_t), NULL)) - { - continue; - } - - result = friendlyName; - break; - } - - if (devInfoSet) - { - SetupDiDestroyDeviceInfoList(devInfoSet); - } - - return result; -} - -uint32_t device_index_from_device_id(FAudio *faudio, LPCWSTR deviceId) -{ - LPCWSTR friendlyName = win_device_id_to_friendly_name(deviceId); - - uint32_t dev_count; - FAudio_GetDeviceCount(faudio, &dev_count); - - for (uint32_t i = 0; i < dev_count; ++i) - { - FAudioDeviceDetails dev_details; - FAudio_GetDeviceDetails(faudio, i, &dev_details); - - if (_wcsicmp((LPCWSTR) dev_details.DisplayName, friendlyName) == 0) - { - return i; - } - } - - return 0; -} diff --git a/cpp/win_registry.cpp b/cpp/win_registry.cpp deleted file mode 100644 index 2f917fe11c..0000000000 --- a/cpp/win_registry.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include - -#include /* snprintf */ - -static bool registry_write_string(HKEY reg, const char *name, const char *value, size_t len) -{ - HRESULT hr = RegSetValueExA( - reg, - name, - 0, - REG_SZ, - reinterpret_cast (value), - static_cast((len + 1) * sizeof(char)) - ); - return hr == ERROR_SUCCESS; -} - -static const char *base_key() -{ - if (sizeof(void *) == 4) - { - return "Software\\Classes\\WOW6432Node\\CLSID"; - } - else - { - return "Software\\Classes\\CLSID"; - } -} - -static void format_clsid(REFIID clsid, char *value, size_t max) -{ - snprintf(value, max, "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", - clsid.Data1, clsid.Data2, clsid.Data3, - clsid.Data4[0], clsid.Data4[1], clsid.Data4[2], clsid.Data4[3], - clsid.Data4[4], clsid.Data4[5], clsid.Data4[6], clsid.Data4[7]); -} - -extern "C" HRESULT register_faudio_dll(void *DllHandle, REFIID clsid) -{ -// not your typical COM register functions because we're "hijacking" the existing XAudio2 registration -// - COM classes are historically registered under HKEY_CLASSES_ROOT -// - on modern Windows version this is a merged from on HKEY_LOCAL_MACHINE/Software/Classes and HKEY_CURRENT_USER/Software/Classes -// - the system-wide configuration is stored under HKEY_LOCAL_MACHINE -// - we override the registration for the XAudio2 DLLs for the current user - - char str_clsid[40]; - format_clsid(clsid, str_clsid, sizeof(str_clsid) / sizeof(char)); - - char key[2048]; - snprintf(key, sizeof(key) / sizeof(char), "%s\\%s\\InProcServer32", base_key(), str_clsid); - - // open registry (creating key if it does not exist) - HKEY registry_key = NULL; - if (RegCreateKeyExA(HKEY_CURRENT_USER, key, 0, NULL, 0, KEY_WRITE, NULL, ®istry_key, NULL)) - { - return E_FAIL; - } - - // retrieve path to the dll - char path[2048]; - DWORD len = GetModuleFileNameA(reinterpret_cast(DllHandle), path, sizeof(key) / sizeof(char)); - - // update registry - registry_write_string(registry_key, NULL, path, len); - RegCloseKey(registry_key); - - return S_OK; -} - -extern "C" HRESULT unregister_faudio_dll(void *DllHandle, REFIID clsid) -{ - // open registry - HKEY registry_key = NULL; - if (RegOpenKeyExA(HKEY_CURRENT_USER, base_key(), 0, DELETE | KEY_SET_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, ®istry_key)) - { - return E_FAIL; - } - - char str_clsid[40]; - format_clsid(clsid, str_clsid, sizeof(str_clsid) / sizeof(char)); - - // delete key - HRESULT hr = RegDeleteTreeA(registry_key, str_clsid); - RegCloseKey(registry_key); - return S_OK; -} diff --git a/cpp/x3daudio.def b/cpp/x3daudio.def deleted file mode 100644 index e15cd22df0..0000000000 --- a/cpp/x3daudio.def +++ /dev/null @@ -1,4 +0,0 @@ -EXPORTS - X3DAudioInitialize @1 - X3DAudioCalculate @2 - diff --git a/cpp/xact3.cpp b/cpp/xact3.cpp deleted file mode 100644 index 5afadadf9b..0000000000 --- a/cpp/xact3.cpp +++ /dev/null @@ -1,668 +0,0 @@ -#include "xact3.h" - -#include - -extern "C" int32_t FACTCALL ReadFile( - void* hFile, - void* lpBuffer, - uint32_t nNumberOfBytesToRead, - uint32_t *lpNumberOfBytesRead, - FACTOverlapped *lpOverlapped -); -extern "C" int32_t FACTCALL GetOverlappedResult( - void* hFile, - FACTOverlapped *lpOverlapped, - uint32_t *lpNumberOfBytesTransferred, - int32_t bWait -); - -/* IXACT3Cue Implementation */ - -class XACT3CueImpl : public IXACT3Cue -{ -public: - XACT3CueImpl(FACTCue *newCue) - { - cue = newCue; - } - COM_METHOD(HRESULT) Play() - { - return FACTCue_Play(cue); - } - COM_METHOD(HRESULT) Stop(uint32_t dwFlags) - { - return FACTCue_Stop(cue, dwFlags); - }; - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) - { - return FACTCue_GetState(cue, pdwState); - } - COM_METHOD(HRESULT) Destroy() - { - return FACTCue_Destroy(cue); - } - COM_METHOD(HRESULT) SetMatrixCoefficients( - uint32_t uSrcChannelCount, - uint32_t uDstChannelCount, - float *pMatrixCoefficients - ) { - return FACTCue_SetMatrixCoefficients( - cue, - uSrcChannelCount, - uDstChannelCount, - pMatrixCoefficients - ); - } - COM_METHOD(uint16_t) GetVariableIndex(const char *szFriendlyName) - { - return FACTCue_GetVariableIndex(cue, szFriendlyName); - } - COM_METHOD(HRESULT) SetVariable(uint16_t nIndex, float nValue) - { - return FACTCue_SetVariable(cue, nIndex, nValue); - } - COM_METHOD(HRESULT) GetVariable(uint16_t nIndex, float *nValue) - { - return FACTCue_GetVariable(cue, nIndex, nValue); - } - COM_METHOD(HRESULT) Pause(int32_t fPause) - { - return FACTCue_Pause(cue, fPause); - } - COM_METHOD(HRESULT) GetProperties( - XACT_CUE_INSTANCE_PROPERTIES **ppProperties - ) { - return FACTCue_GetProperties(cue, ppProperties); - } -#if XACT3_VERSION >= 5 - COM_METHOD(HRESULT) SetOutputVoices( - const XAUDIO2_VOICE_SENDS *pSendList /* Optional! */ - ) { - /* TODO: SetOutputVoices */ - return 0; - } - COM_METHOD(HRESULT) SetOutputVoiceMatrix( - const IXAudio2Voice *pDestinationVoice, /* Optional! */ - uint32_t SourceChannels, - uint32_t DestinationChannels, - const float *pLevelMatrix /* SourceChannels * DestinationChannels */ - ) { - /* TODO: SetOutputVoiceMatrix */ - return 0; - } -#endif /* #if XACT3_VERSION >= 5 */ - - FACTCue *cue; -}; - -/* IXACT3Wave Implementation */ - -class XACT3WaveImpl : public IXACT3Wave -{ -public: - XACT3WaveImpl(FACTWave *newWave) - { - wave = newWave; - } - COM_METHOD(HRESULT) Destroy() - { - return FACTWave_Destroy(wave); - } - COM_METHOD(HRESULT) Play() - { - return FACTWave_Play(wave); - } - COM_METHOD(HRESULT) Stop(uint32_t dwFlags) - { - return FACTWave_Stop(wave, dwFlags); - } - COM_METHOD(HRESULT) Pause(int32_t fPause) - { - return FACTWave_Pause(wave, fPause); - } - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) - { - return FACTWave_GetState(wave, pdwState); - } - COM_METHOD(HRESULT) SetPitch(int16_t pitch) - { - return FACTWave_SetPitch(wave, pitch); - } - COM_METHOD(HRESULT) SetVolume(float volume) - { - return FACTWave_SetVolume(wave, volume); - } - COM_METHOD(HRESULT) SetMatrixCoefficients( - uint32_t uSrcChannelCount, - uint32_t uDstChannelCount, - float *pMatrixCoefficients - ) { - return FACTWave_SetMatrixCoefficients( - wave, - uSrcChannelCount, - uDstChannelCount, - pMatrixCoefficients - ); - } - COM_METHOD(HRESULT) GetProperties( - XACT_WAVE_INSTANCE_PROPERTIES *pProperties - ) { - return FACTWave_GetProperties(wave, pProperties); - } - - FACTWave *wave; -}; - -/* IXACT3SoundBank Implementation */ - -class XACT3SoundBankImpl : public IXACT3SoundBank -{ -public: - XACT3SoundBankImpl(FACTSoundBank *newSoundBank) - { - soundBank = newSoundBank; - } - COM_METHOD(uint16_t) GetCueIndex(const char *szFriendlyName) - { - return FACTSoundBank_GetCueIndex(soundBank, szFriendlyName); - } - COM_METHOD(HRESULT) GetNumCues(uint16_t *pnNumCues) - { - return FACTSoundBank_GetNumCues(soundBank, pnNumCues); - } - COM_METHOD(HRESULT) GetCueProperties( - uint16_t nCueIndex, - XACT_CUE_PROPERTIES *pProperties - ) { - return FACTSoundBank_GetCueProperties( - soundBank, - nCueIndex, - pProperties - ); - } - COM_METHOD(HRESULT) Prepare( - uint16_t nCueIndex, - uint32_t dwFlags, - int32_t timeOffset, - IXACT3Cue** ppCue - ) { - FACTCue *cue; - HRESULT retval = FACTSoundBank_Prepare( - soundBank, - nCueIndex, - dwFlags, - timeOffset, - &cue - ); - *ppCue = new XACT3CueImpl(cue); - return retval; - } - COM_METHOD(HRESULT) Play( - uint16_t nCueIndex, - uint32_t dwFlags, - int32_t timeOffset, - IXACT3Cue** ppCue /* Optional! */ - ) { - if (ppCue == NULL) - { - return FACTSoundBank_Play( - soundBank, - nCueIndex, - dwFlags, - timeOffset, - NULL - ); - } - FACTCue *cue; - HRESULT retval = FACTSoundBank_Play( - soundBank, - nCueIndex, - dwFlags, - timeOffset, - &cue - ); - *ppCue = new XACT3CueImpl(cue); - return retval; - } - COM_METHOD(HRESULT) Stop(uint16_t nCueIndex, uint32_t dwFlags) - { - return FACTSoundBank_Stop(soundBank, nCueIndex, dwFlags); - } - COM_METHOD(HRESULT) Destroy() - { - return FACTSoundBank_Destroy(soundBank); - } - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) - { - return FACTSoundBank_GetState(soundBank, pdwState); - } - - FACTSoundBank *soundBank; -}; - -/* IXACT3WaveBank Implementation */ - -class XACT3WaveBankImpl : public IXACT3WaveBank -{ -public: - XACT3WaveBankImpl(FACTWaveBank *newWaveBank) - { - waveBank = newWaveBank; - } - COM_METHOD(HRESULT) Destroy() - { - return FACTWaveBank_Destroy(waveBank); - } - COM_METHOD(HRESULT) GetNumWaves(uint16_t *pnNumWaves) - { - return FACTWaveBank_GetNumWaves(waveBank, pnNumWaves); - } - COM_METHOD(uint16_t) GetWaveIndex(const char *szFriendlyName) - { - return FACTWaveBank_GetWaveIndex(waveBank, szFriendlyName); - } - COM_METHOD(HRESULT) GetWaveProperties( - uint16_t nWaveIndex, - XACT_WAVE_PROPERTIES *pWaveProperties - ) { - return FACTWaveBank_GetWaveProperties( - waveBank, - nWaveIndex, - pWaveProperties - ); - } - COM_METHOD(HRESULT) Prepare( - uint16_t nWaveIndex, - uint32_t dwFlags, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) { - FACTWave *wave; - HRESULT retval = FACTWaveBank_Prepare( - waveBank, - nWaveIndex, - dwFlags, - dwPlayOffset, - nLoopCount, - &wave - ); - *ppWave = new XACT3WaveImpl(wave); - return retval; - } - COM_METHOD(HRESULT) Play( - uint16_t nWaveIndex, - uint32_t dwFlags, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) { - if (ppWave == NULL) - { - return FACTWaveBank_Play( - waveBank, - nWaveIndex, - dwFlags, - dwPlayOffset, - nLoopCount, - NULL - ); - } - FACTWave *wave; - HRESULT retval = FACTWaveBank_Play( - waveBank, - nWaveIndex, - dwFlags, - dwPlayOffset, - nLoopCount, - &wave - ); - *ppWave = new XACT3WaveImpl(wave); - return retval; - } - COM_METHOD(HRESULT) Stop( - uint16_t nWaveIndex, - uint32_t dwFlags - ) { - return FACTWaveBank_Stop(waveBank, nWaveIndex, dwFlags); - } - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) - { - return FACTWaveBank_GetState(waveBank, pdwState); - } - - FACTWaveBank *waveBank; -}; - -/* IXACT3Engine Implementation */ - -void* CDECL XACT3_INTERNAL_Malloc(size_t size) -{ - return CoTaskMemAlloc(size); -} -void CDECL XACT3_INTERNAL_Free(void* ptr) -{ - CoTaskMemFree(ptr); -} -void* CDECL XACT3_INTERNAL_Realloc(void* ptr, size_t size) -{ - return CoTaskMemRealloc(ptr, size); -} - -class XACT3EngineImpl : public IXACT3Engine -{ -public: - XACT3EngineImpl() - { - FACTCreateEngineWithCustomAllocatorEXT( - 0, - &engine, - XACT3_INTERNAL_Malloc, - XACT3_INTERNAL_Free, - XACT3_INTERNAL_Realloc - ); - } - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void **ppvInterface) - { - if (guid_equals(riid, IID_IXACT3Engine)) - { - *ppvInterface = static_cast(this); - } - else if (guid_equals(riid, IID_IUnknown)) - { - *ppvInterface = static_cast(this); - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - - reinterpret_cast(*ppvInterface)->AddRef(); - - return S_OK; - } - COM_METHOD(ULONG) AddRef() - { - return FACTAudioEngine_AddRef(engine); - } - COM_METHOD(ULONG) Release() - { - ULONG refcount = FACTAudioEngine_Release(engine); - if (refcount == 0) - { - delete this; - } - return 1; - } - COM_METHOD(HRESULT) GetRendererCount( - uint16_t *pnRendererCount - ) { - return FACTAudioEngine_GetRendererCount( - engine, - pnRendererCount - ); - } - COM_METHOD(HRESULT) GetRendererDetails( - uint16_t nRendererIndex, - XACT_RENDERER_DETAILS *pRendererDetails - ) { - return FACTAudioEngine_GetRendererDetails( - engine, - nRendererIndex, - pRendererDetails - ); - } - COM_METHOD(HRESULT) GetFinalMixFormat( - WAVEFORMATEXTENSIBLE *pFinalMixFormat - ) { - return FACTAudioEngine_GetFinalMixFormat( - engine, - pFinalMixFormat - ); - } - COM_METHOD(HRESULT) Initialize( - const XACT_RUNTIME_PARAMETERS *pParams - ) { - XACT_RUNTIME_PARAMETERS params; - - /* TODO: Unwrap FAudio/FAudioMasteringVoice */ - assert(pParams->pXAudio2 == NULL); - assert(pParams->pMasteringVoice == NULL); - - /* Copy so we can modify the parameters a bit... */ - params = *pParams; - params.pXAudio2 = NULL; - params.pMasteringVoice = NULL; - - /* Force Win32 I/O, do NOT use the default! */ - if (pParams->fileIOCallbacks.readFileCallback == NULL) - { - params.fileIOCallbacks.readFileCallback = ReadFile; - } - if (pParams->fileIOCallbacks.getOverlappedResultCallback == NULL) - { - params.fileIOCallbacks.getOverlappedResultCallback = GetOverlappedResult; - } - - return FACTAudioEngine_Initialize(engine, ¶ms); - } - COM_METHOD(HRESULT) ShutDown() - { - return FACTAudioEngine_ShutDown(engine); - } - COM_METHOD(HRESULT) DoWork() - { - return FACTAudioEngine_DoWork(engine); - } - COM_METHOD(HRESULT) CreateSoundBank( - const void *pvBuffer, - uint32_t dwSize, - uint32_t dwFlags, - uint32_t dwAllocAttributes, - IXACT3SoundBank **ppSoundBank - ) { - FACTSoundBank *soundBank; - HRESULT retval = FACTAudioEngine_CreateSoundBank( - engine, - pvBuffer, - dwSize, - dwFlags, - dwAllocAttributes, - &soundBank - ); - *ppSoundBank = new XACT3SoundBankImpl(soundBank); - return retval; - } - COM_METHOD(HRESULT) CreateInMemoryWaveBank( - const void *pvBuffer, - uint32_t dwSize, - uint32_t dwFlags, - uint32_t dwAllocAttributes, - IXACT3WaveBank **ppWaveBank - ) { - FACTWaveBank *waveBank; - HRESULT retval = FACTAudioEngine_CreateInMemoryWaveBank( - engine, - pvBuffer, - dwSize, - dwFlags, - dwAllocAttributes, - &waveBank - ); - *ppWaveBank = new XACT3WaveBankImpl(waveBank); - return retval; - } - COM_METHOD(HRESULT) CreateStreamingWaveBank( - const XACT_STREAMING_PARAMETERS *pParms, - IXACT3WaveBank **ppWaveBank - ) { - FACTWaveBank *waveBank; - HRESULT retval = FACTAudioEngine_CreateStreamingWaveBank( - engine, - pParms, - &waveBank - ); - *ppWaveBank = new XACT3WaveBankImpl(waveBank); - return retval; - } - COM_METHOD(HRESULT) PrepareWave( - uint32_t dwFlags, - const char *szWavePath, - uint32_t wStreamingPacketSize, - uint32_t dwAlignment, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) { - /* TODO: See FACT.c */ - return 0; - } - COM_METHOD(HRESULT) PrepareInMemoryWave( - uint32_t dwFlags, - WAVEBANKENTRY entry, - uint32_t *pdwSeekTable, /* Optional! */ - uint8_t *pbWaveData, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) { - /* TODO: See FACT.c */ - return 0; - } - COM_METHOD(HRESULT) PrepareStreamingWave( - uint32_t dwFlags, - WAVEBANKENTRY entry, - XACT_STREAMING_PARAMETERS streamingParams, - uint32_t dwAlignment, - uint32_t *pdwSeekTable, /* Optional! */ - uint8_t *pbWaveData, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) { - /* TODO: See FACT.c */ - return 0; - } - COM_METHOD(HRESULT) RegisterNotification( - const XACT_NOTIFICATION_DESCRIPTION *pNotificationDescription - ) { - /* We have to unwrap the FACT object first! */ - FACTNotificationDescription desc; - desc.type = pNotificationDescription->type; - desc.flags = pNotificationDescription->flags; - desc.cueIndex = pNotificationDescription->cueIndex; - desc.waveIndex = pNotificationDescription->waveIndex; - desc.pvContext = pNotificationDescription->pvContext; - if (desc.type == FACTNOTIFICATIONTYPE_CUEDESTROYED) - { - desc.pCue = ((XACT3CueImpl*) pNotificationDescription->pCue)->cue; - } - else if (desc.type == FACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED) - { - if (pNotificationDescription->pSoundBank != NULL) - { - desc.pSoundBank = ((XACT3SoundBankImpl*) pNotificationDescription->pSoundBank)->soundBank; - } - else - { - desc.pSoundBank = NULL; - } - } - else if (desc.type == FACTNOTIFICATIONTYPE_WAVEBANKDESTROYED) - { - desc.pWaveBank = ((XACT3WaveBankImpl*) pNotificationDescription->pWaveBank)->waveBank; - } - else if (desc.type == FACTNOTIFICATIONTYPE_WAVEDESTROYED) - { - desc.pWave = ((XACT3WaveImpl*) pNotificationDescription->pWave)->wave; - } - // If you didn't hit an above if, get ready for an assert! - - return FACTAudioEngine_RegisterNotification(engine, &desc); - } - COM_METHOD(HRESULT) UnRegisterNotification( - const XACT_NOTIFICATION_DESCRIPTION *pNotificationDescription - ) { - /* We have to unwrap the FACT object first! */ - FACTNotificationDescription desc; - desc.type = pNotificationDescription->type; - desc.flags = pNotificationDescription->flags; - desc.cueIndex = pNotificationDescription->cueIndex; - desc.waveIndex = pNotificationDescription->waveIndex; - desc.pvContext = pNotificationDescription->pvContext; - if (desc.type == FACTNOTIFICATIONTYPE_CUEDESTROYED) - { - desc.pCue = ((XACT3CueImpl*) pNotificationDescription->pCue)->cue; - } - else if (desc.type == FACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED) - { - desc.pSoundBank = ((XACT3SoundBankImpl*) pNotificationDescription->pSoundBank)->soundBank; - } - else if (desc.type == FACTNOTIFICATIONTYPE_WAVEBANKDESTROYED) - { - desc.pWaveBank = ((XACT3WaveBankImpl*) pNotificationDescription->pWaveBank)->waveBank; - } - else if (desc.type == FACTNOTIFICATIONTYPE_WAVEDESTROYED) - { - desc.pWave = ((XACT3WaveImpl*) pNotificationDescription->pWave)->wave; - } - // If you didn't hit an above if, get ready for an assert! - - return FACTAudioEngine_UnRegisterNotification(engine, &desc); - } - COM_METHOD(uint16_t) GetCategory(const char *szFriendlyName) - { - return FACTAudioEngine_GetCategory(engine, szFriendlyName); - } - COM_METHOD(HRESULT) Stop(uint16_t nCategory, uint32_t dwFlags) - { - return FACTAudioEngine_Stop(engine, nCategory, dwFlags); - } - COM_METHOD(HRESULT) SetVolume(uint16_t nCategory, float volume) - { - return FACTAudioEngine_SetVolume(engine, nCategory, volume); - } - COM_METHOD(HRESULT) Pause(uint16_t nCategory, int32_t fPause) - { - return FACTAudioEngine_Pause(engine, nCategory, fPause); - } - COM_METHOD(uint16_t) GetGlobalVariableIndex( - const char *szFriendlyName - ) { - return FACTAudioEngine_GetGlobalVariableIndex( - engine, - szFriendlyName - ); - } - COM_METHOD(HRESULT) SetGlobalVariable( - uint16_t nIndex, - float nValue - ) { - return FACTAudioEngine_SetGlobalVariable( - engine, - nIndex, - nValue - ); - } - COM_METHOD(HRESULT) GetGlobalVariable( - uint16_t nIndex, - float *pnValue - ) { - return FACTAudioEngine_GetGlobalVariable( - engine, - nIndex, - pnValue - ); - - } -private: - FACTAudioEngine *engine; -}; - -/* Create Function */ - -void *CreateXACT3EngineInternal() -{ - return new XACT3EngineImpl(); -} diff --git a/cpp/xact3.h b/cpp/xact3.h deleted file mode 100644 index db587fc76e..0000000000 --- a/cpp/xact3.h +++ /dev/null @@ -1,334 +0,0 @@ -#ifndef FACT_CPP_XACT3_H -#define FACT_CPP_XACT3_H - -#include "xaudio2.h" -#include - - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef XACT3_VERSION -#define XACT3_VERSION 7 -#endif - -typedef FACTRendererDetails XACT_RENDERER_DETAILS; -typedef FACTFileIOCallbacks XACT_FILEIO_CALLBACKS; -typedef FACTRuntimeParameters XACT_RUNTIME_PARAMETERS; -typedef FACTStreamingParameters XACT_STREAMING_PARAMETERS; -typedef FACTWaveBankRegion WAVEBANKREGION; -typedef FACTWaveBankSampleRegion WAVEBANKSAMPLEREGION; -typedef FACTWaveBankHeader WAVEBANKHEADER; -typedef FACTWaveBankMiniWaveFormat WAVEBANKMINIWAVEFORMAT; -typedef FACTWaveBankEntry WAVEBANKENTRY; -typedef FACTWaveBankEntryCompact WAVEBANKENTRYCOMPACT; -typedef FACTWaveBankData WAVEBANKDATA; -typedef FACTWaveProperties XACT_WAVE_PROPERTIES; -typedef FACTWaveInstanceProperties XACT_WAVE_INSTANCE_PROPERTIES; -typedef FACTCueProperties XACT_CUE_PROPERTIES; -typedef FACTTrackProperties XACT_TRACK_PROPERTIES; -typedef FACTVariationProperties XACT_VARIATION_PROPERTIES; -typedef FACTSoundProperties XACT_SOUND_PROPERTIES; -typedef FACTSoundVariationProperties XACT_SOUND_VARIATION_PROPERTIES; -typedef FACTCueInstanceProperties XACT_CUE_INSTANCE_PROPERTIES; - -typedef FACTReadFileCallback XACT_READFILE_CALLBACK; -typedef FACTGetOverlappedResultCallback XACT_GETOVERLAPPEDRESULT_CALLBACK; - -typedef FACTWaveBankSegIdx WAVEBANKSEGIDX; - -class IXACT3Engine; -class IXACT3SoundBank; -class IXACT3WaveBank; -class IXACT3Wave; -class IXACT3Cue; - -#pragma pack(push, 1) - -typedef struct XACT_NOTIFICATION_DESCRIPTION -{ - uint8_t type; - uint8_t flags; - IXACT3SoundBank *pSoundBank; - IXACT3WaveBank *pWaveBank; - IXACT3Cue *pCue; - IXACT3Wave *pWave; - uint16_t cueIndex; - uint16_t waveIndex; - void* pvContext; -} XACT_NOTIFICATION_DESCRIPTION; - -typedef struct XACT_NOTIFICATION_CUE -{ - uint16_t cueIndex; - IXACT3SoundBank *pSoundBank; - IXACT3Cue *pCue; -} XACT_NOTIFICATION_CUE; - -typedef struct XACT_NOTIFICATION_MARKER -{ - uint16_t cueIndex; - IXACT3SoundBank *pSoundBank; - IXACT3Cue *pCue; - uint32_t marker; -} XACT_NOTIFICATION_MARKER; - -typedef struct XACT_NOTIFICATION_SOUNDBANK -{ - IXACT3SoundBank *pSoundBank; -} XACT_NOTIFICATION_SOUNDBANK; - -typedef struct XACT_NOTIFICATION_WAVEBANK -{ - IXACT3WaveBank *pWaveBank; -} XACT_NOTIFICATION_WAVEBANK; - -typedef struct XACT_NOTIFICATION_VARIABLE -{ - uint16_t cueIndex; - IXACT3SoundBank *pSoundBank; - IXACT3Cue *pCue; - uint16_t variableIndex; - float variableValue; - uint8_t local; -} XACT_NOTIFICATION_VARIABLE; - -typedef struct XACT_NOTIFICATION_GUI -{ - uint32_t reserved; -} XACT_NOTIFICATION_GUI; - -typedef struct XACT_NOTIFICATION_WAVE -{ - IXACT3WaveBank *pWaveBank; - uint16_t waveIndex; - uint16_t cueIndex; - IXACT3SoundBank *pSoundBank; - IXACT3Cue *pCue; - IXACT3Wave *pWave; -} XACT_NOTIFICATION_WAVE; - -typedef struct XACT_NOTIFICATION -{ - uint8_t type; - int32_t timeStamp; - void *pvContext; - union - { - XACT_NOTIFICATION_CUE cue; - XACT_NOTIFICATION_MARKER marker; - XACT_NOTIFICATION_SOUNDBANK soundBank; - XACT_NOTIFICATION_WAVEBANK waveBank; - XACT_NOTIFICATION_VARIABLE variable; - XACT_NOTIFICATION_GUI gui; - XACT_NOTIFICATION_WAVE wave; - }; -} XACT_NOTIFICATION; - -#pragma pack(pop) - -class IXACT3Engine : public IUnknown -{ -public: - COM_METHOD(HRESULT) GetRendererCount( - uint16_t *pnRendererCount - ) = 0; - COM_METHOD(HRESULT) GetRendererDetails( - uint16_t nRendererIndex, - XACT_RENDERER_DETAILS *pRendererDetails - ) = 0; - COM_METHOD(HRESULT) GetFinalMixFormat( - WAVEFORMATEXTENSIBLE *pFinalMixFormat - ) = 0; - COM_METHOD(HRESULT) Initialize( - const XACT_RUNTIME_PARAMETERS *pParams - ) = 0; - COM_METHOD(HRESULT) ShutDown() = 0; - COM_METHOD(HRESULT) DoWork() = 0; - COM_METHOD(HRESULT) CreateSoundBank( - const void *pvBuffer, - uint32_t dwSize, - uint32_t dwFlags, - uint32_t dwAllocAttributes, - IXACT3SoundBank **ppSoundBank - ) = 0; - COM_METHOD(HRESULT) CreateInMemoryWaveBank( - const void *pvBuffer, - uint32_t dwSize, - uint32_t dwFlags, - uint32_t dwAllocAttributes, - IXACT3WaveBank **ppWaveBank - ) = 0; - COM_METHOD(HRESULT) CreateStreamingWaveBank( - const XACT_STREAMING_PARAMETERS *pParms, - IXACT3WaveBank **ppWaveBank - ) = 0; - COM_METHOD(HRESULT) PrepareWave( - uint32_t dwFlags, - const char *szWavePath, - uint32_t wStreamingPacketSize, - uint32_t dwAlignment, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) = 0; - COM_METHOD(HRESULT) PrepareInMemoryWave( - uint32_t dwFlags, - WAVEBANKENTRY entry, - uint32_t *pdwSeekTable, /* Optional! */ - uint8_t *pbWaveData, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) = 0; - COM_METHOD(HRESULT) PrepareStreamingWave( - uint32_t dwFlags, - WAVEBANKENTRY entry, - XACT_STREAMING_PARAMETERS streamingParams, - uint32_t dwAlignment, - uint32_t *pdwSeekTable, /* Optional! */ - uint8_t *pbWaveData, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) = 0; - COM_METHOD(HRESULT) RegisterNotification( - const XACT_NOTIFICATION_DESCRIPTION *pNotificationDescription - ) = 0; - COM_METHOD(HRESULT) UnRegisterNotification( - const XACT_NOTIFICATION_DESCRIPTION *pNotificationDescription - ) = 0; - COM_METHOD(uint16_t) GetCategory(const char *szFriendlyName) = 0; - COM_METHOD(HRESULT) Stop(uint16_t nCategory, uint32_t dwFlags) = 0; - COM_METHOD(HRESULT) SetVolume(uint16_t nCategory, float volume) = 0; - COM_METHOD(HRESULT) Pause(uint16_t nCategory, int32_t fPause) = 0; - COM_METHOD(uint16_t) GetGlobalVariableIndex( - const char *szFriendlyName - ) = 0; - COM_METHOD(HRESULT) SetGlobalVariable( - uint16_t nIndex, - float nValue - ) = 0; - COM_METHOD(HRESULT) GetGlobalVariable( - uint16_t nIndex, - float *pnValue - ) = 0; -}; - -class IXACT3SoundBank -{ -public: - COM_METHOD(uint16_t) GetCueIndex(const char *szFriendlyName) = 0; - COM_METHOD(HRESULT) GetNumCues(uint16_t *pnNumCues) = 0; - COM_METHOD(HRESULT) GetCueProperties( - uint16_t nCueIndex, - XACT_CUE_PROPERTIES *pProperties - ) = 0; - COM_METHOD(HRESULT) Prepare( - uint16_t nCueIndex, - uint32_t dwFlags, - int32_t timeOffset, - IXACT3Cue** ppCue - ) = 0; - COM_METHOD(HRESULT) Play( - uint16_t nCueIndex, - uint32_t dwFlags, - int32_t timeOffset, - IXACT3Cue** ppCue /* Optional! */ - ) = 0; - COM_METHOD(HRESULT) Stop(uint16_t nCueIndex, uint32_t dwFlags) = 0; - COM_METHOD(HRESULT) Destroy() = 0; - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) = 0; -}; - -class IXACT3WaveBank -{ -public: - COM_METHOD(HRESULT) Destroy() = 0; - COM_METHOD(HRESULT) GetNumWaves(uint16_t *pnNumWaves) = 0; - COM_METHOD(uint16_t) GetWaveIndex(const char *szFriendlyName) = 0; - COM_METHOD(HRESULT) GetWaveProperties( - uint16_t nWaveIndex, - XACT_WAVE_PROPERTIES *pWaveProperties - ) = 0; - COM_METHOD(HRESULT) Prepare( - uint16_t nWaveIndex, - uint32_t dwFlags, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) = 0; - COM_METHOD(HRESULT) Play( - uint16_t nWaveIndex, - uint32_t dwFlags, - uint32_t dwPlayOffset, - uint8_t nLoopCount, - IXACT3Wave **ppWave - ) = 0; - COM_METHOD(HRESULT) Stop( - uint16_t nWaveIndex, - uint32_t dwFlags - ) = 0; - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) = 0; -}; - -class IXACT3Wave -{ -public: - COM_METHOD(HRESULT) Destroy() = 0; - COM_METHOD(HRESULT) Play() = 0; - COM_METHOD(HRESULT) Stop(uint32_t dwFlags) = 0; - COM_METHOD(HRESULT) Pause(int32_t fPause) = 0; - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) = 0; - COM_METHOD(HRESULT) SetPitch(int16_t pitch) = 0; - COM_METHOD(HRESULT) SetVolume(float volume) = 0; - COM_METHOD(HRESULT) SetMatrixCoefficients( - uint32_t uSrcChannelCount, - uint32_t uDstChannelCount, - float *pMatrixCoefficients - ) = 0; - COM_METHOD(HRESULT) GetProperties( - XACT_WAVE_INSTANCE_PROPERTIES *pProperties - ) = 0; -}; - -class IXACT3Cue -{ -public: - COM_METHOD(HRESULT) Play() = 0; - COM_METHOD(HRESULT) Stop(uint32_t dwFlags) = 0; - COM_METHOD(HRESULT) GetState(uint32_t *pdwState) = 0; - COM_METHOD(HRESULT) Destroy() = 0; - COM_METHOD(HRESULT) SetMatrixCoefficients( - uint32_t uSrcChannelCount, - uint32_t uDstChannelCount, - float *pMatrixCoefficients - ) = 0; - COM_METHOD(uint16_t) GetVariableIndex(const char *szFriendlyName) = 0; - COM_METHOD(HRESULT) SetVariable(uint16_t nIndex, float nValue) = 0; - COM_METHOD(HRESULT) GetVariable(uint16_t nIndex, float *nValue) = 0; - COM_METHOD(HRESULT) Pause(int32_t fPause) = 0; - COM_METHOD(HRESULT) GetProperties( - XACT_CUE_INSTANCE_PROPERTIES **ppProperties - ) = 0; -#if XACT3_VERSION >= 5 - COM_METHOD(HRESULT) SetOutputVoices( - const XAUDIO2_VOICE_SENDS *pSendList /* Optional! */ - ) = 0; - COM_METHOD(HRESULT) SetOutputVoiceMatrix( - const IXAudio2Voice *pDestinationVoice, /* Optional! */ - uint32_t SourceChannels, - uint32_t DestinationChannels, - const float *pLevelMatrix /* SourceChannels * DestinationChannels */ - ) = 0; -#endif /* XACT_VERSION >= 5 */ -}; - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif // FACT_CPP_XACT3_H diff --git a/cpp/xact3_7.def b/cpp/xact3_7.def deleted file mode 100644 index b0a6be2e50..0000000000 --- a/cpp/xact3_7.def +++ /dev/null @@ -1,6 +0,0 @@ -EXPORTS - DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE - \ No newline at end of file diff --git a/cpp/xapofx.def b/cpp/xapofx.def deleted file mode 100644 index 398bf6e8b9..0000000000 --- a/cpp/xapofx.def +++ /dev/null @@ -1,2 +0,0 @@ -EXPORTS - CreateFX @1 diff --git a/cpp/xaudio2.cpp b/cpp/xaudio2.cpp deleted file mode 100644 index 5fa6874ef8..0000000000 --- a/cpp/xaudio2.cpp +++ /dev/null @@ -1,1396 +0,0 @@ -#include "xaudio2.h" -#include "XAPO.h" - -#include - -/////////////////////////////////////////////////////////////////////////////// -// -// IXAudio2VoiceCallback -// - -struct FAudioVoiceCppCallback -{ - FAudioVoiceCallback callbacks; - IXAudio2VoiceCallback *com; -}; - -static void FAUDIOCALL OnBufferEnd(FAudioVoiceCallback *callback, void *pBufferContext) -{ - reinterpret_cast(callback)->com->OnBufferEnd(pBufferContext); -} - -static void FAUDIOCALL OnBufferStart(FAudioVoiceCallback *callback, void *pBufferContext) -{ - reinterpret_cast(callback)->com->OnBufferStart(pBufferContext); -} - -static void FAUDIOCALL OnLoopEnd(FAudioVoiceCallback *callback, void *pBufferContext) -{ - reinterpret_cast(callback)->com->OnLoopEnd(pBufferContext); -} - -static void FAUDIOCALL OnStreamEnd(FAudioVoiceCallback *callback) -{ - reinterpret_cast(callback)->com->OnStreamEnd(); -} - -static void FAUDIOCALL OnVoiceError( - FAudioVoiceCallback *callback, - void *pBufferContext, - uint32_t Error -) { - reinterpret_cast(callback)->com->OnVoiceError(pBufferContext, Error); -} - -static void FAUDIOCALL OnVoiceProcessingPassEnd(FAudioVoiceCallback *callback) -{ - reinterpret_cast(callback)->com->OnVoiceProcessingPassEnd(); -} - -static void FAUDIOCALL OnVoiceProcessingPassStart( - FAudioVoiceCallback *callback, - uint32_t BytesRequired -) { -#if XAUDIO2_VERSION >= 1 - reinterpret_cast(callback)->com->OnVoiceProcessingPassStart( - BytesRequired); -#else - reinterpret_cast(callback)->com->OnVoiceProcessingPassStart(); -#endif // XAUDIO2_VERSION >= 1 -} - -FAudioVoiceCppCallback *wrap_voice_callback(IXAudio2VoiceCallback *com_interface) -{ - if (com_interface == NULL) - { - return NULL; - } - - FAudioVoiceCppCallback *cb = new FAudioVoiceCppCallback(); - cb->callbacks.OnBufferEnd = OnBufferEnd; - cb->callbacks.OnBufferStart = OnBufferStart; - cb->callbacks.OnLoopEnd = OnLoopEnd; - cb->callbacks.OnStreamEnd = OnStreamEnd; - cb->callbacks.OnVoiceError = OnVoiceError; - cb->callbacks.OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd; - cb->callbacks.OnVoiceProcessingPassStart = OnVoiceProcessingPassStart; - cb->com = com_interface; - - return cb; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// IXAudio2EngineCallback -// - -struct FAudioCppEngineCallback -{ - FAudioEngineCallback callbacks; - IXAudio2EngineCallback *com; - - FAudioCppEngineCallback *next; -}; - -static void FAUDIOCALL OnCriticalError(FAudioEngineCallback *callback, uint32_t Error) -{ - reinterpret_cast(callback)->com->OnCriticalError(Error); -} - -static void FAUDIOCALL OnProcessingPassEnd(FAudioEngineCallback *callback) -{ - reinterpret_cast(callback)->com->OnProcessingPassEnd(); -} - -static void FAUDIOCALL OnProcessingPassStart(FAudioEngineCallback *callback) -{ - reinterpret_cast(callback)->com->OnProcessingPassStart(); -} - -static FAudioCppEngineCallback *wrap_engine_callback(IXAudio2EngineCallback *com_interface) -{ - if (com_interface == NULL) - { - return NULL; - } - - FAudioCppEngineCallback *cb = new FAudioCppEngineCallback(); - cb->callbacks.OnCriticalError = OnCriticalError; - cb->callbacks.OnProcessingPassEnd = OnProcessingPassEnd; - cb->callbacks.OnProcessingPassStart = OnProcessingPassStart; - cb->com = com_interface; - cb->next = NULL; - - return cb; -} - -static FAudioCppEngineCallback *find_and_remove_engine_callback( - FAudioCppEngineCallback *list, - IXAudio2EngineCallback *com -) { - FAudioCppEngineCallback *last = list; - - for (FAudioCppEngineCallback *it = list->next; it != NULL; it = it->next) - { - if (it->com == com) - { - last->next = it->next; - return it; - } - - last = it; - } - - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// -// -// XAUDIO2_VOICE_SENDS / XAUDIO2_SEND_DESCRIPTOR => FAudio -// - -static FAudioVoiceSends *unwrap_voice_sends(const XAUDIO2_VOICE_SENDS *x_sends) -{ - if (x_sends == NULL) - { - return NULL; - } - - FAudioVoiceSends *f_sends = new FAudioVoiceSends; - f_sends->SendCount = x_sends->SendCount; - f_sends->pSends = new FAudioSendDescriptor[f_sends->SendCount]; - - for (uint32_t i = 0; i < f_sends->SendCount; ++i) - { -#if XAUDIO2_VERSION >= 4 - f_sends->pSends[i].Flags = x_sends->pSends[i].Flags; - f_sends->pSends[i].pOutputVoice = x_sends->pSends[i].pOutputVoice->faudio_voice; -#else - f_sends->pSends[i].Flags = 0; - f_sends->pSends[i].pOutputVoice = x_sends->pSends[i]->faudio_voice; -#endif // XAUDIO2_VERSION >= 4 - } - - return f_sends; -} - -static void free_voice_sends(FAudioVoiceSends *f_sends) -{ - if (f_sends != NULL) - { - delete[] f_sends->pSends; - delete f_sends; - } -} - -/////////////////////////////////////////////////////////////////////////////// -// -// XAUDIO2_EFFECT_CHAIN / XAUDIO2_EFFECT_DESCRIPTOR => FAudio -// - -struct FAPOCppBase -{ - FAPO fapo; - IXAPO *xapo; - IXAPOParameters *xapo_params; - LONG refcount; -}; - -static int32_t FAPOCALL AddRef(void *fapo) -{ - FAPOCppBase *base = reinterpret_cast(fapo); - return ++base->refcount; -} - -static int32_t FAPOCALL Release(void *fapo) -{ - FAPOCppBase *base = reinterpret_cast(fapo); - IXAPO *xapo = base->xapo; - LONG ref = --base->refcount; - if (ref == 0) - { - xapo->Release(); - if (base->xapo_params != NULL) - { - base->xapo_params->Release(); - } - delete base; - } - return ref; -} - -static uint32_t FAPOCALL GetRegistrationProperties( - void *fapo, - FAPORegistrationProperties **ppRegistrationProperties) -{ - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->GetRegistrationProperties(ppRegistrationProperties); -} - -static uint32_t FAPOCALL IsInputFormatSupported( - void *fapo, - const FAudioWaveFormatEx *pOutputFormat, - const FAudioWaveFormatEx *pRequestedInputFormat, - FAudioWaveFormatEx **ppSupportedInputFormat -) { - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->IsInputFormatSupported( - pOutputFormat, - pRequestedInputFormat, - ppSupportedInputFormat); -} - -static uint32_t FAPOCALL IsOutputFormatSupported( - void *fapo, - const FAudioWaveFormatEx *pInputFormat, - const FAudioWaveFormatEx *pRequestedOutputFormat, - FAudioWaveFormatEx **ppSupportedOutputFormat -) { - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->IsOutputFormatSupported( - pInputFormat, - pRequestedOutputFormat, - ppSupportedOutputFormat); -} - -static uint32_t FAPOCALL Initialize(void *fapo, const void *pData, uint32_t DataByteSize) -{ - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->Initialize(pData, DataByteSize); -} - -static void FAPOCALL Reset(void *fapo) -{ - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - xapo->Reset(); -} - -static uint32_t FAPOCALL LockForProcess( - void *fapo, - uint32_t InputLockedParameterCount, - const FAPOLockForProcessBufferParameters *pInputLockedParameters, - uint32_t OutputLockedParameterCount, - const FAPOLockForProcessBufferParameters *pOutputLockedParameters -) { - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->LockForProcess( - InputLockedParameterCount, - pInputLockedParameters, - OutputLockedParameterCount, - pOutputLockedParameters); -} - -static void FAPOCALL UnlockForProcess(void *fapo) -{ - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - xapo->UnlockForProcess(); -} - -static void FAPOCALL Process( - void *fapo, - uint32_t InputProcessParameterCount, - const FAPOProcessBufferParameters *pInputProcessParameters, - uint32_t OutputProcessParameterCount, - FAPOProcessBufferParameters *pOutputProcessParameters, - int32_t IsEnabled -) { - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - xapo->Process( - InputProcessParameterCount, - pInputProcessParameters, - OutputProcessParameterCount, - pOutputProcessParameters, - IsEnabled); -} - -static uint32_t FAPOCALL CalcInputFrames(void *fapo, uint32_t OutputFrameCount) -{ - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->CalcInputFrames(OutputFrameCount); -} - -static uint32_t FAPOCALL CalcOutputFrames(void *fapo, uint32_t InputFrameCount) -{ - IXAPO *xapo = reinterpret_cast(fapo)->xapo; - return xapo->CalcOutputFrames(InputFrameCount); -} - -static void FAPOCALL SetParameters( - void *fapoParameters, - const void *pParameters, - uint32_t ParameterByteSize -) { - IXAPOParameters *xapo_params = reinterpret_cast(fapoParameters)->xapo_params; - return xapo_params->SetParameters(pParameters, ParameterByteSize); -} - -static void FAPOCALL GetParameters(void *fapoParameters, void *pParameters, uint32_t ParameterByteSize) -{ - IXAPOParameters *xapo_params = reinterpret_cast(fapoParameters)->xapo_params; - return xapo_params->GetParameters(pParameters, ParameterByteSize); -} - -static FAPO *wrap_xapo_effect(IUnknown *xapo) -{ - if (xapo == NULL) - { - return NULL; - } - - // FIXME: assumes that all effects are derived from CXAPOParametersBase - FAPOCppBase *f_effect = new FAPOCppBase; - f_effect->refcount = 1; - xapo->QueryInterface(IID_IXAPO, (void **)&f_effect->xapo); - xapo->QueryInterface(IID_IXAPOParameters, (void **)&f_effect->xapo_params); - - f_effect->fapo.AddRef = AddRef; - f_effect->fapo.Release = Release; - f_effect->fapo.GetRegistrationProperties = GetRegistrationProperties; - f_effect->fapo.IsInputFormatSupported = IsInputFormatSupported; - f_effect->fapo.IsOutputFormatSupported = IsOutputFormatSupported; - f_effect->fapo.Initialize = Initialize; - f_effect->fapo.Reset = Reset; - f_effect->fapo.LockForProcess = LockForProcess; - f_effect->fapo.UnlockForProcess = UnlockForProcess; - f_effect->fapo.Process = Process; - f_effect->fapo.CalcInputFrames = CalcInputFrames; - f_effect->fapo.CalcOutputFrames = CalcOutputFrames; - f_effect->fapo.GetParameters = GetParameters; - f_effect->fapo.SetParameters = SetParameters; - - return &f_effect->fapo; -} - -static FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *x_chain) -{ - if (x_chain == NULL) - { - return NULL; - } - - FAudioEffectChain *f_chain = new FAudioEffectChain; - f_chain->EffectCount = x_chain->EffectCount; - f_chain->pEffectDescriptors = new FAudioEffectDescriptor[f_chain->EffectCount]; - - for (uint32_t i = 0; i < f_chain->EffectCount; ++i) - { - f_chain->pEffectDescriptors[i].InitialState = x_chain->pEffectDescriptors[i].InitialState; - f_chain->pEffectDescriptors[i].OutputChannels = - x_chain->pEffectDescriptors[i].OutputChannels; - f_chain->pEffectDescriptors[i].pEffect = - wrap_xapo_effect(x_chain->pEffectDescriptors[i].pEffect); - } - - return f_chain; -} - -static void free_effect_chain(FAudioEffectChain *f_chain) -{ - if (f_chain != NULL) - { - delete[] f_chain->pEffectDescriptors; - delete f_chain; - } -} - -/////////////////////////////////////////////////////////////////////////////// -// -// IXAudio2SourceVoice implementation -// - -class XAudio2SourceVoiceImpl : public IXAudio2SourceVoice -{ -public: - XAudio2SourceVoiceImpl( - FAudio *faudio, - const WAVEFORMATEX *pSourceFormat, - UINT32 Flags, - float MaxFrequencyRatio, - IXAudio2VoiceCallback *pCallback, - const XAUDIO2_VOICE_SENDS *pSendList, - const XAUDIO2_EFFECT_CHAIN *pEffectChain) - { - voice_callback = wrap_voice_callback(pCallback); - voice_sends = unwrap_voice_sends(pSendList); - effect_chain = wrap_effect_chain(pEffectChain); - FAudio_CreateSourceVoice( - faudio, - &faudio_voice, - pSourceFormat, - Flags, - MaxFrequencyRatio, - reinterpret_cast(voice_callback), - voice_sends, - effect_chain); - } - - // IXAudio2Voice - COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails) - { -#if XAUDIO2_VERSION > 7 - FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails); -#else - FAudioVoiceDetails fDetails; - FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails); - pVoiceDetails->CreationFlags = fDetails.CreationFlags; - pVoiceDetails->InputChannels = fDetails.InputChannels; - pVoiceDetails->InputSampleRate = fDetails.InputSampleRate; -#endif // XAUDIO2_VERSION <= 7 - } - - COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList) - { - free_voice_sends(voice_sends); - voice_sends = unwrap_voice_sends(pSendList); - return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends); - } - - COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain) - { - free_effect_chain(effect_chain); - effect_chain = wrap_effect_chain(pEffectChain); - return FAudioVoice_SetEffectChain(faudio_voice, effect_chain); - } - - COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet); - } - - COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet); - } - - COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled) - { - FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled); - } - - COM_METHOD(HRESULT) SetEffectParameters( - UINT32 EffectIndex, - const void *pParameters, - UINT32 ParametersByteSize, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetEffectParameters( - faudio_voice, - EffectIndex, - pParameters, - ParametersByteSize, - OperationSet); - } - - COM_METHOD(HRESULT) GetEffectParameters( - UINT32 EffectIndex, - void *pParameters, - UINT32 ParametersByteSize) - { - return FAudioVoice_GetEffectParameters( - faudio_voice, - EffectIndex, - pParameters, - ParametersByteSize); - } - - COM_METHOD(HRESULT) SetFilterParameters( - const XAUDIO2_FILTER_PARAMETERS *pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet); - } - - COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters) - { - FAudioVoice_GetFilterParameters(faudio_voice, pParameters); - } - -#if XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetOutputFilterParameters( - IXAudio2Voice *pDestinationVoice, - const XAUDIO2_FILTER_PARAMETERS *pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetOutputFilterParameters( - faudio_voice, - ((XAudio2SourceVoiceImpl *)pDestinationVoice)->faudio_voice, - pParameters, - OperationSet); - } - - COM_METHOD(void) GetOutputFilterParameters( - IXAudio2Voice *pDestinationVoice, - XAUDIO2_FILTER_PARAMETERS *pParameters - ) { - FAudioVoice_GetOutputFilterParameters( - faudio_voice, - ((XAudio2SourceVoiceImpl *)pDestinationVoice)->faudio_voice, - pParameters); - } -#endif // XAUDIO2_VERSION >= 4 - - COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet); - } - - COM_METHOD(void) GetVolume(float *pVolume) - { - FAudioVoice_GetVolume(faudio_voice, pVolume); - } - - COM_METHOD(HRESULT) SetChannelVolumes( - UINT32 Channels, - const float *pVolumes, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet); - } - - COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes) - { - FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes); - } - - COM_METHOD(HRESULT) SetOutputMatrix( - IXAudio2Voice *pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - const float *pLevelMatrix, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL; - return FAudioVoice_SetOutputMatrix( - faudio_voice, dest, SourceChannels, DestinationChannels, pLevelMatrix, OperationSet); - } - -#if XAUDIO2_VERSION >= 1 - COM_METHOD(void) GetOutputMatrix( -#else - COM_METHOD(HRESULT) GetOutputMatrix( -#endif - IXAudio2Voice *pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - float *pLevelMatrix - ) { - FAudioVoice_GetOutputMatrix( - faudio_voice, - pDestinationVoice->faudio_voice, - SourceChannels, - DestinationChannels, - pLevelMatrix); -#if XAUDIO2_VERSION < 1 - return S_OK; -#endif // XAUDIO2_VERSION < 1 - } - - COM_METHOD(void) DestroyVoice() - { - FAudioVoice_DestroyVoice(faudio_voice); - // FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS - if (voice_callback) - { - delete voice_callback; - } - free_voice_sends(voice_sends); - free_effect_chain(effect_chain); - delete this; - } - - // IXAudio2SourceVoice - COM_METHOD(HRESULT) Start(UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioSourceVoice_Start(faudio_voice, Flags, OperationSet); - } - - COM_METHOD(HRESULT) Stop(UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioSourceVoice_Stop(faudio_voice, Flags, OperationSet); - } - - COM_METHOD(HRESULT) SubmitSourceBuffer( - const XAUDIO2_BUFFER *pBuffer, - const XAUDIO2_BUFFER_WMA *pBufferWMA = NULL) - { - return FAudioSourceVoice_SubmitSourceBuffer(faudio_voice, pBuffer, pBufferWMA); - } - - COM_METHOD(HRESULT) FlushSourceBuffers() - { - return FAudioSourceVoice_FlushSourceBuffers(faudio_voice); - } - - COM_METHOD(HRESULT) Discontinuity() - { - return FAudioSourceVoice_Discontinuity(faudio_voice); - } - - COM_METHOD(HRESULT) ExitLoop(UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioSourceVoice_ExitLoop(faudio_voice, OperationSet); - } - -#if (XAUDIO2_VERSION <= 7) - COM_METHOD(void) GetState(XAUDIO2_VOICE_STATE *pVoiceState) -#else - COM_METHOD(void) GetState(XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags = 0) -#endif - { -#if (XAUDIO2_VERSION <= 7) - FAudioSourceVoice_GetState(faudio_voice, pVoiceState, 0); -#else - FAudioSourceVoice_GetState(faudio_voice, pVoiceState, Flags); -#endif - } - - COM_METHOD(HRESULT) SetFrequencyRatio(float Ratio, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioSourceVoice_SetFrequencyRatio(faudio_voice, Ratio, OperationSet); - } - - COM_METHOD(void) GetFrequencyRatio(float *pRatio) - { - FAudioSourceVoice_GetFrequencyRatio(faudio_voice, pRatio); - } - -#if XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetSourceSampleRate(UINT32 NewSourceSampleRate) - { - return FAudioSourceVoice_SetSourceSampleRate(faudio_voice, NewSourceSampleRate); - } -#endif // XAUDIO2_VERSION >= 4 - -private: - FAudioVoiceCppCallback *voice_callback; - FAudioVoiceSends *voice_sends; - FAudioEffectChain *effect_chain; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// IXAudio2SubmixVoice implementation -// - -class XAudio2SubmixVoiceImpl : public IXAudio2SubmixVoice -{ -public: - XAudio2SubmixVoiceImpl( - FAudio *faudio, - UINT32 InputChannels, - UINT32 InputSampleRate, - UINT32 Flags, - UINT32 ProcessingStage, - const XAUDIO2_VOICE_SENDS *pSendList, - const XAUDIO2_EFFECT_CHAIN *pEffectChain - ) { - voice_sends = unwrap_voice_sends(pSendList); - effect_chain = wrap_effect_chain(pEffectChain); - FAudio_CreateSubmixVoice( - faudio, - &faudio_voice, - InputChannels, - InputSampleRate, - Flags, - ProcessingStage, - voice_sends, - effect_chain); - } - - // IXAudio2Voice - COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails) - { -#if XAUDIO2_VERSION > 7 - FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails); -#else - FAudioVoiceDetails fDetails; - FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails); - pVoiceDetails->CreationFlags = fDetails.CreationFlags; - pVoiceDetails->InputChannels = fDetails.InputChannels; - pVoiceDetails->InputSampleRate = fDetails.InputSampleRate; -#endif // XAUDIO2_VERSION <= 7 - } - - COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList) - { - free_voice_sends(voice_sends); - voice_sends = unwrap_voice_sends(pSendList); - return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends); - } - - COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain) - { - free_effect_chain(effect_chain); - effect_chain = wrap_effect_chain(pEffectChain); - return FAudioVoice_SetEffectChain(faudio_voice, effect_chain); - } - - COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet); - } - - COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet); - } - - COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled) - { - FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled); - } - - COM_METHOD(HRESULT) SetEffectParameters( - UINT32 EffectIndex, - const void *pParameters, - UINT32 ParametersByteSize, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetEffectParameters( - faudio_voice, - EffectIndex, - pParameters, - ParametersByteSize, - OperationSet); - } - - COM_METHOD(HRESULT) GetEffectParameters( - UINT32 EffectIndex, - void *pParameters, - UINT32 ParametersByteSize - ) { - return FAudioVoice_GetEffectParameters( - faudio_voice, - EffectIndex, - pParameters, - ParametersByteSize); - } - - COM_METHOD(HRESULT) SetFilterParameters( - const XAUDIO2_FILTER_PARAMETERS *pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet); - } - - COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters) - { - FAudioVoice_GetFilterParameters(faudio_voice, pParameters); - } - -#if XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetOutputFilterParameters( - IXAudio2Voice *pDestinationVoice, - const XAUDIO2_FILTER_PARAMETERS *pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetOutputFilterParameters( - faudio_voice, - ((XAudio2SubmixVoiceImpl *)pDestinationVoice)->faudio_voice, - pParameters, - OperationSet); - } - - COM_METHOD(void) GetOutputFilterParameters( - IXAudio2Voice *pDestinationVoice, - XAUDIO2_FILTER_PARAMETERS *pParameters - ) { - FAudioVoice_GetOutputFilterParameters( - faudio_voice, ((XAudio2SubmixVoiceImpl *)pDestinationVoice)->faudio_voice, pParameters); - } -#endif // XAUDIO2_VERSION >= 4 - - COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet); - } - - COM_METHOD(void) GetVolume(float *pVolume) - { - FAudioVoice_GetVolume(faudio_voice, pVolume); - } - - COM_METHOD(HRESULT) SetChannelVolumes( - UINT32 Channels, - const float *pVolumes, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet); - } - - COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes) - { - FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes); - } - - COM_METHOD(HRESULT) SetOutputMatrix( - IXAudio2Voice *pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - const float *pLevelMatrix, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL; - return FAudioVoice_SetOutputMatrix( - faudio_voice, - dest, - SourceChannels, - DestinationChannels, - pLevelMatrix, - OperationSet); - } - -#if XAUDIO2_VERSION >= 1 - COM_METHOD(void) GetOutputMatrix( -#else - COM_METHOD(HRESULT) GetOutputMatrix( -#endif - IXAudio2Voice *pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - float *pLevelMatrix - ) { - FAudioVoice_GetOutputMatrix( - faudio_voice, - pDestinationVoice->faudio_voice, - SourceChannels, - DestinationChannels, - pLevelMatrix); -#if XAUDIO2_VERSION < 1 - return S_OK; -#endif // XAUDIO2_VERSION < 1 - } - - COM_METHOD(void) DestroyVoice() - { - FAudioVoice_DestroyVoice(faudio_voice); - // FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS - free_voice_sends(voice_sends); - free_effect_chain(effect_chain); - delete this; - } - -private: - FAudioVoiceSends *voice_sends; - FAudioEffectChain *effect_chain; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// IXAudio2MasteringVoice implementation -// - -#if (XAUDIO2_VERSION >= 8) -uint32_t device_index_from_device_id(FAudio *faudio, LPCWSTR deviceId); -#endif // (XAUDIO2_VERSION >= 8) - -class XAudio2MasteringVoiceImpl : public IXAudio2MasteringVoice -{ -public: -#if (XAUDIO2_VERSION <= 7) - XAudio2MasteringVoiceImpl( - FAudio *faudio, - UINT32 InputChannels, - UINT32 InputSampleRate, - UINT32 Flags, - UINT32 DeviceIndex, - const XAUDIO2_EFFECT_CHAIN *pEffectChain - ) { - voice_sends = NULL; - effect_chain = wrap_effect_chain(pEffectChain); - FAudio_CreateMasteringVoice( - faudio, - &faudio_voice, - InputChannels, - InputSampleRate, - Flags, - DeviceIndex, - effect_chain); - } -#else - XAudio2MasteringVoiceImpl( - FAudio *faudio, - UINT32 InputChannels, - UINT32 InputSampleRate, - UINT32 Flags, - LPCWSTR szDeviceId, - const XAUDIO2_EFFECT_CHAIN *pEffectChain, - int StreamCategory - ) { - uint32_t device_index = 0; - - if (szDeviceId != NULL) - { - device_index = device_index_from_device_id(faudio, szDeviceId); - } - - voice_sends = NULL; - effect_chain = wrap_effect_chain(pEffectChain); - FAudio_CreateMasteringVoice( - faudio, - &faudio_voice, - InputChannels, - InputSampleRate, - Flags, - device_index, - effect_chain); - } -#endif - - // IXAudio2Voice - COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails) - { -#if XAUDIO2_VERSION > 7 - FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails); -#else - FAudioVoiceDetails fDetails; - FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails); - pVoiceDetails->CreationFlags = fDetails.CreationFlags; - pVoiceDetails->InputChannels = fDetails.InputChannels; - pVoiceDetails->InputSampleRate = fDetails.InputSampleRate; -#endif // XAUDIO2_VERSION <= 7 - } - - COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList) - { - free_voice_sends(voice_sends); - voice_sends = unwrap_voice_sends(pSendList); - return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends); - } - - COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain) - { - free_effect_chain(effect_chain); - effect_chain = wrap_effect_chain(pEffectChain); - return FAudioVoice_SetEffectChain(faudio_voice, effect_chain); - } - - COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet); - } - - COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet); - } - - COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled) - { - FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled); - } - - COM_METHOD(HRESULT) SetEffectParameters( - UINT32 EffectIndex, - const void *pParameters, - UINT32 ParametersByteSize, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetEffectParameters( - faudio_voice, - EffectIndex, - pParameters, - ParametersByteSize, - OperationSet); - } - - COM_METHOD(HRESULT) GetEffectParameters( - UINT32 EffectIndex, - void *pParameters, - UINT32 ParametersByteSize - ) { - return FAudioVoice_GetEffectParameters( - faudio_voice, - EffectIndex, - pParameters, - ParametersByteSize); - } - - COM_METHOD(HRESULT) SetFilterParameters( - const XAUDIO2_FILTER_PARAMETERS *pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet); - } - - COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters) - { - FAudioVoice_GetFilterParameters(faudio_voice, pParameters); - } - -#if XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetOutputFilterParameters( - IXAudio2Voice *pDestinationVoice, - const XAUDIO2_FILTER_PARAMETERS *pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetOutputFilterParameters( - faudio_voice, - ((XAudio2MasteringVoiceImpl *)pDestinationVoice)->faudio_voice, - pParameters, - OperationSet); - } - - COM_METHOD(void) GetOutputFilterParameters( - IXAudio2Voice *pDestinationVoice, - XAUDIO2_FILTER_PARAMETERS *pParameters - ) { - FAudioVoice_GetOutputFilterParameters( - faudio_voice, - ((XAudio2MasteringVoiceImpl *)pDestinationVoice)->faudio_voice, - pParameters); - } -#endif // XAUDIO2_VERSION >= 4 - - COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW) - { - return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet); - } - - COM_METHOD(void) GetVolume(float *pVolume) - { - FAudioVoice_GetVolume(faudio_voice, pVolume); - } - - COM_METHOD(HRESULT) SetChannelVolumes( - UINT32 Channels, - const float *pVolumes, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet); - } - - COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes) - { - FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes); - } - - COM_METHOD(HRESULT) SetOutputMatrix( - IXAudio2Voice *pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - const float *pLevelMatrix, - UINT32 OperationSet = FAUDIO_COMMIT_NOW - ) { - FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL; - return FAudioVoice_SetOutputMatrix( - faudio_voice, - dest, - SourceChannels, - DestinationChannels, - pLevelMatrix, - OperationSet); - } - -#if XAUDIO2_VERSION >= 1 - COM_METHOD(void) GetOutputMatrix( -#else - COM_METHOD(HRESULT) GetOutputMatrix( -#endif - IXAudio2Voice *pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - float *pLevelMatrix - ) { - FAudioVoice_GetOutputMatrix( - faudio_voice, - pDestinationVoice->faudio_voice, - SourceChannels, - DestinationChannels, - pLevelMatrix); -#if XAUDIO2_VERSION < 1 - return S_OK; -#endif // XAUDIO2_VERSION < 1 - } - - COM_METHOD(void) DestroyVoice() - { - FAudioVoice_DestroyVoice(faudio_voice); - // FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS - free_voice_sends(voice_sends); - free_effect_chain(effect_chain); - delete this; - } - - // IXAudio2MasteringVoice -#if XAUDIO2_VERSION >= 8 - COM_METHOD(HRESULT) GetChannelMask(uint32_t *pChannelmask) - { - return FAudioMasteringVoice_GetChannelMask(faudio_voice, pChannelmask); - } -#endif - -private: - FAudioVoiceSends *voice_sends; - FAudioEffectChain *effect_chain; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// IXAudio2 implementation -// - -void* CDECL XAudio2_INTERNAL_Malloc(size_t size) -{ - return CoTaskMemAlloc(size); -} -void CDECL XAudio2_INTERNAL_Free(void* ptr) -{ - CoTaskMemFree(ptr); -} -void* CDECL XAudio2_INTERNAL_Realloc(void* ptr, size_t size) -{ - return CoTaskMemRealloc(ptr, size); -} - -class XAudio2Impl : public IXAudio2 -{ -public: - XAudio2Impl() - { - callback_list.com = NULL; - callback_list.next = NULL; - FAudioCOMConstructWithCustomAllocatorEXT( - &faudio, - XAUDIO2_VERSION, - XAudio2_INTERNAL_Malloc, - XAudio2_INTERNAL_Free, - XAudio2_INTERNAL_Realloc - ); - } - - XAudio2Impl(UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor) - { - callback_list.com = NULL; - callback_list.next = NULL; - FAudioCreateWithCustomAllocatorEXT( - &faudio, - Flags, - XAudio2Processor, - XAudio2_INTERNAL_Malloc, - XAudio2_INTERNAL_Free, - XAudio2_INTERNAL_Realloc - ); - } - - COM_METHOD(HRESULT) QueryInterface(REFIID riid, void **ppvInterface) - { - if (guid_equals(riid, IID_IXAudio2)) - { - *ppvInterface = static_cast(this); - } - else if (guid_equals(riid, IID_IUnknown)) - { - *ppvInterface = static_cast(this); - } - else - { - *ppvInterface = NULL; - return E_NOINTERFACE; - } - - reinterpret_cast(*ppvInterface)->AddRef(); - - return S_OK; - } - - COM_METHOD(ULONG) AddRef() - { - return FAudio_AddRef(faudio); - } - - COM_METHOD(ULONG) Release() - { - ULONG refcount = FAudio_Release(faudio); - if (refcount == 0) - { - delete this; - } - return 1; - } - -#if (XAUDIO2_VERSION <= 7) - COM_METHOD(HRESULT) GetDeviceCount(UINT32 *pCount) - { - return FAudio_GetDeviceCount(faudio, pCount); - } - - COM_METHOD(HRESULT) GetDeviceDetails(UINT32 Index, XAUDIO2_DEVICE_DETAILS *pDeviceDetails) - { - return FAudio_GetDeviceDetails(faudio, Index, pDeviceDetails); - } - - COM_METHOD(HRESULT) Initialize( - UINT32 Flags = 0, - XAUDIO2_PROCESSOR XAudio2Processor = FAUDIO_DEFAULT_PROCESSOR - ) { - return FAudio_Initialize(faudio, Flags, XAudio2Processor); - } -#endif // XAUDIO2_VERSION <= 7 - - COM_METHOD(HRESULT) RegisterForCallbacks(IXAudio2EngineCallback *pCallback) - { - FAudioCppEngineCallback *cb = wrap_engine_callback(pCallback); - cb->next = callback_list.next; - callback_list.next = cb; - - return FAudio_RegisterForCallbacks(faudio, reinterpret_cast(cb)); - } - - COM_METHOD(void) UnregisterForCallbacks(IXAudio2EngineCallback *pCallback) - { - FAudioCppEngineCallback *cb = find_and_remove_engine_callback(&callback_list, pCallback); - - if (cb == NULL) - { - return; - } - - FAudio_UnregisterForCallbacks(faudio, reinterpret_cast(cb)); - delete cb; - } - - COM_METHOD(HRESULT) CreateSourceVoice( - IXAudio2SourceVoice **ppSourceVoice, - const WAVEFORMATEX *pSourceFormat, - UINT32 Flags = 0, - float MaxFrequencyRatio = FAUDIO_DEFAULT_FREQ_RATIO, - IXAudio2VoiceCallback *pCallback = NULL, - const XAUDIO2_VOICE_SENDS *pSendList = NULL, - const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL - ) { - *ppSourceVoice = new XAudio2SourceVoiceImpl( - faudio, pSourceFormat, Flags, MaxFrequencyRatio, pCallback, pSendList, pEffectChain); - return S_OK; - } - - COM_METHOD(HRESULT) CreateSubmixVoice( - IXAudio2SubmixVoice **ppSubmixVoice, - UINT32 InputChannels, - UINT32 InputSampleRate, - UINT32 Flags = 0, - UINT32 ProcessingStage = 0, - const XAUDIO2_VOICE_SENDS *pSendList = NULL, - const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL - ) { - *ppSubmixVoice = new XAudio2SubmixVoiceImpl( - faudio, - InputChannels, - InputSampleRate, - Flags, - ProcessingStage, - pSendList, - pEffectChain); - return S_OK; - } - -#if (XAUDIO2_VERSION <= 7) - COM_METHOD(HRESULT) CreateMasteringVoice( - IXAudio2MasteringVoice **ppMasteringVoice, - UINT32 InputChannels = FAUDIO_DEFAULT_CHANNELS, - UINT32 InputSampleRate = FAUDIO_DEFAULT_SAMPLERATE, - UINT32 Flags = 0, - UINT32 DeviceIndex = 0, - const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL - ) { - *ppMasteringVoice = new XAudio2MasteringVoiceImpl( - faudio, InputChannels, InputSampleRate, Flags, DeviceIndex, pEffectChain); - return S_OK; - } -#else - COM_METHOD(HRESULT) CreateMasteringVoice( - IXAudio2MasteringVoice **ppMasteringVoice, - UINT32 InputChannels = FAUDIO_DEFAULT_CHANNELS, - UINT32 InputSampleRate = FAUDIO_DEFAULT_SAMPLERATE, - UINT32 Flags = 0, - LPCWSTR szDeviceId = NULL, - const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL, - int StreamCategory = 6 - ) { - *ppMasteringVoice = new XAudio2MasteringVoiceImpl( - faudio, - InputChannels, - InputSampleRate, - Flags, - szDeviceId, - pEffectChain, - StreamCategory); - return S_OK; - } -#endif - - COM_METHOD(HRESULT) StartEngine() - { - return FAudio_StartEngine(faudio); - } - - COM_METHOD(void) StopEngine() - { - FAudio_StopEngine(faudio); - } - - COM_METHOD(HRESULT) CommitChanges(UINT32 OperationSet) - { - return FAudio_CommitOperationSet(faudio, OperationSet); - } - - COM_METHOD(void) GetPerformanceData(XAUDIO2_PERFORMANCE_DATA *pPerfData) - { -#if XAUDIO2_VERSION >= 3 - FAudio_GetPerformanceData(faudio, pPerfData); -#else - FAudioPerformanceData fPerfData; - FAudio_GetPerformanceData(faudio, &fPerfData); - - pPerfData->AudioCyclesSinceLastQuery = fPerfData.AudioCyclesSinceLastQuery; - pPerfData->TotalCyclesSinceLastQuery = fPerfData.TotalCyclesSinceLastQuery; - pPerfData->MinimumCyclesPerQuantum = fPerfData.MinimumCyclesPerQuantum; - pPerfData->MaximumCyclesPerQuantum = fPerfData.MaximumCyclesPerQuantum; - pPerfData->MemoryUsageInBytes = fPerfData.MemoryUsageInBytes; - pPerfData->CurrentLatencyInSamples = fPerfData.CurrentLatencyInSamples; - pPerfData->GlitchesSinceEngineStarted = fPerfData.GlitchesSinceEngineStarted; - pPerfData->ActiveSourceVoiceCount = fPerfData.ActiveSourceVoiceCount; - pPerfData->TotalSourceVoiceCount = fPerfData.TotalSourceVoiceCount; - pPerfData->ActiveSubmixVoiceCount = fPerfData.ActiveSubmixVoiceCount; - pPerfData->TotalSubmixVoiceCount = fPerfData.ActiveSubmixVoiceCount; - pPerfData->ActiveXmaSourceVoices = fPerfData.ActiveXmaSourceVoices; - pPerfData->ActiveXmaStreams = fPerfData.ActiveXmaStreams; -#endif // XAUDIO2_VERSION >= 3 - } - - COM_METHOD(void) - SetDebugConfiguration( - XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration, - void *pReserved = NULL - ) { - FAudio_SetDebugConfiguration( - faudio, - pDebugConfiguration, - pReserved); - } - -private: - FAudio *faudio; - FAudioCppEngineCallback callback_list; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -// Create function -// - -void *CreateXAudio2Internal() -{ - return new XAudio2Impl(); -} - -#if XAUDIO2_VERSION >= 8 - -extern "C" FAUDIOCPP_API XAudio2Create(IXAudio2 **ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor) -{ - // FAudio only accepts one processor - *ppXAudio2 = new XAudio2Impl(Flags, FAUDIO_DEFAULT_PROCESSOR); - return S_OK; -} - -#endif // XAUDIO2_VERSION >= 8 diff --git a/cpp/xaudio2.h b/cpp/xaudio2.h deleted file mode 100644 index b667559c24..0000000000 --- a/cpp/xaudio2.h +++ /dev/null @@ -1,301 +0,0 @@ -#ifndef FACT_CPP_XAUDIO2_H -#define FACT_CPP_XAUDIO2_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef FAUDIOCPP_EXPORTS -#define FAUDIOCPP_API HRESULT __stdcall -#else -#define FAUDIOCPP_API __declspec(dllimport) HRESULT __stdcall -#endif - -#ifndef XAUDIO2_VERSION -#define XAUDIO2_VERSION 7 -#endif - -#include "com_utils.h" - -typedef FAudioProcessor XAUDIO2_PROCESSOR; -typedef FAudioDeviceDetails XAUDIO2_DEVICE_DETAILS; -typedef FAudioWaveFormatEx WAVEFORMATEX; -typedef FAudioWaveFormatExtensible WAVEFORMATEXTENSIBLE; -typedef FAudioDebugConfiguration XAUDIO2_DEBUG_CONFIGURATION; -typedef FAudioFilterParameters XAUDIO2_FILTER_PARAMETERS; -typedef FAudioBuffer XAUDIO2_BUFFER; -typedef FAudioBufferWMA XAUDIO2_BUFFER_WMA; -typedef FAudioVoiceState XAUDIO2_VOICE_STATE; - -class IXAudio2EngineCallback; -class IXAudio2Voice; -class IXAudio2SourceVoice; -class IXAudio2SubmixVoice; -class IXAudio2MasteringVoice; -class IXAudio2VoiceCallback; - -#pragma pack(push, 1) - -#if XAUDIO2_VERSION >= 4 -typedef struct XAUDIO2_SEND_DESCRIPTOR { - UINT32 Flags; - IXAudio2Voice *pOutputVoice; -} XAUDIO2_SEND_DESCRIPTOR; - -typedef struct XAUDIO2_VOICE_SENDS { - UINT32 SendCount; - XAUDIO2_SEND_DESCRIPTOR *pSends; -} XAUDIO2_VOICE_SENDS; -#else -typedef struct XAUDIO2_VOICE_SENDS { - UINT32 SendCount; - IXAudio2Voice **pSends; -} XAUDIO2_VOICE_SENDS; -#endif - -typedef struct XAUDIO2_EFFECT_DESCRIPTOR { - IUnknown *pEffect; - BOOL InitialState; - UINT32 OutputChannels; -} XAUDIO2_EFFECT_DESCRIPTOR; - -typedef struct XAUDIO2_EFFECT_CHAIN { - UINT32 EffectCount; - XAUDIO2_EFFECT_DESCRIPTOR *pEffectDescriptors; -} XAUDIO2_EFFECT_CHAIN; - -#if XAUDIO2_VERSION >= 3 -typedef FAudioPerformanceData XAUDIO2_PERFORMANCE_DATA; -#else -typedef struct XAUDIO2_PERFORMANCE_DATA -{ - uint64_t AudioCyclesSinceLastQuery; - uint64_t TotalCyclesSinceLastQuery; - uint32_t MinimumCyclesPerQuantum; - uint32_t MaximumCyclesPerQuantum; - uint32_t MemoryUsageInBytes; - uint32_t CurrentLatencyInSamples; - uint32_t GlitchesSinceEngineStarted; - uint32_t ActiveSourceVoiceCount; - uint32_t TotalSourceVoiceCount; - uint32_t ActiveSubmixVoiceCount; - uint32_t TotalSubmixVoiceCount; - uint32_t ActiveXmaSourceVoices; - uint32_t ActiveXmaStreams; -} XAUDIO2_PERFORMANCE_DATA; -#endif// XAUDIO2_VERSION >= 3 - -#if XAUDIO2_VERSION > 7 -typedef FAudioVoiceDetails XAUDIO2_VOICE_DETAILS; -#else -typedef struct XAUDIO2_VOICE_DETAILS { - uint32_t CreationFlags; - uint32_t InputChannels; - uint32_t InputSampleRate; -} XAUDIO2_VOICE_DETAILS; -#endif // XAUDIO2_VERSION > 7 - -#pragma pack(pop) - -class IXAudio2Voice { -public: - COM_METHOD(void) GetVoiceDetails (XAUDIO2_VOICE_DETAILS* pVoiceDetails) = 0; - COM_METHOD(HRESULT) SetOutputVoices (const XAUDIO2_VOICE_SENDS* pSendList) = 0; - COM_METHOD(HRESULT) SetEffectChain (const XAUDIO2_EFFECT_CHAIN* pEffectChain) = 0; - COM_METHOD(HRESULT) EnableEffect ( - UINT32 EffectIndex, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(HRESULT) DisableEffect ( - UINT32 EffectIndex, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(void) GetEffectState (UINT32 EffectIndex, BOOL* pEnabled) = 0; - COM_METHOD(HRESULT) SetEffectParameters ( - UINT32 EffectIndex, - const void* pParameters, - UINT32 ParametersByteSize, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(HRESULT) GetEffectParameters ( - UINT32 EffectIndex, - void* pParameters, - UINT32 ParametersByteSize) = 0; - COM_METHOD(HRESULT) SetFilterParameters ( - const XAUDIO2_FILTER_PARAMETERS* pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(void) GetFilterParameters (XAUDIO2_FILTER_PARAMETERS* pParameters) = 0; -#if XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetOutputFilterParameters ( - IXAudio2Voice* pDestinationVoice, - const XAUDIO2_FILTER_PARAMETERS* pParameters, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(void) GetOutputFilterParameters ( - IXAudio2Voice* pDestinationVoice, - XAUDIO2_FILTER_PARAMETERS* pParameters) = 0; -#endif // XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetVolume ( - float Volume, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(void) GetVolume (float* pVolume) = 0; - COM_METHOD(HRESULT) SetChannelVolumes ( - UINT32 Channels, - const float* pVolumes, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(void) GetChannelVolumes (UINT32 Channels, float* pVolumes) = 0; - COM_METHOD(HRESULT) SetOutputMatrix ( - IXAudio2Voice* pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - const float* pLevelMatrix, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; -#if XAUDIO2_VERSION >= 1 - COM_METHOD(void) GetOutputMatrix ( -#else - COM_METHOD(HRESULT) GetOutputMatrix ( -#endif // XAUDIO2_VERSION >= 1 - IXAudio2Voice* pDestinationVoice, - UINT32 SourceChannels, - UINT32 DestinationChannels, - float* pLevelMatrix) = 0; - COM_METHOD(void) DestroyVoice() = 0; - -public: - // not the ideal solution but the cleanest way I known to get to the common FAudioVoice object - // from a IXAudioVoice pointer to any derived class (without changing the vtable) - FAudioVoice *faudio_voice; -}; - -class IXAudio2SourceVoice : public IXAudio2Voice { -public: - COM_METHOD(HRESULT) Start (UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(HRESULT) Stop (UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(HRESULT) SubmitSourceBuffer ( - const XAUDIO2_BUFFER* pBuffer, - const XAUDIO2_BUFFER_WMA* pBufferWMA = NULL) = 0; - COM_METHOD(HRESULT) FlushSourceBuffers () = 0; - COM_METHOD(HRESULT) Discontinuity () = 0; - COM_METHOD(HRESULT) ExitLoop (UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; -#if (XAUDIO2_VERSION <= 7) - COM_METHOD(void) GetState ( XAUDIO2_VOICE_STATE* pVoiceState) = 0; -#else - COM_METHOD(void) GetState ( XAUDIO2_VOICE_STATE* pVoiceState, UINT32 Flags = 0) = 0; -#endif - COM_METHOD(HRESULT) SetFrequencyRatio ( - float Ratio, - UINT32 OperationSet = FAUDIO_COMMIT_NOW) = 0; - COM_METHOD(void) GetFrequencyRatio (float* pRatio) = 0; -#if XAUDIO2_VERSION >= 4 - COM_METHOD(HRESULT) SetSourceSampleRate (UINT32 NewSourceSampleRate) = 0; -#endif // XAUDIO2_VERSION >= 4 -}; - -class IXAudio2SubmixVoice : public IXAudio2Voice { - -}; - -class IXAudio2MasteringVoice : public IXAudio2Voice { -public: -#if (XAUDIO2_VERSION >= 8) - COM_METHOD(HRESULT) GetChannelMask (uint32_t *pChannelmask) = 0; -#endif -}; - -class IXAudio2VoiceCallback { -public: -#if XAUDIO2_VERSION >= 1 - COM_METHOD(void) OnVoiceProcessingPassStart (UINT32 BytesRequired) = 0; -#else - COM_METHOD(void) OnVoiceProcessingPassStart () = 0; -#endif // XAUDIO2_VERSION >= 1 - COM_METHOD(void) OnVoiceProcessingPassEnd () = 0; - COM_METHOD(void) OnStreamEnd () = 0; - COM_METHOD(void) OnBufferStart (void* pBufferContext) = 0; - COM_METHOD(void) OnBufferEnd (void* pBufferContext) = 0; - COM_METHOD(void) OnLoopEnd (void* pBufferContext) = 0; - COM_METHOD(void) OnVoiceError (void* pBufferContext, HRESULT Error) = 0; -}; - -class IXAudio2EngineCallback { -public: - COM_METHOD(void) OnProcessingPassStart () = 0; - COM_METHOD(void) OnProcessingPassEnd () = 0; - COM_METHOD(void) OnCriticalError (HRESULT Error) = 0; -}; - -class IXAudio2 : public IUnknown { -public: -#if (XAUDIO2_VERSION <= 7) - COM_METHOD(HRESULT) GetDeviceCount(UINT32 *pCount) = 0; - COM_METHOD(HRESULT) GetDeviceDetails (UINT32 Index, XAUDIO2_DEVICE_DETAILS* pDeviceDetails) = 0; - COM_METHOD(HRESULT) Initialize ( - UINT32 Flags = 0, - XAUDIO2_PROCESSOR XAudio2Processor = FAUDIO_DEFAULT_PROCESSOR) = 0; -#endif // XAUDIO2_VERSION <= 7 - - COM_METHOD(HRESULT) RegisterForCallbacks (IXAudio2EngineCallback* pCallback) = 0; - COM_METHOD(void) UnregisterForCallbacks ( IXAudio2EngineCallback* pCallback) = 0; - - COM_METHOD(HRESULT) CreateSourceVoice ( - IXAudio2SourceVoice** ppSourceVoice, - const WAVEFORMATEX* pSourceFormat, - UINT32 Flags = 0, - float MaxFrequencyRatio = FAUDIO_DEFAULT_FREQ_RATIO, - IXAudio2VoiceCallback* pCallback = NULL, - const XAUDIO2_VOICE_SENDS* pSendList = NULL, - const XAUDIO2_EFFECT_CHAIN* pEffectChain = NULL) = 0; - - COM_METHOD(HRESULT) CreateSubmixVoice( - IXAudio2SubmixVoice** ppSubmixVoice, - UINT32 InputChannels, - UINT32 InputSampleRate, - UINT32 Flags = 0, - UINT32 ProcessingStage = 0, - const XAUDIO2_VOICE_SENDS* pSendList = NULL, - const XAUDIO2_EFFECT_CHAIN* pEffectChain = NULL) = 0; - -#if XAUDIO2_VERSION <= 7 - COM_METHOD(HRESULT) CreateMasteringVoice( - IXAudio2MasteringVoice** ppMasteringVoice, - UINT32 InputChannels = FAUDIO_DEFAULT_CHANNELS, - UINT32 InputSampleRate = FAUDIO_DEFAULT_SAMPLERATE, - UINT32 Flags = 0, - UINT32 DeviceIndex = 0, - const XAUDIO2_EFFECT_CHAIN* pEffectChain = NULL) = 0; -#else - COM_METHOD(HRESULT) CreateMasteringVoice ( - IXAudio2MasteringVoice** ppMasteringVoice, - UINT32 InputChannels = FAUDIO_DEFAULT_CHANNELS, - UINT32 InputSampleRate = FAUDIO_DEFAULT_SAMPLERATE, - UINT32 Flags = 0, - LPCWSTR szDeviceId = NULL, - const XAUDIO2_EFFECT_CHAIN* pEffectChain = NULL, - int StreamCategory = 6) = 0; // FIXME: type was AUDIO_STREAM_CATEGORY (scoped enum so int for now) -#endif // XAUDIO2_VERSION <= 7 - - COM_METHOD(HRESULT) StartEngine() = 0; - COM_METHOD(void) StopEngine() = 0; - - COM_METHOD(HRESULT) CommitChanges(UINT32 OperationSet) = 0; - - COM_METHOD(void) GetPerformanceData(XAUDIO2_PERFORMANCE_DATA* pPerfData) = 0; - - COM_METHOD(void) SetDebugConfiguration( - XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration, - void* pReserved = NULL) = 0; -}; - -#if XAUDIO2_VERSION >= 8 - -FAUDIOCPP_API XAudio2Create( - IXAudio2 **ppXAudio2, - UINT32 Flags, - XAUDIO2_PROCESSOR XAudio2Processor -); - -#endif // XAUDIO2_VERSION >= 8 - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif // FACT_CPP_XAUDIO2_H diff --git a/cpp/xaudio2_7.def b/cpp/xaudio2_7.def deleted file mode 100644 index b0a6be2e50..0000000000 --- a/cpp/xaudio2_7.def +++ /dev/null @@ -1,6 +0,0 @@ -EXPORTS - DllCanUnloadNow PRIVATE - DllGetClassObject PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE - \ No newline at end of file diff --git a/cpp/xaudio2_9.def b/cpp/xaudio2_9.def deleted file mode 100644 index befe89bc85..0000000000 --- a/cpp/xaudio2_9.def +++ /dev/null @@ -1,7 +0,0 @@ -EXPORTS - XAudio2Create @1 - CreateAudioReverb @2 - CreateAudioVolumeMeter @3 - CreateFX @4 - X3DAudioCalculate @5 - X3DAudioInitialize @6 diff --git a/csharp/FAudio.cs b/csharp/FAudio.cs index c6e8c29e99..cea9e43333 100644 --- a/csharp/FAudio.cs +++ b/csharp/FAudio.cs @@ -1,6 +1,6 @@ /* FAudio# - C# Wrapper for FAudio * - * Copyright (c) 2018-2021 Ethan Lee. + * Copyright (c) 2018-2024 Ethan Lee. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -68,7 +68,7 @@ private static int Utf8Size(string str) } return buffer; } - + #endregion #region FAudio API @@ -78,9 +78,9 @@ private static int Utf8Size(string str) public const uint FAUDIO_TARGET_VERSION = 8; public const uint FAUDIO_ABI_VERSION = 0; - public const uint FAUDIO_MAJOR_VERSION = 21; - public const uint FAUDIO_MINOR_VERSION = 3; - public const uint FAUDIO_PATCH_VERSION = 5; + public const uint FAUDIO_MAJOR_VERSION = 25; + public const uint FAUDIO_MINOR_VERSION = 2; + public const uint FAUDIO_PATCH_VERSION = 0; public const uint FAUDIO_COMPILED_VERSION = ( (FAUDIO_ABI_VERSION * 100 * 100 * 100) + @@ -176,6 +176,22 @@ public struct FAudioADPCMWaveFormat */ } + public struct FAudioXMA2WaveFormatEx + { + public FAudioWaveFormatEx wfx; + public ushort wNumStreams; + public uint dwChannelMask; + public uint dwSamplesEncoded; + public uint dwBytesPerBlock; + public uint dwPlayBegin; + public uint dwPlayLength; + public uint dwLoopBegin; + public uint dwLoopLength; + public byte bLoopCount; + public byte bEncoderVersion; + public ushort wBlockCount; + }; + [StructLayout(LayoutKind.Sequential, Pack = 1)] public unsafe struct FAudioDeviceDetails { @@ -405,6 +421,18 @@ public static extern uint FAudio_CreateSourceVoice( IntPtr pEffectChain /* FAudioEffectChain* */ ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint FAudio_CreateSourceVoice( + IntPtr audio, /* FAudio* */ + out IntPtr ppSourceVoice, /* FAudioSourceVoice** */ + IntPtr pSourceFormat, /* FAudioWaveFormatEx* */ + uint Flags, + float MaxFrequencyRatio, + IntPtr pCallback, /* FAudioVoiceCallback* */ + IntPtr pSendList, /* FAudioVoiceSends* */ + IntPtr pEffectChain /* FAudioEffectChain* */ + ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern uint FAudio_CreateSubmixVoice( IntPtr audio, /* FAudio* */ @@ -602,6 +630,11 @@ public static extern void FAudioVoice_DestroyVoice( IntPtr voice /* FAudioVoice* */ ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint FAudioVoice_DestroyVoiceSafeEXT( + IntPtr voice /* FAudioVoice* */ + ); + /* FAudioSourceVoice Interface */ [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] @@ -625,6 +658,13 @@ public static extern uint FAudioSourceVoice_SubmitSourceBuffer( IntPtr pBufferWMA /* const FAudioBufferWMA* */ ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint FAudioSourceVoice_SubmitSourceBuffer( + IntPtr voice, /* FAudioSourceVoice* */ + ref FAudioBuffer pBuffer, + ref FAudioBufferWMA pBufferWMA + ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern uint FAudioSourceVoice_FlushSourceBuffers( IntPtr voice /* FAudioSourceVoice* */ @@ -848,7 +888,152 @@ public struct FAudioFXReverbParameters9 #region FAPO API + public const int FAPO_MIN_CHANNELS = 1, + FAPO_MAX_CHANNELS = 64, + FAPO_MIN_FRAMERATE = 1000, + FAPO_MAX_FRAMERATE = 200000, + FAPO_REGISTRATION_STRING_LENGTH = 256; + + public enum FAPOBufferFlags { + FAPO_BUFFER_SILENT, + FAPO_BUFFER_VALID + } + + [Flags] + public enum FAPOMiscFlags : uint { + FAPO_FLAG_CHANNELS_MUST_MATCH = 0x00000001, + FAPO_FLAG_FRAMERATE_MUST_MATCH = 0x00000002, + FAPO_FLAG_BITSPERSAMPLE_MUST_MATCH = 0x00000004, + FAPO_FLAG_BUFFERCOUNT_MUST_MATCH = 0x00000008, + FAPO_FLAG_INPLACE_SUPPORTED = 0x00000010, + FAPO_FLAG_INPLACE_REQUIRED = 0x00000020, + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int AddRefFunc(IntPtr fapo); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate int ReleaseFunc(IntPtr fapo); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint GetRegistrationPropertiesFunc( + IntPtr fapo, + IntPtr ppRegistrationProperties + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint IsInputFormatSupportedFunc( + IntPtr fapo, + IntPtr pOutputFormat, + IntPtr pRequestedInputFormat, + IntPtr ppSupportedInputFormat + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint IsOutputFormatSupportedFunc( + IntPtr fapo, + IntPtr pInputFormat, + IntPtr pRequestedOutputFormat, + IntPtr ppSupportedOutputFormat + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint InitializeFunc( + IntPtr fapo, + IntPtr pData, + uint DataByteSize + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ResetFunc( + IntPtr fapo + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint LockForProcessFunc ( + IntPtr fapo, + uint InputLockedParameterCount, + ref FAPOLockForProcessBufferParameters pInputLockedParameters, + uint OutputLockedParameterCount, + ref FAPOLockForProcessBufferParameters pOutputLockedParameters + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void UnlockForProcessFunc ( + IntPtr fapo + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void ProcessFunc ( + IntPtr fapo, + uint InputProcessParameterCount, + ref FAPOProcessBufferParameters pInputProcessParameters, + uint OutputProcessParameterCount, + ref FAPOProcessBufferParameters pOutputProcessParameters, + int IsEnabled + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint CalcInputFramesFunc ( + IntPtr fapo, + uint OutputFrameCount + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate uint CalcOutputFramesFunc ( + IntPtr fapo, + uint InputFrameCount + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void SetParametersFunc ( + IntPtr fapo, + IntPtr pParameters, + uint ParameterByteSize + ); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void GetParametersFunc ( + IntPtr fapo, + IntPtr pParameters, + uint ParameterByteSize + ); + /* TODO */ + [StructLayout(LayoutKind.Sequential)] + public struct FAPO { + public IntPtr AddRef; + public IntPtr Release; + public IntPtr GetRegistrationProperties; + public IntPtr IsInputFormatSupported; + public IntPtr IsOutputFormatSupported; + public IntPtr Initialize; + public IntPtr Reset; + public IntPtr LockForProcess; + public IntPtr UnlockForProcess; + public IntPtr Process; + public IntPtr CalcInputFrames; + public IntPtr CalcOutputFrames; + public IntPtr SetParameters; + public IntPtr GetParameters; + } + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct FAPORegistrationProperties + { + public Guid clsid; + public fixed char FriendlyName[FAPO_REGISTRATION_STRING_LENGTH]; /* Win32 wchar_t */ + public fixed char CopyrightInfo[FAPO_REGISTRATION_STRING_LENGTH]; /* Win32 wchar_t */ + public uint MajorVersion; + public uint MinorVersion; + public uint Flags; + public uint MinInputBufferCount; + public uint MaxInputBufferCount; + public uint MinOutputBufferCount; + public uint MaxOutputBufferCount; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct FAPOLockForProcessBufferParameters + { + public IntPtr pFormat; + uint MaxFrameCount; + } + + [StructLayout(LayoutKind.Sequential)] + public struct FAPOProcessBufferParameters + { + public IntPtr pBuffer; + public FAPOBufferFlags BufferFlags; + public uint ValidFrameCount; + } #endregion @@ -856,6 +1041,58 @@ public struct FAudioFXReverbParameters9 /* TODO */ + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct FAPOBase { + public FAPO FAPO; + public IntPtr Destructor; + public IntPtr OnSetParameters; + + IntPtr m_pRegistrationProperties; + IntPtr m_pfnMatrixMixFunction; + IntPtr m_pfl32MatrixCoefficients; + uint m_nSrcFormatType; + byte m_fIsScalarMatrix; + byte m_fIsLocked; + IntPtr m_pParameterBlocks; + IntPtr m_pCurrentParameters; + IntPtr m_pCurrentParametersInternal; + uint m_uCurrentParametersIndex; + uint m_uParameterBlockByteSize; + byte m_fNewerResultsReady; + byte m_fProducer; + + /* Protected Variables */ + int m_lReferenceCount; /* LONG */ + + /* Allocator callbacks, NOT part of XAPOBase spec! */ + IntPtr pMalloc; + IntPtr pFree; + IntPtr pRealloc; + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint CreateFAPOBase( + IntPtr fapo, + // The create operation does not copy this into its own persistent storage! This pointer must remain valid. + IntPtr pRegistrationProperties, + IntPtr pParameterBlocks, + uint parameterBlockByteSize, + byte fProducer + ); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern uint CreateFAPOBaseWithCustomAllocatorEXT( + IntPtr fapo, + // The create operation does not copy this into its own persistent storage! This pointer must remain valid. + IntPtr pRegistrationProperties, + IntPtr pParameterBlocks, + uint parameterBlockByteSize, + byte fProducer, + IntPtr customMalloc, + IntPtr customFree, + IntPtr customRealloc + ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern uint FAPOBase_Release(IntPtr fapo); @@ -1912,7 +2149,7 @@ public struct F3DAUDIO_DISTANCE_CURVE_POINT [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct F3DAUDIO_DISTANCE_CURVE { - IntPtr pPoints; /* F3DAUDIO_DISTANCE_CURVE_POINT* */ + public IntPtr pPoints; /* F3DAUDIO_DISTANCE_CURVE_POINT* */ public uint PointCount; } @@ -2333,6 +2570,14 @@ public static extern int stb_vorbis_get_samples_float_interleaved( int num_floats ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public static extern int stb_vorbis_get_samples_float_interleaved( + IntPtr f, + int channels, + IntPtr buffer, + int num_floats + ); + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern int stb_vorbis_get_samples_float( IntPtr f, @@ -2342,4 +2587,43 @@ int num_samples ); #endregion + + #region qoa + + /* Because, again, why not? */ + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public extern static IntPtr qoa_open_from_memory(IntPtr bytes, uint size, int free_on_close); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + private static extern unsafe IntPtr qoa_open_from_filename( + byte* filename + ); + + public static unsafe IntPtr qoa_open_from_filename( + string filename + ) { + int utf8BufSize = Utf8Size(filename); + byte* utf8Buf = stackalloc byte[utf8BufSize]; + return qoa_open_from_filename( + Utf8Encode(filename, utf8Buf, utf8BufSize) + ); + } + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public extern static unsafe void qoa_attributes(IntPtr qoa, out uint channels, out uint samplerate, out uint samples_per_channel_per_frame, out uint total_samples_per_channel); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public extern static unsafe uint qoa_decode_next_frame(IntPtr qoa, short *sample_data); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public extern static unsafe void qoa_seek_frame(IntPtr qoa, int frame_index); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public extern static unsafe void qoa_decode_entire(IntPtr qoa, short *sample_data); + + [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] + public extern static unsafe void qoa_close(IntPtr qoa); + + #endregion } diff --git a/csharp/LICENSE b/csharp/LICENSE index 81b42ce8af..effb3ef881 100644 --- a/csharp/LICENSE +++ b/csharp/LICENSE @@ -1,6 +1,6 @@ /* FAudio# - C# Wrapper for FAudio * - * Copyright (c) 2018-2021 Ethan Lee. + * Copyright (c) 2018-2024 Ethan Lee. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/extensions/DestroyVoiceSafeEXT.txt b/extensions/DestroyVoiceSafeEXT.txt new file mode 100644 index 0000000000..13983c1b0e --- /dev/null +++ b/extensions/DestroyVoiceSafeEXT.txt @@ -0,0 +1,22 @@ +DestroyVoiceSafeEXT - Expose whether or not a voice was actually destroyed + +About +----- +XAudio's function for exporting voices has the ability to fail - however, the +function declaration does not have a return value, so there is no way to safely +determine on the client side whether or not a voice was actually destroyed. +This extension adds a function that is otherwise identical, but includes a +result code to allow checking for failures. + +Dependencies +------------ +This extension does not interact with any non-standard XAudio features. + +New Procedures and Functions +---------------------------- +FAUDIOAPI uint32_t FAudioVoice_DestroyVoiceSafeEXT(FAudioVoice *voice); + +How to Use +---------- +This extension acts identially to the existing DestroyVoice, but with and added +return value - it will return 0 on success or non-0 on failure. diff --git a/extensions/FilterWetDryMixEXT.txt b/extensions/FilterWetDryMixEXT.txt new file mode 100644 index 0000000000..00dbdd1576 --- /dev/null +++ b/extensions/FilterWetDryMixEXT.txt @@ -0,0 +1,67 @@ +FilterWetDryMixEXT - Allow voice/send filters to apply a wet/dry mix + +About +----- +The default XAudio specification allows for applying filters and effects. While +effects have the capability of applying wet/dry mixes to their processing, +filters do not have this feature. Filters are, for the most part, just another +effect that's very clearly defined, so adding a wet/dry calculation to the +existing filter algorithm is trivial. + +Dependencies +------------ +This extension does not interact with any non-standard XAudio features. + +New Defines +----------- +#define FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT 1.0f + +New Types +--------- +typedef struct FAudioFilterParametersEXT +{ + FAudioFilterType Type; + float Frequency; /* [0, FAUDIO_MAX_FILTER_FREQUENCY] */ + float OneOverQ; /* [0, FAUDIO_MAX_FILTER_ONEOVERQ] */ + float WetDryMix; /* [0, 1] */ +} FAudioFilterParametersEXT; + +New Procedures and Functions +---------------------------- +FAUDIOAPI uint32_t FAudioVoice_SetFilterParametersEXT( + FAudioVoice* voice, + const FAudioFilterParametersEXT* pParameters, + uint32_t OperationSet +); + +FAUDIOAPI void FAudioVoice_GetFilterParametersEXT( + FAudioVoice* voice, + FAudioFilterParametersEXT* pParameters +); + +FAUDIOAPI uint32_t FAudioVoice_SetOutputFilterParametersEXT( + FAudioVoice* voice, + FAudioVoice* pDestinationVoice, + const FAudioFilterParametersEXT* pParameters, + uint32_t OperationSet +); + +FAUDIOAPI void FAudioVoice_GetOutputFilterParametersEXT( + FAudioVoice* voice, + FAudioVoice* pDestinationVoice, + FAudioFilterParametersEXT* pParameters +); + +How to Use +---------- +This extension acts identially to the existing FAudioFilterParameters, but with +an added WetDryMix structure member - set this value to apply a wet/dry mix. + +FAQ +--- +Q: Does the behavior of the stock filter functions change? +A: No. Calls to the original functions will apply a WetDryMix value of 1, so as + to sound as the function would have originally intended. This is subject to + change in future revisions; in the current implementation, preserving the + current wet/dry value would have required additional mutex activity, which + could degrade performance for users of the stock API. diff --git a/include/F3DAudio.h b/include/F3DAudio.h index 5fbb618243..cca0432c75 100644 --- a/include/F3DAudio.h +++ b/include/F3DAudio.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/include/FACT.h b/include/FACT.h index 579b716881..7134f5ccc1 100644 --- a/include/FACT.h +++ b/include/FACT.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/include/FACT3D.h b/include/FACT3D.h index 6ac02a8298..b40224179c 100644 --- a/include/FACT3D.h +++ b/include/FACT3D.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/include/FAPO.h b/include/FAPO.h index 0609770047..5b8442bc6f 100644 --- a/include/FAPO.h +++ b/include/FAPO.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/include/FAPOBase.h b/include/FAPOBase.h index c2fcdd2981..a9351cd3c9 100644 --- a/include/FAPOBase.h +++ b/include/FAPOBase.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/include/FAPOFX.h b/include/FAPOFX.h index 5aae441b2c..3600886e55 100644 --- a/include/FAPOFX.h +++ b/include/FAPOFX.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/include/FAudio.h b/include/FAudio.h index 3e01039b6f..faf8d8089d 100644 --- a/include/FAudio.h +++ b/include/FAudio.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -239,6 +239,14 @@ typedef struct FAudioFilterParameters float OneOverQ; /* [0, FAUDIO_MAX_FILTER_ONEOVERQ] */ } FAudioFilterParameters; +typedef struct FAudioFilterParametersEXT +{ + FAudioFilterType Type; + float Frequency; /* [0, FAUDIO_MAX_FILTER_FREQUENCY] */ + float OneOverQ; /* [0, FAUDIO_MAX_FILTER_ONEOVERQ] */ + float WetDryMix; /* [0, 1] */ +} FAudioFilterParametersEXT; + typedef struct FAudioBuffer { /* Either 0 or FAUDIO_END_OF_STREAM */ @@ -312,6 +320,25 @@ typedef struct FAudioDebugConfiguration #pragma pack(pop) +/* This ISN'T packed. Strictly speaking it wouldn't have mattered anyway but eh. + * See https://github.com/microsoft/DirectXTK/issues/256 + */ +typedef struct FAudioXMA2WaveFormatEx +{ + FAudioWaveFormatEx wfx; + uint16_t wNumStreams; + uint32_t dwChannelMask; + uint32_t dwSamplesEncoded; + uint32_t dwBytesPerBlock; + uint32_t dwPlayBegin; + uint32_t dwPlayLength; + uint32_t dwLoopBegin; + uint32_t dwLoopLength; + uint8_t bLoopCount; + uint8_t bEncoderVersion; + uint16_t wBlockCount; +} FAudioXMA2WaveFormat; + /* Constants */ #define FAUDIO_E_OUT_OF_MEMORY 0x8007000e @@ -356,6 +383,7 @@ typedef struct FAudioDebugConfiguration #define FAUDIO_DEFAULT_FILTER_TYPE FAudioLowPassFilter #define FAUDIO_DEFAULT_FILTER_FREQUENCY FAUDIO_MAX_FILTER_FREQUENCY #define FAUDIO_DEFAULT_FILTER_ONEOVERQ 1.0f +#define FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT 1.0f #define FAUDIO_LOG_ERRORS 0x0001 #define FAUDIO_LOG_WARNINGS 0x0002 @@ -465,9 +493,9 @@ extern FAudioGUID DATAFORMAT_SUBTYPE_IEEE_FLOAT; #define FAUDIO_TARGET_VERSION 8 /* Targeting compatibility with XAudio 2.8 */ #define FAUDIO_ABI_VERSION 0 -#define FAUDIO_MAJOR_VERSION 21 -#define FAUDIO_MINOR_VERSION 3 -#define FAUDIO_PATCH_VERSION 5 +#define FAUDIO_MAJOR_VERSION 25 +#define FAUDIO_MINOR_VERSION 2 +#define FAUDIO_PATCH_VERSION 0 #define FAUDIO_COMPILED_VERSION ( \ (FAUDIO_ABI_VERSION * 100 * 100 * 100) + \ @@ -890,6 +918,58 @@ FAUDIOAPI void FAudioVoice_GetOutputFilterParameters( FAudioFilterParameters *pParameters ); +/* Sets the filter variables for a voice. + * This is only valid on voices with the USEFILTER flag. + * + * pParameters: See FAudioFilterParametersEXT for details. + * OperationSet: See CommitChanges. Default is FAUDIO_COMMIT_NOW. + * + * Returns 0 on success. + */ +FAUDIOAPI uint32_t FAudioVoice_SetFilterParametersEXT( + FAudioVoice* voice, + const FAudioFilterParametersEXT* pParameters, + uint32_t OperationSet +); + +/* Requests the filter variables for a voice. + * This is only valid on voices with the USEFILTER flag. + * + * pParameters: See FAudioFilterParametersEXT for details. + */ +FAUDIOAPI void FAudioVoice_GetFilterParametersEXT( + FAudioVoice* voice, + FAudioFilterParametersEXT* pParameters +); + +/* Sets the filter variables for a voice's output voice. + * This is only valid on sends with the USEFILTER flag. + * + * pDestinationVoice: An output voice from the voice's send list. + * pParameters: See FAudioFilterParametersEXT for details. + * OperationSet: See CommitChanges. Default is FAUDIO_COMMIT_NOW. + * + * Returns 0 on success. + */ +FAUDIOAPI uint32_t FAudioVoice_SetOutputFilterParametersEXT( + FAudioVoice* voice, + FAudioVoice* pDestinationVoice, + const FAudioFilterParametersEXT* pParameters, + uint32_t OperationSet +); + +/* Requests the filter variables for a voice's output voice. + * This is only valid on sends with the USEFILTER flag. + * + * pDestinationVoice: An output voice from the voice's send list. + * pParameters: See FAudioFilterParametersEXT for details. + */ +FAUDIOAPI void FAudioVoice_GetOutputFilterParametersEXT( + FAudioVoice* voice, + FAudioVoice* pDestinationVoice, + FAudioFilterParametersEXT* pParameters +); + /* Sets the global volume of a voice. * * Volume: Amplitude ratio. 1.0f is default, 0.0f is silence. @@ -984,6 +1064,11 @@ FAUDIOAPI void FAudioVoice_GetOutputMatrix( /* Removes this voice from the audio graph and frees memory. */ FAUDIOAPI void FAudioVoice_DestroyVoice(FAudioVoice *voice); +/* + * Returns S_OK on success and E_FAIL if voice could not be destroyed (e. g., because it is in use). + */ +FAUDIOAPI uint32_t FAudioVoice_DestroyVoiceSafeEXT(FAudioVoice *voice); + /* FAudioSourceVoice Interface */ /* Starts processing for a source voice. diff --git a/include/FAudioFX.h b/include/FAudioFX.h index 22052d33e8..2ed0d2ab8f 100644 --- a/include/FAudioFX.h +++ b/include/FAudioFX.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/F3DAudio.c b/src/F3DAudio.c index bc2b9edad2..8da22fcb01 100644 --- a/src/F3DAudio.c +++ b/src/F3DAudio.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -1274,7 +1274,7 @@ static inline void CalculateMatrix( } } } - else + else if (curConfig != NULL) { listenerToEmitter = VectorScale(emitterToListener, -1.0f); @@ -1351,8 +1351,10 @@ static inline void CalculateMatrix( } } } - - + } + else + { + FAudio_assert(0 && "Config info not found!"); } /* TODO: add post check to validate values diff --git a/src/FACT.c b/src/FACT.c index 27bd9916c9..013cea36b5 100644 --- a/src/FACT.c +++ b/src/FACT.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -167,14 +167,82 @@ uint32_t FACTAudioEngine_Initialize( FAudio_PlatformLockMutex(pEngine->apiLock); - /* Parse the file */ - parseRet = FACT_INTERNAL_ParseAudioEngine(pEngine, pParams); - if (parseRet != 0) + if (!pParams->pGlobalSettingsBuffer || pParams->globalSettingsBufferSize == 0) { - FAudio_PlatformUnlockMutex(pEngine->apiLock); - return parseRet; + /* No file? Just go with a safe default. (Also why are you using XACT) */ + pEngine->categoryCount = 3; + pEngine->variableCount = 0; + pEngine->rpcCount = 0; + pEngine->dspPresetCount = 0; + pEngine->dspParameterCount = 0; + + pEngine->categories = (FACTAudioCategory*) pEngine->pMalloc( + sizeof(FACTAudioCategory) * pEngine->categoryCount + ); + pEngine->categoryNames = (char**) pEngine->pMalloc( + sizeof(char*) * pEngine->categoryCount + ); + + pEngine->categoryNames[0] = pEngine->pMalloc(7); + FAudio_strlcpy(pEngine->categoryNames[0], "Global", 7); + pEngine->categories[0].instanceLimit = 255; + pEngine->categories[0].fadeInMS = 0; + pEngine->categories[0].fadeOutMS = 0; + pEngine->categories[0].maxInstanceBehavior = 0; + pEngine->categories[0].parentCategory = -1; + pEngine->categories[0].volume = 1.0f; + pEngine->categories[0].visibility = 1; + pEngine->categories[0].instanceCount = 0; + pEngine->categories[0].currentVolume = 1.0f; + + pEngine->categoryNames[1] = pEngine->pMalloc(8); + FAudio_strlcpy(pEngine->categoryNames[1], "Default", 8); + pEngine->categories[1].instanceLimit = 255; + pEngine->categories[1].fadeInMS = 0; + pEngine->categories[1].fadeOutMS = 0; + pEngine->categories[1].maxInstanceBehavior = 0; + pEngine->categories[1].parentCategory = 0; + pEngine->categories[1].volume = 1.0f; + pEngine->categories[1].visibility = 1; + pEngine->categories[1].instanceCount = 0; + pEngine->categories[1].currentVolume = 1.0f; + + pEngine->categoryNames[2] = pEngine->pMalloc(6); + FAudio_strlcpy(pEngine->categoryNames[2], "Music", 6); + pEngine->categories[2].instanceLimit = 255; + pEngine->categories[2].fadeInMS = 0; + pEngine->categories[2].fadeOutMS = 0; + pEngine->categories[2].maxInstanceBehavior = 0; + pEngine->categories[2].parentCategory = 0; + pEngine->categories[2].volume = 1.0f; + pEngine->categories[2].visibility = 1; + pEngine->categories[2].instanceCount = 0; + pEngine->categories[2].currentVolume = 1.0f; + + pEngine->variables = NULL; + pEngine->variableNames = NULL; + pEngine->globalVariableValues = NULL; + pEngine->rpcs = NULL; + pEngine->dspPresets = NULL; + } + else + { + /* Parse the file */ + parseRet = FACT_INTERNAL_ParseAudioEngine(pEngine, pParams); + if (parseRet != 0) + { + FAudio_PlatformUnlockMutex(pEngine->apiLock); + return parseRet; + } } + /* Peristent Notifications */ + pEngine->notifications = 0; + pEngine->cue_context = NULL; + pEngine->sb_context = NULL; + pEngine->wb_context = NULL; + pEngine->wave_context = NULL; + /* Assign the callbacks */ pEngine->notificationCallback = pParams->fnNotificationCallback; pEngine->pReadFile = pParams->fileIOCallbacks.readFileCallback; @@ -222,6 +290,7 @@ uint32_t FACTAudioEngine_Initialize( NULL ) != 0) { FAudio_Release(pEngine->audio); + FAudio_PlatformUnlockMutex(pEngine->apiLock); return FAUDIO_E_INVALID_CALL; } } @@ -284,6 +353,16 @@ uint32_t FACTAudioEngine_ShutDown(FACTAudioEngine *pEngine) FAudio_StopEngine(pEngine->audio); } + /* Purge All pending notifactions */ + while (pEngine->wb_notifications_list) + { + FACTNotification *note = (FACTNotification*) pEngine->wb_notifications_list->entry; + pEngine->notificationCallback(note); + LinkedList_RemoveEntry(&pEngine->wb_notifications_list, note, pEngine->apiLock, pEngine->pFree); + } + + pEngine->notifications = 0; + /* This method destroys all existing cues, sound banks, and wave banks. * It blocks until all cues are destroyed. */ @@ -365,9 +444,17 @@ uint32_t FACTAudioEngine_DoWork(FACTAudioEngine *pEngine) uint8_t i; FACTCue *cue; LinkedList *list; + FACTNotification *note; FAudio_PlatformLockMutex(pEngine->apiLock); + while (pEngine->wb_notifications_list) + { + note = (FACTNotification*) pEngine->wb_notifications_list->entry; + pEngine->notificationCallback(note); + LinkedList_RemoveEntry(&pEngine->wb_notifications_list, note, pEngine->apiLock, pEngine->pFree); + } + list = pEngine->sbList; while (list != NULL) { @@ -427,6 +514,7 @@ uint32_t FACTAudioEngine_CreateInMemoryWaveBank( uint32_t dwAllocAttributes, FACTWaveBank **ppWaveBank ) { + FACTNotification *note; uint32_t retval; FAudio_PlatformLockMutex(pEngine->apiLock); retval = FACT_INTERNAL_ParseWaveBank( @@ -439,6 +527,14 @@ uint32_t FACTAudioEngine_CreateInMemoryWaveBank( 0, ppWaveBank ); + if (pEngine->notifications & NOTIFY_WAVEBANKPREPARED) + { + note = (FACTNotification*) pEngine->pMalloc(sizeof(FACTNotification)); + note->type = FACTNOTIFICATIONTYPE_WAVEBANKPREPARED; + note->waveBank.pWaveBank = *ppWaveBank; + note->pvContext = pEngine->wb_context; + LinkedList_AddEntry(&pEngine->wb_notifications_list, note, pEngine->apiLock, pEngine->pMalloc); + } FAudio_PlatformUnlockMutex(pEngine->apiLock); return retval; } @@ -448,6 +544,7 @@ uint32_t FACTAudioEngine_CreateStreamingWaveBank( const FACTStreamingParameters *pParms, FACTWaveBank **ppWaveBank ) { + FACTNotification *note; uint32_t retval, packetSize; FAudio_PlatformLockMutex(pEngine->apiLock); if ( pEngine->pReadFile == FACT_INTERNAL_DefaultReadFile && @@ -470,6 +567,14 @@ uint32_t FACTAudioEngine_CreateStreamingWaveBank( 1, ppWaveBank ); + if (pEngine->notifications & NOTIFY_WAVEBANKPREPARED) + { + note = (FACTNotification*) pEngine->pMalloc(sizeof(FACTNotification)); + note->type = FACTNOTIFICATIONTYPE_WAVEBANKPREPARED; + note->waveBank.pWaveBank = *ppWaveBank; + note->pvContext = pEngine->wb_context; + LinkedList_AddEntry(&pEngine->wb_notifications_list, note, pEngine->apiLock, pEngine->pMalloc); + } FAudio_PlatformUnlockMutex(pEngine->apiLock); return retval; } @@ -627,6 +732,7 @@ uint32_t FACTAudioEngine_RegisterNotification( /* WaveBanks */ #define PERSIST_ACTION pEngine->wb_context = pNotificationDescription->pvContext; else HANDLE_PERSIST(WAVEBANKPREPARED) + else HANDLE_PERSIST(WAVEBANKSTREAMING_INVALIDCONTENT) #undef PERSIST_ACTION /* Anything else? */ @@ -750,6 +856,7 @@ uint32_t FACTAudioEngine_UnRegisterNotification( /* WaveBanks */ #define PERSIST_ACTION pEngine->wb_context = pNotificationDescription->pvContext; else HANDLE_PERSIST(WAVEBANKPREPARED) + else HANDLE_PERSIST(WAVEBANKSTREAMING_INVALIDCONTENT) #undef PERSIST_ACTION /* Anything else? */ @@ -1132,7 +1239,7 @@ uint32_t FACTSoundBank_Prepare( break; } } - if ((*ppCue)->variation->flags == 3) + if ((*ppCue)->variation && (*ppCue)->variation->flags == 3) { (*ppCue)->interactive = pSoundBank->parentEngine->variables[ (*ppCue)->variation->variable @@ -1315,16 +1422,13 @@ uint32_t FACTSoundBank_Destroy(FACTSoundBank *pSoundBank) FACTCue_Destroy(pSoundBank->cueList); } - if (pSoundBank->parentEngine != NULL) - { - /* Remove this SoundBank from the Engine list */ - LinkedList_RemoveEntry( - &pSoundBank->parentEngine->sbList, - pSoundBank, - pSoundBank->parentEngine->sbLock, - pSoundBank->parentEngine->pFree - ); - } + /* Remove this SoundBank from the Engine list */ + LinkedList_RemoveEntry( + &pSoundBank->parentEngine->sbList, + pSoundBank, + pSoundBank->parentEngine->sbLock, + pSoundBank->parentEngine->pFree + ); /* SoundBank Name */ pSoundBank->parentEngine->pFree(pSoundBank->name); @@ -1491,16 +1595,13 @@ uint32_t FACTWaveBank_Destroy(FACTWaveBank *pWaveBank) } } - if (pWaveBank->parentEngine != NULL) - { - /* Remove this WaveBank from the Engine list */ - LinkedList_RemoveEntry( - &pWaveBank->parentEngine->wbList, - pWaveBank, - pWaveBank->parentEngine->wbLock, - pWaveBank->parentEngine->pFree - ); - } + /* Remove this WaveBank from the Engine list */ + LinkedList_RemoveEntry( + &pWaveBank->parentEngine->wbList, + pWaveBank, + pWaveBank->parentEngine->wbLock, + pWaveBank->parentEngine->pFree + ); /* Free everything, finally. */ pWaveBank->parentEngine->pFree(pWaveBank->name); @@ -1545,6 +1646,11 @@ uint32_t FACTWaveBank_Destroy(FACTWaveBank *pWaveBank) } FAudio_PlatformDestroyMutex(pWaveBank->waveLock); + if (pWaveBank->waveBankNames != NULL) + { + pWaveBank->parentEngine->pFree(pWaveBank->waveBankNames); + } + mutex = pWaveBank->parentEngine->apiLock; pWaveBank->parentEngine->pFree(pWaveBank); FAudio_PlatformUnlockMutex(mutex); @@ -1600,8 +1706,26 @@ uint16_t FACTWaveBank_GetWaveIndex( FACTWaveBank *pWaveBank, const char *szFriendlyName ) { - FAudio_assert(0 && "WaveBank name tables are not supported!"); - return 0; + uint16_t i; + char *curName; + if (pWaveBank == NULL || pWaveBank->waveBankNames == NULL) + { + return FACTINDEX_INVALID; + } + + FAudio_PlatformLockMutex(pWaveBank->parentEngine->apiLock); + curName = pWaveBank->waveBankNames; + for (i = 0; i < pWaveBank->entryCount; i += 1, curName += 64) + { + if (FAudio_strncmp(szFriendlyName, curName, 64) == 0) + { + FAudio_PlatformUnlockMutex(pWaveBank->parentEngine->apiLock); + return i; + } + } + FAudio_PlatformUnlockMutex(pWaveBank->parentEngine->apiLock); + + return FACTINDEX_INVALID; } uint32_t FACTWaveBank_GetWaveProperties( @@ -1619,11 +1743,21 @@ uint32_t FACTWaveBank_GetWaveProperties( entry = &pWaveBank->entries[nWaveIndex]; - /* FIXME: Name tables! -flibit */ - FAudio_zero( - pWaveProperties->friendlyName, - sizeof(pWaveProperties->friendlyName) - ); + if (pWaveBank->waveBankNames) + { + FAudio_memcpy( + pWaveProperties->friendlyName, + &pWaveBank->waveBankNames[nWaveIndex * 64], + sizeof(pWaveProperties->friendlyName) + ); + } + else + { + FAudio_zero( + pWaveProperties->friendlyName, + sizeof(pWaveProperties->friendlyName) + ); + } pWaveProperties->format = entry->Format; pWaveProperties->durationInSamples = entry->PlayRegion.dwLength; @@ -1640,6 +1774,10 @@ uint32_t FACTWaveBank_GetWaveProperties( ((entry->Format.wBlockAlign + 16) * 2) ); } + else + { + FAudio_assert(0 && "Unrecognized wFormatTag!"); + } pWaveProperties->loopRegion = entry->LoopRegion; pWaveProperties->streaming = pWaveBank->streaming; @@ -1660,8 +1798,14 @@ uint32_t FACTWaveBank_Prepare( FAudioBufferWMA bufferWMA; FAudioVoiceSends sends; FAudioSendDescriptor send; - FAudioADPCMWaveFormat format; + union + { + FAudioWaveFormatEx pcm; + FAudioADPCMWaveFormat adpcm; + FAudioXMA2WaveFormat xma2; + } format; FACTWaveBankEntry *entry; + FACTSeekTable *seek; if (pWaveBank == NULL) { *ppWave = NULL; @@ -1706,38 +1850,78 @@ uint32_t FACTWaveBank_Prepare( send.pOutputVoice = pWaveBank->parentEngine->master; sends.SendCount = 1; sends.pSends = &send; - format.wfx.nChannels = entry->Format.nChannels; - format.wfx.nSamplesPerSec = entry->Format.nSamplesPerSec; + format.pcm.nChannels = entry->Format.nChannels; + format.pcm.nSamplesPerSec = entry->Format.nSamplesPerSec; if (entry->Format.wFormatTag == 0x0) { - format.wfx.wFormatTag = FAUDIO_FORMAT_PCM; - format.wfx.wBitsPerSample = 8 << entry->Format.wBitsPerSample; - format.wfx.nBlockAlign = format.wfx.nChannels * format.wfx.wBitsPerSample / 8; - format.wfx.nAvgBytesPerSec = format.wfx.nBlockAlign * format.wfx.nSamplesPerSec; - format.wfx.cbSize = 0; + format.pcm.wFormatTag = FAUDIO_FORMAT_PCM; + format.pcm.wBitsPerSample = 8 << entry->Format.wBitsPerSample; + format.pcm.nBlockAlign = format.pcm.nChannels * format.pcm.wBitsPerSample / 8; + format.pcm.nAvgBytesPerSec = format.pcm.nBlockAlign * format.pcm.nSamplesPerSec; + format.pcm.cbSize = 0; } else if (entry->Format.wFormatTag == 0x1) { - /* XMA2 is quite similar to WMA Pro. */ + /* XMA2 is quite similar to WMA Pro... is what everyone thought. + * What a great way to start this comment. + * + * Let's reconstruct the extra data because who knows what decoder we're dealing with in . + * It's also a good exercise in understanding XMA2 metadata and feeding blocks into the decoder properly. + * At the time of writing this patch, it's FFmpeg via gstreamer which doesn't even respect most of this. + * ... which means: good luck to whoever ends up finding inaccuracies here in the future! + * + * dwLoopLength seems to match dwPlayLength in everything I've seen that had bLoopCount == 0. + * dwLoopBegin can be > 0 even with bLoopCount == 0 because why not. Let's ignore that. + * + * dwSamplesEncoded is usually close to dwPlayLength but not always (if ever?) equal. Let's assume equality. + * The XMA2 seek table uses sample indices as opposed to WMA's byte index seek table. + * + * nBlockAlign uses aWMABlockAlign given the entire WMA Pro thing BUT it's expected to be the block size for decoding. + * The XMA2 block size MUST be a multiple of 2048 BUT entry->PlayRegion.dwLength / seek->entryCount doesn't respect that. + * And even when correctly guesstimating the block size, we sometimes end up with block sizes >= 64k BYTES. nBlockAlign IS 16-BIT! + * Scrap nBlockAlign. I've given up and made all FAudio gstreamer functions use dwBytesPerBlock if available. + * Still though, if we don't want FAudio_INTERNAL_DecodeGSTREAMER to hang, the total data length must match (see SoundEffect.cs in FNA). + * As such, we round up when guessing the block size, feed GStreamer with zeroes^Wundersized blocks and hope for the best. + * + * This is FUN. + * -ade + */ FAudio_assert(entry->Format.wBitsPerSample != 0); - format.wfx.wFormatTag = FAUDIO_FORMAT_XMAUDIO2; - format.wfx.nAvgBytesPerSec = aWMAAvgBytesPerSec[entry->Format.wBlockAlign >> 5]; - format.wfx.nBlockAlign = aWMABlockAlign[entry->Format.wBlockAlign & 0x1F]; - format.wfx.wBitsPerSample = 16; - format.wfx.cbSize = 0; + seek = &pWaveBank->seekTables[nWaveIndex]; + format.pcm.wFormatTag = FAUDIO_FORMAT_XMAUDIO2; + format.pcm.wBitsPerSample = 16; + format.pcm.nAvgBytesPerSec = aWMAAvgBytesPerSec[entry->Format.wBlockAlign >> 5]; + format.pcm.nBlockAlign = aWMABlockAlign[entry->Format.wBlockAlign & 0x1F]; + format.pcm.cbSize = ( + sizeof(FAudioXMA2WaveFormat) - + sizeof(FAudioWaveFormatEx) + ); + format.xma2.wNumStreams = (format.pcm.nChannels + 1) / 2; + format.xma2.dwChannelMask = format.pcm.nChannels > 1 ? 0xFFFFFFFF >> (32 - format.pcm.nChannels) : 0; + format.xma2.dwSamplesEncoded = seek->entries[seek->entryCount - 1]; + format.xma2.dwBytesPerBlock = (uint16_t) FAudio_ceil( + (double) entry->PlayRegion.dwLength / + (double) seek->entryCount / + 2048.0 + ) * 2048; + format.xma2.dwPlayBegin = format.xma2.dwLoopBegin = 0; + format.xma2.dwPlayLength = format.xma2.dwLoopLength = format.xma2.dwSamplesEncoded; + format.xma2.bLoopCount = 0; + format.xma2.bEncoderVersion = 4; + format.xma2.wBlockCount = seek->entryCount; } else if (entry->Format.wFormatTag == 0x2) { - format.wfx.wFormatTag = FAUDIO_FORMAT_MSADPCM; - format.wfx.nBlockAlign = (entry->Format.wBlockAlign + 22) * format.wfx.nChannels; - format.wfx.wBitsPerSample = 16; - format.wfx.cbSize = ( + format.pcm.wFormatTag = FAUDIO_FORMAT_MSADPCM; + format.pcm.nBlockAlign = (entry->Format.wBlockAlign + 22) * format.pcm.nChannels; + format.pcm.wBitsPerSample = 16; + format.pcm.cbSize = ( sizeof(FAudioADPCMWaveFormat) - sizeof(FAudioWaveFormatEx) ); - format.wSamplesPerBlock = ( - ((format.wfx.nBlockAlign / format.wfx.nChannels) - 6) * 2 + format.adpcm.wSamplesPerBlock = ( + ((format.pcm.nBlockAlign / format.pcm.nChannels) - 6) * 2 ); } else if (entry->Format.wFormatTag == 0x3) @@ -1745,11 +1929,11 @@ uint32_t FACTWaveBank_Prepare( /* Apparently this is used to detect WMA Pro...? */ FAudio_assert(entry->Format.wBitsPerSample == 0); - format.wfx.wFormatTag = FAUDIO_FORMAT_WMAUDIO2; - format.wfx.nAvgBytesPerSec = aWMAAvgBytesPerSec[entry->Format.wBlockAlign >> 5]; - format.wfx.nBlockAlign = aWMABlockAlign[entry->Format.wBlockAlign & 0x1F]; - format.wfx.wBitsPerSample = 16; - format.wfx.cbSize = 0; + format.pcm.wFormatTag = FAUDIO_FORMAT_WMAUDIO2; + format.pcm.nAvgBytesPerSec = aWMAAvgBytesPerSec[entry->Format.wBlockAlign >> 5]; + format.pcm.nBlockAlign = aWMABlockAlign[entry->Format.wBlockAlign & 0x1F]; + format.pcm.wBitsPerSample = 16; + format.pcm.cbSize = 0; } else { @@ -1765,11 +1949,11 @@ uint32_t FACTWaveBank_Prepare( (*ppWave)->callback.callback.OnVoiceProcessingPassEnd = NULL; (*ppWave)->callback.callback.OnVoiceProcessingPassStart = NULL; (*ppWave)->callback.wave = *ppWave; - (*ppWave)->srcChannels = format.wfx.nChannels; + (*ppWave)->srcChannels = format.pcm.nChannels; FAudio_CreateSourceVoice( pWaveBank->parentEngine->audio, &(*ppWave)->voice, - &format.wfx, + &format.pcm, FAUDIO_VOICE_USEFILTER, /* FIXME: Can this be optional? */ 4.0f, (FAudioVoiceCallback*) &(*ppWave)->callback, @@ -1779,19 +1963,19 @@ uint32_t FACTWaveBank_Prepare( if (pWaveBank->streaming) { /* Init stream cache info */ - if (format.wfx.wFormatTag == FAUDIO_FORMAT_PCM) + if (format.pcm.wFormatTag == FAUDIO_FORMAT_PCM) { (*ppWave)->streamSize = ( - format.wfx.nSamplesPerSec * - format.wfx.nBlockAlign + format.pcm.nSamplesPerSec * + format.pcm.nBlockAlign ); } - else if (format.wfx.wFormatTag == FAUDIO_FORMAT_MSADPCM) + else if (format.pcm.wFormatTag == FAUDIO_FORMAT_MSADPCM) { (*ppWave)->streamSize = ( - format.wfx.nSamplesPerSec / - format.wSamplesPerBlock * - format.wfx.nBlockAlign + format.pcm.nSamplesPerSec / + format.adpcm.wSamplesPerBlock * + format.pcm.nBlockAlign ); } else @@ -1801,7 +1985,7 @@ uint32_t FACTWaveBank_Prepare( /* XACT does NOT support loop subregions for these formats */ FAudio_assert(entry->LoopRegion.dwStartSample == 0); - FAudio_assert(entry->LoopRegion.dwTotalSamples == entry->Duration); + FAudio_assert(entry->LoopRegion.dwTotalSamples == 0 || entry->LoopRegion.dwTotalSamples == entry->Duration); } (*ppWave)->streamCache = (uint8_t*) pWaveBank->parentEngine->pMalloc( (*ppWave)->streamSize @@ -1836,8 +2020,7 @@ uint32_t FACTWaveBank_Prepare( buffer.LoopCount = nLoopCount; } buffer.pContext = NULL; - if ( format.wfx.wFormatTag == FAUDIO_FORMAT_WMAUDIO2 || - format.wfx.wFormatTag == FAUDIO_FORMAT_XMAUDIO2 ) + if (format.pcm.wFormatTag == FAUDIO_FORMAT_WMAUDIO2) { bufferWMA.pDecodedPacketCumulativeBytes = pWaveBank->seekTables[nWaveIndex].entries; @@ -2025,11 +2208,13 @@ uint32_t FACTWave_Stop(FACTWave *pWave, uint32_t dwFlags) { FACTNotification note; note.type = FACTNOTIFICATIONTYPE_WAVESTOP; + note.wave.cueIndex = pWave->parentCue->index; + note.wave.pCue = pWave->parentCue; + note.wave.pSoundBank = pWave->parentCue->parentBank; note.wave.pWave = pWave; - if (pWave->parentBank->parentEngine->notifications & NOTIFY_WAVESTOP) - { - note.pvContext = pWave->parentBank->parentEngine->wave_context; - } + note.wave.pWaveBank = pWave->parentBank; + note.pvContext = pWave->parentBank->parentEngine->wave_context; + pWave->parentBank->parentEngine->notificationCallback(¬e); } @@ -2231,7 +2416,6 @@ uint32_t FACTCue_Destroy(FACTCue *pCue) { FACTCue *cue, *prev; FAudioMutex mutex; - FACTNotification note; if (pCue == NULL) { return 1; @@ -2265,20 +2449,7 @@ uint32_t FACTCue_Destroy(FACTCue *pCue) FAudio_assert(cue != NULL && "Could not find Cue reference!"); pCue->parentBank->parentEngine->pFree(pCue->variableValues); - if (pCue->notifyOnDestroy || pCue->parentBank->parentEngine->notifications & NOTIFY_CUEDESTROY) - { - note.type = FACTNOTIFICATIONTYPE_CUEDESTROYED; - note.cue.pCue = pCue; - if (pCue->parentBank->parentEngine->notifications & NOTIFY_CUEDESTROY) - { - note.pvContext = pCue->parentBank->parentEngine->cue_context; - } - else - { - note.pvContext = pCue->usercontext; - } - pCue->parentBank->parentEngine->notificationCallback(¬e); - } + FACT_INTERNAL_SendCueNotification(pCue, NOTIFY_CUEDESTROY, FACTNOTIFICATIONTYPE_CUEDESTROYED); mutex = pCue->parentBank->parentEngine->apiLock; pCue->parentBank->parentEngine->pFree(pCue); @@ -2529,6 +2700,8 @@ uint32_t FACTCue_Stop(FACTCue *pCue, uint32_t dwFlags) } } + FACT_INTERNAL_SendCueNotification(pCue, NOTIFY_CUESTOP, FACTNOTIFICATIONTYPE_CUESTOP); + FAudio_PlatformUnlockMutex(pCue->parentBank->parentEngine->apiLock); return 0; } @@ -2596,6 +2769,8 @@ uint32_t FACTCue_SetMatrixCoefficients( } } + FACT_INTERNAL_SendCueNotification(pCue, NOTIFY_CUESTOP, FACTNOTIFICATIONTYPE_CUESTOP); + FAudio_PlatformUnlockMutex(pCue->parentBank->parentEngine->apiLock); return 0; } diff --git a/src/FACT3D.c b/src/FACT3D.c index c9a8f61a4d..434107fca1 100644 --- a/src/FACT3D.c +++ b/src/FACT3D.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FACT_internal.c b/src/FACT_internal.c index 68d2140942..3839a15c21 100644 --- a/src/FACT_internal.c +++ b/src/FACT_internal.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -39,6 +39,8 @@ #define FACT_CONTENT_VERSION_3_4 45 #define FACT_CONTENT_VERSION_3_1 44 #define FACT_CONTENT_VERSION_3_0 43 +#define FACT_CONTENT_VERSION_2_4 41 +#define FACT_CONTENT_VERSION_2_0 37 static inline int FACT_INTERNAL_SupportedContent(uint16_t version) { @@ -66,6 +68,30 @@ static inline float FACT_INTERNAL_CalculateAmplitudeRatio(float decibel) return (float) FAudio_pow(10.0, decibel / 2000.0); } +static inline float FACT_INTERNAL_CalculateFilterFrequency( + float desiredFrequency, + uint32_t sampleRate +) { + /* This is needed to convert linear frequencies to the value + * FAudio_INTERNAL_FilterVoice expects, in order for it to actually + * filter at the correct frequency. + * + * The formula is... + * + * (2 * sin(pi * (desired filter cutoff frequency) / sampleRate)) + * + * ... but it behaves badly as the filter frequency gets too high as a + * fraction of the sample rate, hence the mins. + * + * -@Woflox + */ + float freq = 2.0f * FAudio_sinf( + F3DAUDIO_PI * + FAudio_min(desiredFrequency / sampleRate, 0.5f) + ); + return FAudio_min(freq, 1.0f); +} + static inline void FACT_INTERNAL_ReadFile( FACTReadFileCallback pReadFile, FACTGetOverlappedResultCallback pGetOverlappedResult, @@ -390,12 +416,17 @@ void FACT_INTERNAL_GetNextWave( { const float rngQFactor = 1.0f / ( FACT_INTERNAL_rng() * - (evt->wave.maxQFactor - evt->wave.minQFactor) + (evt->wave.maxQFactor - evt->wave.minQFactor) + + evt->wave.minQFactor + ); + const float rngFrequency = FACT_INTERNAL_CalculateFilterFrequency( + ( + FACT_INTERNAL_rng() * + (evt->wave.maxFrequency - evt->wave.minFrequency) + + evt->wave.minFrequency + ), + cue->parentBank->parentEngine->audio->master->master.inputSampleRate ); - const float rngFrequency = ( - FACT_INTERNAL_rng() * - (evt->wave.maxFrequency - evt->wave.minFrequency) - ) / 20000.0f; if (trackInst->activeWave.wave != NULL) { /* Variation on Loop */ @@ -430,7 +461,18 @@ void FACT_INTERNAL_GetNextWave( else { trackInst->upcomingWave.baseQFactor = 1.0f / (track->qfactor / 3.0f); - trackInst->upcomingWave.baseFrequency = track->frequency / 20000.0f; + trackInst->upcomingWave.baseFrequency = FACT_INTERNAL_CalculateFilterFrequency( + track->frequency, + cue->parentBank->parentEngine->audio->master->master.inputSampleRate + ); + + /* FIXME: For some reason the 0.67 Q Factor causes problems, but it's also + * the only possible value until ~1 so just clamp it for now. + */ + trackInst->upcomingWave.baseQFactor = FAudio_min( + trackInst->upcomingWave.baseQFactor, + 1.0f + ); } /* Try to change loop counter at the very end */ @@ -473,7 +515,7 @@ uint8_t FACT_INTERNAL_CreateSound(FACTCue *cue, uint16_t fadeInMS) /* Sound */ baseSound = cue->sound; } - else + else if (cue->variation) { /* Variation */ if (cue->variation->flags == 3) @@ -888,7 +930,7 @@ void FACT_INTERNAL_DestroySound(FACTSoundInstance *sound) /* TODO: if (sound->parentCue->playingSounds == NULL) */ { sound->parentCue->state |= FACT_STATE_STOPPED; - sound->parentCue->state &= ~(FACT_STATE_PLAYING | FACT_STATE_STOPPING); + sound->parentCue->state &= ~(FACT_STATE_PLAYING | FACT_STATE_PAUSED | FACT_STATE_STOPPING); sound->parentCue->data->instanceCount -= 1; FACT_INTERNAL_SendCueNotification(sound->parentCue, NOTIFY_CUESTOP, FACTNOTIFICATIONTYPE_CUESTOP); @@ -898,12 +940,18 @@ void FACT_INTERNAL_DestroySound(FACTSoundInstance *sound) void FACT_INTERNAL_BeginFadeOut(FACTSoundInstance *sound, uint16_t fadeOutMS) { + /* FIXME: Even for 0ms it seems to want to be in STOPPING for one frame. + * Should we still destroy but defer state changes to the next frame? + * -flibit + */ +#if 0 if (fadeOutMS == 0) { /* No fade? Screw it, just delete us */ FACT_INTERNAL_DestroySound(sound); return; } +#endif sound->fadeType = 2; /* Out */ sound->fadeStart = FAudio_timems(); @@ -985,21 +1033,21 @@ float FACT_INTERNAL_CalculateRPC( } else if (rpc->points[i].type == 1) /* Fast */ { - result += maxY * (1.0f - FAudio_pow(1.0f - FAudio_pow(deltaXNormalized, 1.0f / 1.5f), 1.5f)); + result += maxY * (1.0f - FAudio_powf(1.0f - FAudio_powf(deltaXNormalized, 1.0f / 1.5f), 1.5f)); } else if (rpc->points[i].type == 2) /* Slow */ { - result += maxY * (1.0f - FAudio_pow(1.0f - FAudio_pow(deltaXNormalized, 1.5f), 1.0f / 1.5f)); + result += maxY * (1.0f - FAudio_powf(1.0f - FAudio_powf(deltaXNormalized, 1.5f), 1.0f / 1.5f)); } else if (rpc->points[i].type == 3) /* SinCos */ { if (maxY > 0.0f) { - result += maxY * (1.0f - FAudio_pow(1.0f - FAudio_sqrtf(deltaXNormalized), 2.0f)); + result += maxY * (1.0f - FAudio_powf(1.0f - FAudio_sqrtf(deltaXNormalized), 2.0f)); } else { - result += maxY * (1.0f - FAudio_sqrtf(1.0f - FAudio_pow(deltaXNormalized, 2.0f))); + result += maxY * (1.0f - FAudio_sqrtf(1.0f - FAudio_powf(deltaXNormalized, 2.0f))); } } else @@ -1092,7 +1140,10 @@ void FACT_INTERNAL_UpdateRPCs( else if (rpc->parameter == RPC_PARAMETER_FILTERFREQUENCY) { /* Yes, just overwrite... */ - data->rpcFilterFreq = rpcResult / 20000.0f; + data->rpcFilterFreq = FACT_INTERNAL_CalculateFilterFrequency( + rpcResult, + engine->audio->master->master.inputSampleRate + ); } else if (rpc->parameter == RPC_PARAMETER_FILTERQFACTOR) { @@ -1617,7 +1668,7 @@ void FACT_INTERNAL_UpdateCue(FACTCue *cue) FACTSoundInstance *sound; /* Interactive sound selection */ - if (!(cue->data->flags & 0x04) && cue->variation->flags == 3) + if (!(cue->data->flags & 0x04) && cue->variation && cue->variation->flags == 3) { /* Interactive */ if (cue->parentBank->parentEngine->variables[cue->variation->variable].accessibility & 0x04) @@ -1722,8 +1773,12 @@ int32_t FACT_INTERNAL_APIThread(void* enginePtr) if (cue->state & FACT_STATE_PAUSED) { - cue = cue->next; - continue; + /* Funky edge case where we need to keep updating even when paused */ + if (!(cue->state & FACT_STATE_STOPPING)) + { + cue = cue->next; + continue; + } } if (cue->playingSound != NULL) @@ -1888,8 +1943,7 @@ void FACT_INTERNAL_OnBufferEnd(FAudioVoiceCallback *callback, void* pContext) buffer.pContext = NULL; /* Submit, finally. */ - if ( entry->Format.wFormatTag == 0x1 || - entry->Format.wFormatTag == 0x3 ) + if (entry->Format.wFormatTag == 0x3) { bufferWMA.pDecodedPacketCumulativeBytes = c->wave->parentBank->seekTables[c->wave->index].entries; @@ -2022,8 +2076,8 @@ uint32_t FACT_INTERNAL_ParseAudioEngine( rpcOffset, dspPresetOffset, dspParameterOffset; - uint16_t blob1Count, blob2Count; - uint8_t version, tool; + uint16_t blob1Count, blob2Count, tool; + uint8_t version; uint8_t se; uint32_t magic; size_t memsize; @@ -2032,12 +2086,6 @@ uint32_t FACT_INTERNAL_ParseAudioEngine( uint8_t *ptr = (uint8_t*) pParams->pGlobalSettingsBuffer; uint8_t *start = ptr; - /* FIXME: Should be recorded so we can return the correct error */ - if (!pParams->pGlobalSettingsBuffer || pParams->globalSettingsBufferSize == 0) - { - return 0; - } - magic = read_u32(&ptr, 0); se = magic == 0x58475346; /* Swap Endian */ if (magic != 0x46534758 && magic != 0x58475346) /* 'XGSF' */ @@ -2180,7 +2228,8 @@ uint32_t FACT_INTERNAL_ParseAudioEngine( { pEngine->dspPresetCodes[i] = (uint32_t) (ptr - start); pEngine->dspPresets[i].accessibility = read_u8(&ptr); - pEngine->dspPresets[i].parameterCount = read_u32(&ptr, se); + pEngine->dspPresets[i].parameterCount = read_u16(&ptr, se); + ptr += 2; /* Unknown value */ pEngine->dspPresets[i].parameters = (FACTDSPParameter*) pEngine->pMalloc( sizeof(FACTDSPParameter) * pEngine->dspPresets[i].parameterCount @@ -2246,13 +2295,6 @@ uint32_t FACT_INTERNAL_ParseAudioEngine( ptr += memsize; } - /* Peristent Notifications */ - pEngine->notifications = 0; - pEngine->cue_context = NULL; - pEngine->sb_context = NULL; - pEngine->wb_context = NULL; - pEngine->wave_context = NULL; - /* Store this pointer in case we're asked to free it */ if (pParams->globalSettingsFlags & FACT_FLAG_MANAGEDATA) { @@ -2321,8 +2363,9 @@ void FACT_INTERNAL_ParseTrackEvents( track->events[i].wave.angle = read_u16(ptr, se); /* Track Variation */ - track->events[i].wave.complex.trackCount = read_u16(ptr, se); - track->events[i].wave.complex.variation = read_u16(ptr, se); + evtInfo = read_u32(ptr, se); + track->events[i].wave.complex.trackCount = evtInfo & 0xFFFF; + track->events[i].wave.complex.variation = (evtInfo >> 16) & 0xFFFF; *ptr += 4; /* Unknown values */ track->events[i].wave.complex.tracks = (uint16_t*) pMalloc( sizeof(uint16_t) * @@ -2393,8 +2436,9 @@ void FACT_INTERNAL_ParseTrackEvents( track->events[i].wave.variationFlags = read_u16(ptr, se); /* Track Variation */ - track->events[i].wave.complex.trackCount = read_u16(ptr, se); - track->events[i].wave.complex.variation = read_u16(ptr, se); + evtInfo = read_u32(ptr, se); + track->events[i].wave.complex.trackCount = evtInfo & 0xFFFF; + track->events[i].wave.complex.variation = (evtInfo >> 16) & 0xFFFF; *ptr += 4; /* Unknown values */ track->events[i].wave.complex.tracks = (uint16_t*) pMalloc( sizeof(uint16_t) * @@ -2498,6 +2542,7 @@ uint32_t FACT_INTERNAL_ParseSoundBank( cueNameIndexOffset, soundOffset; uint32_t entryCountAndFlags; + uint16_t filterData; uint8_t platform; size_t memsize; uint16_t i, j, k, cur, tool; @@ -2583,6 +2628,7 @@ uint32_t FACT_INTERNAL_ParseSoundBank( /* WaveBank Name data */ FAudio_assert((ptr - start) == wavebankNameOffset); + ptr = start + wavebankNameOffset; sb->wavebankNames = (char**) pEngine->pMalloc( sizeof(char*) * sb->wavebankCount @@ -2745,19 +2791,18 @@ uint32_t FACT_INTERNAL_ParseSoundBank( continue; } - sb->sounds[i].tracks[j].filter = read_u8(&ptr); - if (sb->sounds[i].tracks[j].filter & 0x01) + filterData = read_u16(&ptr, se); + if (filterData & 0x0001) { sb->sounds[i].tracks[j].filter = - (sb->sounds[i].tracks[j].filter >> 1) & 0x02; + (filterData >> 1) & 0x02; } else { /* Huh...? */ sb->sounds[i].tracks[j].filter = 0xFF; } - - sb->sounds[i].tracks[j].qfactor = read_u8(&ptr); + sb->sounds[i].tracks[j].qfactor = (filterData >> 8) & 0xFF; sb->sounds[i].tracks[j].frequency = read_u16(&ptr, se); } @@ -2786,45 +2831,55 @@ uint32_t FACT_INTERNAL_ParseSoundBank( /* Simple Cue data */ FAudio_assert(cueSimpleCount == 0 || (ptr - start) == cueSimpleOffset); - for (i = 0; i < cueSimpleCount; i += 1, cur += 1) + if (cueSimpleCount > 0) { - sb->cues[cur].flags = read_u8(&ptr); - sb->cues[cur].sbCode = read_u32(&ptr, se); - sb->cues[cur].transitionOffset = 0; - sb->cues[cur].instanceLimit = 0xFF; - sb->cues[cur].fadeInMS = 0; - sb->cues[cur].fadeOutMS = 0; - sb->cues[cur].maxInstanceBehavior = 0; - sb->cues[cur].instanceCount = 0; + ptr = start + cueSimpleOffset; + + for (i = 0; i < cueSimpleCount; i += 1, cur += 1) + { + sb->cues[cur].flags = read_u8(&ptr); + sb->cues[cur].sbCode = read_u32(&ptr, se); + sb->cues[cur].transitionOffset = 0; + sb->cues[cur].instanceLimit = 0xFF; + sb->cues[cur].fadeInMS = 0; + sb->cues[cur].fadeOutMS = 0; + sb->cues[cur].maxInstanceBehavior = 0; + sb->cues[cur].instanceCount = 0; + } } /* Complex Cue data */ FAudio_assert(cueComplexCount == 0 || (ptr - start) == cueComplexOffset); - for (i = 0; i < cueComplexCount; i += 1, cur += 1) + if (cueComplexCount > 0) { - sb->cues[cur].flags = read_u8(&ptr); - sb->cues[cur].sbCode = read_u32(&ptr, se); - sb->cues[cur].transitionOffset = read_u32(&ptr, se); - if (sb->cues[cur].transitionOffset == 0xFFFFFFFF) - { - /* FIXME: Why */ - sb->cues[cur].transitionOffset = 0; - } - sb->cues[cur].instanceLimit = read_u8(&ptr); - sb->cues[cur].fadeInMS = read_u16(&ptr, se); - sb->cues[cur].fadeOutMS = read_u16(&ptr, se); - sb->cues[cur].maxInstanceBehavior = read_u8(&ptr) >> 3; - sb->cues[cur].instanceCount = 0; + ptr = start + cueComplexOffset; - if (!(sb->cues[cur].flags & 0x04)) - { - /* FIXME: Is this the only way to get this...? */ - sb->variationCount += 1; - } - if (sb->cues[cur].transitionOffset > 0) + for (i = 0; i < cueComplexCount; i += 1, cur += 1) { - /* FIXME: Is this the only way to get this...? */ - sb->transitionCount += 1; + sb->cues[cur].flags = read_u8(&ptr); + sb->cues[cur].sbCode = read_u32(&ptr, se); + sb->cues[cur].transitionOffset = read_u32(&ptr, se); + if (sb->cues[cur].transitionOffset == 0xFFFFFFFF) + { + /* FIXME: Why */ + sb->cues[cur].transitionOffset = 0; + } + sb->cues[cur].instanceLimit = read_u8(&ptr); + sb->cues[cur].fadeInMS = read_u16(&ptr, se); + sb->cues[cur].fadeOutMS = read_u16(&ptr, se); + sb->cues[cur].maxInstanceBehavior = read_u8(&ptr) >> 3; + sb->cues[cur].instanceCount = 0; + + if (!(sb->cues[cur].flags & 0x04)) + { + /* FIXME: Is this the only way to get this...? */ + sb->variationCount += 1; + } + if (sb->cues[cur].transitionOffset > 0) + { + /* FIXME: Is this the only way to get this...? */ + sb->transitionCount += 1; + } } } @@ -2832,6 +2887,7 @@ uint32_t FACT_INTERNAL_ParseSoundBank( if (sb->variationCount > 0) { FAudio_assert((ptr - start) == variationOffset); + ptr = start + variationOffset; sb->variations = (FACTVariationTable*) pEngine->pMalloc( sizeof(FACTVariationTable) * sb->variationCount @@ -2917,6 +2973,7 @@ uint32_t FACT_INTERNAL_ParseSoundBank( if (sb->transitionCount > 0) { FAudio_assert((ptr - start) == transitionOffset); + ptr = start + transitionOffset; sb->transitions = (FACTTransitionTable*) pEngine->pMalloc( sizeof(FACTTransitionTable) * sb->transitionCount @@ -2964,6 +3021,7 @@ uint32_t FACT_INTERNAL_ParseSoundBank( if (cueNameIndexOffset != -1) { FAudio_assert((ptr - start) == cueNameIndexOffset); + ptr = start + cueNameIndexOffset; ptr += 6 * sb->cueCount; /* FIXME: index as assert value? */ } @@ -2971,6 +3029,7 @@ uint32_t FACT_INTERNAL_ParseSoundBank( if (cueNameOffset != -1) { FAudio_assert((ptr - start) == cueNameOffset); + ptr = start + cueNameOffset; sb->cueNames = (char**) pEngine->pMalloc( sizeof(char*) * sb->cueCount @@ -3058,7 +3117,17 @@ uint32_t FACT_INTERNAL_ParseWaveBank( #define DOSWAP_64(x) x = FAudio_swap64BE(x) fileOffset = offset; - READ(&header, sizeof(header)) + + FAudio_zero(&header, sizeof(header)); + READ(&header.dwSignature, sizeof(header.dwSignature)); + READ(&header.dwVersion, sizeof(header.dwVersion)); + if (header.dwVersion > FACT_CONTENT_VERSION_2_4) + { + READ(&header.dwHeaderVersion, sizeof(header.dwHeaderVersion)); + } + + READ(&header.Segments, sizeof(header.Segments)); + se = header.dwSignature == 0x57424E44; if (se) { @@ -3076,12 +3145,20 @@ uint32_t FACT_INTERNAL_ParseWaveBank( return -1; /* TODO: NOT XACT FILE */ } - if (!FACT_INTERNAL_SupportedContent(header.dwVersion)) + /* We support all Wavebank versions - Restore when SoundBank support them also. */ + /*if (!FACT_INTERNAL_SupportedContent(header.dwVersion)) + { + return -2; + } + */ + if ( header.dwVersion < FACT_CONTENT_VERSION_2_4 || + header.dwVersion > FACT_CONTENT_VERSION ) { return -2; } - if (!FACT_INTERNAL_SupportedWBContent(header.dwHeaderVersion)) + if ( header.dwVersion > FACT_CONTENT_VERSION_2_4 && + !FACT_INTERNAL_SupportedWBContent(header.dwHeaderVersion) ) { return -3; } @@ -3282,12 +3359,17 @@ uint32_t FACT_INTERNAL_ParseWaveBank( wb->seekTables = NULL; } - /* TODO: WaveBank Entry Names + /* WaveBank Entry Names */ if (wbinfo.dwFlags & FACT_WAVEBANK_FLAGS_ENTRYNAMES) { SEEKSET(header.Segments[FACT_WAVEBANK_SEGIDX_ENTRYNAMES].dwOffset) + wb->waveBankNames = (char*) pEngine->pMalloc(64 * wbinfo.dwEntryCount); + READ(wb->waveBankNames, 64 * wbinfo.dwEntryCount); + } + else + { + wb->waveBankNames = NULL; } - */ /* Add to the Engine WaveBank list */ LinkedList_AddEntry( diff --git a/src/FACT_internal.h b/src/FACT_internal.h index a5067e9808..c7001a0fce 100644 --- a/src/FACT_internal.h +++ b/src/FACT_internal.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -89,7 +89,7 @@ typedef struct FACTDSPParameter typedef struct FACTDSPPreset { uint8_t accessibility; - uint32_t parameterCount; + uint16_t parameterCount; FACTDSPParameter *parameters; } FACTDSPPreset; @@ -111,7 +111,8 @@ typedef enum FACTNoticationsFlags NOTIFY_WAVESTOP = 0x00002000, NOTIFY_WAVELOOPED = 0x00004000, NOTIFY_WAVEDESTROY = 0x00008000, - NOTIFY_WAVEBANKPREPARED = 0x00010000 + NOTIFY_WAVEBANKPREPARED = 0x00010000, + NOTIFY_WAVEBANKSTREAMING_INVALIDCONTENT = 0x00020000 } FACTNoticationsFlags; /* Internal SoundBank Types */ @@ -440,6 +441,7 @@ struct FACTAudioEngine void *sb_context; void *wb_context; void *wave_context; + LinkedList *wb_notifications_list; /* Settings handle */ void *settings; @@ -490,6 +492,7 @@ struct FACTWaveBank FACTWaveBankEntry *entries; uint32_t *entryRefs; FACTSeekTable *seekTables; + char *waveBankNames; /* I/O information */ uint32_t packetSize; diff --git a/src/FAPOBase.c b/src/FAPOBase.c index 91b294ddab..27a98e1216 100644 --- a/src/FAPOBase.c +++ b/src/FAPOBase.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAPOFX.c b/src/FAPOFX.c index 70739bd061..5e9c3b82c2 100644 --- a/src/FAPOFX.c +++ b/src/FAPOFX.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAPOFX_echo.c b/src/FAPOFX_echo.c index d87d5c5b95..ec6454384f 100644 --- a/src/FAPOFX_echo.c +++ b/src/FAPOFX_echo.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAPOFX_eq.c b/src/FAPOFX_eq.c index 4ac45728aa..1b575e6bdf 100644 --- a/src/FAPOFX_eq.c +++ b/src/FAPOFX_eq.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAPOFX_masteringlimiter.c b/src/FAPOFX_masteringlimiter.c index 1b02ffe90a..2a8bb92dda 100644 --- a/src/FAPOFX_masteringlimiter.c +++ b/src/FAPOFX_masteringlimiter.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAPOFX_reverb.c b/src/FAPOFX_reverb.c index 782dddafa2..bd2ea48e24 100644 --- a/src/FAPOFX_reverb.c +++ b/src/FAPOFX_reverb.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAudio.c b/src/FAudio.c index 8032b1e3c4..8a4ad9a4b0 100644 --- a/src/FAudio.c +++ b/src/FAudio.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -278,6 +278,7 @@ uint32_t FAudio_CreateSourceVoice( (*ppSourceVoice)->filter.Type = FAUDIO_DEFAULT_FILTER_TYPE; (*ppSourceVoice)->filter.Frequency = FAUDIO_DEFAULT_FILTER_FREQUENCY; (*ppSourceVoice)->filter.OneOverQ = FAUDIO_DEFAULT_FILTER_ONEOVERQ; + (*ppSourceVoice)->filter.WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; (*ppSourceVoice)->sendLock = FAudio_PlatformCreateMutex(); LOG_MUTEX_CREATE(audio, (*ppSourceVoice)->sendLock) (*ppSourceVoice)->effectLock = FAudio_PlatformCreateMutex(); @@ -293,8 +294,8 @@ uint32_t FAudio_CreateSourceVoice( if ( pSourceFormat->wFormatTag == FAUDIO_FORMAT_PCM || pSourceFormat->wFormatTag == FAUDIO_FORMAT_IEEE_FLOAT || - pSourceFormat->wFormatTag == FAUDIO_FORMAT_XMAUDIO2 || - pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO2 ) + pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO2 || + pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO3 ) { FAudioWaveFormatExtensible *fmtex = (FAudioWaveFormatExtensible*) audio->pMalloc( sizeof(FAudioWaveFormatExtensible) @@ -317,14 +318,14 @@ uint32_t FAudio_CreateSourceVoice( { FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(FAudioGUID)); } - else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_XMAUDIO2) - { - FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_XMAUDIO2, sizeof(FAudioGUID)); - } else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO2) { FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_WMAUDIO2, sizeof(FAudioGUID)); } + else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_WMAUDIO3) + { + FAudio_memcpy(&fmtex->SubFormat, &DATAFORMAT_SUBTYPE_WMAUDIO3, sizeof(FAudioGUID)); + } (*ppSourceVoice)->src.format = &fmtex->Format; } else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_MSADPCM) @@ -355,6 +356,31 @@ uint32_t FAudio_CreateSourceVoice( ) - 6) * 2; (*ppSourceVoice)->src.format = &fmtex->wfx; } + else if (pSourceFormat->wFormatTag == FAUDIO_FORMAT_XMAUDIO2) + { + FAudioXMA2WaveFormat *fmtex = (FAudioXMA2WaveFormat*) audio->pMalloc( + sizeof(FAudioXMA2WaveFormat) + ); + + /* Copy what we can, ideally the sizes match! */ + size_t cbSize = sizeof(FAudioWaveFormatEx) + pSourceFormat->cbSize; + FAudio_memcpy( + fmtex, + pSourceFormat, + FAudio_min(cbSize, sizeof(FAudioXMA2WaveFormat)) + ); + if (cbSize < sizeof(FAudioXMA2WaveFormat)) + { + FAudio_zero( + ((uint8_t*) fmtex) + cbSize, + sizeof(FAudioADPCMWaveFormat) - cbSize + ); + } + + /* Does XAudio2 validate this input?! */ + fmtex->wfx.cbSize = sizeof(FAudioXMA2WaveFormat) - sizeof(FAudioWaveFormatEx); + (*ppSourceVoice)->src.format = &fmtex->wfx; + } else { /* direct copy anything else */ @@ -429,18 +455,17 @@ uint32_t FAudio_CreateSourceVoice( } else if ( COMPARE_GUID(WMAUDIO2) || COMPARE_GUID(WMAUDIO3) || - COMPARE_GUID(WMAUDIO_LOSSLESS) || - COMPARE_GUID(XMAUDIO2) ) + COMPARE_GUID(WMAUDIO_LOSSLESS) ) { -#ifdef HAVE_GSTREAMER - if (FAudio_GSTREAMER_init(*ppSourceVoice, fmtex->SubFormat.Data1) != 0) +#ifdef HAVE_WMADEC + if (FAudio_WMADEC_init(*ppSourceVoice, fmtex->SubFormat.Data1) != 0) { (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR; } #else FAudio_assert(0 && "xWMA is not supported!"); (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR; -#endif /* HAVE_GSTREAMER */ +#endif /* HAVE_WMADEC */ } else { @@ -448,6 +473,18 @@ uint32_t FAudio_CreateSourceVoice( } #undef COMPARE_GUID } + else if ((*ppSourceVoice)->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2) + { +#ifdef HAVE_WMADEC + if (FAudio_WMADEC_init(*ppSourceVoice, FAUDIO_FORMAT_XMAUDIO2) != 0) + { + (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR; + } +#else + FAudio_assert(0 && "XMA2 is not supported!"); + (*ppSourceVoice)->src.decode = FAudio_INTERNAL_DecodeWMAERROR; +#endif /* HAVE_WMADEC */ + } else if ((*ppSourceVoice)->src.format->wFormatTag == FAUDIO_FORMAT_MSADPCM) { (*ppSourceVoice)->src.decode = ((*ppSourceVoice)->src.format->nChannels == 2) ? @@ -555,6 +592,7 @@ uint32_t FAudio_CreateSubmixVoice( (*ppSubmixVoice)->filter.Type = FAUDIO_DEFAULT_FILTER_TYPE; (*ppSubmixVoice)->filter.Frequency = FAUDIO_DEFAULT_FILTER_FREQUENCY; (*ppSubmixVoice)->filter.OneOverQ = FAUDIO_DEFAULT_FILTER_ONEOVERQ; + (*ppSubmixVoice)->filter.WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; (*ppSubmixVoice)->sendLock = FAudio_PlatformCreateMutex(); LOG_MUTEX_CREATE(audio, (*ppSubmixVoice)->sendLock) (*ppSubmixVoice)->effectLock = FAudio_PlatformCreateMutex(); @@ -647,16 +685,27 @@ uint32_t FAudio_CreateMasteringVoice( uint32_t DeviceIndex, const FAudioEffectChain *pEffectChain ) { - FAudioDeviceDetails details; - LOG_API_ENTER(audio) /* For now we only support one allocated master voice at a time */ FAudio_assert(audio->master == NULL); - if (FAudio_GetDeviceDetails(audio, DeviceIndex, &details) != 0) + if ( InputChannels == FAUDIO_DEFAULT_CHANNELS || + InputSampleRate == FAUDIO_DEFAULT_SAMPLERATE ) { - return FAUDIO_E_INVALID_CALL; + FAudioDeviceDetails details; + if (FAudio_GetDeviceDetails(audio, DeviceIndex, &details) != 0) + { + return FAUDIO_E_INVALID_CALL; + } + if (InputChannels == FAUDIO_DEFAULT_CHANNELS) + { + InputChannels = details.OutputFormat.Format.nChannels; + } + if (InputSampleRate == FAUDIO_DEFAULT_SAMPLERATE) + { + InputSampleRate = details.OutputFormat.Format.nSamplesPerSec; + } } *ppMasteringVoice = (FAudioMasteringVoice*) audio->pMalloc(sizeof(FAudioVoice)); @@ -673,12 +722,8 @@ uint32_t FAudio_CreateMasteringVoice( (*ppMasteringVoice)->volume = 1.0f; /* Master Properties */ - (*ppMasteringVoice)->master.inputChannels = (InputChannels == FAUDIO_DEFAULT_CHANNELS) ? - details.OutputFormat.Format.nChannels : - InputChannels; - (*ppMasteringVoice)->master.inputSampleRate = (InputSampleRate == FAUDIO_DEFAULT_SAMPLERATE) ? - details.OutputFormat.Format.nSamplesPerSec : - InputSampleRate; + (*ppMasteringVoice)->master.inputChannels = InputChannels; + (*ppMasteringVoice)->master.inputSampleRate = InputSampleRate; /* Sends/Effects */ FAudio_zero(&(*ppMasteringVoice)->sends, sizeof(FAudioVoiceSends)); @@ -1258,8 +1303,8 @@ uint32_t FAudioVoice_SetOutputVoices( /* Allocate the whole send filter array if needed... */ if (voice->sendFilter == NULL) { - voice->sendFilter = (FAudioFilterParameters*) voice->audio->pMalloc( - sizeof(FAudioFilterParameters) * pSendList->SendCount + voice->sendFilter = (FAudioFilterParametersEXT*) voice->audio->pMalloc( + sizeof(FAudioFilterParametersEXT) * pSendList->SendCount ); } if (voice->sendFilterState == NULL) @@ -1277,6 +1322,7 @@ uint32_t FAudioVoice_SetOutputVoices( voice->sendFilter[i].Type = FAUDIO_DEFAULT_FILTER_TYPE; voice->sendFilter[i].Frequency = FAUDIO_DEFAULT_FILTER_FREQUENCY; voice->sendFilter[i].OneOverQ = FAUDIO_DEFAULT_FILTER_ONEOVERQ; + voice->sendFilter[i].WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; voice->sendFilterState[i] = (FAudioFilterState*) voice->audio->pMalloc( sizeof(FAudioFilterState) * outChannels ); @@ -1602,9 +1648,9 @@ uint32_t FAudioVoice_GetEffectParameters( return 0; } -uint32_t FAudioVoice_SetFilterParameters( +uint32_t FAudioVoice_SetFilterParametersEXT( FAudioVoice *voice, - const FAudioFilterParameters *pParameters, + const FAudioFilterParametersEXT *pParameters, uint32_t OperationSet ) { LOG_API_ENTER(voice->audio) @@ -1640,7 +1686,7 @@ uint32_t FAudioVoice_SetFilterParameters( FAudio_memcpy( &voice->filter, pParameters, - sizeof(FAudioFilterParameters) + sizeof(FAudioFilterParametersEXT) ); FAudio_PlatformUnlockMutex(voice->filterLock); LOG_MUTEX_UNLOCK(voice->audio, voice->filterLock) @@ -1649,9 +1695,23 @@ uint32_t FAudioVoice_SetFilterParameters( return 0; } -void FAudioVoice_GetFilterParameters( +uint32_t FAudioVoice_SetFilterParameters( + FAudioVoice* voice, + const FAudioFilterParameters* pParameters, + uint32_t OperationSet +) { + FAudioFilterParametersEXT ext_parameters; + ext_parameters.Type = pParameters->Type; + ext_parameters.OneOverQ = pParameters->OneOverQ; + ext_parameters.Frequency = pParameters->Frequency; + ext_parameters.WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; + + return FAudioVoice_SetFilterParametersEXT(voice, &ext_parameters, OperationSet); +} + +void FAudioVoice_GetFilterParametersEXT( FAudioVoice *voice, - FAudioFilterParameters *pParameters + FAudioFilterParametersEXT *pParameters ) { LOG_API_ENTER(voice->audio) @@ -1675,17 +1735,34 @@ void FAudioVoice_GetFilterParameters( FAudio_memcpy( pParameters, &voice->filter, - sizeof(FAudioFilterParameters) + sizeof(FAudioFilterParametersEXT) ); FAudio_PlatformUnlockMutex(voice->filterLock); LOG_MUTEX_UNLOCK(voice->audio, voice->filterLock) LOG_API_EXIT(voice->audio) } -uint32_t FAudioVoice_SetOutputFilterParameters( +void FAudioVoice_GetFilterParameters( + FAudioVoice* voice, + FAudioFilterParameters* pParameters +) { + FAudioFilterParametersEXT ext_parameters; + ext_parameters.Type = pParameters->Type; + ext_parameters.OneOverQ = pParameters->OneOverQ; + ext_parameters.Frequency = pParameters->Frequency; + ext_parameters.WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; + + FAudioVoice_GetFilterParametersEXT(voice, &ext_parameters); + + pParameters->Type = ext_parameters.Type; + pParameters->Frequency = ext_parameters.Frequency; + pParameters->OneOverQ = ext_parameters.OneOverQ; +} + +uint32_t FAudioVoice_SetOutputFilterParametersEXT( FAudioVoice *voice, FAudioVoice *pDestinationVoice, - const FAudioFilterParameters *pParameters, + const FAudioFilterParametersEXT *pParameters, uint32_t OperationSet ) { uint32_t i; @@ -1753,7 +1830,7 @@ uint32_t FAudioVoice_SetOutputFilterParameters( FAudio_memcpy( &voice->sendFilter[i], pParameters, - sizeof(FAudioFilterParameters) + sizeof(FAudioFilterParametersEXT) ); FAudio_PlatformUnlockMutex(voice->sendLock); @@ -1762,10 +1839,25 @@ uint32_t FAudioVoice_SetOutputFilterParameters( return 0; } -void FAudioVoice_GetOutputFilterParameters( +uint32_t FAudioVoice_SetOutputFilterParameters( + FAudioVoice* voice, + FAudioVoice* pDestinationVoice, + const FAudioFilterParameters* pParameters, + uint32_t OperationSet +) { + FAudioFilterParametersEXT ext_parameters; + ext_parameters.Type = pParameters->Type; + ext_parameters.OneOverQ = pParameters->OneOverQ; + ext_parameters.Frequency = pParameters->Frequency; + ext_parameters.WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; + + return FAudioVoice_SetOutputFilterParametersEXT(voice, pDestinationVoice, &ext_parameters, OperationSet); +} + +void FAudioVoice_GetOutputFilterParametersEXT( FAudioVoice *voice, FAudioVoice *pDestinationVoice, - FAudioFilterParameters *pParameters + FAudioFilterParametersEXT *pParameters ) { uint32_t i; @@ -1821,7 +1913,7 @@ void FAudioVoice_GetOutputFilterParameters( FAudio_memcpy( pParameters, &voice->sendFilter[i], - sizeof(FAudioFilterParameters) + sizeof(FAudioFilterParametersEXT) ); FAudio_PlatformUnlockMutex(voice->sendLock); @@ -1876,6 +1968,24 @@ uint32_t FAudioVoice_SetVolume( return 0; } +void FAudioVoice_GetOutputFilterParameters( + FAudioVoice* voice, + FAudioVoice* pDestinationVoice, + FAudioFilterParameters* pParameters +) { + FAudioFilterParametersEXT ext_parameters; + ext_parameters.Type = pParameters->Type; + ext_parameters.OneOverQ = pParameters->OneOverQ; + ext_parameters.Frequency = pParameters->Frequency; + ext_parameters.WetDryMix = FAUDIO_DEFAULT_FILTER_WETDRYMIX_EXT; + + FAudioVoice_GetOutputFilterParametersEXT(voice, pDestinationVoice, &ext_parameters); + + pParameters->Type = ext_parameters.Type; + pParameters->Frequency = ext_parameters.Frequency; + pParameters->OneOverQ = ext_parameters.OneOverQ; +} + void FAudioVoice_GetVolume( FAudioVoice *voice, float *pVolume @@ -2155,11 +2265,71 @@ void FAudioVoice_GetOutputMatrix( LOG_API_EXIT(voice->audio) } -void FAudioVoice_DestroyVoice(FAudioVoice *voice) +static uint32_t check_for_sends_to_voice(FAudioVoice *voice) { + FAudio *audio = voice->audio; + uint32_t ret = 0; + FAudioSourceVoice *source; + FAudioSubmixVoice *submix; + LinkedList *list; uint32_t i; + + FAudio_PlatformLockMutex(audio->sourceLock); + list = audio->sources; + while (list != NULL) + { + source = (FAudioSourceVoice*) list->entry; + for (i = 0; i < source->sends.SendCount; i += 1) + if (source->sends.pSends[i].pOutputVoice == voice) + { + ret = 0x80004005; /* E_FAIL */ + break; + } + if (ret) + break; + list = list->next; + } + FAudio_PlatformUnlockMutex(audio->sourceLock); + + if (ret) + return ret; + + FAudio_PlatformLockMutex(audio->submixLock); + list = audio->submixes; + while (list != NULL) + { + submix = (FAudioSubmixVoice*) list->entry; + for (i = 0; i < submix->sends.SendCount; i += 1) + if (submix->sends.pSends[i].pOutputVoice == voice) + { + ret = 0x80004005; /* E_FAIL */ + break; + } + if (ret) + break; + list = list->next; + } + FAudio_PlatformUnlockMutex(audio->submixLock); + + return ret; +} + +uint32_t FAudioVoice_DestroyVoiceSafeEXT(FAudioVoice *voice) +{ + uint32_t i, ret; LOG_API_ENTER(voice->audio) + if ((ret = check_for_sends_to_voice(voice))) + { + LOG_ERROR( + voice->audio, + "Voice %p is an output for other voice(s)", + voice + ) + LOG_API_EXIT(voice->audio) + return ret; + } + /* TODO: Check for dependencies and remove from audio graph first! */ FAudio_OPERATIONSET_ClearAllForVoice(voice); @@ -2208,12 +2378,12 @@ void FAudioVoice_DestroyVoice(FAudioVoice *voice) voice->audio->pFree(voice->src.format); LOG_MUTEX_DESTROY(voice->audio, voice->src.bufferLock) FAudio_PlatformDestroyMutex(voice->src.bufferLock); -#ifdef HAVE_GSTREAMER - if (voice->src.gstreamer) +#ifdef HAVE_WMADEC + if (voice->src.wmadec) { - FAudio_GSTREAMER_free(voice); + FAudio_WMADEC_free(voice); } -#endif /* HAVE_GSTREAMER */ +#endif /* HAVE_WMADEC */ } else if (voice->type == FAUDIO_VOICE_SUBMIX) { @@ -2333,6 +2503,12 @@ void FAudioVoice_DestroyVoice(FAudioVoice *voice) LOG_API_EXIT(voice->audio) FAudio_Release(voice->audio); voice->audio->pFree(voice); + return 0; +} + +void FAudioVoice_DestroyVoice(FAudioVoice *voice) +{ + FAudioVoice_DestroyVoiceSafeEXT(voice); } /* FAudioSourceVoice Interface */ @@ -2421,10 +2597,12 @@ uint32_t FAudioSourceVoice_SubmitSourceBuffer( ) FAudio_assert(voice->type == FAUDIO_VOICE_SOURCE); -#ifdef HAVE_GSTREAMER - FAudio_assert( (voice->src.gstreamer != NULL && pBufferWMA != NULL) || - (voice->src.gstreamer == NULL && pBufferWMA == NULL) ); -#endif /* HAVE_GSTREAMER */ +#ifdef HAVE_WMADEC + FAudio_assert( (voice->src.wmadec != NULL && (pBufferWMA != NULL || + (voice->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2 || + voice->src.format->wFormatTag == FAUDIO_FORMAT_EXTENSIBLE))) || + (voice->src.wmadec == NULL && (pBufferWMA == NULL && voice->src.format->wFormatTag != FAUDIO_FORMAT_XMAUDIO2)) ); +#endif /* HAVE_WMADEC */ /* Start off with whatever they just sent us... */ playBegin = pBuffer->PlayBegin; @@ -2451,6 +2629,11 @@ uint32_t FAudioSourceVoice_SubmitSourceBuffer( fmtex->wSamplesPerBlock ) - playBegin; } + else if (voice->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2) + { + FAudioXMA2WaveFormat *fmtex = (FAudioXMA2WaveFormat*) voice->src.format; + playLength = fmtex->dwSamplesEncoded - playBegin; + } else if (pBufferWMA != NULL) { playLength = ( @@ -2467,7 +2650,7 @@ uint32_t FAudioSourceVoice_SubmitSourceBuffer( } } - if (pBuffer->LoopCount > 0 && pBufferWMA == NULL) + if (pBuffer->LoopCount > 0 && pBufferWMA == NULL && voice->src.format->wFormatTag != FAUDIO_FORMAT_XMAUDIO2) { /* "The value of LoopBegin must be less than PlayBegin + PlayLength" */ if (loopBegin >= (playBegin + playLength)) @@ -2509,7 +2692,7 @@ uint32_t FAudioSourceVoice_SubmitSourceBuffer( pBuffer->AudioBytes / voice->src.format->nBlockAlign ) * voice->src.format->nBlockAlign; } - else if (pBufferWMA != NULL) + else if (pBufferWMA != NULL || voice->src.format->wFormatTag == FAUDIO_FORMAT_XMAUDIO2) { /* WMA only supports looping the whole buffer */ loopBegin = 0; diff --git a/src/FAudioFX_reverb.c b/src/FAudioFX_reverb.c index a9ce06a5ce..219495e791 100644 --- a/src/FAudioFX_reverb.c +++ b/src/FAudioFX_reverb.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -130,11 +130,13 @@ static inline float DspDelay_Process(DspDelay *filter, float sample_in) return delay_out; } +/* FIXME: This is currently unused! What was it for...? -flibit static inline float DspDelay_Tap(DspDelay *filter, uint32_t delay) { FAudio_assert(delay <= filter->delay); return filter->buffer[(filter->write_idx - delay + filter->capacity) % filter->capacity]; } +*/ static inline void DspDelay_Reset(DspDelay *filter) { @@ -181,7 +183,7 @@ static inline void DspBiQuad_Change( float q, float gain ) { - const float TWOPI = 6.283185307179586476925286766559005; + const float TWOPI = (float)6.283185307179586476925286766559005; float theta_c = (TWOPI * frequency) / (float) filter->sampleRate; float mu = DbGainToFactor(gain); float beta = (type == DSP_BIQUAD_LOWSHELVING) ? @@ -477,13 +479,68 @@ static float APF_OUT_DELAYS[REVERB_COUNT_APF_OUT] = 7.73f }; -static const float STEREO_SPREAD[4] = +typedef enum FAudio_ChannelPositionFlags { - 0.0f, - 0.5216f, - 0.0f, - 0.5216f -}; + Position_Left = 0x1, + Position_Right = 0x2, + Position_Center = 0x4, + Position_Rear = 0x8, +} FAudio_ChannelPositionFlags; + +static FAudio_ChannelPositionFlags FAudio_GetChannelPositionFlags(int32_t total_channels, int32_t channel) +{ + switch (total_channels) + { + case 1: + return Position_Center; + + case 2: + return (channel == 0) ? Position_Left : Position_Right; + + case 4: + switch (channel) + { + case 0: + return Position_Left; + case 1: + return Position_Right; + case 2: + return Position_Left | Position_Rear; + case 3: + return Position_Right | Position_Rear; + } + FAudio_assert(0 && "Unsupported channel count"); + break; + case 5: + switch (channel) + { + case 0: + return Position_Left; + case 1: + return Position_Right; + case 2: + return Position_Center; + case 3: + return Position_Left | Position_Rear; + case 4: + return Position_Right | Position_Rear; + } + FAudio_assert(0 && "Unsupported channel count"); + break; + default: + FAudio_assert(0 && "Unsupported channel count"); + break; + } + + /* shouldn't happen, but default to left speaker */ + return Position_Left; +} + +float FAudio_GetStereoSpreadDelayMS(int32_t total_channels, int32_t channel) +{ + FAudio_ChannelPositionFlags flags = FAudio_GetChannelPositionFlags(total_channels, channel); + return (flags & Position_Right) ? 0.5216f : 0.0f; +} typedef struct DspReverbChannel { @@ -503,7 +560,7 @@ typedef struct DspReverb int32_t in_channels; int32_t out_channels; int32_t reverb_channels; - DspReverbChannel channel[4]; + DspReverbChannel channel[5]; float early_gain; float reverb_gain; @@ -521,7 +578,7 @@ static inline void DspReverb_Create( ) { int32_t i, c; - FAudio_assert(in_channels == 1 || in_channels == 2); + FAudio_assert(in_channels == 1 || in_channels == 2 || in_channels == 6); FAudio_assert(out_channels == 1 || out_channels == 2 || out_channels == 6); FAudio_zero(reverb, sizeof(DspReverb)); @@ -538,7 +595,14 @@ static inline void DspReverb_Create( ); } - reverb->reverb_channels = (out_channels == 6) ? 4 : out_channels; + if (out_channels == 6) + { + reverb->reverb_channels = (in_channels == 6) ? 5 : 4; + } + else + { + reverb->reverb_channels = out_channels; + } for (c = 0; c < reverb->reverb_channels; c += 1) { @@ -554,7 +618,7 @@ static inline void DspReverb_Create( DspCombShelving_Initialize( &reverb->channel[c].lpf_comb[i], sampleRate, - COMB_DELAYS[i] + STEREO_SPREAD[c], + COMB_DELAYS[i] + FAudio_GetStereoSpreadDelayMS(reverb->reverb_channels, c), 500, 500, -6, @@ -569,7 +633,7 @@ static inline void DspReverb_Create( DspAllPass_Initialize( &reverb->channel[c].apf_out[i], sampleRate, - APF_OUT_DELAYS[i] + STEREO_SPREAD[c], + APF_OUT_DELAYS[i] + FAudio_GetStereoSpreadDelayMS(reverb->reverb_channels, c), 0.5f, pMalloc ); @@ -634,13 +698,6 @@ static inline void DspReverb_SetParameters( FAudioFXReverbParameters *params ) { float early_diffusion, late_diffusion; - float channel_delay[4] = - { - 0.0f, - 0.0f, - params->RearDelay, - params->RearDelay - }; DspCombShelving *comb; int32_t i, c; @@ -662,9 +719,14 @@ static inline void DspReverb_SetParameters( /* Reverberation */ for (c = 0; c < reverb->reverb_channels; c += 1) { + float channel_delay = + (FAudio_GetChannelPositionFlags(reverb->reverb_channels, c) & Position_Rear) ? + params->RearDelay : + 0.0f; + DspDelay_Change( &reverb->channel[c].reverb_delay, - (float) params->ReverbDelay + channel_delay[c] + (float) params->ReverbDelay + channel_delay ); for (i = 0; i < REVERB_COUNT_COMB; i += 1) @@ -674,7 +736,7 @@ static inline void DspReverb_SetParameters( /* Set decay time of comb filter */ DspDelay_Change( &comb->comb_delay, - COMB_DELAYS[i] + STEREO_SPREAD[c] + COMB_DELAYS[i] + FAudio_GetStereoSpreadDelayMS(reverb->reverb_channels, c) ); comb->comb_feedback_gain = DspComb_FeedbackFromRT60( &comb->comb_delay, @@ -709,11 +771,14 @@ static inline void DspReverb_SetParameters( for (c = 0; c < reverb->reverb_channels; c += 1) { + FAudio_ChannelPositionFlags position = FAudio_GetChannelPositionFlags(reverb->reverb_channels, c); + float gain; + for (i = 0; i < REVERB_COUNT_APF_OUT; i += 1) { DspAllPass_Change( &reverb->channel[c].apf_out[i], - APF_OUT_DELAYS[i] + STEREO_SPREAD[c], + APF_OUT_DELAYS[i] + FAudio_GetStereoSpreadDelayMS(reverb->reverb_channels, c), late_diffusion ); } @@ -726,24 +791,39 @@ static inline void DspReverb_SetParameters( params->RoomFilterMain + params->RoomFilterHF ); - reverb->channel[c].gain = 1.5f - ( - ((c % 2 == 0 ? - params->PositionMatrixLeft : - params->PositionMatrixRight - ) / 27.0f) * 0.5f - ); - if (c >= 2) + if (position & Position_Left) + { + gain = params->PositionMatrixLeft; + } + else if (position & Position_Right) + { + gain = params->PositionMatrixRight; + } + else /*if (position & Position_Center) */ + { + gain = (params->PositionMatrixLeft + params->PositionMatrixRight) / 2.0f; + } + reverb->channel[c].gain = 1.5f - (gain / 27.0f) * 0.5f; + + if (position & Position_Rear) { /* Rear-channel Attenuation */ reverb->channel[c].gain *= 0.75f; } - reverb->channel[c].early_gain = 1.2f - ( - ((c % 2 == 0 ? - params->PositionLeft : - params->PositionRight - ) / 6.0f) * 0.2f - ); + if (position & Position_Left) + { + gain = params->PositionLeft; + } + else if (position & Position_Right) + { + gain = params->PositionRight; + } + else /*if (position & Position_Center) */ + { + gain = (params->PositionLeft + params->PositionRight) / 2.0f; + } + reverb->channel[c].early_gain = 1.2f - (gain / 6.0f) * 0.2f; reverb->channel[c].early_gain = ( reverb->channel[c].early_gain * reverb->early_gain @@ -937,35 +1017,35 @@ static inline float DspReverb_INTERNAL_Process_2_to_2( size_t sample_count ) { const float *in_end = samples_in + sample_count; - float in, in_ratio, early, late[2]; + float in, early, late[2]; float squared_sum = 0; while (samples_in < in_end) { /* Input - Combine 2 channels into 1 */ in = (samples_in[0] + samples_in[1]) / 2.0f; - in_ratio = in * reverb->dry_ratio; - samples_in += 2; /* Early Reflections */ early = DspReverb_INTERNAL_ProcessEarly(reverb, in); /* Reverberation with Wet/Dry Mix */ - late[0] = DspReverb_INTERNAL_ProcessChannel( + late[0] = (DspReverb_INTERNAL_ProcessChannel( reverb, &reverb->channel[0], early - ); + ) * reverb->wet_ratio) + samples_in[0] * reverb->dry_ratio; late[1] = (DspReverb_INTERNAL_ProcessChannel( reverb, &reverb->channel[1], early - ) * reverb->wet_ratio) + in_ratio; + ) * reverb->wet_ratio) + samples_in[1] * reverb->dry_ratio; squared_sum += (late[0] * late[0]) + (late[1] * late[1]); /* Output */ *samples_out++ = late[0]; *samples_out++ = late[1]; + + samples_in += 2; } return squared_sum; @@ -1015,6 +1095,52 @@ static inline float DspReverb_INTERNAL_Process_2_to_5p1( return squared_sum; } +static inline float DspReverb_INTERNAL_Process_5p1_to_5p1( + DspReverb *reverb, + float *restrict samples_in, + float *restrict samples_out, + size_t sample_count +) { + const float *in_end = samples_in + sample_count; + float in, in_ratio, early, late[5]; + float squared_sum = 0; + int32_t c; + + while (samples_in < in_end) + { + /* Input - Combine non-LFE channels into 1 */ + in = (samples_in[0] + samples_in[1] + samples_in[2] + + samples_in[4] + samples_in[5]) / 5.0f; + in_ratio = in * reverb->dry_ratio; + + /* Early Reflections */ + early = DspReverb_INTERNAL_ProcessEarly(reverb, in); + + /* Reverberation with Wet/Dry Mix */ + for (c = 0; c < 5; c += 1) + { + late[c] = (DspReverb_INTERNAL_ProcessChannel( + reverb, + &reverb->channel[c], + early + ) * reverb->wet_ratio) + in_ratio; + squared_sum += late[c] * late[c]; + } + + /* Output */ + *samples_out++ = late[0]; /* Front Left */ + *samples_out++ = late[1]; /* Front Right */ + *samples_out++ = late[2]; /* Center */ + *samples_out++ = samples_in[3]; /* LFE, pass through */ + *samples_out++ = late[3]; /* Rear Left */ + *samples_out++ = late[4]; /* Rear Right */ + + samples_in += 6; + } + + return squared_sum; +} + #undef OUTPUT_SAMPLE /* Reverb FAPO Implementation */ @@ -1148,7 +1274,8 @@ uint32_t FAudioFXReverb_IsInputFormatSupported( else if (pOutputFormat->nChannels == 6) { if ( pRequestedInputFormat->nChannels != 1 && - pRequestedInputFormat->nChannels != 2 ) + pRequestedInputFormat->nChannels != 2 && + pRequestedInputFormat->nChannels != 6 ) { SET_SUPPORTED_FIELD(nChannels, 1); } @@ -1200,6 +1327,13 @@ uint32_t FAudioFXReverb_IsOutputFormatSupported( SET_SUPPORTED_FIELD(nChannels, pInputFormat->nChannels); } } + else if (pInputFormat->nChannels == 6) + { + if (pRequestedOutputFormat->nChannels != 6) + { + SET_SUPPORTED_FIELD(nChannels, pInputFormat->nChannels); + } + } else { SET_SUPPORTED_FIELD(nChannels, 1); @@ -1252,7 +1386,9 @@ uint32_t FAudioFXReverb_LockForProcess( pOutputLockedParameters->pFormat->nChannels == 6)) || (pInputLockedParameters->pFormat->nChannels == 2 && (pOutputLockedParameters->pFormat->nChannels == 2 || - pOutputLockedParameters->pFormat->nChannels == 6)))) + pOutputLockedParameters->pFormat->nChannels == 6)) || + (pInputLockedParameters->pFormat->nChannels == 6 && + pOutputLockedParameters->pFormat->nChannels == 6))) { return FAPO_E_FORMAT_UNSUPPORTED; } @@ -1273,6 +1409,22 @@ uint32_t FAudioFXReverb_LockForProcess( fapo->base.pMalloc ); + /* Initialize the effect to a default setting */ + if (fapo->apiVersion == 9) + { + DspReverb_SetParameters9( + &fapo->reverb, + (FAudioFXReverbParameters9*) fapo->base.m_pParameterBlocks + ); + } + else + { + DspReverb_SetParameters( + &fapo->reverb, + (FAudioFXReverbParameters*) fapo->base.m_pParameterBlocks + ); + } + /* Call parent to do basic validation */ return FAPOBase_LockForProcess( &fapo->base, @@ -1295,7 +1447,7 @@ static inline void FAudioFXReverb_CopyBuffer( return; } - /* 1 -> 1 or 2 -> 2 */ + /* equal channel count */ if (fapo->inBlockAlign == fapo->outBlockAlign) { FAudio_memcpy( @@ -1353,6 +1505,24 @@ void FAudioFXReverb_Process( FAudioFXReverbParameters *params; uint8_t update_params = FAPOBase_ParametersChanged(&fapo->base); float total; + + params = (FAudioFXReverbParameters*) FAPOBase_BeginProcess(&fapo->base); + + /* Update parameters before doing anything else */ + if (update_params) + { + if (fapo->apiVersion == 9) + { + DspReverb_SetParameters9( + &fapo->reverb, + (FAudioFXReverbParameters9*) params + ); + } + else + { + DspReverb_SetParameters(&fapo->reverb, params); + } + } /* Handle disabled filter */ if (IsEnabled == 0) @@ -1369,6 +1539,7 @@ void FAudioFXReverb_Process( ); } + FAPOBase_EndProcess(&fapo->base); return; } @@ -1382,24 +1553,6 @@ void FAudioFXReverb_Process( ); } - params = (FAudioFXReverbParameters*) FAPOBase_BeginProcess(&fapo->base); - - /* Update parameters */ - if (update_params) - { - if (fapo->apiVersion == 9) - { - DspReverb_SetParameters9( - &fapo->reverb, - (FAudioFXReverbParameters9*) params - ); - } - else - { - DspReverb_SetParameters(&fapo->reverb, params); - } - } - /* Run reverb effect */ #define PROCESS(pin, pout) \ DspReverb_INTERNAL_Process_##pin##_to_##pout( \ @@ -1421,10 +1574,14 @@ void FAudioFXReverb_Process( { total = PROCESS(1, 5p1); } - else + else if (fapo->reverb.in_channels == 2) { total = PROCESS(2, 5p1); } + else /* 5.1 */ + { + total = PROCESS(5p1, 5p1); + } break; } #undef PROCESS @@ -1528,16 +1685,6 @@ uint32_t FAudioCreateReverbWithCustomAllocatorEXT( sizeof(FAudioFXReverbParameters) * 3 ); result->apiVersion = 7; - #define INITPARAMS(offset) \ - FAudio_memcpy( \ - params + sizeof(FAudioFXReverbParameters) * offset, \ - &fxdefault, \ - sizeof(FAudioFXReverbParameters) \ - ); - INITPARAMS(0) - INITPARAMS(1) - INITPARAMS(2) - #undef INITPARAMS /* Initialize... */ FAudio_memcpy( @@ -1573,6 +1720,13 @@ uint32_t FAudioCreateReverbWithCustomAllocatorEXT( result->base.Destructor = FAudioFXReverb_Free; #undef ASSIGN_VT + /* Prepare the default parameters */ + result->base.base.Initialize( + result, + &fxdefault, + sizeof(FAudioFXReverbParameters) + ); + /* Finally. */ *ppApo = &result->base.base; return 0; @@ -1701,16 +1855,6 @@ uint32_t FAudioCreateReverb9WithCustomAllocatorEXT( sizeof(FAudioFXReverbParameters9) * 3 ); result->apiVersion = 9; - #define INITPARAMS(offset) \ - FAudio_memcpy( \ - params + sizeof(FAudioFXReverbParameters9) * offset, \ - &fxdefault, \ - sizeof(FAudioFXReverbParameters9) \ - ); - INITPARAMS(0) - INITPARAMS(1) - INITPARAMS(2) - #undef INITPARAMS /* Initialize... */ FAudio_memcpy( @@ -1746,6 +1890,13 @@ uint32_t FAudioCreateReverb9WithCustomAllocatorEXT( result->base.Destructor = FAudioFXReverb_Free; #undef ASSIGN_VT + /* Prepare the default parameters */ + result->base.base.Initialize( + result, + &fxdefault, + sizeof(FAudioFXReverbParameters9) + ); + /* Finally. */ *ppApo = &result->base.base; return 0; diff --git a/src/FAudioFX_volumemeter.c b/src/FAudioFX_volumemeter.c index ded77b9908..07c1c132e4 100644 --- a/src/FAudioFX_volumemeter.c +++ b/src/FAudioFX_volumemeter.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from diff --git a/src/FAudio_gstreamer.c b/src/FAudio_gstreamer.c deleted file mode 100644 index 18bd64ae70..0000000000 --- a/src/FAudio_gstreamer.c +++ /dev/null @@ -1,750 +0,0 @@ -/* FAudio - XAudio Reimplementation for FNA - * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team - * Copyright (c) 2019-2021 Andrew Eikum for CodeWeavers, Inc - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source distribution. - * - * Ethan "flibitijibibo" Lee - * - */ - -#ifdef HAVE_GSTREAMER - -#include "FAudio_internal.h" - -#include -#include -#include - -typedef struct FAudioGSTREAMER -{ - GstPad *srcpad; - GstElement *pipeline; - GstElement *dst; - GstElement *resampler; - GstSegment segment; - uint8_t *convertCache, *prevConvertCache; - size_t convertCacheLen, prevConvertCacheLen; - uint32_t curBlock, prevBlock; - size_t *blockSizes; -} FAudioGSTREAMER; - -#define SIZE_FROM_DST(sample) \ - ((sample) * voice->src.format->nChannels * sizeof(float)) -#define SIZE_FROM_SRC(sample) \ - ((sample) * voice->src.format->nChannels * (voice->src.format->wBitsPerSample / 8)) -#define SIZE_FROM_DST(sample) \ - ((sample) * voice->src.format->nChannels * sizeof(float)) -#define SAMPLES_FROM_SRC(len) \ - ((len) / voice->src.format->nChannels / (voice->src.format->wBitsPerSample / 8)) -#define SAMPLES_FROM_DST(len) \ - ((len) / voice->src.format->nChannels / sizeof(float)) -#define SIZE_SRC_TO_DST(len) \ - ((len) * (sizeof(float) / (voice->src.format->wBitsPerSample / 8))) -#define SIZE_DST_TO_SRC(len) \ - ((len) / (sizeof(float) / (voice->src.format->wBitsPerSample / 8))) - -static int FAudio_GSTREAMER_RestartDecoder(FAudioGSTREAMER *gstreamer) -{ - GstEvent *event; - - event = gst_event_new_flush_start(); - gst_pad_push_event(gstreamer->srcpad, event); - - event = gst_event_new_flush_stop(TRUE); - gst_pad_push_event(gstreamer->srcpad, event); - - event = gst_event_new_segment(&gstreamer->segment); - gst_pad_push_event(gstreamer->srcpad, event); - - gstreamer->curBlock = ~0u; - gstreamer->prevBlock = ~0u; - - if (gst_element_set_state(gstreamer->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) - { - return 0; - } - - return 1; -} - -static int FAudio_GSTREAMER_CheckForBusErrors(FAudioVoice *voice) -{ - GstBus *bus; - GstMessage *msg; - GError *err = NULL; - gchar *debug_info = NULL; - int ret = 0; - - bus = gst_pipeline_get_bus(GST_PIPELINE(voice->src.gstreamer->pipeline)); - - while((msg = gst_bus_pop_filtered(bus, GST_MESSAGE_ERROR))) - { - switch(GST_MESSAGE_TYPE(msg)) - { - case GST_MESSAGE_ERROR: - gst_message_parse_error(msg, &err, &debug_info); - LOG_ERROR( - voice->audio, - "Got gstreamer bus error from %s: %s (%s)", - GST_OBJECT_NAME(msg->src), - err->message, - debug_info ? debug_info : "none" - ) - g_clear_error(&err); - g_free(debug_info); - gst_message_unref(msg); - ret = 1; - break; - default: - gst_message_unref(msg); - break; - } - } - - gst_object_unref(bus); - - return ret; -} - -static size_t FAudio_GSTREAMER_FillConvertCache( - FAudioVoice *voice, - FAudioBuffer *buffer, - size_t maxBytes -) { - GstBuffer *src, *dst; - GstSample *sample; - GstMapInfo info; - size_t pulled, clipStartBytes, clipEndBytes, toCopyBytes; - GstAudioClippingMeta *cmeta; - GstFlowReturn push_ret; - - LOG_FUNC_ENTER(voice->audio) - - /* Write current block to input buffer, push to pipeline */ - src = gst_buffer_new_allocate( - NULL, - voice->src.format->nBlockAlign, - NULL - ); - - if ( gst_buffer_fill( - src, - 0, - buffer->pAudioData + ( - voice->src.format->nBlockAlign * - voice->src.gstreamer->curBlock - ), - voice->src.format->nBlockAlign - ) != voice->src.format->nBlockAlign ) - { - LOG_ERROR( - voice->audio, - "for voice %p, failed to copy whole chunk into buffer", - voice - ); - gst_buffer_unref(src); - return (size_t) -1; - } - - push_ret = gst_pad_push(voice->src.gstreamer->srcpad, src); - if( push_ret != GST_FLOW_OK && - push_ret != GST_FLOW_EOS ) - { - LOG_ERROR( - voice->audio, - "for voice %p, pushing buffer failed: 0x%x", - voice, - push_ret - ); - return (size_t) -1; - } - - pulled = 0; - while (1) - { - /* Pull frames one into cache */ - sample = gst_app_sink_try_pull_sample( - GST_APP_SINK(voice->src.gstreamer->dst), - 0 - ); - - if (!sample) - { - /* done decoding */ - break; - } - dst = gst_sample_get_buffer(sample); - gst_buffer_map(dst, &info, GST_MAP_READ); - - cmeta = gst_buffer_get_audio_clipping_meta(dst); - if (cmeta) - { - FAudio_assert(cmeta->format == GST_FORMAT_DEFAULT /* == samples */); - clipStartBytes = SIZE_FROM_DST(cmeta->start); - clipEndBytes = SIZE_FROM_DST(cmeta->end); - } - else - { - clipStartBytes = 0; - clipEndBytes = 0; - } - - toCopyBytes = FAudio_min(info.size - (clipStartBytes + clipEndBytes), maxBytes - pulled); - - if (voice->src.gstreamer->convertCacheLen < pulled + toCopyBytes) - { - voice->src.gstreamer->convertCacheLen = pulled + toCopyBytes; - voice->src.gstreamer->convertCache = (uint8_t*) voice->audio->pRealloc( - voice->src.gstreamer->convertCache, - pulled + toCopyBytes - ); - } - - - FAudio_memcpy(voice->src.gstreamer->convertCache + pulled, - info.data + clipStartBytes, - toCopyBytes - ); - - gst_buffer_unmap(dst, &info); - gst_sample_unref(sample); - - pulled += toCopyBytes; - } - - LOG_FUNC_EXIT(voice->audio) - - return pulled; -} - -static int FAudio_GSTREAMER_DecodeBlock(FAudioVoice *voice, FAudioBuffer *buffer, uint32_t block, size_t maxBytes) -{ - FAudioGSTREAMER *gstreamer = voice->src.gstreamer; - uint8_t *tmpBuf; - size_t tmpLen; - - if (gstreamer->curBlock != ~0u && block != gstreamer->curBlock + 1) - { - /* XAudio2 allows looping back to start of XMA buffers, but nothing else */ - if (block != 0) - { - LOG_ERROR( - voice->audio, - "for voice %p, out of sequence block: %u (cur: %d)\n", - voice, - block, - gstreamer->curBlock - ); - } - FAudio_assert(block == 0); - if (!FAudio_GSTREAMER_RestartDecoder(gstreamer)) - { - LOG_WARNING( - voice->audio, - "%s", - "Restarting decoder failed!" - ) - } - } - - /* store previous block to allow for minor rewinds (FAudio quirk) */ - tmpBuf = gstreamer->prevConvertCache; - tmpLen = gstreamer->prevConvertCacheLen; - gstreamer->prevConvertCache = gstreamer->convertCache; - gstreamer->prevConvertCacheLen = gstreamer->convertCacheLen; - gstreamer->convertCache = tmpBuf; - gstreamer->convertCacheLen = tmpLen; - - gstreamer->prevBlock = gstreamer->curBlock; - gstreamer->curBlock = block; - - gstreamer->blockSizes[block] = FAudio_GSTREAMER_FillConvertCache( - voice, - buffer, - maxBytes - ); - - return gstreamer->blockSizes[block] != (size_t) -1; -} - -static void FAudio_INTERNAL_DecodeGSTREAMER( - FAudioVoice *voice, - FAudioBuffer *buffer, - float *decodeCache, - uint32_t samples -) { - size_t byteOffset, siz, maxBytes; - uint32_t curBlock, curBufferOffset; - uint8_t *convertCache; - int error = 0; - FAudioGSTREAMER *gstreamer = voice->src.gstreamer; - - LOG_FUNC_ENTER(voice->audio) - - if (!gstreamer->blockSizes) - { - size_t sz = voice->src.bufferList->bufferWMA.PacketCount * sizeof(*gstreamer->blockSizes); - gstreamer->blockSizes = (size_t *) voice->audio->pMalloc(sz); - memset(gstreamer->blockSizes, 0xff, sz); - } - - curBufferOffset = voice->src.curBufferOffset; -decode: - byteOffset = SIZE_FROM_DST(curBufferOffset); - - /* the last block size can truncate the length of the buffer */ - maxBytes = SIZE_SRC_TO_DST(voice->src.bufferList->bufferWMA.pDecodedPacketCumulativeBytes[voice->src.bufferList->bufferWMA.PacketCount - 1]); - for (curBlock = 0; curBlock < voice->src.bufferList->bufferWMA.PacketCount; curBlock += 1) - { - /* decode to get real size */ - if (gstreamer->blockSizes[curBlock] == (size_t)-1) - { - if (!FAudio_GSTREAMER_DecodeBlock(voice, buffer, curBlock, maxBytes)) - { - error = 1; - goto done; - } - } - - if (gstreamer->blockSizes[curBlock] > byteOffset) - { - /* ensure curBlock is decoded in either slot */ - if (gstreamer->curBlock != curBlock && gstreamer->prevBlock != curBlock) - { - if (!FAudio_GSTREAMER_DecodeBlock(voice, buffer, curBlock, maxBytes)) - { - error = 1; - goto done; - } - } - break; - } - - byteOffset -= gstreamer->blockSizes[curBlock]; - maxBytes -= gstreamer->blockSizes[curBlock]; - if(maxBytes == 0) - break; - } - - if (curBlock >= voice->src.bufferList->bufferWMA.PacketCount || maxBytes == 0) - { - goto done; - } - - /* If we're in a different block from last time, decode! */ - if (curBlock == gstreamer->curBlock) - { - convertCache = gstreamer->convertCache; - } - else if (curBlock == gstreamer->prevBlock) - { - convertCache = gstreamer->prevConvertCache; - } - else - { - convertCache = NULL; - FAudio_assert(0 && "Somehow got an undecoded curBlock!"); - } - - /* Copy to decodeCache, finally. */ - siz = FAudio_min(SIZE_FROM_DST(samples), gstreamer->blockSizes[curBlock] - byteOffset); - if (convertCache) - { - FAudio_memcpy( - decodeCache, - convertCache + byteOffset, - siz - ); - } - else - { - FAudio_memset( - decodeCache, - 0, - siz - ); - } - - /* Increment pointer, decrement remaining sample count */ - decodeCache += siz / sizeof(float); - samples -= SAMPLES_FROM_DST(siz); - curBufferOffset += SAMPLES_FROM_DST(siz); - -done: - if (FAudio_GSTREAMER_CheckForBusErrors(voice)) - { - LOG_ERROR( - voice->audio, - "%s", - "Got a bus error after decoding!" - ) - - error = 1; - } - - /* If the cache isn't filled yet, keep decoding! */ - if (samples > 0) - { - if ( !error && - curBlock < voice->src.bufferList->bufferWMA.PacketCount - 1 ) - { - goto decode; - } - - /* out of stuff to decode, write blank and exit */ - FAudio_memset(decodeCache, 0, SIZE_FROM_DST(samples)); - } - - LOG_FUNC_EXIT(voice->audio) -} - -void FAudio_GSTREAMER_end_buffer(FAudioSourceVoice *pSourceVoice) -{ - FAudioGSTREAMER *gstreamer = pSourceVoice->src.gstreamer; - - LOG_FUNC_ENTER(pSourceVoice->audio) - - pSourceVoice->audio->pFree(gstreamer->blockSizes); - gstreamer->blockSizes = NULL; - - gstreamer->curBlock = ~0u; - gstreamer->prevBlock = ~0u; - - LOG_FUNC_EXIT(pSourceVoice->audio) -} - -static void FAudio_GSTREAMER_NewDecodebinPad(GstElement *decodebin, - GstPad *pad, gpointer user) -{ - FAudioGSTREAMER *gstreamer = user; - GstPad *ac_sink; - - ac_sink = gst_element_get_static_pad(gstreamer->resampler, "sink"); - if (GST_PAD_IS_LINKED(ac_sink)) - { - gst_object_unref(ac_sink); - return; - } - - gst_pad_link(pad, ac_sink); - - gst_object_unref(ac_sink); -} - -uint32_t FAudio_GSTREAMER_init(FAudioSourceVoice *pSourceVoice, uint32_t type) -{ - FAudioGSTREAMER *result; - GstElement *decoder = NULL, *converter = NULL; - GstCaps *caps; - int version; - GstBuffer *codec_data; - size_t codec_data_size; - uint8_t *extradata; - uint8_t fakeextradata[16]; - GstPad *decoder_sink; - GstEvent *event; - - LOG_FUNC_ENTER(pSourceVoice->audio) - - /* Init GStreamer statically. The docs tell us not to exit, so I guess - * we're supposed to just leak! - */ - if (!gst_is_initialized()) - { - /* Apparently they ask for this to leak... */ - gst_init(NULL, NULL); - } - - /* Match the format with the codec */ - switch (type) - { - #define GSTTYPE(fmt, ver) \ - case FAUDIO_FORMAT_##fmt: version = ver; break; - GSTTYPE(WMAUDIO2, 2) - GSTTYPE(WMAUDIO3, 3) - GSTTYPE(WMAUDIO_LOSSLESS, 4) - /* FIXME: XMA2 */ - #undef GSTTYPE - default: - LOG_ERROR( - pSourceVoice->audio, - "%X codec not supported!", - type - ) - LOG_FUNC_EXIT(pSourceVoice->audio) - return FAUDIO_E_UNSUPPORTED_FORMAT; - } - - /* Set up the GStreamer pipeline. - * Note that we're not assigning names, since many pipelines will exist - * at the same time (one per source voice). - */ - result = (FAudioGSTREAMER*) pSourceVoice->audio->pMalloc(sizeof(FAudioGSTREAMER)); - FAudio_zero(result, sizeof(FAudioGSTREAMER)); - - result->pipeline = gst_pipeline_new(NULL); - - decoder = gst_element_factory_make("decodebin", NULL); - if (!decoder) - { - LOG_ERROR( - pSourceVoice->audio, - "Unable to create gstreamer decodebin; is %zu-bit gst-plugins-base installed?", - sizeof(void *) * 8 - ) - goto free_without_bin; - } - - g_signal_connect(decoder, "pad-added", G_CALLBACK(FAudio_GSTREAMER_NewDecodebinPad), result); - - result->srcpad = gst_pad_new(NULL, GST_PAD_SRC); - - result->resampler = gst_element_factory_make("audioresample", NULL); - if (!result->resampler) - { - LOG_ERROR( - pSourceVoice->audio, - "Unable to create gstreamer audioresample; is %zu-bit gst-plugins-base installed?", - sizeof(void *) * 8 - ) - goto free_without_bin; - } - - converter = gst_element_factory_make("audioconvert", NULL); - if (!converter) - { - LOG_ERROR( - pSourceVoice->audio, - "Unable to create gstreamer audioconvert; is %zu-bit gst-plugins-base installed?", - sizeof(void *) * 8 - ) - goto free_without_bin; - } - - result->dst = gst_element_factory_make("appsink", NULL); - if (!result->dst) - { - LOG_ERROR( - pSourceVoice->audio, - "Unable to create gstreamer appsink; is %zu-bit gst-plugins-base installed?", - sizeof(void *) * 8 - ) - goto free_without_bin; - } - - /* turn off sync so we can pull data without waiting for it to "play" in realtime */ - g_object_set(G_OBJECT(result->dst), "sync", FALSE, "async", TRUE, NULL); - - /* Compile the pipeline, finally. */ - if (!gst_pad_set_active(result->srcpad, TRUE)) - { - LOG_ERROR( - pSourceVoice->audio, - "%s", - "Unable to activate srcpad" - ) - goto free_without_bin; - } - - gst_bin_add_many( - GST_BIN(result->pipeline), - decoder, - result->resampler, - converter, - result->dst, - NULL - ); - - decoder_sink = gst_element_get_static_pad(decoder, "sink"); - - if (gst_pad_link(result->srcpad, decoder_sink) != GST_PAD_LINK_OK) - { - LOG_ERROR( - pSourceVoice->audio, - "%s", - "Unable to get link our src pad to decoder sink pad" - ) - gst_object_unref(decoder_sink); - goto free_with_bin; - } - - gst_object_unref(decoder_sink); - - if (!gst_element_link_many( - result->resampler, - converter, - result->dst, - NULL)) - { - LOG_ERROR( - pSourceVoice->audio, - "%s", - "Unable to get link pipeline" - ) - goto free_with_bin; - } - - /* send stream-start */ - event = gst_event_new_stream_start("faudio/gstreamer"); - gst_pad_push_event(result->srcpad, event); - - /* Prepare the input format */ - if (type == FAUDIO_FORMAT_WMAUDIO3) - { - const FAudioWaveFormatExtensible *wfx = - (FAudioWaveFormatExtensible*) pSourceVoice->src.format; - extradata = (uint8_t*) &wfx->Samples; - codec_data_size = pSourceVoice->src.format->cbSize; - } - else if (type == FAUDIO_FORMAT_WMAUDIO2) - { - FAudio_zero(fakeextradata, sizeof(fakeextradata)); - fakeextradata[4] = 31; - - extradata = fakeextradata; - codec_data_size = sizeof(fakeextradata); - } - else - { - extradata = NULL; - FAudio_assert(0 && "Unrecognized WMA format!"); - } - codec_data = gst_buffer_new_and_alloc(codec_data_size); - gst_buffer_fill(codec_data, 0, extradata, codec_data_size); - caps = gst_caps_new_simple( - "audio/x-wma", - "wmaversion", G_TYPE_INT, version, - "bitrate", G_TYPE_INT, pSourceVoice->src.format->nAvgBytesPerSec * 8, - "channels", G_TYPE_INT, pSourceVoice->src.format->nChannels, - "rate", G_TYPE_INT, pSourceVoice->src.format->nSamplesPerSec, - "block_align", G_TYPE_INT, pSourceVoice->src.format->nBlockAlign, - "depth", G_TYPE_INT, pSourceVoice->src.format->wBitsPerSample, - "codec_data", GST_TYPE_BUFFER, codec_data, - NULL - ); - event = gst_event_new_caps(caps); - gst_pad_push_event(result->srcpad, event); - gst_caps_unref(caps); - gst_buffer_unref(codec_data); - - /* Prepare the output format */ - caps = gst_caps_new_simple( - "audio/x-raw", - "format", G_TYPE_STRING, gst_audio_format_to_string(GST_AUDIO_FORMAT_F32), - "layout", G_TYPE_STRING, "interleaved", - "channels", G_TYPE_INT, pSourceVoice->src.format->nChannels, - "rate", G_TYPE_INT, pSourceVoice->src.format->nSamplesPerSec, - NULL - ); - - gst_app_sink_set_caps(GST_APP_SINK(result->dst), caps); - gst_caps_unref(caps); - - gst_segment_init(&result->segment, GST_FORMAT_TIME); - - if (!FAudio_GSTREAMER_RestartDecoder(result)) - { - LOG_ERROR( - pSourceVoice->audio, - "%s", - "Starting decoder failed!" - ) - goto free_with_bin; - } - - pSourceVoice->src.gstreamer = result; - pSourceVoice->src.decode = FAudio_INTERNAL_DecodeGSTREAMER; - - if (FAudio_GSTREAMER_CheckForBusErrors(pSourceVoice)) - { - LOG_ERROR( - pSourceVoice->audio, - "%s", - "Got a bus error after creation!" - ) - - pSourceVoice->src.gstreamer = NULL; - pSourceVoice->src.decode = NULL; - - goto free_with_bin; - } - - LOG_FUNC_EXIT(pSourceVoice->audio) - return 0; - -free_without_bin: - if (result->dst) - { - gst_object_unref(result->dst); - } - if (converter) - { - gst_object_unref(converter); - } - if (result->resampler) - { - gst_object_unref(result->resampler); - } - if (result->srcpad) - { - gst_object_unref(result->srcpad); - } - if (decoder) - { - gst_object_unref(decoder); - } - if (result->pipeline) - { - gst_object_unref(result->pipeline); - } - pSourceVoice->audio->pFree(result); - LOG_FUNC_EXIT(pSourceVoice->audio) - return FAUDIO_E_UNSUPPORTED_FORMAT; - -free_with_bin: - gst_object_unref(result->srcpad); - gst_object_unref(result->pipeline); - pSourceVoice->audio->pFree(result); - LOG_FUNC_EXIT(pSourceVoice->audio) - return FAUDIO_E_UNSUPPORTED_FORMAT; -} - -void FAudio_GSTREAMER_free(FAudioSourceVoice *voice) -{ - LOG_FUNC_ENTER(voice->audio) - gst_element_set_state(voice->src.gstreamer->pipeline, GST_STATE_NULL); - gst_object_unref(voice->src.gstreamer->pipeline); - gst_object_unref(voice->src.gstreamer->srcpad); - voice->audio->pFree(voice->src.gstreamer->convertCache); - voice->audio->pFree(voice->src.gstreamer->prevConvertCache); - voice->audio->pFree(voice->src.gstreamer->blockSizes); - voice->audio->pFree(voice->src.gstreamer); - voice->src.gstreamer = NULL; - LOG_FUNC_EXIT(voice->audio) -} - -#else - -extern int this_tu_is_empty; - -#endif /* HAVE_GSTREAMER */ - -/* vim: set noexpandtab shiftwidth=8 tabstop=8: */ diff --git a/src/FAudio_internal.c b/src/FAudio_internal.c index 78ab0483d2..37609ae888 100644 --- a/src/FAudio_internal.c +++ b/src/FAudio_internal.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -105,6 +105,7 @@ static const char *get_wformattag_string(const FAudioWaveFormatEx *fmt) FMT_STRING(IEEE_FLOAT) FMT_STRING(XMAUDIO2) FMT_STRING(WMAUDIO2) + FMT_STRING(WMAUDIO3) FMT_STRING(EXTENSIBLE) #undef FMT_STRING return "UNKNOWN!"; @@ -211,9 +212,9 @@ void LinkedList_RemoveEntry( FAudioFreeFunc pFree ) { LinkedList *latest, *prev; + FAudio_PlatformLockMutex(lock); latest = *start; prev = latest; - FAudio_PlatformLockMutex(lock); while (latest != NULL) { if (latest->entry == toRemove) @@ -305,14 +306,14 @@ static uint32_t FAudio_INTERNAL_GetBytesRequested( LOG_FUNC_ENTER(voice->audio) -#ifdef HAVE_GSTREAMER - if (voice->src.gstreamer != NULL) +#ifdef HAVE_WMADEC + if (voice->src.wmadec != NULL) { /* Always 0, per the spec */ LOG_FUNC_EXIT(voice->audio) return 0; } -#endif /* HAVE_GSTREAMER */ +#endif /* HAVE_WMADEC */ while (list != NULL && decoding > 0) { buffer = &list->buffer; @@ -382,6 +383,12 @@ static void FAudio_INTERNAL_DecodeBuffers( if ( voice->src.callback != NULL && voice->src.callback->OnBufferStart != NULL ) { + FAudio_PlatformUnlockMutex(voice->src.bufferLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock) + + FAudio_PlatformUnlockMutex(voice->sendLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock) + FAudio_PlatformUnlockMutex(voice->audio->sourceLock); LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) @@ -392,6 +399,12 @@ static void FAudio_INTERNAL_DecodeBuffers( FAudio_PlatformLockMutex(voice->audio->sourceLock); LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + + FAudio_PlatformLockMutex(voice->sendLock); + LOG_MUTEX_LOCK(voice->audio, voice->sendLock) + + FAudio_PlatformLockMutex(voice->src.bufferLock); + LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock) } } @@ -441,6 +454,12 @@ static void FAudio_INTERNAL_DecodeBuffers( if ( voice->src.callback != NULL && voice->src.callback->OnLoopEnd != NULL ) { + FAudio_PlatformUnlockMutex(voice->src.bufferLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock) + + FAudio_PlatformUnlockMutex(voice->sendLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock) + FAudio_PlatformUnlockMutex(voice->audio->sourceLock); LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) @@ -451,16 +470,22 @@ static void FAudio_INTERNAL_DecodeBuffers( FAudio_PlatformLockMutex(voice->audio->sourceLock); LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + + FAudio_PlatformLockMutex(voice->sendLock); + LOG_MUTEX_LOCK(voice->audio, voice->sendLock) + + FAudio_PlatformLockMutex(voice->src.bufferLock); + LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock) } } else { -#ifdef HAVE_GSTREAMER - if (voice->src.gstreamer != NULL) +#ifdef HAVE_WMADEC + if (voice->src.wmadec != NULL) { - FAudio_GSTREAMER_end_buffer(voice); + FAudio_WMADEC_end_buffer(voice); } -#endif /* HAVE_GSTREAMER */ +#endif /* HAVE_WMADEC */ /* For EOS we can stop storing fraction offsets */ if (buffer->Flags & FAUDIO_END_OF_STREAM) { @@ -503,6 +528,12 @@ static void FAudio_INTERNAL_DecodeBuffers( /* Callbacks */ if (voice->src.callback != NULL) { + FAudio_PlatformUnlockMutex(voice->src.bufferLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock) + + FAudio_PlatformUnlockMutex(voice->sendLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock) + FAudio_PlatformUnlockMutex(voice->audio->sourceLock); LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) @@ -521,6 +552,15 @@ static void FAudio_INTERNAL_DecodeBuffers( ); } + FAudio_PlatformLockMutex(voice->audio->sourceLock); + LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + + FAudio_PlatformLockMutex(voice->sendLock); + LOG_MUTEX_LOCK(voice->audio, voice->sendLock) + + FAudio_PlatformLockMutex(voice->src.bufferLock); + LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock) + /* One last chance at redemption */ if (buffer == NULL && voice->src.bufferList != NULL) { @@ -530,14 +570,29 @@ static void FAudio_INTERNAL_DecodeBuffers( if (buffer != NULL && voice->src.callback->OnBufferStart != NULL) { + FAudio_PlatformUnlockMutex(voice->src.bufferLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock) + + FAudio_PlatformUnlockMutex(voice->sendLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->sendLock) + + FAudio_PlatformUnlockMutex(voice->audio->sourceLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) + voice->src.callback->OnBufferStart( voice->src.callback, buffer->pContext ); - } - FAudio_PlatformLockMutex(voice->audio->sourceLock); - LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + FAudio_PlatformLockMutex(voice->audio->sourceLock); + LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + + FAudio_PlatformLockMutex(voice->sendLock); + LOG_MUTEX_LOCK(voice->audio, voice->sendLock) + + FAudio_PlatformLockMutex(voice->src.bufferLock); + LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock) + } } voice->audio->pFree(toDelete); @@ -598,7 +653,7 @@ static void FAudio_INTERNAL_DecodeBuffers( static inline void FAudio_INTERNAL_FilterVoice( FAudio *audio, - const FAudioFilterParameters *filter, + const FAudioFilterParametersEXT *filter, FAudioFilterState *filterState, float *samples, uint32_t numSamples, @@ -630,7 +685,7 @@ static inline void FAudio_INTERNAL_FilterVoice( filterState[ci][FAudioHighPassFilter] = samples[j * numChannels + ci] - filterState[ci][FAudioLowPassFilter] - (filter->OneOverQ * filterState[ci][FAudioBandPassFilter]); filterState[ci][FAudioBandPassFilter] = (filter->Frequency * filterState[ci][FAudioHighPassFilter]) + filterState[ci][FAudioBandPassFilter]; filterState[ci][FAudioNotchFilter] = filterState[ci][FAudioHighPassFilter] + filterState[ci][FAudioLowPassFilter]; - samples[j * numChannels + ci] = filterState[ci][filter->Type]; + samples[j * numChannels + ci] = filterState[ci][filter->Type] * filter->WetDryMix + samples[j * numChannels + ci] * (1.0f - filter->WetDryMix); } LOG_FUNC_EXIT(audio) @@ -1249,6 +1304,9 @@ static void FAudio_INTERNAL_FlushPendingBuffers(FAudioSourceVoice *voice) if (voice->src.callback != NULL && voice->src.callback->OnBufferEnd != NULL) { + FAudio_PlatformUnlockMutex(voice->src.bufferLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->src.bufferLock) + FAudio_PlatformUnlockMutex(voice->audio->sourceLock); LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) @@ -1259,6 +1317,9 @@ static void FAudio_INTERNAL_FlushPendingBuffers(FAudioSourceVoice *voice) FAudio_PlatformLockMutex(voice->audio->sourceLock); LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + + FAudio_PlatformLockMutex(voice->src.bufferLock); + LOG_MUTEX_LOCK(voice->audio, voice->src.bufferLock) } voice->audio->pFree(entry); } @@ -1862,7 +1923,7 @@ void FAudio_INTERNAL_DecodeMonoMSADPCM( int32_t midOffset; /* PCM block cache */ - int16_t blockCache[1012]; /* Max block size */ + int16_t *blockCache; /* Block size */ uint32_t bsize = ((FAudioADPCMWaveFormat*) voice->src.format)->wSamplesPerBlock; @@ -1879,6 +1940,7 @@ void FAudio_INTERNAL_DecodeMonoMSADPCM( midOffset = (voice->src.curBufferOffset % bsize); /* Read in each block directly to the decode cache */ + blockCache = (int16_t*) FAudio_alloca(bsize * sizeof(int16_t)); while (done < samples) { copy = FAudio_min(samples - done, bsize - midOffset); @@ -1896,6 +1958,7 @@ void FAudio_INTERNAL_DecodeMonoMSADPCM( done += copy; midOffset = 0; } + FAudio_dealloca(blockCache); LOG_FUNC_EXIT(voice->audio) } @@ -1913,7 +1976,7 @@ void FAudio_INTERNAL_DecodeStereoMSADPCM( int32_t midOffset; /* PCM block cache */ - int16_t blockCache[2024]; /* Max block size */ + int16_t *blockCache; /* Align, block size */ uint32_t bsize = ((FAudioADPCMWaveFormat*) voice->src.format)->wSamplesPerBlock; @@ -1930,6 +1993,7 @@ void FAudio_INTERNAL_DecodeStereoMSADPCM( midOffset = (voice->src.curBufferOffset % bsize); /* Read in each block directly to the decode cache */ + blockCache = (int16_t*) FAudio_alloca(bsize * 2 * sizeof(int16_t)); while (done < samples) { copy = FAudio_min(samples - done, bsize - midOffset); @@ -1947,6 +2011,7 @@ void FAudio_INTERNAL_DecodeStereoMSADPCM( done += copy; midOffset = 0; } + FAudio_dealloca(blockCache); LOG_FUNC_EXIT(voice->audio) } diff --git a/src/FAudio_internal.h b/src/FAudio_internal.h index 9441c5738d..039ab92164 100644 --- a/src/FAudio_internal.h +++ b/src/FAudio_internal.h @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -28,19 +28,24 @@ #include "FAPOBase.h" #include -#ifdef FAUDIO_UNKNOWN_PLATFORM + +#ifdef FAUDIO_WIN32_PLATFORM #include #include #include +#include #include #include #include +#define WIN32_LEAN_AND_MEAN +#include + #define FAudio_malloc malloc #define FAudio_realloc realloc #define FAudio_free free -#define FAudio_alloca(x) alloca(uint8_t, x) -#define FAudio_dealloca(x) dealloca(x) +#define FAudio_alloca(x) alloca(x) +#define FAudio_dealloca(x) (void)(x) #define FAudio_zero(ptr, size) memset(ptr, '\0', size) #define FAudio_memset(ptr, val, size) memset(ptr, val, size) #define FAudio_memcpy(dst, src, size) memcpy(dst, src, size) @@ -49,9 +54,11 @@ #define FAudio_strlen(ptr) strlen(ptr) #define FAudio_strcmp(str1, str2) strcmp(str1, str2) -#define FAudio_strlcpy(ptr1, ptr2, size) strlcpy(ptr1, ptr2, size) +#define FAudio_strncmp(str1, str2, size) strncmp(str1, str2, size) +#define FAudio_strlcpy(ptr1, ptr2, size) lstrcpynA(ptr1, ptr2, size) #define FAudio_pow(x, y) pow(x, y) +#define FAudio_powf(x, y) powf(x, y) #define FAudio_log(x) log(x) #define FAudio_log10(x) log10(x) #define FAudio_sin(x) sin(x) @@ -76,11 +83,12 @@ #define FAudio_assert assert #define FAudio_snprintf snprintf #define FAudio_vsnprintf vsnprintf -#define FAudio_Log(msg) fprintf(stderr, "%s\n", msg) #define FAudio_getenv getenv #define FAudio_PRIu64 PRIu64 #define FAudio_PRIx64 PRIx64 +extern void FAudio_Log(char const *msg); + /* FIXME: Assuming little-endian! */ #define FAudio_swap16LE(x) (x) #define FAudio_swap16BE(x) \ @@ -103,11 +111,44 @@ ((x << 24) & 0x00FF000000000000) | \ ((x << 32) & 0xFF00000000000000) #else + +#ifdef FAUDIO_SDL3_PLATFORM +#include +#include +#include +#include + +#define FAudio_swap16LE(x) SDL_Swap16LE(x) +#define FAudio_swap16BE(x) SDL_Swap16BE(x) +#define FAudio_swap32LE(x) SDL_Swap32LE(x) +#define FAudio_swap32BE(x) SDL_Swap32BE(x) +#define FAudio_swap64LE(x) SDL_Swap64LE(x) +#define FAudio_swap64BE(x) SDL_Swap64BE(x) + +/* SDL3 allows memcpy/memset for compiler optimization reasons */ +#ifdef SDL_SLOW_MEMCPY +#define STB_MEMCPY_OVERRIDE +#endif +#ifdef SDL_SLOW_MEMSET +#define STB_MEMSET_OVERRIDE +#endif +#else #include #include #include #include +#define FAudio_swap16LE(x) SDL_SwapLE16(x) +#define FAudio_swap16BE(x) SDL_SwapBE16(x) +#define FAudio_swap32LE(x) SDL_SwapLE32(x) +#define FAudio_swap32BE(x) SDL_SwapBE32(x) +#define FAudio_swap64LE(x) SDL_SwapLE64(x) +#define FAudio_swap64BE(x) SDL_SwapBE64(x) + +#define STB_MEMCPY_OVERRIDE +#define STB_MEMSET_OVERRIDE +#endif + #define FAudio_malloc SDL_malloc #define FAudio_realloc SDL_realloc #define FAudio_free SDL_free @@ -121,9 +162,11 @@ #define FAudio_strlen(ptr) SDL_strlen(ptr) #define FAudio_strcmp(str1, str2) SDL_strcmp(str1, str2) +#define FAudio_strncmp(str1, str2, size) SDL_strncmp(str1, str1, size) #define FAudio_strlcpy(ptr1, ptr2, size) SDL_strlcpy(ptr1, ptr2, size) #define FAudio_pow(x, y) SDL_pow(x, y) +#define FAudio_powf(x, y) SDL_powf(x, y) #define FAudio_log(x) SDL_log(x) #define FAudio_log10(x) SDL_log10(x) #define FAudio_sin(x) SDL_sin(x) @@ -164,13 +207,6 @@ #define FAudio_getenv SDL_getenv #define FAudio_PRIu64 SDL_PRIu64 #define FAudio_PRIx64 SDL_PRIx64 - -#define FAudio_swap16LE(x) SDL_SwapLE16(x) -#define FAudio_swap16BE(x) SDL_SwapBE16(x) -#define FAudio_swap32LE(x) SDL_SwapLE32(x) -#define FAudio_swap32BE(x) SDL_SwapBE32(x) -#define FAudio_swap64LE(x) SDL_SwapLE64(x) -#define FAudio_swap64BE(x) SDL_SwapBE64(x) #endif /* Easy Macros */ @@ -203,6 +239,15 @@ #define restrict #endif +/* Alignment macro for gcc/clang/msvc */ +#if defined(__clang__) || defined(__GNUC__) +#define ALIGN(type, boundary) type __attribute__((aligned(boundary))) +#elif defined(_MSC_VER) +#define ALIGN(type, boundary) __declspec(align(boundary)) type +#else +#define ALIGN(type, boundary) type +#endif + /* Threading Types */ typedef void* FAudioThread; @@ -316,13 +361,13 @@ void FAudio_OPERATIONSET_QueueSetEffectParameters( ); void FAudio_OPERATIONSET_QueueSetFilterParameters( FAudioVoice *voice, - const FAudioFilterParameters *pParameters, + const FAudioFilterParametersEXT *pParameters, uint32_t OperationSet ); void FAudio_OPERATIONSET_QueueSetOutputFilterParameters( FAudioVoice *voice, FAudioVoice *pDestinationVoice, - const FAudioFilterParameters *pParameters, + const FAudioFilterParametersEXT *pParameters, uint32_t OperationSet ); void FAudio_OPERATIONSET_QueueSetVolume( @@ -426,7 +471,7 @@ struct FAudioVoice float **sendCoefficients; float **mixCoefficients; FAudioMixCallback *sendMix; - FAudioFilterParameters *sendFilter; + FAudioFilterParametersEXT *sendFilter; FAudioFilterState **sendFilterState; struct { @@ -438,7 +483,7 @@ struct FAudioVoice uint8_t *parameterUpdates; uint8_t *inPlaceProcessing; } effects; - FAudioFilterParameters filter; + FAudioFilterParametersEXT filter; FAudioFilterState *filterState; FAudioMutex sendLock; FAudioMutex effectLock; @@ -464,10 +509,10 @@ struct FAudioVoice uint64_t curBufferOffsetDec; uint32_t curBufferOffset; - /* GStreamer */ -#ifdef HAVE_GSTREAMER - struct FAudioGSTREAMER *gstreamer; -#endif /* HAVE_GSTREAMER*/ + /* WMA decoding */ +#ifdef HAVE_WMADEC + struct FAudioWMADEC *wmadec; +#endif /* HAVE_WMADEC*/ /* Read-only */ float maxFreqRatio; @@ -611,10 +656,10 @@ void FAudio_INTERNAL_debug_fmt( #define LOG_FUNC_ENTER(engine) PRINT_DEBUG(engine, FUNC_CALLS, "FUNC Enter", "%s", __func__) #define LOG_FUNC_EXIT(engine) PRINT_DEBUG(engine, FUNC_CALLS, "FUNC Exit", "%s", __func__) /* TODO: LOG_TIMING */ -#define LOG_MUTEX_CREATE(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Create", "%p", mutex) -#define LOG_MUTEX_DESTROY(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Destroy", "%p", mutex) -#define LOG_MUTEX_LOCK(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Lock", "%p", mutex) -#define LOG_MUTEX_UNLOCK(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Unlock", "%p", mutex) +#define LOG_MUTEX_CREATE(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Create", "%p (%s)", mutex, #mutex) +#define LOG_MUTEX_DESTROY(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Destroy", "%p (%s)", mutex, #mutex) +#define LOG_MUTEX_LOCK(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Lock", "%p (%s)", mutex, #mutex) +#define LOG_MUTEX_UNLOCK(engine, mutex) PRINT_DEBUG(engine, LOCKS, "Mutex Unlock", "%p (%s)", mutex, #mutex) /* TODO: LOG_MEMORY */ /* TODO: LOG_STREAMING */ @@ -732,13 +777,13 @@ DECODE_FUNC(StereoMSADPCM) DECODE_FUNC(WMAERROR) #undef DECODE_FUNC -/* GStreamer */ +/* WMA decoding */ -#ifdef HAVE_GSTREAMER -uint32_t FAudio_GSTREAMER_init(FAudioSourceVoice *pSourceVoice, uint32_t type); -void FAudio_GSTREAMER_free(FAudioSourceVoice *voice); -void FAudio_GSTREAMER_end_buffer(FAudioSourceVoice *voice); -#endif /* HAVE_GSTREAMER */ +#ifdef HAVE_WMADEC +uint32_t FAudio_WMADEC_init(FAudioSourceVoice *pSourceVoice, uint32_t type); +void FAudio_WMADEC_free(FAudioSourceVoice *voice); +void FAudio_WMADEC_end_buffer(FAudioSourceVoice *voice); +#endif /* HAVE_WMADEC */ /* Platform Functions */ diff --git a/src/FAudio_internal_simd.c b/src/FAudio_internal_simd.c index 8746d358ca..7b7997b2ad 100644 --- a/src/FAudio_internal_simd.c +++ b/src/FAudio_internal_simd.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -32,23 +32,23 @@ * https://hg.icculus.org/icculus/mojoAL/file/default/mojoal.c */ -#if defined(__x86_64__) || defined(_M_X64) +#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64ec__) || defined(_M_ARM64EC) /* Some platforms fail to define this... */ - #ifndef __SSE2__ - #define __SSE2__ 1 + #ifndef __ARM_NEON__ + #define __ARM_NEON__ 1 #endif - /* x86_64 guarantees SSE2. */ + /* AArch64 guarantees NEON. */ #define NEED_SCALAR_CONVERTER_FALLBACKS 0 -#elif defined(__aarch64__) || defined(_M_ARM64) +#elif defined(__x86_64__) || defined(_M_X64) /* Some platforms fail to define this... */ - #ifndef __ARM_NEON__ - #define __ARM_NEON__ 1 + #ifndef __SSE2__ + #define __SSE2__ 1 #endif - /* AArch64 guarantees NEON. */ + /* x86_64 guarantees SSE2. */ #define NEED_SCALAR_CONVERTER_FALLBACKS 0 -#elif __MACOSX__ +#elif __MACOSX__ && !defined(__POWERPC__) /* Some build systems may need to specify this. */ #if !defined(__SSE2__) && !defined(__ARM_NEON__) #error macOS does not have SSE2/NEON? Bad compiler? @@ -62,7 +62,7 @@ #endif /* Our NEON paths require AArch64, don't check __ARM_NEON__ here */ -#if defined(__aarch64__) || defined(_M_ARM64) +#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64ec__) || defined(_M_ARM64EC) #include #define HAVE_NEON_INTRINSICS 1 #endif @@ -285,10 +285,10 @@ void FAudio_INTERNAL_Convert_U8_To_F32_NEON( const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); /* convert top 8 bytes to 8 uint16 */ const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); /* convert bottom 8 bytes to 8 uint16 */ /* split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. */ - vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128)); - vst1q_f32(dst+4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128)); - vst1q_f32(dst+8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128)); - vst1q_f32(dst+12, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128)); + vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128)); + vst1q_f32(dst+4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128)); + vst1q_f32(dst+8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128)); + vst1q_f32(dst+12, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128)); i -= 16; mmsrc -= 16; dst -= 16; } @@ -903,7 +903,7 @@ void FAudio_INTERNAL_ResampleMono_NEON( cur_frac = vdupq_n_s32( (uint32_t) (cur_scalar & FIXED_FRACTION_MASK) - DOUBLE_TO_FIXED(0.5) ); - int32_t __attribute__((aligned(16))) data[4] = + ALIGN(int32_t, 16) data[4] = { 0, (uint32_t) (resampleStep & FIXED_FRACTION_MASK), @@ -1077,7 +1077,7 @@ void FAudio_INTERNAL_ResampleStereo_NEON( cur_frac = vdupq_n_s32( (uint32_t) (cur_scalar & FIXED_FRACTION_MASK) - DOUBLE_TO_FIXED(0.5) ); - int32_t __attribute__((aligned(16))) data[4] = + ALIGN(int32_t, 16) data[4] = { 0, 0, diff --git a/src/FAudio_operationset.c b/src/FAudio_operationset.c index f17cd9270d..b5cae528e3 100644 --- a/src/FAudio_operationset.c +++ b/src/FAudio_operationset.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -70,12 +70,12 @@ struct FAudio_OPERATIONSET_Operation } SetEffectParameters; struct { - FAudioFilterParameters Parameters; + FAudioFilterParametersEXT Parameters; } SetFilterParameters; struct { FAudioVoice *pDestinationVoice; - FAudioFilterParameters Parameters; + FAudioFilterParametersEXT Parameters; } SetOutputFilterParameters; struct { @@ -169,7 +169,7 @@ static inline void ExecuteOperation(FAudio_OPERATIONSET_Operation *op) break; case FAUDIOOP_SETFILTERPARAMETERS: - FAudioVoice_SetFilterParameters( + FAudioVoice_SetFilterParametersEXT( op->Voice, &op->Data.SetFilterParameters.Parameters, FAUDIO_COMMIT_NOW @@ -177,7 +177,7 @@ static inline void ExecuteOperation(FAudio_OPERATIONSET_Operation *op) break; case FAUDIOOP_SETOUTPUTFILTERPARAMETERS: - FAudioVoice_SetOutputFilterParameters( + FAudioVoice_SetOutputFilterParametersEXT( op->Voice, op->Data.SetOutputFilterParameters.pDestinationVoice, &op->Data.SetOutputFilterParameters.Parameters, @@ -472,7 +472,7 @@ void FAudio_OPERATIONSET_QueueSetEffectParameters( void FAudio_OPERATIONSET_QueueSetFilterParameters( FAudioVoice *voice, - const FAudioFilterParameters *pParameters, + const FAudioFilterParametersEXT *pParameters, uint32_t OperationSet ) { FAudio_OPERATIONSET_Operation *op; @@ -489,7 +489,7 @@ void FAudio_OPERATIONSET_QueueSetFilterParameters( FAudio_memcpy( &op->Data.SetFilterParameters.Parameters, pParameters, - sizeof(FAudioFilterParameters) + sizeof(FAudioFilterParametersEXT) ); FAudio_PlatformUnlockMutex(voice->audio->operationLock); @@ -499,7 +499,7 @@ void FAudio_OPERATIONSET_QueueSetFilterParameters( void FAudio_OPERATIONSET_QueueSetOutputFilterParameters( FAudioVoice *voice, FAudioVoice *pDestinationVoice, - const FAudioFilterParameters *pParameters, + const FAudioFilterParametersEXT *pParameters, uint32_t OperationSet ) { FAudio_OPERATIONSET_Operation *op; @@ -517,7 +517,7 @@ void FAudio_OPERATIONSET_QueueSetOutputFilterParameters( FAudio_memcpy( &op->Data.SetOutputFilterParameters.Parameters, pParameters, - sizeof(FAudioFilterParameters) + sizeof(FAudioFilterParametersEXT) ); FAudio_PlatformUnlockMutex(voice->audio->operationLock); diff --git a/src/FAudio_platform_sdl2.c b/src/FAudio_platform_sdl2.c index 2164a2feb7..9eaa157047 100644 --- a/src/FAudio_platform_sdl2.c +++ b/src/FAudio_platform_sdl2.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -24,12 +24,14 @@ * */ +#if !defined(FAUDIO_WIN32_PLATFORM) && !defined(FAUDIO_SDL3_PLATFORM) + #include "FAudio_internal.h" #include -#if !SDL_VERSION_ATLEAST(2, 0, 9) -#error "SDL version older than 2.0.9" +#if !SDL_VERSION_ATLEAST(2, 24, 0) +#error "SDL version older than 2.24.0" #endif /* !SDL_VERSION_ATLEAST */ /* Mixer Thread */ @@ -50,8 +52,70 @@ static void FAudio_INTERNAL_MixCallback(void *userdata, Uint8 *stream, int len) /* Platform Functions */ +static void FAudio_INTERNAL_PrioritizeDirectSound() +{ + int numdrivers, i, wasapi, directsound; + void *dll, *proc; + + if (SDL_GetHint("SDL_AUDIODRIVER") != NULL) + { + /* Already forced to something, ignore */ + return; + } + + /* Windows 10+ decided to break version detection, so instead of doing + * it the right way we have to do something dumb like search for an + * export that's only in Windows 10 or newer. + * -flibit + */ + if (SDL_strcmp(SDL_GetPlatform(), "Windows") != 0) + { + return; + } + dll = SDL_LoadObject("USER32.DLL"); + if (dll == NULL) + { + return; + } + proc = SDL_LoadFunction(dll, "SetProcessDpiAwarenessContext"); + SDL_UnloadObject(dll); /* We aren't really using this, unload now */ + if (proc != NULL) + { + /* OS is new enough to trust WASAPI, bail */ + return; + } + + /* Check to see if we have both Windows drivers in the list */ + numdrivers = SDL_GetNumAudioDrivers(); + wasapi = -1; + directsound = -1; + for (i = 0; i < numdrivers; i += 1) + { + const char *driver = SDL_GetAudioDriver(i); + if (SDL_strcmp(driver, "wasapi") == 0) + { + wasapi = i; + } + else if (SDL_strcmp(driver, "directsound") == 0) + { + directsound = i; + } + } + + /* We force if and only if both drivers exist and wasapi is earlier */ + if ((wasapi > -1) && (directsound > -1)) + { + if (wasapi < directsound) + { + SDL_SetHint("SDL_AUDIODRIVER", "directsound"); + } + } +} + void FAudio_PlatformAddRef() { + FAudio_INTERNAL_PrioritizeDirectSound(); + /* SDL tracks ref counts for each subsystem */ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { @@ -79,16 +143,15 @@ void FAudio_PlatformInit( ) { SDL_AudioDeviceID device; SDL_AudioSpec want, have; - const char *driver; - int changes = 0; FAudio_assert(mixFormat != NULL); FAudio_assert(updateSize != NULL); + FAudio_assert((mixFormat->Format.nChannels <= 255) && "mixFormat->Format.nChannels out of range!"); /* Build the device spec */ want.freq = mixFormat->Format.nSamplesPerSec; - want.format = AUDIO_F32; - want.channels = mixFormat->Format.nChannels; + want.format = AUDIO_F32SYS; + want.channels = (Uint8)(mixFormat->Format.nChannels); want.silence = 0; want.callback = FAudio_INTERNAL_MixCallback; want.userdata = audio; @@ -106,48 +169,6 @@ void FAudio_PlatformInit( want.samples = want.freq / 100; } - /* FIXME: SDL bug! - * The PulseAudio backend does this annoying thing where it halves the - * buffer size to prevent latency issues: - * - * https://hg.libsdl.org/SDL/file/df343364c6c5/src/audio/pulseaudio/SDL_pulseaudio.c#l577 - * - * To get the _actual_ quantum size we want, we just double the buffer - * size and allow SDL to set the quantum size back to normal. - * -flibit - */ - driver = SDL_GetCurrentAudioDriver(); - if (SDL_strcmp(driver, "pulseaudio") == 0) - { - want.samples *= 2; - changes = SDL_AUDIO_ALLOW_SAMPLES_CHANGE; - } - - /* FIXME: SDL bug! - * The most common backends support varying samples values, but many - * require a power-of-two value, which XAudio2 is not a fan of. - * Normally SDL creates an intermediary stream to handle this, but this - * has not been written yet: - * https://bugzilla.libsdl.org/show_bug.cgi?id=5136 - * -flibit - */ - else if ( SDL_strcmp(driver, "emscripten") == 0 || - SDL_strcmp(driver, "dsp") == 0 ) - { - want.samples -= 1; - want.samples |= want.samples >> 1; - want.samples |= want.samples >> 2; - want.samples |= want.samples >> 4; - want.samples |= want.samples >> 8; - want.samples |= want.samples >> 16; - want.samples += 1; - SDL_Log( - "Forcing FAudio quantum to a power-of-two.\n" - "You don't actually want this, it's technically a bug:\n" - "https://bugzilla.libsdl.org/show_bug.cgi?id=5136" - ); - } - /* Open the device (or at least try to) */ iosretry: device = SDL_OpenAudioDevice( @@ -155,7 +176,7 @@ void FAudio_PlatformInit( 0, &want, &have, - changes + 0 ); if (device == 0) { @@ -222,7 +243,7 @@ uint32_t FAudio_PlatformGetDeviceDetails( const char *name, *envvar; int channels, rate; SDL_AudioSpec spec; - uint32_t devcount, i; + uint32_t devcount; FAudio_zero(details, sizeof(FAudioDeviceDetails)); @@ -282,85 +303,27 @@ uint32_t FAudio_PlatformGetDeviceDetails( channels = 0; } -#if SDL_VERSION_ATLEAST(2, 0, 15) + /* Get the device format from the OS */ if (index == 0) { - /* Okay, so go grab something from the liquor cabinet and get - * ready, because this loop is a bit of a trip: - * - * We can't get the spec for the default device, because in - * audio land a "default device" is a completely foreign idea, - * some APIs support it but in reality you just have to pass - * NULL as a driver string and the sound server figures out the - * rest. In some psychotic universe the device can even be a - * network address. No, seriously. - * - * So what do we do? Well, at least in my experience shipping - * for the PC, the easiest thing to do is assume that the - * highest spec in the list is what you should target, even if - * it turns out that's not the default at the time you create - * your device. - * - * Consider a laptop that has built-in stereo speakers, but is - * connected to a home theater system with 5.1 audio. It may be - * the case that the stereo audio is active, but the user may - * at some point move audio to 5.1, at which point the server - * will simply move the endpoint from underneath us and move our - * output stream to the new device. At that point, you _really_ - * want to already be pushing out 5.1, because if not the user - * will be stuck recreating the whole program, which on many - * platforms is an instant cert failure. The tradeoff is that - * you're potentially downmixing a 5.1 stream to stereo, which - * is a bit wasteful, but presumably the hardware can handle it - * if they were able to use a 5.1 system to begin with. - * - * So, we just aim for the highest channel count on the system. - * We also do this with sample rate to a lesser degree; we try - * to use a single device spec at a time, so it may be that - * the sample rate you get isn't the highest from the list if - * another device had a higher channel count. - * - * Lastly, if you set SDL_AUDIO_CHANNELS but not - * SDL_AUDIO_FREQUENCY, we don't bother checking for a sample - * rate, we fall through to the hardcoded value at the bottom of - * this function. - * - * I'm so tired. - * - * -flibit - */ - if (channels <= 0) + /* TODO: Do we want to squeeze the name into the output? */ + if (SDL_GetDefaultAudioInfo(NULL, &spec, 0) < 0) { - const uint8_t setRate = (rate <= 0); - devcount -= 1; /* Subtracting the default index */ - for (i = 0; i < devcount; i += 1) - { - SDL_GetAudioDeviceSpec(i, 0, &spec); - if (spec.channels > channels) - { - channels = spec.channels; - if (setRate) - { - /* May be 0! That's okay! */ - rate = spec.freq; - } - } - } + SDL_zero(spec); } } else { SDL_GetAudioDeviceSpec(index - 1, 0, &spec); - if ((spec.freq > 0) && (rate <= 0)) - { - rate = spec.freq; - } - if ((spec.channels > 0) && (channels <= 0)) - { - channels = spec.channels; - } } -#endif /* SDL >= 2.0.15 */ + if ((spec.freq > 0) && (rate <= 0)) + { + rate = spec.freq; + } + if ((spec.channels > 0) && (spec.channels < 9) && (channels <= 0)) + { + channels = spec.channels; + } /* If we make it all the way here with no format, hardcode a sane one */ if (rate <= 0) @@ -704,3 +667,9 @@ void FAudio_UTF8_To_UTF16(const char *src, uint16_t *dst, size_t len) } /* vim: set noexpandtab shiftwidth=8 tabstop=8: */ + +#else + +extern int this_tu_is_empty; + +#endif /* !defined(FAUDIO_WIN32_PLATFORM) && !defined(FAUDIO_SDL3_PLATFORM) */ diff --git a/src/FAudio_platform_sdl3.c b/src/FAudio_platform_sdl3.c new file mode 100644 index 0000000000..916fdf000f --- /dev/null +++ b/src/FAudio_platform_sdl3.c @@ -0,0 +1,734 @@ +/* FAudio - XAudio Reimplementation for FNA + * + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ + +#ifdef FAUDIO_SDL3_PLATFORM + +#include "FAudio_internal.h" + +#include + +typedef struct SDLAudioDevice +{ + FAudio *audio; + SDL_AudioStream *stream; + float *stagingBuffer; + size_t stagingLen; +} SDLAudioDevice; + +/* Mixer Thread */ + +static void FAudio_INTERNAL_MixCallback( + void *userdata, + SDL_AudioStream *stream, + int additional_amount, + int total_amount +) { + SDLAudioDevice *dev = (SDLAudioDevice*) userdata; + + if (!dev->audio->active) + { + /* Nothing to do, SDL will fill in for us */ + return; + } + + while (additional_amount > 0) + { + FAudio_zero(dev->stagingBuffer, dev->stagingLen); + FAudio_INTERNAL_UpdateEngine(dev->audio, dev->stagingBuffer); + SDL_PutAudioStreamData( + stream, + dev->stagingBuffer, + dev->stagingLen + ); + additional_amount -= dev->stagingLen; + } +} + +/* Platform Functions */ + +static void FAudio_INTERNAL_PrioritizeDirectSound() +{ + int numdrivers, i, wasapi, directsound; + void *dll, *proc; + + if (SDL_GetHint("SDL_AUDIO_DRIVER") != NULL) + { + /* Already forced to something, ignore */ + return; + } + + /* Windows 10+ decided to break version detection, so instead of doing + * it the right way we have to do something dumb like search for an + * export that's only in Windows 10 or newer. + * -flibit + */ + if (SDL_strcmp(SDL_GetPlatform(), "Windows") != 0) + { + return; + } + dll = SDL_LoadObject("USER32.DLL"); + if (dll == NULL) + { + return; + } + proc = SDL_LoadFunction(dll, "SetProcessDpiAwarenessContext"); + SDL_UnloadObject(dll); /* We aren't really using this, unload now */ + if (proc != NULL) + { + /* OS is new enough to trust WASAPI, bail */ + return; + } + + /* Check to see if we have both Windows drivers in the list */ + numdrivers = SDL_GetNumAudioDrivers(); + wasapi = -1; + directsound = -1; + for (i = 0; i < numdrivers; i += 1) + { + const char *driver = SDL_GetAudioDriver(i); + if (SDL_strcmp(driver, "wasapi") == 0) + { + wasapi = i; + } + else if (SDL_strcmp(driver, "directsound") == 0) + { + directsound = i; + } + } + + /* We force if and only if both drivers exist and wasapi is earlier */ + if ((wasapi > -1) && (directsound > -1)) + { + if (wasapi < directsound) + { + SDL_SetHint("SDL_AUDIO_DRIVER", "directsound"); + } + } +} + +void FAudio_PlatformAddRef() +{ + FAudio_INTERNAL_PrioritizeDirectSound(); + + /* SDL tracks ref counts for each subsystem */ + if (!SDL_InitSubSystem(SDL_INIT_AUDIO)) + { + SDL_Log("SDL_INIT_AUDIO failed: %s", SDL_GetError()); + } + FAudio_INTERNAL_InitSIMDFunctions( + SDL_HasSSE2(), + SDL_HasNEON() + ); +} + +void FAudio_PlatformRelease() +{ + /* SDL tracks ref counts for each subsystem */ + SDL_QuitSubSystem(SDL_INIT_AUDIO); +} + +void FAudio_PlatformInit( + FAudio *audio, + uint32_t flags, + uint32_t deviceIndex, + FAudioWaveFormatExtensible *mixFormat, + uint32_t *updateSize, + void** platformDevice +) { + SDLAudioDevice *result; + SDL_AudioDeviceID devID; + SDL_AudioSpec spec; + int wantSamples; + + FAudio_assert(mixFormat != NULL); + FAudio_assert(updateSize != NULL); + + /* Build the device spec */ + spec.freq = mixFormat->Format.nSamplesPerSec; + spec.format = SDL_AUDIO_F32; + spec.channels = mixFormat->Format.nChannels; + if (flags & FAUDIO_1024_QUANTUM) + { + /* Get the sample count for a 21.33ms frame. + * For 48KHz this should be 1024. + */ + wantSamples = (int) ( + spec.freq / (1000.0 / (64.0 / 3.0)) + ); + } + else + { + wantSamples = spec.freq / 100; + } + + if (deviceIndex == 0) + { + devID = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; + } + else + { + int devcount; + SDL_AudioDeviceID *devs = SDL_GetAudioPlaybackDevices(&devcount); + + /* Bounds checking is done before this function is called */ + devID = devs[deviceIndex - 1]; + + SDL_free(devs); + } + + result = (SDLAudioDevice*) SDL_malloc(sizeof(SDLAudioDevice)); + result->audio = audio; + result->stagingLen = wantSamples * spec.channels * sizeof(float); + result->stagingBuffer = (float*) SDL_malloc(result->stagingLen); + + /* Open the device (or at least try to) */ + result->stream = SDL_OpenAudioDeviceStream( + devID, + &spec, + FAudio_INTERNAL_MixCallback, + result + ); + + /* Write up the received format for the engine */ + WriteWaveFormatExtensible( + mixFormat, + spec.channels, + spec.freq, + &DATAFORMAT_SUBTYPE_IEEE_FLOAT + ); + *updateSize = wantSamples; + + /* SDL_AudioDeviceID is a Uint32, anybody using a 16-bit PC still? */ + *platformDevice = result; + + /* Start the thread! */ + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(result->stream)); +} + +void FAudio_PlatformQuit(void* platformDevice) +{ + SDLAudioDevice *dev = (SDLAudioDevice*) platformDevice; + SDL_AudioDeviceID devID = SDL_GetAudioStreamDevice(dev->stream); + SDL_DestroyAudioStream(dev->stream); + SDL_CloseAudioDevice(devID); + SDL_free(dev->stagingBuffer); + SDL_free(dev); +} + +uint32_t FAudio_PlatformGetDeviceCount() +{ + int devcount; + SDL_free(SDL_GetAudioPlaybackDevices(&devcount)); + if (devcount == 0) + { + return 0; + } + SDL_assert(devcount > 0); + return devcount + 1; /* Add one for "Default Device" */ +} + +void FAudio_UTF8_To_UTF16(const char *src, uint16_t *dst, size_t len); + +uint32_t FAudio_PlatformGetDeviceDetails( + uint32_t index, + FAudioDeviceDetails *details +) { + const char *name, *envvar; + int channels, rate; + SDL_AudioSpec spec; + int devcount; + SDL_AudioDeviceID *devs; + + FAudio_zero(details, sizeof(FAudioDeviceDetails)); + + devs = SDL_GetAudioPlaybackDevices(&devcount); + if (index > devcount) + { + SDL_free(devs); + return FAUDIO_E_INVALID_CALL; + } + + details->DeviceID[0] = L'0' + index; + if (index == 0) + { + name = "Default Device"; + details->Role = FAudioGlobalDefaultDevice; + + /* This variable will look like a DSound GUID or WASAPI ID, i.e. + * "{0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B}" + */ + envvar = SDL_getenv("FAUDIO_FORCE_DEFAULT_DEVICEID"); + if (envvar != NULL) + { + FAudio_UTF8_To_UTF16( + envvar, + (uint16_t*) details->DeviceID, + sizeof(details->DeviceID) + ); + } + } + else + { + name = SDL_GetAudioDeviceName(devs[index - 1]); + details->Role = FAudioNotDefaultDevice; + } + FAudio_UTF8_To_UTF16( + name, + (uint16_t*) details->DisplayName, + sizeof(details->DisplayName) + ); + + /* Environment variables take precedence over all possible values */ + envvar = SDL_getenv("SDL_AUDIO_FREQUENCY"); + if (envvar != NULL) + { + rate = SDL_atoi(envvar); + } + else + { + rate = 0; + } + envvar = SDL_getenv("SDL_AUDIO_CHANNELS"); + if (envvar != NULL) + { + channels = SDL_atoi(envvar); + } + else + { + channels = 0; + } + + /* Get the device format from the OS */ + if (index == 0) + { + if (!SDL_GetAudioDeviceFormat(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL)) + { + SDL_zero(spec); + } + } + else + { + if (!SDL_GetAudioDeviceFormat(devs[index - 1], &spec, NULL)) + { + SDL_zero(spec); + } + } + SDL_free(devs); + if ((spec.freq > 0) && (rate <= 0)) + { + rate = spec.freq; + } + if ((spec.channels > 0) && (spec.channels < 9) && (channels <= 0)) + { + channels = spec.channels; + } + + /* If we make it all the way here with no format, hardcode a sane one */ + if (rate <= 0) + { + rate = 48000; + } + if (channels <= 0) + { + channels = 2; + } + + /* Write the format, finally. */ + WriteWaveFormatExtensible( + &details->OutputFormat, + channels, + rate, + &DATAFORMAT_SUBTYPE_PCM + ); + return 0; +} + +/* Threading */ + +FAudioThread FAudio_PlatformCreateThread( + FAudioThreadFunc func, + const char *name, + void* data +) { + return (FAudioThread) SDL_CreateThread( + (SDL_ThreadFunction) func, + name, + data + ); +} + +void FAudio_PlatformWaitThread(FAudioThread thread, int32_t *retval) +{ + SDL_WaitThread((SDL_Thread*) thread, retval); +} + +void FAudio_PlatformThreadPriority(FAudioThreadPriority priority) +{ + SDL_SetCurrentThreadPriority((SDL_ThreadPriority) priority); +} + +uint64_t FAudio_PlatformGetThreadID(void) +{ + return (uint64_t) SDL_GetCurrentThreadID(); +} + +FAudioMutex FAudio_PlatformCreateMutex() +{ + return (FAudioMutex) SDL_CreateMutex(); +} + +void FAudio_PlatformDestroyMutex(FAudioMutex mutex) +{ + SDL_DestroyMutex((SDL_Mutex*) mutex); +} + +void FAudio_PlatformLockMutex(FAudioMutex mutex) +{ + SDL_LockMutex((SDL_Mutex*) mutex); +} + +void FAudio_PlatformUnlockMutex(FAudioMutex mutex) +{ + SDL_UnlockMutex((SDL_Mutex*) mutex); +} + +void FAudio_sleep(uint32_t ms) +{ + SDL_Delay(ms); +} + +/* Time */ + +uint32_t FAudio_timems() +{ + return SDL_GetTicks(); +} + +/* FAudio I/O */ + +static size_t FAUDIOCALL FAudio_INTERNAL_ioread( + void *data, + void *dst, + size_t size, + size_t count +) { + return SDL_ReadIO((SDL_IOStream*) data, dst, size * count) / size; +} + +static int64_t FAUDIOCALL FAudio_INTERNAL_ioseek( + void *data, + int64_t offset, + int whence +) { + return SDL_SeekIO((SDL_IOStream*) data, offset, whence); +} + +static int FAUDIOCALL FAudio_INTERNAL_ioclose( + void *data +) { + return SDL_CloseIO((SDL_IOStream*) data); +} + +FAudioIOStream* FAudio_fopen(const char *path) +{ + FAudioIOStream *io = (FAudioIOStream*) FAudio_malloc( + sizeof(FAudioIOStream) + ); + SDL_IOStream *stream = SDL_IOFromFile(path, "rb"); + io->data = stream; + io->read = FAudio_INTERNAL_ioread; + io->seek = FAudio_INTERNAL_ioseek; + io->close = FAudio_INTERNAL_ioclose; + io->lock = FAudio_PlatformCreateMutex(); + return io; +} + +FAudioIOStream* FAudio_memopen(void *mem, int len) +{ + FAudioIOStream *io = (FAudioIOStream*) FAudio_malloc( + sizeof(FAudioIOStream) + ); + SDL_IOStream *stream = SDL_IOFromMem(mem, len); + io->data = stream; + io->read = FAudio_INTERNAL_ioread; + io->seek = FAudio_INTERNAL_ioseek; + io->close = FAudio_INTERNAL_ioclose; + io->lock = FAudio_PlatformCreateMutex(); + return io; +} + +uint8_t* FAudio_memptr(FAudioIOStream *io, size_t offset) +{ + SDL_PropertiesID props = SDL_GetIOProperties((SDL_IOStream*) io->data); + FAudio_assert(SDL_HasProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER)); + return ((uint8_t*) SDL_GetPointerProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER, NULL)) + offset; +} + +void FAudio_close(FAudioIOStream *io) +{ + io->close(io->data); + FAudio_PlatformDestroyMutex((FAudioMutex) io->lock); + FAudio_free(io); +} + +#ifdef FAUDIO_DUMP_VOICES +static size_t FAUDIOCALL FAudio_INTERNAL_iowrite( + void *data, + const void *src, + size_t size, + size_t count +) { + SDL_WriteIO((SDL_IOStream*) data, src, size * count); +} + +static size_t FAUDIOCALL FAudio_INTERNAL_iosize( + void *data +) { + return SDL_GetIOSize((SDL_IOStream*) data); +} + +FAudioIOStreamOut* FAudio_fopen_out(const char *path, const char *mode) +{ + FAudioIOStreamOut *io = (FAudioIOStreamOut*) FAudio_malloc( + sizeof(FAudioIOStreamOut) + ); + SDL_IOStream *stream = SDL_IOFromFile(path, mode); + io->data = stream; + io->read = FAudio_INTERNAL_ioread; + io->write = FAudio_INTERNAL_iowrite; + io->seek = FAudio_INTERNAL_ioseek; + io->size = FAudio_INTERNAL_iosize; + io->close = FAudio_INTERNAL_ioclose; + io->lock = FAudio_PlatformCreateMutex(); + return io; +} + +void FAudio_close_out(FAudioIOStreamOut *io) +{ + io->close(io->data); + FAudio_PlatformDestroyMutex((FAudioMutex) io->lock); + FAudio_free(io); +} +#endif /* FAUDIO_DUMP_VOICES */ + +/* UTF8->UTF16 Conversion, taken from PhysicsFS */ + +#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF +#define UNICODE_BOGUS_CHAR_CODEPOINT '?' + +static uint32_t FAudio_UTF8_CodePoint(const char **_str) +{ + const char *str = *_str; + uint32_t retval = 0; + uint32_t octet = (uint32_t) ((uint8_t) *str); + uint32_t octet2, octet3, octet4; + + if (octet == 0) /* null terminator, end of string. */ + return 0; + + else if (octet < 128) /* one octet char: 0 to 127 */ + { + (*_str)++; /* skip to next possible start of codepoint. */ + return octet; + } /* else if */ + + else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */ + { + /* + * Apparently each of these is supposed to be flagged as a bogus + * char, instead of just resyncing to the next valid codepoint. + */ + (*_str)++; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + else if (octet < 224) /* two octets */ + { + (*_str)++; /* advance at least one byte in case of an error */ + octet -= (128+64); + octet2 = (uint32_t) ((uint8_t) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 1; /* skip to next possible start of codepoint. */ + retval = ((octet << 6) | (octet2 - 128)); + if ((retval >= 0x80) && (retval <= 0x7FF)) + return retval; + } /* else if */ + + else if (octet < 240) /* three octets */ + { + (*_str)++; /* advance at least one byte in case of an error */ + octet -= (128+64+32); + octet2 = (uint32_t) ((uint8_t) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet3 = (uint32_t) ((uint8_t) *(++str)); + if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 2; /* skip to next possible start of codepoint. */ + retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) ); + + /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + switch (retval) + { + case 0xD800: + case 0xDB7F: + case 0xDB80: + case 0xDBFF: + case 0xDC00: + case 0xDF80: + case 0xDFFF: + return UNICODE_BOGUS_CHAR_VALUE; + } /* switch */ + + /* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */ + if ((retval >= 0x800) && (retval <= 0xFFFD)) + return retval; + } /* else if */ + + else if (octet < 248) /* four octets */ + { + (*_str)++; /* advance at least one byte in case of an error */ + octet -= (128+64+32+16); + octet2 = (uint32_t) ((uint8_t) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet3 = (uint32_t) ((uint8_t) *(++str)); + if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet4 = (uint32_t) ((uint8_t) *(++str)); + if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 3; /* skip to next possible start of codepoint. */ + retval = ( ((octet << 18)) | ((octet2 - 128) << 12) | + ((octet3 - 128) << 6) | ((octet4 - 128)) ); + if ((retval >= 0x10000) && (retval <= 0x10FFFF)) + return retval; + } /* else if */ + + /* + * Five and six octet sequences became illegal in rfc3629. + * We throw the codepoint away, but parse them to make sure we move + * ahead the right number of bytes and don't overflow the buffer. + */ + + else if (octet < 252) /* five octets */ + { + (*_str)++; /* advance at least one byte in case of an error */ + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 4; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + else /* six octets */ + { + (*_str)++; /* advance at least one byte in case of an error */ + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (uint32_t) ((uint8_t) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 6; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + return UNICODE_BOGUS_CHAR_VALUE; +} + +void FAudio_UTF8_To_UTF16(const char *src, uint16_t *dst, size_t len) +{ + len -= sizeof (uint16_t); /* save room for null char. */ + while (len >= sizeof (uint16_t)) + { + uint32_t cp = FAudio_UTF8_CodePoint(&src); + if (cp == 0) + break; + else if (cp == UNICODE_BOGUS_CHAR_VALUE) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + + if (cp > 0xFFFF) /* encode as surrogate pair */ + { + if (len < (sizeof (uint16_t) * 2)) + break; /* not enough room for the pair, stop now. */ + + cp -= 0x10000; /* Make this a 20-bit value */ + + *(dst++) = 0xD800 + ((cp >> 10) & 0x3FF); + len -= sizeof (uint16_t); + + cp = 0xDC00 + (cp & 0x3FF); + } /* if */ + + *(dst++) = cp; + len -= sizeof (uint16_t); + } /* while */ + + *dst = 0; +} + +/* vim: set noexpandtab shiftwidth=8 tabstop=8: */ + +#else + +extern int this_tu_is_empty; + +#endif /* FAUDIO_SDL3_PLATFORM */ diff --git a/src/FAudio_platform_win32.c b/src/FAudio_platform_win32.c new file mode 100644 index 0000000000..9e90a21199 --- /dev/null +++ b/src/FAudio_platform_win32.c @@ -0,0 +1,1853 @@ +/* FAudio - XAudio Reimplementation for FNA + * + * Copyright (c) 2011-2020 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from + * the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in a + * product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * Ethan "flibitijibibo" Lee + * + */ + +#ifdef FAUDIO_WIN32_PLATFORM + +#include "FAudio_internal.h" + +#include + +#define COBJMACROS +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +DEFINE_GUID(CLSID_CWMADecMediaObject, 0x2eeb4adf, 0x4578, 0x4d10, 0xbc, 0xa7, 0xbb, 0x95, 0x5f, 0x56, 0x32, 0x0a); + +#ifdef _MSC_VER +DEFINE_GUID(IID_IAudioClient, 0x1CB9AD4C, 0xDBFA, 0x4c32, 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2); +DEFINE_GUID(IID_IAudioRenderClient, 0xF294ACFC, 0x3146, 0x4483, 0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2); +DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6); +DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E); +#endif + +DEFINE_MEDIATYPE_GUID(MFAudioFormat_XMAudio2, FAUDIO_FORMAT_XMAUDIO2); + +static CRITICAL_SECTION faudio_cs = { NULL, -1, 0, 0, 0, 0 }; +static IMMDeviceEnumerator *device_enumerator; +static HRESULT init_hr; + +struct FAudioWin32PlatformData +{ + IAudioClient *client; + HANDLE audioThread; + HANDLE stopEvent; +}; + +struct FAudioAudioClientThreadArgs +{ + WAVEFORMATEXTENSIBLE format; + IAudioClient *client; + HANDLE events[2]; + FAudio *audio; + UINT updateSize; +}; + +void FAudio_Log(char const *msg) +{ + OutputDebugStringA(msg); +} + +static HMODULE kernelbase = NULL; +static HRESULT (WINAPI *my_SetThreadDescription)(HANDLE, PCWSTR) = NULL; + +static void FAudio_resolve_SetThreadDescription(void) +{ + kernelbase = LoadLibraryA("kernelbase.dll"); + if (!kernelbase) + return; + + my_SetThreadDescription = (HRESULT (WINAPI *)(HANDLE, PCWSTR)) GetProcAddress(kernelbase, "SetThreadDescription"); + if (!my_SetThreadDescription) + { + FreeLibrary(kernelbase); + kernelbase = NULL; + } +} + +static void FAudio_set_thread_name(char const *name) +{ + int ret; + WCHAR *nameW; + + if (!my_SetThreadDescription) + return; + + ret = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0); + + nameW = FAudio_malloc(ret * sizeof(WCHAR)); + if (!nameW) + return; + + ret = MultiByteToWideChar(CP_UTF8, 0, name, -1, nameW, ret); + if (ret) + my_SetThreadDescription(GetCurrentThread(), nameW); + + FAudio_free(nameW); +} + +static HRESULT FAudio_FillAudioClientBuffer( + struct FAudioAudioClientThreadArgs *args, + IAudioRenderClient *client, + UINT frames, + UINT padding +) { + HRESULT hr = S_OK; + BYTE *buffer; + + while (padding + args->updateSize <= frames) + { + hr = IAudioRenderClient_GetBuffer( + client, + frames - padding, + &buffer + ); + if (FAILED(hr)) return hr; + + FAudio_zero( + buffer, + args->updateSize * args->format.Format.nBlockAlign + ); + + if (args->audio->active) + { + FAudio_INTERNAL_UpdateEngine( + args->audio, + (float*) buffer + ); + } + + hr = IAudioRenderClient_ReleaseBuffer( + client, + args->updateSize, + 0 + ); + if (FAILED(hr)) return hr; + + padding += args->updateSize; + } + + return hr; +} + +static DWORD WINAPI FAudio_AudioClientThread(void *user) +{ + struct FAudioAudioClientThreadArgs *args = user; + IAudioRenderClient *render_client; + HRESULT hr = S_OK; + UINT frames, padding = 0; + + FAudio_set_thread_name(__func__); + + hr = IAudioClient_GetService( + args->client, + &IID_IAudioRenderClient, + (void **)&render_client + ); + FAudio_assert(!FAILED(hr) && "Failed to get IAudioRenderClient service!"); + + hr = IAudioClient_GetBufferSize(args->client, &frames); + FAudio_assert(!FAILED(hr) && "Failed to get IAudioClient buffer size!"); + + hr = FAudio_FillAudioClientBuffer(args, render_client, frames, 0); + FAudio_assert(!FAILED(hr) && "Failed to initialize IAudioClient buffer!"); + + hr = IAudioClient_Start(args->client); + FAudio_assert(!FAILED(hr) && "Failed to start IAudioClient!"); + + while (WaitForMultipleObjects(2, args->events, FALSE, INFINITE) == WAIT_OBJECT_0) + { + hr = IAudioClient_GetCurrentPadding(args->client, &padding); + if (hr == AUDCLNT_E_DEVICE_INVALIDATED) + { + /* Device was removed, just exit */ + break; + } + FAudio_assert(!FAILED(hr) && "Failed to get IAudioClient current padding!"); + + hr = FAudio_FillAudioClientBuffer(args, render_client, frames, padding); + FAudio_assert(!FAILED(hr) && "Failed to fill IAudioClient buffer!"); + } + + hr = IAudioClient_Stop(args->client); + FAudio_assert(!FAILED(hr) && "Failed to stop IAudioClient!"); + + IAudioRenderClient_Release(render_client); + FAudio_free(args); + return 0; +} + +/* Sets `defaultDeviceIndex` to the default audio device index in + * `deviceCollection`. + * On failure, `defaultDeviceIndex` is not modified and the latest error is + * returned. */ +static HRESULT FAudio_DefaultDeviceIndex( + IMMDeviceCollection *deviceCollection, + uint32_t* defaultDeviceIndex +) { + IMMDevice *device; + HRESULT hr; + uint32_t i, count; + WCHAR *default_guid; + WCHAR *device_guid; + + /* Open the default device and get its GUID. */ + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint( + device_enumerator, + eRender, + eConsole, + &device + ); + if (FAILED(hr)) + { + return hr; + } + hr = IMMDevice_GetId(device, &default_guid); + if (FAILED(hr)) + { + IMMDevice_Release(device); + return hr; + } + + /* Free the default device. */ + IMMDevice_Release(device); + + hr = IMMDeviceCollection_GetCount(deviceCollection, &count); + if (FAILED(hr)) + { + CoTaskMemFree(default_guid); + return hr; + } + + for (i = 0; i < count; i += 1) + { + /* Open the device and get its GUID. */ + hr = IMMDeviceCollection_Item(deviceCollection, i, &device); + if (FAILED(hr)) { + CoTaskMemFree(default_guid); + return hr; + } + hr = IMMDevice_GetId(device, &device_guid); + if (FAILED(hr)) + { + CoTaskMemFree(default_guid); + IMMDevice_Release(device); + return hr; + } + + if (lstrcmpW(default_guid, device_guid) == 0) + { + /* Device found. */ + CoTaskMemFree(default_guid); + CoTaskMemFree(device_guid); + IMMDevice_Release(device); + *defaultDeviceIndex = i; + return S_OK; + } + + CoTaskMemFree(device_guid); + IMMDevice_Release(device); + } + + /* This should probably never happen. Just in case, set + * `defaultDeviceIndex` to 0 and return S_OK. */ + CoTaskMemFree(default_guid); + *defaultDeviceIndex = 0; + return S_OK; +} + +/* Open `device`, corresponding to `deviceIndex`. `deviceIndex` 0 always + * corresponds to the default device. XAudio reorders the devices so that the + * default device is always at index 0, so we mimick this behavior here by + * swapping the devices at indexes 0 and `defaultDeviceIndex`. + */ +static HRESULT FAudio_OpenDevice(uint32_t deviceIndex, IMMDevice **device) +{ + IMMDeviceCollection *deviceCollection; + HRESULT hr; + uint32_t defaultDeviceIndex; + uint32_t actualIndex; + + *device = NULL; + + hr = IMMDeviceEnumerator_EnumAudioEndpoints( + device_enumerator, + eRender, + DEVICE_STATE_ACTIVE, + &deviceCollection + ); + if (FAILED(hr)) + { + return hr; + } + + /* Get the default device index. */ + hr = FAudio_DefaultDeviceIndex(deviceCollection, &defaultDeviceIndex); + if (FAILED(hr)) + { + IMMDeviceCollection_Release(deviceCollection); + return hr; + } + + if (deviceIndex == 0) { + /* Default device. */ + actualIndex = defaultDeviceIndex; + } else if (deviceIndex == defaultDeviceIndex) { + /* Open the device at index 0 instead of the "correct" one. */ + actualIndex = 0; + } else { + /* Otherwise, just open the device. */ + actualIndex = deviceIndex; + + } + hr = IMMDeviceCollection_Item(deviceCollection, actualIndex, device); + if (FAILED(hr)) + { + IMMDeviceCollection_Release(deviceCollection); + return hr; + } + + IMMDeviceCollection_Release(deviceCollection); + + return hr; +} + +void FAudio_PlatformInit( + FAudio *audio, + uint32_t flags, + uint32_t deviceIndex, + FAudioWaveFormatExtensible *mixFormat, + uint32_t *updateSize, + void** platformDevice +) { + struct FAudioAudioClientThreadArgs *args; + struct FAudioWin32PlatformData *data; + REFERENCE_TIME duration; + WAVEFORMATEX *closest; + IMMDevice *device = NULL; + HRESULT hr; + HANDLE audioEvent = NULL; + BOOL has_sse2 = IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); +#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64ec__) || defined(_M_ARM64EC) + BOOL has_neon = TRUE; +#elif defined(__arm__) || defined(_M_ARM) + BOOL has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE); +#else + BOOL has_neon = FALSE; +#endif + FAudio_INTERNAL_InitSIMDFunctions(has_sse2, has_neon); + FAudio_resolve_SetThreadDescription(); + + FAudio_PlatformAddRef(); + + *platformDevice = NULL; + + args = FAudio_malloc(sizeof(*args)); + FAudio_assert(!!args && "Failed to allocate FAudio thread args!"); + + data = FAudio_malloc(sizeof(*data)); + FAudio_assert(!!data && "Failed to allocate FAudio platform data!"); + FAudio_zero(data, sizeof(*data)); + + args->format.Format.wFormatTag = mixFormat->Format.wFormatTag; + args->format.Format.nChannels = mixFormat->Format.nChannels; + args->format.Format.nSamplesPerSec = mixFormat->Format.nSamplesPerSec; + args->format.Format.nAvgBytesPerSec = mixFormat->Format.nAvgBytesPerSec; + args->format.Format.nBlockAlign = mixFormat->Format.nBlockAlign; + args->format.Format.wBitsPerSample = mixFormat->Format.wBitsPerSample; + args->format.Format.cbSize = mixFormat->Format.cbSize; + + if (args->format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + args->format.Samples.wValidBitsPerSample = mixFormat->Samples.wValidBitsPerSample; + args->format.dwChannelMask = mixFormat->dwChannelMask; + FAudio_memcpy( + &args->format.SubFormat, + &mixFormat->SubFormat, + sizeof(GUID) + ); + } + + audioEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + FAudio_assert(!!audioEvent && "Failed to create FAudio thread buffer event!"); + + data->stopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + FAudio_assert(!!data->stopEvent && "Failed to create FAudio thread stop event!"); + + hr = FAudio_OpenDevice(deviceIndex, &device); + FAudio_assert(!FAILED(hr) && "Failed to get audio device!"); + + hr = IMMDevice_Activate( + device, + &IID_IAudioClient, + CLSCTX_ALL, + NULL, + (void **)&data->client + ); + FAudio_assert(!FAILED(hr) && "Failed to create audio client!"); + IMMDevice_Release(device); + + if (flags & FAUDIO_1024_QUANTUM) duration = 213333; + else duration = 100000; + + hr = IAudioClient_IsFormatSupported( + data->client, + AUDCLNT_SHAREMODE_SHARED, + &args->format.Format, + &closest + ); + FAudio_assert(!FAILED(hr) && "Failed to find supported audio format!"); + + if (closest) + { + if (closest->wFormatTag != WAVE_FORMAT_EXTENSIBLE) args->format.Format = *closest; + else args->format = *(WAVEFORMATEXTENSIBLE *)closest; + CoTaskMemFree(closest); + } + + hr = IAudioClient_Initialize( + data->client, + AUDCLNT_SHAREMODE_SHARED, + AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + duration * 3, + 0, + &args->format.Format, + &GUID_NULL + ); + FAudio_assert(!FAILED(hr) && "Failed to initialize audio client!"); + + hr = IAudioClient_SetEventHandle(data->client, audioEvent); + FAudio_assert(!FAILED(hr) && "Failed to set audio client event!"); + + mixFormat->Format.wFormatTag = args->format.Format.wFormatTag; + mixFormat->Format.nChannels = args->format.Format.nChannels; + mixFormat->Format.nSamplesPerSec = args->format.Format.nSamplesPerSec; + mixFormat->Format.nAvgBytesPerSec = args->format.Format.nAvgBytesPerSec; + mixFormat->Format.nBlockAlign = args->format.Format.nBlockAlign; + mixFormat->Format.wBitsPerSample = args->format.Format.wBitsPerSample; + + if (args->format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + mixFormat->Format.cbSize = sizeof(FAudioWaveFormatExtensible) - sizeof(FAudioWaveFormatEx); + mixFormat->Samples.wValidBitsPerSample = args->format.Samples.wValidBitsPerSample; + mixFormat->dwChannelMask = args->format.dwChannelMask; + FAudio_memcpy( + &mixFormat->SubFormat, + &args->format.SubFormat, + sizeof(GUID) + ); + } + else + { + mixFormat->Format.cbSize = sizeof(FAudioWaveFormatEx); + } + + args->client = data->client; + args->events[0] = audioEvent; + args->events[1] = data->stopEvent; + args->audio = audio; + if (flags & FAUDIO_1024_QUANTUM) args->updateSize = args->format.Format.nSamplesPerSec / (1000.0 / (64.0 / 3.0)); + else args->updateSize = args->format.Format.nSamplesPerSec / 100; + + data->audioThread = CreateThread(NULL, 0, &FAudio_AudioClientThread, args, 0, NULL); + FAudio_assert(!!data->audioThread && "Failed to create audio client thread!"); + + *updateSize = args->updateSize; + *platformDevice = data; + return; +} + +void FAudio_PlatformQuit(void* platformDevice) +{ + struct FAudioWin32PlatformData *data = platformDevice; + + SetEvent(data->stopEvent); + WaitForSingleObject(data->audioThread, INFINITE); + if (data->client) IAudioClient_Release(data->client); + if (kernelbase) + { + my_SetThreadDescription = NULL; + FreeLibrary(kernelbase); + kernelbase = NULL; + } + FAudio_PlatformRelease(); +} + +void FAudio_PlatformAddRef() +{ + HRESULT hr; + EnterCriticalSection(&faudio_cs); + if (!device_enumerator) + { + init_hr = CoInitialize(NULL); + hr = CoCreateInstance( + &CLSID_MMDeviceEnumerator, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IMMDeviceEnumerator, + (void**)&device_enumerator + ); + FAudio_assert(!FAILED(hr) && "CoCreateInstance failed!"); + } + else IMMDeviceEnumerator_AddRef(device_enumerator); + LeaveCriticalSection(&faudio_cs); +} + +void FAudio_PlatformRelease() +{ + EnterCriticalSection(&faudio_cs); + if (!IMMDeviceEnumerator_Release(device_enumerator)) + { + device_enumerator = NULL; + if (SUCCEEDED(init_hr)) CoUninitialize(); + } + LeaveCriticalSection(&faudio_cs); +} + +uint32_t FAudio_PlatformGetDeviceCount(void) +{ + IMMDeviceCollection *device_collection; + uint32_t count; + HRESULT hr; + + FAudio_PlatformAddRef(); + + hr = IMMDeviceEnumerator_EnumAudioEndpoints( + device_enumerator, + eRender, + DEVICE_STATE_ACTIVE, + &device_collection + ); + if (FAILED(hr)) { + FAudio_PlatformRelease(); + return 0; + } + + hr = IMMDeviceCollection_GetCount(device_collection, &count); + if (FAILED(hr)) { + IMMDeviceCollection_Release(device_collection); + FAudio_PlatformRelease(); + return 0; + } + + IMMDeviceCollection_Release(device_collection); + + FAudio_PlatformRelease(); + + return count; +} + +uint32_t FAudio_PlatformGetDeviceDetails( + uint32_t index, + FAudioDeviceDetails *details +) { + WAVEFORMATEX *format, *obtained; + WAVEFORMATEXTENSIBLE *ext; + IAudioClient *client; + IMMDevice *device; + IPropertyStore* properties; + PROPVARIANT deviceName; + uint32_t count = 0; + uint32_t ret = 0; + HRESULT hr; + WCHAR *str; + GUID sub; + + FAudio_memset(details, 0, sizeof(FAudioDeviceDetails)); + + FAudio_PlatformAddRef(); + + count = FAudio_PlatformGetDeviceCount(); + if (index >= count) + { + FAudio_PlatformRelease(); + return FAUDIO_E_INVALID_CALL; + } + + hr = FAudio_OpenDevice(index, &device); + FAudio_assert(!FAILED(hr) && "Failed to get audio endpoint!"); + + if (index == 0) + { + details->Role = FAudioGlobalDefaultDevice; + } + else + { + details->Role = FAudioNotDefaultDevice; + } + + /* Set the Device Display Name */ + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &properties); + FAudio_assert(!FAILED(hr) && "Failed to open device property store!"); + hr = IPropertyStore_GetValue(properties, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &deviceName); + FAudio_assert(!FAILED(hr) && "Failed to get audio device friendly name!"); + lstrcpynW((LPWSTR)details->DisplayName, deviceName.pwszVal, ARRAYSIZE(details->DisplayName) - 1); + PropVariantClear(&deviceName); + IPropertyStore_Release(properties); + + /* Set the Device ID */ + hr = IMMDevice_GetId(device, &str); + FAudio_assert(!FAILED(hr) && "Failed to get audio endpoint id!"); + lstrcpynW((LPWSTR)details->DeviceID, str, ARRAYSIZE(details->DeviceID) - 1); + CoTaskMemFree(str); + + hr = IMMDevice_Activate( + device, + &IID_IAudioClient, + CLSCTX_ALL, + NULL, + (void **)&client + ); + FAudio_assert(!FAILED(hr) && "Failed to activate audio client!"); + + hr = IAudioClient_GetMixFormat(client, &format); + FAudio_assert(!FAILED(hr) && "Failed to get audio client mix format!"); + + if (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + ext = (WAVEFORMATEXTENSIBLE *)format; + sub = ext->SubFormat; + FAudio_memcpy( + &ext->SubFormat, + &DATAFORMAT_SUBTYPE_PCM, + sizeof(GUID) + ); + + hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, format, &obtained); + if (FAILED(hr)) + { + ext->SubFormat = sub; + } + else if (obtained) + { + CoTaskMemFree(format); + format = obtained; + } + } + + details->OutputFormat.Format.wFormatTag = format->wFormatTag; + details->OutputFormat.Format.nChannels = format->nChannels; + details->OutputFormat.Format.nSamplesPerSec = format->nSamplesPerSec; + details->OutputFormat.Format.nAvgBytesPerSec = format->nAvgBytesPerSec; + details->OutputFormat.Format.nBlockAlign = format->nBlockAlign; + details->OutputFormat.Format.wBitsPerSample = format->wBitsPerSample; + details->OutputFormat.Format.cbSize = format->cbSize; + + if (format->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + ext = (WAVEFORMATEXTENSIBLE *)format; + details->OutputFormat.Samples.wValidBitsPerSample = ext->Samples.wValidBitsPerSample; + details->OutputFormat.dwChannelMask = ext->dwChannelMask; + FAudio_memcpy( + &details->OutputFormat.SubFormat, + &ext->SubFormat, + sizeof(GUID) + ); + } + else + { + details->OutputFormat.dwChannelMask = GetMask(format->nChannels); + } + + CoTaskMemFree(format); + + IAudioClient_Release(client); + + IMMDevice_Release(device); + + FAudio_PlatformRelease(); + + return ret; +} + +FAudioMutex FAudio_PlatformCreateMutex(void) +{ + CRITICAL_SECTION *cs; + + cs = FAudio_malloc(sizeof(CRITICAL_SECTION)); + if (!cs) return NULL; + + InitializeCriticalSection(cs); + + return cs; +} + +void FAudio_PlatformLockMutex(FAudioMutex mutex) +{ + if (mutex) EnterCriticalSection(mutex); +} + +void FAudio_PlatformUnlockMutex(FAudioMutex mutex) +{ + if (mutex) LeaveCriticalSection(mutex); +} + +void FAudio_PlatformDestroyMutex(FAudioMutex mutex) +{ + if (mutex) DeleteCriticalSection(mutex); + FAudio_free(mutex); +} + +struct FAudioThreadArgs +{ + FAudioThreadFunc func; + const char *name; + void* data; +}; + +static DWORD WINAPI FaudioThreadWrapper(void *user) +{ + struct FAudioThreadArgs *args = user; + DWORD ret; + + FAudio_set_thread_name(args->name); + ret = args->func(args->data); + + FAudio_free(args); + return ret; +} + +FAudioThread FAudio_PlatformCreateThread( + FAudioThreadFunc func, + const char *name, + void* data +) { + struct FAudioThreadArgs *args; + + if (!(args = FAudio_malloc(sizeof(*args)))) return NULL; + args->func = func; + args->name = name; + args->data = data; + + return CreateThread(NULL, 0, &FaudioThreadWrapper, args, 0, NULL); +} + +void FAudio_PlatformWaitThread(FAudioThread thread, int32_t *retval) +{ + WaitForSingleObject(thread, INFINITE); + if (retval != NULL) GetExitCodeThread(thread, (DWORD *)retval); +} + +void FAudio_PlatformThreadPriority(FAudioThreadPriority priority) +{ + /* FIXME */ +} + +uint64_t FAudio_PlatformGetThreadID(void) +{ + return GetCurrentThreadId(); +} + +void FAudio_sleep(uint32_t ms) +{ + Sleep(ms); +} + +uint32_t FAudio_timems() +{ + return GetTickCount(); +} + +/* FAudio I/O */ + +static size_t FAUDIOCALL FAudio_FILE_read( + void *data, + void *dst, + size_t size, + size_t count +) { + if (!data) return 0; + return fread(dst, size, count, data); +} + +static int64_t FAUDIOCALL FAudio_FILE_seek( + void *data, + int64_t offset, + int whence +) { + if (!data) return -1; + fseek(data, offset, whence); + return ftell(data); +} + +static int FAUDIOCALL FAudio_FILE_close(void *data) +{ + if (!data) return 0; + fclose(data); + return 0; +} + +FAudioIOStream* FAudio_fopen(const char *path) +{ + FAudioIOStream *io; + + io = (FAudioIOStream*) FAudio_malloc(sizeof(FAudioIOStream)); + if (!io) return NULL; + + io->data = fopen(path, "rb"); + io->read = FAudio_FILE_read; + io->seek = FAudio_FILE_seek; + io->close = FAudio_FILE_close; + io->lock = FAudio_PlatformCreateMutex(); + + return io; +} + +struct FAudio_mem +{ + char *mem; + int64_t len; + int64_t pos; +}; + +static size_t FAUDIOCALL FAudio_mem_read( + void *data, + void *dst, + size_t size, + size_t count +) { + struct FAudio_mem *io = data; + size_t len = size * count; + + if (!data) return 0; + + while (len && len > (io->len - io->pos)) len -= size; + FAudio_memcpy(dst, io->mem + io->pos, len); + io->pos += len; + + return len; +} + +static int64_t FAUDIOCALL FAudio_mem_seek( + void *data, + int64_t offset, + int whence +) { + struct FAudio_mem *io = data; + if (!data) return -1; + + if (whence == SEEK_SET) + { + if (io->len > offset) io->pos = offset; + else io->pos = io->len; + } + if (whence == SEEK_CUR) + { + if (io->len > io->pos + offset) io->pos += offset; + else io->pos = io->len; + } + if (whence == SEEK_END) + { + if (io->len > offset) io->pos = io->len - offset; + else io->pos = 0; + } + + return io->pos; +} + +static int FAUDIOCALL FAudio_mem_close(void *data) +{ + if (!data) return 0; + FAudio_free(data); + return 0; +} + +FAudioIOStream* FAudio_memopen(void *mem, int len) +{ + struct FAudio_mem *data; + FAudioIOStream *io; + + io = (FAudioIOStream*) FAudio_malloc(sizeof(FAudioIOStream)); + if (!io) return NULL; + + data = FAudio_malloc(sizeof(struct FAudio_mem)); + if (!data) + { + FAudio_free(io); + return NULL; + } + + data->mem = mem; + data->len = len; + data->pos = 0; + + io->data = data; + io->read = FAudio_mem_read; + io->seek = FAudio_mem_seek; + io->close = FAudio_mem_close; + io->lock = FAudio_PlatformCreateMutex(); + return io; +} + +uint8_t* FAudio_memptr(FAudioIOStream *io, size_t offset) +{ + struct FAudio_mem *memio = io->data; + return memio->mem + offset; +} + +void FAudio_close(FAudioIOStream *io) +{ + io->close(io->data); + FAudio_PlatformDestroyMutex((FAudioMutex) io->lock); + FAudio_free(io); +} + +/* XNA Song implementation over Win32 MF */ + +static FAudioWaveFormatEx activeSongFormat; +IMFSourceReader *activeSong; +static uint8_t *songBuffer; +static SIZE_T songBufferSize; + +static float songVolume = 1.0f; +static FAudio *songAudio = NULL; +static FAudioMasteringVoice *songMaster = NULL; + +static FAudioSourceVoice *songVoice = NULL; +static FAudioVoiceCallback callbacks; + +/* Internal Functions */ + +static void XNA_SongSubmitBuffer(FAudioVoiceCallback *callback, void *pBufferContext) +{ + IMFMediaBuffer *media_buffer; + FAudioBuffer buffer; + IMFSample *sample; + HRESULT hr; + DWORD flags, buffer_size = 0; + BYTE *buffer_ptr; + + LOG_FUNC_ENTER(songAudio); + + FAudio_memset(&buffer, 0, sizeof(buffer)); + + hr = IMFSourceReader_ReadSample( + activeSong, + MF_SOURCE_READER_FIRST_AUDIO_STREAM, + 0, + NULL, + &flags, + NULL, + &sample + ); + FAudio_assert(!FAILED(hr) && "Failed to read audio sample!"); + + if (flags & MF_SOURCE_READERF_ENDOFSTREAM) + { + buffer.Flags = FAUDIO_END_OF_STREAM; + } + else + { + hr = IMFSample_ConvertToContiguousBuffer( + sample, + &media_buffer + ); + FAudio_assert(!FAILED(hr) && "Failed to get sample buffer!"); + + hr = IMFMediaBuffer_Lock( + media_buffer, + &buffer_ptr, + NULL, + &buffer_size + ); + FAudio_assert(!FAILED(hr) && "Failed to lock buffer bytes!"); + + if (songBufferSize < buffer_size) + { + songBufferSize = buffer_size; + songBuffer = FAudio_realloc(songBuffer, songBufferSize); + FAudio_assert(songBuffer != NULL && "Failed to allocate song buffer!"); + } + FAudio_memcpy(songBuffer, buffer_ptr, buffer_size); + + hr = IMFMediaBuffer_Unlock(media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to unlock buffer bytes!"); + + IMFMediaBuffer_Release(media_buffer); + IMFSample_Release(sample); + } + + if (buffer_size > 0) + { + buffer.AudioBytes = buffer_size; + buffer.pAudioData = songBuffer; + buffer.PlayBegin = 0; + buffer.PlayLength = buffer_size / activeSongFormat.nBlockAlign; + buffer.LoopBegin = 0; + buffer.LoopLength = 0; + buffer.LoopCount = 0; + buffer.pContext = NULL; + FAudioSourceVoice_SubmitSourceBuffer( + songVoice, + &buffer, + NULL + ); + } + + LOG_FUNC_EXIT(songAudio); +} + +static void XNA_SongKill() +{ + if (songVoice != NULL) + { + FAudioSourceVoice_Stop(songVoice, 0, 0); + FAudioVoice_DestroyVoice(songVoice); + songVoice = NULL; + } + if (activeSong) + { + IMFSourceReader_Release(activeSong); + activeSong = NULL; + } + FAudio_free(songBuffer); + songBuffer = NULL; + songBufferSize = 0; +} + +/* "Public" API */ + +FAUDIOAPI void XNA_SongInit() +{ + HRESULT hr; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + FAudio_assert(!FAILED(hr) && "Failed to initialize Media Foundation!"); + + FAudioCreate(&songAudio, 0, FAUDIO_DEFAULT_PROCESSOR); + FAudio_CreateMasteringVoice( + songAudio, + &songMaster, + FAUDIO_DEFAULT_CHANNELS, + FAUDIO_DEFAULT_SAMPLERATE, + 0, + 0, + NULL + ); +} + +FAUDIOAPI void XNA_SongQuit() +{ + XNA_SongKill(); + FAudioVoice_DestroyVoice(songMaster); + FAudio_Release(songAudio); + MFShutdown(); +} + +FAUDIOAPI float XNA_PlaySong(const char *name) +{ + IMFAttributes *attributes = NULL; + IMFMediaType *media_type = NULL; + UINT32 channels, samplerate; + UINT64 duration; + PROPVARIANT var; + HRESULT hr; + WCHAR filename_w[MAX_PATH]; + + LOG_FUNC_ENTER(songAudio); + LOG_INFO(songAudio, "name %s\n", name); + XNA_SongKill(); + + MultiByteToWideChar(CP_UTF8, 0, name, -1, filename_w, MAX_PATH); + + hr = MFCreateAttributes(&attributes, 1); + FAudio_assert(!FAILED(hr) && "Failed to create attributes!"); + hr = MFCreateSourceReaderFromURL( + filename_w, + attributes, + &activeSong + ); + FAudio_assert(!FAILED(hr) && "Failed to create source reader!"); + IMFAttributes_Release(attributes); + + hr = MFCreateMediaType(&media_type); + FAudio_assert(!FAILED(hr) && "Failed to create media type!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_MAJOR_TYPE, + &MFMediaType_Audio + ); + FAudio_assert(!FAILED(hr) && "Failed to set major type!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_SUBTYPE, + &MFAudioFormat_Float + ); + FAudio_assert(!FAILED(hr) && "Failed to set sub type!"); + hr = IMFSourceReader_SetCurrentMediaType( + activeSong, + MF_SOURCE_READER_FIRST_AUDIO_STREAM, + NULL, + media_type + ); + FAudio_assert(!FAILED(hr) && "Failed to set source media type!"); + hr = IMFSourceReader_SetStreamSelection( + activeSong, + MF_SOURCE_READER_FIRST_AUDIO_STREAM, + TRUE + ); + FAudio_assert(!FAILED(hr) && "Failed to select source stream!"); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType( + activeSong, + MF_SOURCE_READER_FIRST_AUDIO_STREAM, + &media_type + ); + FAudio_assert(!FAILED(hr) && "Failed to get current media type!"); + hr = IMFMediaType_GetUINT32( + media_type, + &MF_MT_AUDIO_NUM_CHANNELS, + &channels + ); + FAudio_assert(!FAILED(hr) && "Failed to get channel count!"); + hr = IMFMediaType_GetUINT32( + media_type, + &MF_MT_AUDIO_SAMPLES_PER_SECOND, + &samplerate + ); + FAudio_assert(!FAILED(hr) && "Failed to get sample rate!"); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetPresentationAttribute( + activeSong, + MF_SOURCE_READER_MEDIASOURCE, + &MF_PD_DURATION, + &var + ); + FAudio_assert(!FAILED(hr) && "Failed to get song duration!"); + hr = PropVariantToInt64(&var, &duration); + FAudio_assert(!FAILED(hr) && "Failed to get song duration!"); + PropVariantClear(&var); + + activeSongFormat.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT; + activeSongFormat.nChannels = channels; + activeSongFormat.nSamplesPerSec = samplerate; + activeSongFormat.wBitsPerSample = sizeof(float) * 8; + activeSongFormat.nBlockAlign = activeSongFormat.nChannels * activeSongFormat.wBitsPerSample / 8; + activeSongFormat.nAvgBytesPerSec = activeSongFormat.nSamplesPerSec * activeSongFormat.nBlockAlign; + activeSongFormat.cbSize = 0; + + /* Init voice */ + FAudio_zero(&callbacks, sizeof(FAudioVoiceCallback)); + callbacks.OnBufferEnd = XNA_SongSubmitBuffer; + FAudio_CreateSourceVoice( + songAudio, + &songVoice, + &activeSongFormat, + 0, + 1.0f, /* No pitch shifting here! */ + &callbacks, + NULL, + NULL + ); + FAudioVoice_SetVolume(songVoice, songVolume, 0); + XNA_SongSubmitBuffer(NULL, NULL); + + /* Finally. */ + FAudioSourceVoice_Start(songVoice, 0, 0); + LOG_FUNC_EXIT(songAudio); + return duration / 10000000.; +} + +FAUDIOAPI void XNA_PauseSong() +{ + if (songVoice == NULL) + { + return; + } + FAudioSourceVoice_Stop(songVoice, 0, 0); +} + +FAUDIOAPI void XNA_ResumeSong() +{ + if (songVoice == NULL) + { + return; + } + FAudioSourceVoice_Start(songVoice, 0, 0); +} + +FAUDIOAPI void XNA_StopSong() +{ + XNA_SongKill(); +} + +FAUDIOAPI void XNA_SetSongVolume(float volume) +{ + songVolume = volume; + if (songVoice != NULL) + { + FAudioVoice_SetVolume(songVoice, songVolume, 0); + } +} + +FAUDIOAPI uint32_t XNA_GetSongEnded() +{ + FAudioVoiceState state; + if (songVoice == NULL || activeSong == NULL) + { + return 1; + } + FAudioSourceVoice_GetState(songVoice, &state, 0); + return state.BuffersQueued == 0 && state.SamplesPlayed == 0; +} + +FAUDIOAPI void XNA_EnableVisualization(uint32_t enable) +{ + /* TODO: Enable/Disable FAPO effect */ +} + +FAUDIOAPI uint32_t XNA_VisualizationEnabled() +{ + /* TODO: Query FAPO effect enabled */ + return 0; +} + +FAUDIOAPI void XNA_GetSongVisualizationData( + float *frequencies, + float *samples, + uint32_t count +) { + /* TODO: Visualization FAPO that reads in Song samples, FFT analysis */ +} + +/* FAudio WMADEC implementation over Win32 MF */ + +struct FAudioWMADEC +{ + IMFTransform *decoder; + IMFSample *output_sample; + + char *output_buf; + size_t output_pos; + size_t output_size; + size_t input_pos; + size_t input_size; +}; + +static HRESULT FAudio_WMAMF_ProcessInput( + FAudioVoice *voice, + FAudioBuffer *buffer +) { + struct FAudioWMADEC *impl = voice->src.wmadec; + IMFMediaBuffer *media_buffer; + IMFSample *sample; + DWORD copy_size; + BYTE *copy_buf; + HRESULT hr; + + copy_size = min(buffer->AudioBytes - impl->input_pos, impl->input_size); + if (!copy_size) return S_FALSE; + LOG_INFO(voice->audio, "pushing %x bytes at %x", copy_size, impl->input_pos); + + hr = MFCreateSample(&sample); + FAudio_assert(!FAILED(hr) && "Failed to create sample!"); + hr = MFCreateMemoryBuffer(copy_size, &media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to create buffer!"); + hr = IMFMediaBuffer_SetCurrentLength(media_buffer, copy_size); + FAudio_assert(!FAILED(hr) && "Failed to set buffer length!"); + hr = IMFMediaBuffer_Lock( + media_buffer, + ©_buf, + NULL, + ©_size + ); + FAudio_assert(!FAILED(hr) && "Failed to lock buffer bytes!"); + FAudio_memcpy(copy_buf, buffer->pAudioData + impl->input_pos, copy_size); + hr = IMFMediaBuffer_Unlock(media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to unlock buffer bytes!"); + + hr = IMFSample_AddBuffer(sample, media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to buffer to sample!"); + IMFMediaBuffer_Release(media_buffer); + + hr = IMFTransform_ProcessInput(impl->decoder, 0, sample, 0); + IMFSample_Release(sample); + if (hr == MF_E_NOTACCEPTING) return S_OK; + if (FAILED(hr)) + { + LOG_ERROR(voice->audio, "IMFTransform_ProcessInput returned %#x", hr); + return hr; + } + + impl->input_pos += copy_size; + return S_OK; +}; + +static HRESULT FAudio_WMAMF_ProcessOutput( + FAudioVoice *voice, + FAudioBuffer *buffer +) { + struct FAudioWMADEC *impl = voice->src.wmadec; + MFT_OUTPUT_DATA_BUFFER output; + IMFMediaBuffer *media_buffer; + DWORD status, copy_size; + BYTE *copy_buf; + HRESULT hr; + + while (1) + { + FAudio_memset(&output, 0, sizeof(output)); + output.pSample = impl->output_sample; + hr = IMFTransform_ProcessOutput(impl->decoder, 0, 1, &output, &status); + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) return S_FALSE; + if (FAILED(hr)) + { + LOG_ERROR(voice->audio, "IMFTransform_ProcessInput returned %#x", hr); + return hr; + } + + if (output.dwStatus & MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE) continue; + + hr = IMFSample_ConvertToContiguousBuffer( + output.pSample, + &media_buffer + ); + FAudio_assert(!FAILED(hr) && "Failed to get sample buffer!"); + hr = IMFMediaBuffer_Lock( + media_buffer, + ©_buf, + NULL, + ©_size + ); + FAudio_assert(!FAILED(hr) && "Failed to lock buffer bytes!"); + if (impl->output_pos + copy_size > impl->output_size) + { + impl->output_size = max( + impl->output_pos + copy_size, + impl->output_size * 3 / 2 + ); + impl->output_buf = voice->audio->pRealloc( + impl->output_buf, + impl->output_size + ); + FAudio_assert(impl->output_buf && "Failed to resize output buffer!"); + } + FAudio_memcpy(impl->output_buf + impl->output_pos, copy_buf, copy_size); + impl->output_pos += copy_size; + LOG_INFO(voice->audio, "pulled %x bytes at %x", copy_size, impl->output_pos); + hr = IMFMediaBuffer_Unlock(media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to unlock buffer bytes!"); + + IMFMediaBuffer_Release(media_buffer); + if (!impl->output_sample) IMFSample_Release(output.pSample); + } + + return S_OK; +}; + +static void FAudio_INTERNAL_DecodeWMAMF( + FAudioVoice *voice, + FAudioBuffer *buffer, + float *decodeCache, + uint32_t samples +) { + const FAudioWaveFormatExtensible *wfx = (FAudioWaveFormatExtensible *)voice->src.format; + size_t samples_pos, samples_size, copy_size = 0; + struct FAudioWMADEC *impl = voice->src.wmadec; + HRESULT hr; + + LOG_FUNC_ENTER(voice->audio) + + if (!impl->output_pos) + { + if (wfx->Format.wFormatTag == FAUDIO_FORMAT_EXTENSIBLE) + { + const FAudioBufferWMA *wma = &voice->src.bufferList->bufferWMA; + const UINT32 *output_sizes = wma->pDecodedPacketCumulativeBytes; + + impl->input_size = wfx->Format.nBlockAlign; + impl->output_size = max( + impl->output_size, + output_sizes[wma->PacketCount - 1] + ); + } + else + { + const FAudioXMA2WaveFormat *xwf = (const FAudioXMA2WaveFormat *)wfx; + + impl->input_size = xwf->dwBytesPerBlock; + impl->output_size = max( + impl->output_size, + (size_t) xwf->dwSamplesEncoded * + voice->src.format->nChannels * + (voice->src.format->wBitsPerSample / 8) + ); + } + + impl->output_buf = voice->audio->pRealloc( + impl->output_buf, + impl->output_size + ); + FAudio_assert(impl->output_buf && "Failed to allocate output buffer!"); + + LOG_INFO(voice->audio, "sending BOS to %p", impl->decoder); + hr = IMFTransform_ProcessMessage( + impl->decoder, + MFT_MESSAGE_NOTIFY_START_OF_STREAM, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed to notify decoder stream start!"); + FAudio_WMAMF_ProcessInput(voice, buffer); + } + + samples_pos = voice->src.curBufferOffset * voice->src.format->nChannels * sizeof(float); + samples_size = samples * voice->src.format->nChannels * sizeof(float); + + while (impl->output_pos < samples_pos + samples_size) + { + hr = FAudio_WMAMF_ProcessOutput(voice, buffer); + if (FAILED(hr)) goto error; + if (hr == S_OK) continue; + + hr = FAudio_WMAMF_ProcessInput(voice, buffer); + if (FAILED(hr)) goto error; + if (hr == S_OK) continue; + + if (!impl->input_size) break; + + LOG_INFO(voice->audio, "sending EOS to %p", impl->decoder); + hr = IMFTransform_ProcessMessage( + impl->decoder, + MFT_MESSAGE_NOTIFY_END_OF_STREAM, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed to send EOS!"); + impl->input_size = 0; + } + + if (impl->output_pos > samples_pos) + { + copy_size = FAudio_min(impl->output_pos - samples_pos, samples_size); + FAudio_memcpy(decodeCache, impl->output_buf + samples_pos, copy_size); + } + FAudio_zero(decodeCache + copy_size, samples_size - copy_size); + LOG_INFO( + voice->audio, + "decoded %x / %x bytes, copied %x / %x bytes", + impl->output_pos, + impl->output_size, + copy_size, + samples_size + ); + + LOG_FUNC_EXIT(voice->audio) + return; + +error: + FAudio_zero(decodeCache, samples * voice->src.format->nChannels * sizeof(float)); + LOG_FUNC_EXIT(voice->audio) +} + +uint32_t FAudio_WMADEC_init(FAudioSourceVoice *voice, uint32_t type) +{ + static const uint8_t fake_codec_data[16] = {0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t fake_codec_data_wma3[18] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0}; + const FAudioWaveFormatExtensible *wfx = (FAudioWaveFormatExtensible *)voice->src.format; + struct FAudioWMADEC *impl; + MFT_OUTPUT_STREAM_INFO info = {0}; + IMFMediaBuffer *media_buffer; + IMFMediaType *media_type; + IMFTransform *decoder; + HRESULT hr; + UINT32 i, value; + GUID guid; + + LOG_FUNC_ENTER(voice->audio) + + if (!(impl = voice->audio->pMalloc(sizeof(*impl)))) return -1; + FAudio_memset(impl, 0, sizeof(*impl)); + + hr = CoCreateInstance( + &CLSID_CWMADecMediaObject, + 0, + CLSCTX_INPROC_SERVER, + &IID_IMFTransform, + (void **)&decoder + ); + if (FAILED(hr)) + { + voice->audio->pFree(impl->output_buf); + return -2; + } + + hr = MFCreateMediaType(&media_type); + FAudio_assert(!FAILED(hr) && "Failed create media type!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_MAJOR_TYPE, + &MFMediaType_Audio + ); + FAudio_assert(!FAILED(hr) && "Failed set media major type!"); + + switch (type) + { + case FAUDIO_FORMAT_WMAUDIO2: + hr = IMFMediaType_SetBlob( + media_type, + &MF_MT_USER_DATA, + (void *)fake_codec_data, + sizeof(fake_codec_data) + ); + FAudio_assert(!FAILED(hr) && "Failed set codec private data!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_SUBTYPE, + &MFAudioFormat_WMAudioV8 + ); + FAudio_assert(!FAILED(hr) && "Failed set media sub type!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + wfx->Format.nBlockAlign + ); + FAudio_assert(!FAILED(hr) && "Failed set input block align!"); + break; + case FAUDIO_FORMAT_WMAUDIO3: + *(uint16_t *)fake_codec_data_wma3 = voice->src.format->wBitsPerSample; + for (i = 0; i < voice->src.format->nChannels; i++) + { + fake_codec_data_wma3[2] <<= 1; + fake_codec_data_wma3[2] |= 1; + } + hr = IMFMediaType_SetBlob( + media_type, + &MF_MT_USER_DATA, + (void *)fake_codec_data_wma3, + sizeof(fake_codec_data_wma3) + ); + FAudio_assert(!FAILED(hr) && "Failed set codec private data!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_SUBTYPE, + &MFAudioFormat_WMAudioV9 + ); + FAudio_assert(!FAILED(hr) && "Failed set media sub type!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + wfx->Format.nBlockAlign + ); + FAudio_assert(!FAILED(hr) && "Failed set input block align!"); + break; + case FAUDIO_FORMAT_WMAUDIO_LOSSLESS: + hr = IMFMediaType_SetBlob( + media_type, + &MF_MT_USER_DATA, + (void *)&wfx->Samples, + wfx->Format.cbSize + ); + FAudio_assert(!FAILED(hr) && "Failed set codec private data!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_SUBTYPE, + &MFAudioFormat_WMAudio_Lossless + ); + FAudio_assert(!FAILED(hr) && "Failed set media sub type!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + wfx->Format.nBlockAlign + ); + FAudio_assert(!FAILED(hr) && "Failed set input block align!"); + break; + case FAUDIO_FORMAT_XMAUDIO2: + { + const FAudioXMA2WaveFormat *xwf = (const FAudioXMA2WaveFormat *)wfx; + hr = IMFMediaType_SetBlob( + media_type, + &MF_MT_USER_DATA, + (void *)&wfx->Samples, + wfx->Format.cbSize + ); + FAudio_assert(!FAILED(hr) && "Failed set codec private data!"); + hr = IMFMediaType_SetGUID( + media_type, + &MF_MT_SUBTYPE, + &MFAudioFormat_XMAudio2 + ); + FAudio_assert(!FAILED(hr) && "Failed set media sub type!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + xwf->dwBytesPerBlock + ); + FAudio_assert(!FAILED(hr) && "Failed set input block align!"); + break; + } + default: + FAudio_assert(0 && "Unsupported type!"); + break; + } + + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BITS_PER_SAMPLE, + wfx->Format.wBitsPerSample + ); + FAudio_assert(!FAILED(hr) && "Failed set input bits per sample!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, + wfx->Format.nAvgBytesPerSec + ); + FAudio_assert(!FAILED(hr) && "Failed set input bytes per sample!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_NUM_CHANNELS, + wfx->Format.nChannels + ); + FAudio_assert(!FAILED(hr) && "Failed set input channel count!"); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_SAMPLES_PER_SECOND, + wfx->Format.nSamplesPerSec + ); + FAudio_assert(!FAILED(hr) && "Failed set input sample rate!"); + + hr = IMFTransform_SetInputType( + decoder, + 0, + media_type, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed set decoder input type!"); + IMFMediaType_Release(media_type); + + i = 0; + while (SUCCEEDED(hr)) + { + hr = IMFTransform_GetOutputAvailableType( + decoder, + 0, + i++, + &media_type + ); + FAudio_assert(!FAILED(hr) && "Failed get output media type!"); + + hr = IMFMediaType_GetGUID( + media_type, + &MF_MT_MAJOR_TYPE, + &guid + ); + FAudio_assert(!FAILED(hr) && "Failed get media major type!"); + if (!IsEqualGUID(&MFMediaType_Audio, &guid)) goto next; + + hr = IMFMediaType_GetGUID( + media_type, + &MF_MT_SUBTYPE, + &guid + ); + FAudio_assert(!FAILED(hr) && "Failed get media major type!"); + if (!IsEqualGUID(&MFAudioFormat_Float, &guid)) goto next; + + hr = IMFMediaType_GetUINT32( + media_type, + &MF_MT_AUDIO_BITS_PER_SAMPLE, + &value + ); + if (FAILED(hr)) + { + value = 32; + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BITS_PER_SAMPLE, + value + ); + } + FAudio_assert(!FAILED(hr) && "Failed get bits per sample!"); + if (value != 32) goto next; + + hr = IMFMediaType_GetUINT32( + media_type, + &MF_MT_AUDIO_NUM_CHANNELS, + &value + ); + if (FAILED(hr)) + { + value = wfx->Format.nChannels; + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_NUM_CHANNELS, + value + ); + } + FAudio_assert(!FAILED(hr) && "Failed get channel count!"); + if (value != wfx->Format.nChannels) goto next; + + hr = IMFMediaType_GetUINT32( + media_type, + &MF_MT_AUDIO_SAMPLES_PER_SECOND, + &value + ); + if (FAILED(hr)) + { + value = wfx->Format.nSamplesPerSec; + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_SAMPLES_PER_SECOND, + value + ); + } + FAudio_assert(!FAILED(hr) && "Failed get sample rate!"); + if (value != wfx->Format.nSamplesPerSec) goto next; + + hr = IMFMediaType_GetUINT32( + media_type, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + &value + ); + if (FAILED(hr)) + { + value = wfx->Format.nChannels * sizeof(float); + hr = IMFMediaType_SetUINT32( + media_type, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + value + ); + } + FAudio_assert(!FAILED(hr) && "Failed get block align!"); + if (value == wfx->Format.nChannels * sizeof(float)) break; + +next: + IMFMediaType_Release(media_type); + } + FAudio_assert(!FAILED(hr) && "Failed to find output media type!"); + hr = IMFTransform_SetOutputType(decoder, 0, media_type, 0); + FAudio_assert(!FAILED(hr) && "Failed set decoder output type!"); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputStreamInfo(decoder, 0, &info); + FAudio_assert(!FAILED(hr) && "Failed to get output stream info!"); + + impl->decoder = decoder; + if (!(info.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES)) + { + hr = MFCreateSample(&impl->output_sample); + FAudio_assert(!FAILED(hr) && "Failed to create sample!"); + hr = MFCreateMemoryBuffer(info.cbSize, &media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to create buffer!"); + hr = IMFSample_AddBuffer(impl->output_sample, media_buffer); + FAudio_assert(!FAILED(hr) && "Failed to buffer to sample!"); + IMFMediaBuffer_Release(media_buffer); + } + + hr = IMFTransform_ProcessMessage( + decoder, + MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed to start decoder stream!"); + + voice->src.wmadec = impl; + voice->src.decode = FAudio_INTERNAL_DecodeWMAMF; + + LOG_FUNC_EXIT(voice->audio); + return 0; +} + +void FAudio_WMADEC_free(FAudioSourceVoice *voice) +{ + struct FAudioWMADEC *impl = voice->src.wmadec; + HRESULT hr; + + LOG_FUNC_ENTER(voice->audio) + FAudio_PlatformLockMutex(voice->audio->sourceLock); + LOG_MUTEX_LOCK(voice->audio, voice->audio->sourceLock) + + if (impl->input_size) + { + LOG_INFO(voice->audio, "sending EOS to %p", impl->decoder); + hr = IMFTransform_ProcessMessage( + impl->decoder, + MFT_MESSAGE_NOTIFY_END_OF_STREAM, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed to send EOS!"); + impl->input_size = 0; + } + if (impl->output_pos) + { + LOG_INFO(voice->audio, "sending DRAIN to %p", impl->decoder); + hr = IMFTransform_ProcessMessage( + impl->decoder, + MFT_MESSAGE_COMMAND_DRAIN, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed to send DRAIN!"); + impl->output_pos = 0; + } + + if (impl->output_sample) IMFSample_Release(impl->output_sample); + IMFTransform_Release(impl->decoder); + voice->audio->pFree(impl->output_buf); + voice->audio->pFree(voice->src.wmadec); + voice->src.wmadec = NULL; + voice->src.decode = NULL; + + FAudio_PlatformUnlockMutex(voice->audio->sourceLock); + LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) + LOG_FUNC_EXIT(voice->audio) +} + +void FAudio_WMADEC_end_buffer(FAudioSourceVoice *voice) +{ + struct FAudioWMADEC *impl = voice->src.wmadec; + HRESULT hr; + + LOG_FUNC_ENTER(voice->audio) + + if (impl->input_size) + { + LOG_INFO(voice->audio, "sending EOS to %p", impl->decoder); + hr = IMFTransform_ProcessMessage( + impl->decoder, + MFT_MESSAGE_NOTIFY_END_OF_STREAM, + 0 + ); + FAudio_assert(!FAILED(hr) && "Failed to send EOS!"); + impl->input_size = 0; + } + impl->output_pos = 0; + impl->input_pos = 0; + + LOG_FUNC_EXIT(voice->audio) +} + +#else + +extern int this_tu_is_empty; + +#endif /* FAUDIO_WIN32_PLATFORM */ diff --git a/src/XNA_Song.c b/src/XNA_Song.c index 1a98d40014..73f9991056 100644 --- a/src/XNA_Song.c +++ b/src/XNA_Song.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -33,14 +33,18 @@ #define malloc FAudio_malloc #define realloc FAudio_realloc #define free FAudio_free +#ifdef STB_MEMSET_OVERRIDE #ifdef memset /* Thanks, Apple! */ #undef memset #endif #define memset FAudio_memset +#endif /* STB_MEMSET_OVERRIDE */ +#ifdef STB_MEMCPY_OVERRIDE #ifdef memcpy /* Thanks, Apple! */ #undef memcpy #endif #define memcpy FAudio_memcpy +#endif /* STB_MEMCPY_OVERRIDE */ #define memcmp FAudio_memcmp #define pow FAudio_pow @@ -70,6 +74,7 @@ #define SEEK_END FAUDIO_SEEK_END #define EOF FAUDIO_EOF #define fopen(path, mode) FAudio_fopen(path) +#define fopen_s(io, path, mode) (!(*io = FAudio_fopen(path))) #define fclose(io) FAudio_close(io) #define fread(dst, size, count, io) io->read(io->data, dst, size, count) #define fseek(io, offset, whence) io->seek(io->data, offset, whence) @@ -79,16 +84,27 @@ #define STB_VORBIS_NO_INTEGER_CONVERSION 1 #include "stb_vorbis.h" +#include "qoa_decoder.h" + /* Globals */ static float songVolume = 1.0f; static FAudio *songAudio = NULL; static FAudioMasteringVoice *songMaster = NULL; +static unsigned int songLength = 0; +static unsigned int songOffset = 0; static FAudioSourceVoice *songVoice = NULL; static FAudioVoiceCallback callbacks; -static stb_vorbis *activeSong = NULL; -static stb_vorbis_info activeSongInfo; +static stb_vorbis *activeVorbisSong = NULL; +static stb_vorbis_info activeVorbisSongInfo; + +static qoa *activeQoaSong = NULL; +static unsigned int qoaChannels = 0; +static unsigned int qoaSampleRate = 0; +static unsigned int qoaSamplesPerChannelPerFrame = 0; +static unsigned int qoaTotalSamplesPerChannel = 0; + static uint8_t *songCache; /* Internal Functions */ @@ -96,20 +112,35 @@ static uint8_t *songCache; static void XNA_SongSubmitBuffer(FAudioVoiceCallback *callback, void *pBufferContext) { FAudioBuffer buffer; - uint32_t decoded = stb_vorbis_get_samples_float_interleaved( - activeSong, - activeSongInfo.channels, - (float*) songCache, - activeSongInfo.sample_rate * activeSongInfo.channels - ); + uint32_t decoded = 0; + + if (activeVorbisSong != NULL) + { + decoded = stb_vorbis_get_samples_float_interleaved( + activeVorbisSong, + activeVorbisSongInfo.channels, + (float*) songCache, + activeVorbisSongInfo.sample_rate * activeVorbisSongInfo.channels + ); + buffer.AudioBytes = decoded * activeVorbisSongInfo.channels * sizeof(float); + } + else if (activeQoaSong != NULL) + { + /* TODO: decode multiple frames? */ + decoded = qoa_decode_next_frame( + activeQoaSong, + (short*) songCache + ); + buffer.AudioBytes = decoded * qoaChannels * sizeof(short); + } + if (decoded == 0) { return; } - buffer.Flags = (decoded < activeSongInfo.sample_rate) ? - FAUDIO_END_OF_STREAM : - 0; - buffer.AudioBytes = decoded * activeSongInfo.channels * sizeof(float); + + songOffset += decoded; + buffer.Flags = (songOffset >= songLength) ? FAUDIO_END_OF_STREAM : 0; buffer.pAudioData = songCache; buffer.PlayBegin = 0; buffer.PlayLength = decoded; @@ -137,10 +168,15 @@ static void XNA_SongKill() FAudio_free(songCache); songCache = NULL; } - if (activeSong != NULL) + if (activeVorbisSong != NULL) { - stb_vorbis_close(activeSong); - activeSong = NULL; + stb_vorbis_close(activeVorbisSong); + activeVorbisSong = NULL; + } + if (activeQoaSong != NULL) + { + qoa_close(activeQoaSong); + activeQoaSong = NULL; } } @@ -172,17 +208,45 @@ FAUDIOAPI float XNA_PlaySong(const char *name) FAudioWaveFormatEx format; XNA_SongKill(); - activeSong = stb_vorbis_open_filename(name, NULL, NULL); + activeVorbisSong = stb_vorbis_open_filename(name, NULL, NULL); - /* Set format info */ - activeSongInfo = stb_vorbis_get_info(activeSong); - format.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT; - format.nChannels = activeSongInfo.channels; - format.nSamplesPerSec = activeSongInfo.sample_rate; - format.wBitsPerSample = sizeof(float) * 8; - format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; - format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; - format.cbSize = 0; + if (activeVorbisSong != NULL) + { + activeVorbisSongInfo = stb_vorbis_get_info(activeVorbisSong); + format.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT; + format.nChannels = activeVorbisSongInfo.channels; + format.nSamplesPerSec = activeVorbisSongInfo.sample_rate; + format.wBitsPerSample = sizeof(float) * 8; + format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; + format.cbSize = 0; + + songOffset = 0; + songLength = stb_vorbis_stream_length_in_samples(activeVorbisSong); + } + else /* It's not vorbis, try qoa!*/ + { + activeQoaSong = qoa_open_from_filename(name); + + if (activeQoaSong == NULL) + { + /* It's neither vorbis nor qoa, time to bail */ + return 0; + } + + qoa_attributes(activeQoaSong, &qoaChannels, &qoaSampleRate, &qoaSamplesPerChannelPerFrame, &qoaTotalSamplesPerChannel); + + format.wFormatTag = FAUDIO_FORMAT_PCM; + format.nChannels = qoaChannels; + format.nSamplesPerSec = qoaSampleRate; + format.wBitsPerSample = 16; + format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; + format.cbSize = 0; + + songOffset = 0; + songLength = qoaTotalSamplesPerChannel; + } /* Allocate decode cache */ songCache = (uint8_t*) FAudio_malloc(format.nAvgBytesPerSec); @@ -203,12 +267,30 @@ FAUDIOAPI float XNA_PlaySong(const char *name) FAudioVoice_SetVolume(songVoice, songVolume, 0); /* Okay, this song is decoding now */ - stb_vorbis_seek_start(activeSong); + if (activeVorbisSong != NULL) + { + stb_vorbis_seek_start(activeVorbisSong); + } + else if (activeQoaSong != NULL) + { + qoa_seek_frame(activeQoaSong, 0); + } + XNA_SongSubmitBuffer(NULL, NULL); /* Finally. */ FAudioSourceVoice_Start(songVoice, 0, 0); - return stb_vorbis_stream_length_in_seconds(activeSong); + + if (activeVorbisSong != NULL) + { + return stb_vorbis_stream_length_in_seconds(activeVorbisSong); + } + else if (activeQoaSong != NULL) + { + return qoaTotalSamplesPerChannel / (float) qoaSampleRate; + } + + return 0; } FAUDIOAPI void XNA_PauseSong() @@ -246,12 +328,12 @@ FAUDIOAPI void XNA_SetSongVolume(float volume) FAUDIOAPI uint32_t XNA_GetSongEnded() { FAudioVoiceState state; - if (songVoice == NULL || activeSong == NULL) + if (songVoice == NULL || (activeVorbisSong == NULL && activeQoaSong == NULL)) { return 1; } FAudioSourceVoice_GetState(songVoice, &state, 0); - return state.BuffersQueued == 0; + return state.BuffersQueued == 0 && state.SamplesPlayed == 0; } FAUDIOAPI void XNA_EnableVisualization(uint32_t enable) diff --git a/src/matrix_defaults.inl b/src/matrix_defaults.inl index 2262a6a074..6f540f289d 100644 --- a/src/matrix_defaults.inl +++ b/src/matrix_defaults.inl @@ -1,6 +1,68 @@ /* This was generated by making 8 sources and 8 submixes, then assigning each * submix to each voice and dumping the output matrix. Terrible, but it worked! */ +/* +int main(int argc, char **argv) +{ + CoInitialize(NULL); + + IXAudio2 *engine; + XAudio2Create(&engine); + + IXAudio2MasteringVoice *master; + engine->CreateMasteringVoice(&master); + + FILE *fileOut = fopen("matrix_defaults.inl", "w"); + for (int srcChans = 1; srcChans < 9; srcChans += 1) + { + fprintf(fileOut, "{\n"); + for (int dstChans = 1; dstChans < 9; dstChans += 1) + { + IXAudio2SubmixVoice *submix; + engine->CreateSubmixVoice(&submix, dstChans, 48000); + + XAUDIO2_SEND_DESCRIPTOR sendDesc; + sendDesc.Flags = 0; + sendDesc.pOutputVoice = submix; + + XAUDIO2_VOICE_SENDS sends; + sends.SendCount = 1; + sends.pSends = &sendDesc; + + WAVEFORMATEX fmt; + fmt.wFormatTag = 1; + fmt.nChannels = srcChans; + fmt.nSamplesPerSec = 48000; + fmt.wBitsPerSample = 16; + fmt.nBlockAlign = srcChans * (fmt.wBitsPerSample / 8); + fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec; + fmt.cbSize = 0; + + IXAudio2SourceVoice *source; + engine->CreateSourceVoice(&source, &fmt, 0, 2.0f, NULL, &sends); + + float matrix[8 * 8]; + source->GetOutputMatrix(submix, srcChans, dstChans, matrix); + fprintf(fileOut, "\t{ "); + for (int i = 0; i < srcChans * dstChans; i += 1) + { + fprintf(fileOut, "%.9f%s ", matrix[i], (i == ((srcChans * dstChans) - 1)) ? "" : ","); + } + fprintf(fileOut, "}%s\n", (dstChans == 8) ? "" : ","); + + source->DestroyVoice(); + submix->DestroyVoice(); + } + fprintf(fileOut, "}%s\n", (srcChans == 8) ? "" : ","); + } + fclose(fileOut); + + master->DestroyVoice(); + engine->Release(); + CoUninitialize(); + return 0; +} +*/ { /* 1 x 1 */ { 1.000000000f }, diff --git a/src/qoa_decoder.h b/src/qoa_decoder.h new file mode 100644 index 0000000000..a64936f2e5 --- /dev/null +++ b/src/qoa_decoder.h @@ -0,0 +1,536 @@ +/* QOA decoder API for FAudio + +Copyright (c) 2024 Ethan Lee. + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. + +Ethan "flibitijibibo" Lee + +Original version: + +Copyright (c) 2024, Dominic Szablewski - https://phoboslab.org +SPDX-License-Identifier: MIT + +QOA - The "Quite OK Audio" format for fast, lossy audio compression + + +-- Data Format + +QOA encodes pulse-code modulated (PCM) audio data with up to 255 channels, +sample rates from 1 up to 16777215 hertz and a bit depth of 16 bits. + +The compression method employed in QOA is lossy; it discards some information +from the uncompressed PCM data. For many types of audio signals this compression +is "transparent", i.e. the difference from the original file is often not +audible. + +QOA encodes 20 samples of 16 bit PCM data into slices of 64 bits. A single +sample therefore requires 3.2 bits of storage space, resulting in a 5x +compression (16 / 3.2). + +A QOA file consists of an 8 byte file header, followed by a number of frames. +Each frame contains an 8 byte frame header, the current 16 byte en-/decoder +state per channel and 256 slices per channel. Each slice is 8 bytes wide and +encodes 20 samples of audio data. + +All values, including the slices, are big endian. The file layout is as follows: + +struct { + struct { + char magic[4]; // magic bytes "qoaf" + uint32_t samples; // samples per channel in this file + } file_header; + + struct { + struct { + uint8_t num_channels; // no. of channels + uint24_t samplerate; // samplerate in hz + uint16_t fsamples; // samples per channel in this frame + uint16_t fsize; // frame size (includes this header) + } frame_header; + + struct { + int16_t history[4]; // most recent last + int16_t weights[4]; // most recent last + } lms_state[num_channels]; + + qoa_slice_t slices[256][num_channels]; + + } frames[ceil(samples / (256 * 20))]; +} qoa_file_t; + +Each `qoa_slice_t` contains a quantized scalefactor `sf_quant` and 20 quantized +residuals `qrNN`: + +.- QOA_SLICE -- 64 bits, 20 samples --------------------------/ /------------. +| Byte[0] | Byte[1] | Byte[2] \ \ Byte[7] | +| 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 | 7 6 5 / / 2 1 0 | +|------------+--------+--------+--------+---------+---------+-\ \--+---------| +| sf_quant | qr00 | qr01 | qr02 | qr03 | qr04 | / / | qr19 | +`-------------------------------------------------------------\ \------------` + +Each frame except the last must contain exactly 256 slices per channel. The last +frame may contain between 1 .. 256 (inclusive) slices per channel. The last +slice (for each channel) in the last frame may contain less than 20 samples; the +slice still must be 8 bytes wide, with the unused samples zeroed out. + +Channels are interleaved per slice. E.g. for 2 channel stereo: +slice[0] = L, slice[1] = R, slice[2] = L, slice[3] = R ... + +A valid QOA file or stream must have at least one frame. Each frame must contain +at least one channel and one sample with a samplerate between 1 .. 16777215 +(inclusive). + +If the total number of samples is not known by the encoder, the samples in the +file header may be set to 0x00000000 to indicate that the encoder is +"streaming". In a streaming context, the samplerate and number of channels may +differ from frame to frame. For static files (those with samples set to a +non-zero value), each frame must have the same number of channels and same +samplerate. + +Note that this implementation of QOA only handles files with a known total +number of samples. + +A decoder should support at least 8 channels. The channel layout for channel +counts 1 .. 8 is: + + 1. Mono + 2. L, R + 3. L, R, C + 4. FL, FR, B/SL, B/SR + 5. FL, FR, C, B/SL, B/SR + 6. FL, FR, C, LFE, B/SL, B/SR + 7. FL, FR, C, LFE, B, SL, SR + 8. FL, FR, C, LFE, BL, BR, SL, SR + +QOA predicts each audio sample based on the previously decoded ones using a +"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the +dequantized residual forms the final output sample. + +*/ + +#define QOA_MIN_FILESIZE 16 +#define QOA_MAX_CHANNELS 8 + +#define QOA_SLICE_LEN 20 +#define QOA_SLICES_PER_FRAME 256 +#define QOA_FRAME_LEN (QOA_SLICES_PER_FRAME * QOA_SLICE_LEN) +#define QOA_LMS_LEN 4 +#define QOA_MAGIC 0x716f6166 /* 'qoaf' */ + +#define QOA_FRAME_SIZE(channels, slices) \ + (8 + QOA_LMS_LEN * 4 * channels + 8 * slices * channels) + +typedef struct { + int history[QOA_LMS_LEN]; + int weights[QOA_LMS_LEN]; +} qoa_lms_t; + +typedef struct { + unsigned int channels; + unsigned int samplerate; + unsigned int samples; + qoa_lms_t lms[QOA_MAX_CHANNELS]; + #ifdef QOA_RECORD_TOTAL_ERROR + double error; + #endif +} qoa_desc; + +typedef struct { + unsigned char *bytes; + unsigned int size; + unsigned int frame_index; + unsigned int frame_size; + unsigned short samples_per_channel_per_frame; + int free_on_close; + qoa_desc qoa; +} qoa_data; + +typedef unsigned long long qoa_uint64_t; + +typedef struct qoa qoa; + +/* NOTE: this API only supports "static" type QOA files. "streaming" type files are not supported!! */ +FAUDIOAPI qoa *qoa_open_from_memory(unsigned char *bytes, unsigned int size, int free_on_close); +FAUDIOAPI qoa *qoa_open_from_filename(const char *filename); +FAUDIOAPI void qoa_attributes(qoa *qoa, unsigned int *channels, unsigned int *samplerate, unsigned int *samples_per_channel_per_frame, unsigned int *total_samples_per_channel); +FAUDIOAPI unsigned int qoa_decode_next_frame(qoa *qoa, short *sample_data); /* decode the next frame into a preallocated buffer */ +FAUDIOAPI void qoa_seek_frame(qoa *qoa, int frame_index); +FAUDIOAPI void qoa_decode_entire(qoa *qoa, short *sample_data); /* fill a buffer with the entire qoa data decoded */ +FAUDIOAPI void qoa_close(qoa *qoa); + +/* The quant_tab provides an index into the dequant_tab for residuals in the +range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at +the higher end. Note that the residual zero is identical to the lowest positive +value. This is mostly fine, since the qoa_div() function always rounds away +from zero. */ + +static const int qoa_quant_tab[17] = { + 7, 7, 7, 5, 5, 3, 3, 1, /* -8..-1 */ + 0, /* 0 */ + 0, 2, 2, 4, 4, 6, 6, 6 /* 1.. 8 */ +}; + + +/* We have 16 different scalefactors. Like the quantized residuals these become +less accurate at the higher end. In theory, the highest scalefactor that we +would need to encode the highest 16bit residual is (2**16)/8 = 8192. However we +rely on the LMS filter to predict samples accurately enough that a maximum +residual of one quarter of the 16 bit range is sufficient. I.e. with the +scalefactor 2048 times the quant range of 8 we can encode residuals up to 2**14. + +The scalefactor values are computed as: +scalefactor_tab[s] <- round(pow(s + 1, 2.75)) */ + +static const int qoa_scalefactor_tab[16] = { + 1, 7, 21, 45, 84, 138, 211, 304, 421, 562, 731, 928, 1157, 1419, 1715, 2048 +}; + + +/* The reciprocal_tab maps each of the 16 scalefactors to their rounded +reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in +the encoder with just one multiplication instead of an expensive division. We +do this in .16 fixed point with integers, instead of floats. + +The reciprocal_tab is computed as: +reciprocal_tab[s] <- ((1<<16) + scalefactor_tab[s] - 1) / scalefactor_tab[s] */ + +static const int qoa_reciprocal_tab[16] = { + 65536, 9363, 3121, 1457, 781, 475, 311, 216, 156, 117, 90, 71, 57, 47, 39, 32 +}; + + +/* The dequant_tab maps each of the scalefactors and quantized residuals to +their unscaled & dequantized version. + +Since qoa_div rounds away from the zero, the smallest entries are mapped to 3/4 +instead of 1. The dequant_tab assumes the following dequantized values for each +of the quant_tab indices and is computed as: +float dqt[8] = {0.75, -0.75, 2.5, -2.5, 4.5, -4.5, 7, -7}; +dequant_tab[s][q] <- round_ties_away_from_zero(scalefactor_tab[s] * dqt[q]) + +The rounding employed here is "to nearest, ties away from zero", i.e. positive +and negative values are treated symmetrically. +*/ + +static const int qoa_dequant_tab[16][8] = { + { 1, -1, 3, -3, 5, -5, 7, -7}, + { 5, -5, 18, -18, 32, -32, 49, -49}, + { 16, -16, 53, -53, 95, -95, 147, -147}, + { 34, -34, 113, -113, 203, -203, 315, -315}, + { 63, -63, 210, -210, 378, -378, 588, -588}, + { 104, -104, 345, -345, 621, -621, 966, -966}, + { 158, -158, 528, -528, 950, -950, 1477, -1477}, + { 228, -228, 760, -760, 1368, -1368, 2128, -2128}, + { 316, -316, 1053, -1053, 1895, -1895, 2947, -2947}, + { 422, -422, 1405, -1405, 2529, -2529, 3934, -3934}, + { 548, -548, 1828, -1828, 3290, -3290, 5117, -5117}, + { 696, -696, 2320, -2320, 4176, -4176, 6496, -6496}, + { 868, -868, 2893, -2893, 5207, -5207, 8099, -8099}, + {1064, -1064, 3548, -3548, 6386, -6386, 9933, -9933}, + {1286, -1286, 4288, -4288, 7718, -7718, 12005, -12005}, + {1536, -1536, 5120, -5120, 9216, -9216, 14336, -14336}, +}; + + +/* The Least Mean Squares Filter is the heart of QOA. It predicts the next +sample based on the previous 4 reconstructed samples. It does so by continuously +adjusting 4 weights based on the residual of the previous prediction. + +The next sample is predicted as the sum of (weight[i] * history[i]). + +The adjustment of the weights is done with a "Sign-Sign-LMS" that adds or +subtracts the residual to each weight, based on the corresponding sample from +the history. This, surprisingly, is sufficient to get worthwhile predictions. + +This is all done with fixed point integers. Hence the right-shifts when updating +the weights and calculating the prediction. */ + +static int qoa_lms_predict(qoa_lms_t *lms) { + int prediction = 0; + int i; + for (i = 0; i < QOA_LMS_LEN; i++) { + prediction += lms->weights[i] * lms->history[i]; + } + return prediction >> 13; +} + +static void qoa_lms_update(qoa_lms_t *lms, int sample, int residual) { + int delta = residual >> 4; + int i; + for (i = 0; i < QOA_LMS_LEN; i++) { + lms->weights[i] += lms->history[i] < 0 ? -delta : delta; + } + + for (i = 0; i < QOA_LMS_LEN-1; i++) { + lms->history[i] = lms->history[i+1]; + } + lms->history[QOA_LMS_LEN-1] = sample; +} + + +/* qoa_div() implements a rounding division, but avoids rounding to zero for +small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still +returns as 0, which is handled in the qoa_quant_tab[]. +qoa_div() takes an index into the .16 fixed point qoa_reciprocal_tab as an +argument, so it can do the division with a cheaper integer multiplication. */ + +static inline int qoa_div(int v, int scalefactor) { + int reciprocal = qoa_reciprocal_tab[scalefactor]; + int n = (v * reciprocal + (1 << 15)) >> 16; + n = n + ((v > 0) - (v < 0)) - ((n > 0) - (n < 0)); /* round away from 0 */ + return n; +} + +static inline int qoa_clamp(int v, int min, int max) { + if (v < min) { return min; } + if (v > max) { return max; } + return v; +} + +/* This specialized clamp function for the signed 16 bit range improves decode +performance quite a bit. The extra if() statement works nicely with the CPUs +branch prediction as this branch is rarely taken. */ + +static inline int qoa_clamp_s16(int v) { + if ((unsigned int)(v + 32768) > 65535) { + if (v < -32768) { return -32768; } + if (v > 32767) { return 32767; } + } + return v; +} + +static inline qoa_uint64_t qoa_read_u64(const unsigned char *bytes, unsigned int *p) { + bytes += *p; + *p += 8; + return + ((qoa_uint64_t)(bytes[0]) << 56) | ((qoa_uint64_t)(bytes[1]) << 48) | + ((qoa_uint64_t)(bytes[2]) << 40) | ((qoa_uint64_t)(bytes[3]) << 32) | + ((qoa_uint64_t)(bytes[4]) << 24) | ((qoa_uint64_t)(bytes[5]) << 16) | + ((qoa_uint64_t)(bytes[6]) << 8) | ((qoa_uint64_t)(bytes[7]) << 0); +} + +/* ----------------------------------------------------------------------------- + Decoder */ + +static unsigned int qoa_decode_header(qoa_data *data) { + unsigned int p = 0; + qoa_uint64_t file_header, frame_header; + if (data->size < QOA_MIN_FILESIZE) { + return 0; + } + + /* Read the file header, verify the magic number ('qoaf') and read the + total number of samples. */ + file_header = qoa_read_u64(data->bytes, &p); + + if ((file_header >> 32) != QOA_MAGIC) { + return 0; + } + + data->qoa.samples = file_header & 0xffffffff; + if (!data->qoa.samples) { + return 0; + } + + /* Peek into the first frame header to get the number of channels and + the samplerate. */ + frame_header = qoa_read_u64(data->bytes, &p); + data->qoa.channels = (frame_header >> 56) & 0x0000ff; + data->qoa.samplerate = (frame_header >> 32) & 0xffffff; + data->samples_per_channel_per_frame = (frame_header >> 16) & 0x00ffff; + + if (data->qoa.channels == 0 || data->qoa.channels == 0 || data->qoa.samplerate == 0) { + return 0; + } + + return 8; +} + +qoa *qoa_open_from_memory(unsigned char *bytes, unsigned int size, int free_on_close) +{ + qoa_data *data = (qoa_data*) malloc(sizeof(qoa_data)); + data->bytes = bytes; + data->size = size; + data->frame_index = 0; + data->free_on_close = free_on_close; + if (qoa_decode_header(data) == 0) + { + qoa_close((qoa*) data); + return NULL; + } + data->frame_size = QOA_FRAME_SIZE(data->qoa.channels, QOA_SLICES_PER_FRAME); + return (qoa*) data; +} + +static qoa *qoa_open_from_file(FILE *file, int free_on_close) +{ + unsigned char *bytes; + unsigned int len, start; + start = (unsigned int) ftell(file); + fseek(file, 0, SEEK_END); + len = (unsigned int) (ftell(file) - start); + fseek(file, start, SEEK_SET); + + bytes = malloc(len); + fread(bytes, 1, len, file); + fclose(file); + + return qoa_open_from_memory(bytes, len, free_on_close); +} + +qoa *qoa_open_from_filename(const char *filename) +{ + FILE *f; + f = fopen(filename, "rb"); + + if (f) + return qoa_open_from_file(f, TRUE); + + return NULL; +} + +void qoa_attributes( + qoa *qoa, + unsigned int *channels, + unsigned int *samplerate, + unsigned int *samples_per_channel_per_frame, + unsigned int *total_samples_per_channel +) { + qoa_data *data = (qoa_data*) qoa; + *channels = data->qoa.channels; + *samplerate = data->qoa.samplerate; + *samples_per_channel_per_frame = data->samples_per_channel_per_frame; + *total_samples_per_channel = data->qoa.samples; +} + +static unsigned int qoa_frame_start(qoa_data *data, int frame_index) { + return 8 + (data->frame_size * frame_index); +} + +unsigned int qoa_decode_next_frame(qoa *qoa, short *sample_data) { + qoa_data *data = (qoa_data*) qoa; + unsigned int channels, samplerate, samples, frame_size, data_size, + num_slices, max_total_samples, sample_index, c, p; + int scalefactor, slice_start, slice_end, predicted, quantized, + dequantized, reconstructed, si, i; + qoa_uint64_t frame_header, history, weights, slice; + + p = qoa_frame_start(data, data->frame_index); + + /* Reached the end */ + if (p >= data->size) + { + return 0; + } + + /* Read and verify the frame header */ + frame_header = qoa_read_u64(data->bytes, &p); + channels = (frame_header >> 56) & 0x0000ff; + samplerate = (frame_header >> 32) & 0xffffff; + samples = (frame_header >> 16) & 0x00ffff; + frame_size = (frame_header ) & 0x00ffff; + + data_size = frame_size - 8 - QOA_LMS_LEN * 4 * channels; + num_slices = data_size / 8; + max_total_samples = num_slices * QOA_SLICE_LEN; + + if ( + channels != data->qoa.channels || + samplerate != data->qoa.samplerate || + frame_size > data->size || + samples * channels > max_total_samples + ) { + return 0; + } + + /* Read the LMS state: 4 x 2 bytes history, 4 x 2 bytes weights per channel */ + for (c = 0; c < channels; c++) { + history = qoa_read_u64(data->bytes, &p); + weights = qoa_read_u64(data->bytes, &p); + for (i = 0; i < QOA_LMS_LEN; i++) { + data->qoa.lms[c].history[i] = ((signed short)(history >> 48)); + history <<= 16; + data->qoa.lms[c].weights[i] = ((signed short)(weights >> 48)); + weights <<= 16; + } + } + + /* Decode all slices for all channels in this frame */ + for (sample_index = 0; sample_index < samples; sample_index += QOA_SLICE_LEN) { + for (c = 0; c < channels; c++) { + slice = qoa_read_u64(data->bytes, &p); + + scalefactor = (slice >> 60) & 0xf; + slice_start = sample_index * channels + c; + slice_end = qoa_clamp(sample_index + QOA_SLICE_LEN, 0, samples) * channels + c; + + for (si = slice_start; si < slice_end; si += channels) { + predicted = qoa_lms_predict(&data->qoa.lms[c]); + quantized = (slice >> 57) & 0x7; + dequantized = qoa_dequant_tab[scalefactor][quantized]; + reconstructed = qoa_clamp_s16(predicted + dequantized); + + sample_data[si] = reconstructed; + slice <<= 3; + + qoa_lms_update(&data->qoa.lms[c], reconstructed, dequantized); + } + } + } + + data->frame_index += 1; + return samples; +} + +void qoa_seek_frame(qoa *qoa, int frame_index) { + qoa_data* data = (qoa_data*) qoa; + data->frame_index = frame_index; +} + +void qoa_decode_entire(qoa *qoa, short *sample_data) { + qoa_data* data = (qoa_data *) qoa; + unsigned int frame_count, sample_index, sample_count; + int total_samples; + short *sample_ptr; + uint32_t i; + + /* Calculate the required size of the sample buffer and allocate */ + total_samples = data->qoa.samples * data->qoa.channels; + + frame_count = (data->size - 64) / data->frame_size; + sample_index = 0; + + for (i = 0; i < frame_count; i += 1) + { + sample_ptr = sample_data + sample_index * data->qoa.channels; + sample_count = qoa_decode_next_frame(qoa, sample_ptr); + sample_index += sample_count; + } +} + +void qoa_close(qoa *qoa) +{ + qoa_data *data = (qoa_data*) qoa; + if (data->free_on_close) + { + free(data->bytes); + } + free(qoa); +} diff --git a/src/stb.h b/src/stb.h index 2415296888..f412e0f8ed 100644 --- a/src/stb.h +++ b/src/stb.h @@ -207,7 +207,7 @@ CREDITS * binding various stdlib functions stb.h uses to FAudio's stdlib. * -flibit */ -#ifndef FAUDIO_UNKNOWN_PLATFORM +#ifdef STB_MEMCPY_OVERRIDE #ifdef memcpy /* Thanks Apple! */ #undef memcpy #endif diff --git a/src/stb_vorbis.h b/src/stb_vorbis.h index 3a6e009ba5..bba90fe477 100644 --- a/src/stb_vorbis.h +++ b/src/stb_vorbis.h @@ -1382,7 +1382,7 @@ static void skip(vorb *z, int n) } #ifndef STB_VORBIS_NO_STDIO { - long x = ftell(z->f); + int64_t x = ftell(z->f); fseek(z->f, x+n, SEEK_SET); } #endif diff --git a/utils/facttool/facttool.cpp b/utils/facttool/facttool.cpp index 0ac7ac295d..877959a3b2 100644 --- a/utils/facttool/facttool.cpp +++ b/utils/facttool/facttool.cpp @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -30,7 +30,7 @@ #include "../uicommon/imgui.h" -#include +#include #include #include @@ -55,11 +55,6 @@ std::vector wavebankShows; std::vector waves; -void FAudioTool_Init() -{ - /* Nothing to do... */ -} - void FAudioTool_Quit() { for (size_t i = 0; i < soundBanks.size(); i += 1) diff --git a/utils/showriffheader/showriffheader.cpp b/utils/showriffheader/showriffheader.cpp index 9dca959c81..c822a16f12 100644 --- a/utils/showriffheader/showriffheader.cpp +++ b/utils/showriffheader/showriffheader.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include diff --git a/utils/testfilter/audio_faudio.cpp b/utils/testfilter/audio_faudio.cpp index f8c4deb765..5ec83ceb64 100644 --- a/utils/testfilter/audio_faudio.cpp +++ b/utils/testfilter/audio_faudio.cpp @@ -1,7 +1,7 @@ #include "audio.h" #include -#include +#include #include struct AudioContext diff --git a/utils/testfilter/audio_player.h b/utils/testfilter/audio_player.h index 987484dc61..5cd1314cdd 100644 --- a/utils/testfilter/audio_player.h +++ b/utils/testfilter/audio_player.h @@ -3,7 +3,7 @@ #include "oscillator.h" #include "audio.h" -#include +#include class AudioPlayer { diff --git a/utils/testfilter/testfilter.cpp b/utils/testfilter/testfilter.cpp index f918e4779b..cc822c9080 100644 --- a/utils/testfilter/testfilter.cpp +++ b/utils/testfilter/testfilter.cpp @@ -23,11 +23,6 @@ int next_window_dims(int y_pos, int height) return y_pos + height; } -void FAudioTool_Init() -{ - /* Nothing to do... */ -} - void FAudioTool_Quit() { /* Nothing to do... */ diff --git a/utils/testparse/testparse.c b/utils/testparse/testparse.c index 5d1254a371..ddf7584011 100644 --- a/utils/testparse/testparse.c +++ b/utils/testparse/testparse.c @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -25,7 +25,8 @@ */ #include /* DO NOT INCLUDE THIS IN REAL CODE! */ -#include +#include /* printf */ +#include static void print_soundbank(FACTAudioEngine *engine, uint8_t *buf, size_t len) { diff --git a/utils/testreverb/audio_faudio.cpp b/utils/testreverb/audio_faudio.cpp index 8efa30a27d..a69ba39a06 100644 --- a/utils/testreverb/audio_faudio.cpp +++ b/utils/testreverb/audio_faudio.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include struct AudioContext { diff --git a/utils/testreverb/testreverb.cpp b/utils/testreverb/testreverb.cpp index d0418d1fe8..3b8ca72ea9 100644 --- a/utils/testreverb/testreverb.cpp +++ b/utils/testreverb/testreverb.cpp @@ -15,11 +15,6 @@ int next_window_dims(int y_pos, int height) return y_pos + height; } -void FAudioTool_Init() -{ - /* Nothing to do... */ -} - void FAudioTool_Quit() { /* Nothing to do... */ diff --git a/utils/testvolumemeter/testvolumemeter.cpp b/utils/testvolumemeter/testvolumemeter.cpp index 42c66f7b91..8be230f87e 100644 --- a/utils/testvolumemeter/testvolumemeter.cpp +++ b/utils/testvolumemeter/testvolumemeter.cpp @@ -15,11 +15,6 @@ int next_window_dims(int y_pos, int height) return y_pos + height; } -void FAudioTool_Init() -{ - /* Nothing to do... */ -} - void FAudioTool_Quit() { /* Nothing to do... */ diff --git a/utils/testxwma/testxwma.cpp b/utils/testxwma/testxwma.cpp index a8b64c54e0..93eb288518 100644 --- a/utils/testxwma/testxwma.cpp +++ b/utils/testxwma/testxwma.cpp @@ -1,5 +1,7 @@ #include -#include +#include +#include /* malloc */ +#include /* FILE* */ #include diff --git a/utils/uicommon/FAudioUI_main.cpp b/utils/uicommon/FAudioUI_main.cpp index 6cfebc9605..db2819b41b 100644 --- a/utils/uicommon/FAudioUI_main.cpp +++ b/utils/uicommon/FAudioUI_main.cpp @@ -1,6 +1,6 @@ /* FAudio - XAudio Reimplementation for FNA * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team + * Copyright (c) 2011-2024 Ethan Lee, Luigi Auriemma, and the MonoGame Team * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from @@ -29,146 +29,86 @@ * -flibit */ -#include -#include - -/* GL Function typedefs */ -#define GL_PROC(ret, func, parms) \ - typedef ret (GLAPIENTRY *glfntype_##func) parms; -#include "glfuncs.h" -#undef GL_PROC -/* GL Function declarations */ -#define GL_PROC(ret, func, parms) \ - glfntype_##func INTERNAL_##func; -#include "glfuncs.h" -#undef GL_PROC -/* Remap GL function names to internal entry points */ -#include "glmacros.h" +#include +#include +#include "imgui.h" /* Defined by the tools using this UI framework */ extern const char* TOOL_NAME; extern int TOOL_WIDTH; extern int TOOL_HEIGHT; -extern void FAudioTool_Init(); extern void FAudioTool_Update(); extern void FAudioTool_Quit(); -/* FAudioUI_ui.cpp */ - -extern void UI_Init( - int tab, - int left, - int right, - int up, - int down, - int pgup, - int pgdown, - int home, - int end, - int del, - int backspace, - int enter, - int escape, - int a, - int c, - int v, - int x, - int y, - int z, - unsigned char **pixels, - int *tw, - int *th -); -extern void UI_Quit(); -extern uint8_t UI_Update( - int ww, - int wh, - int dw, - int dh, - int mx, - int my, - uint8_t mouse1, - uint8_t mouse2, - uint8_t mouse3, - int8_t wheel, - float deltaTime -); -extern void UI_Render(); -extern void UI_SubmitKey( - int key, - uint8_t down, - uint8_t shift, - uint8_t ctrl, - uint8_t alt, - uint8_t gui -); -extern void UI_SubmitText(char *text); -extern void UI_SetFontTexture(void* texture); - -/* FAudioUI_ui.cpp Callbacks */ - -void main_setupviewport(int fbw, int fbh, float dw, float dh) +/* ImGui Callbacks */ + +static void RenderDrawLists(ImDrawData *draw_data) { - glViewport(0, 0, fbw, fbh); - glLoadIdentity(); - glOrtho(0.0f, dw, dh, 0.0f, -1.0f, 1.0f); -} + ImGuiIO& io = ImGui::GetIO(); + SDL_Renderer *renderer = (SDL_Renderer*) io.BackendRendererUserData; + SDL_Rect rect; -void main_setupvertexattribs( - int stride, - const void *vtx, - const void *txc, - const void *clr -) { - glVertexPointer( - 2, - GL_FLOAT, - stride, - vtx - ); - glTexCoordPointer( - 2, - GL_FLOAT, - stride, - txc - ); - glColorPointer( - 4, - GL_UNSIGNED_BYTE, - stride, - clr - ); -} + /* Set up viewport/scissor rects (based on display size/scale */ + rect.x = 0; + rect.y = 0; + rect.w = (int) (io.DisplaySize.x * io.DisplayFramebufferScale.x); + rect.h = (int) (io.DisplaySize.y * io.DisplayFramebufferScale.y); + if (rect.w == 0 || rect.h == 0) + { + /* No point in rendering to nowhere... */ + return; + } + draw_data->ScaleClipRects(io.DisplayFramebufferScale); + SDL_SetRenderViewport(renderer, &rect); -void main_draw( - void *texture, - int sx, - int sy, - int sw, - int sh, - int count, - int idxSize, - const void *idx -) { - glBindTexture(GL_TEXTURE_2D, (GLuint) (intptr_t) texture); - glScissor(sx, sy, sw, sh); - glDrawElements( - GL_TRIANGLES, - count, - idxSize == 2 ? - GL_UNSIGNED_SHORT : - GL_UNSIGNED_INT, - idx - ); + /* Submit draw commands */ + #define OFFSETOF(TYPE, ELEMENT) ((size_t) &(((TYPE*) NULL)->ELEMENT)) + for (int cmd_l = 0; cmd_l < draw_data->CmdListsCount; cmd_l += 1) + { + const ImDrawList* cmd_list = draw_data->CmdLists[cmd_l]; + const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; + const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; + + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i += 1) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + const char *vtx = (const char*) (vtx_buffer + pcmd->VtxOffset); + const char *xy = vtx + OFFSETOF(ImDrawVert, pos); + const char *uv = vtx + OFFSETOF(ImDrawVert, uv); + const char *cl = vtx + OFFSETOF(ImDrawVert, col); + + rect.x = (int) pcmd->ClipRect.x; + rect.y = (int) pcmd->ClipRect.y; + rect.w = (int) (pcmd->ClipRect.z - pcmd->ClipRect.x); + rect.h = (int) (pcmd->ClipRect.w - pcmd->ClipRect.y); + SDL_SetRenderClipRect(renderer, &rect); + + SDL_RenderGeometryRaw( + renderer, + (SDL_Texture*) pcmd->TextureId, + (const float*) xy, + (int) sizeof(ImDrawVert), + (const SDL_FColor*) cl, + (int) sizeof(ImDrawVert), + (const float*) uv, + (int) sizeof(ImDrawVert), + cmd_list->VtxBuffer.Size - pcmd->VtxOffset, + idx_buffer + pcmd->IdxOffset, + pcmd->ElemCount, + sizeof(ImDrawIdx) + ); + } + } + #undef OFFSETOF } -const char* main_getclipboardtext(void* userdata) +static const char* GetClipboardText(void* userdata) { return SDL_GetClipboardText(); } -void main_setclipboardtext(void* userdata, const char *text) +static void SetClipboardText(void* userdata, const char *text) { SDL_SetClipboardText(text); } @@ -179,15 +119,16 @@ int main(int argc, char **argv) { /* Basic stuff */ SDL_Window *window; - SDL_GLContext context; + SDL_Renderer *renderer; SDL_Event evt; uint8_t run = 1; /* ImGui interop */ + ImGuiContext *imContext; SDL_Keymod kmod; uint8_t mouseClicked[3]; int8_t mouseWheel; - int mx, my; + float mx, my; uint32_t mouseState; int ww, wh, dw, dh; Uint32 tCur, tLast = 0; @@ -195,155 +136,144 @@ int main(int argc, char **argv) /* ImGui texture */ unsigned char *pixels; int tw, th; - GLuint fontTexture; + SDL_Texture *fontTexture; /* Create window/context */ SDL_Init(SDL_INIT_VIDEO); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); window = SDL_CreateWindow( TOOL_NAME, - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, TOOL_WIDTH, TOOL_HEIGHT, - ( - SDL_WINDOW_OPENGL | - SDL_WINDOW_RESIZABLE | - SDL_WINDOW_ALLOW_HIGHDPI - ) + SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY ); - context = SDL_GL_CreateContext(window); - SDL_GL_SetSwapInterval(1); - - /* GL function loading */ - #define GL_PROC(ret, func, parms) \ - INTERNAL_##func = (glfntype_##func) SDL_GL_GetProcAddress(#func); - #include "glfuncs.h" - #undef GL_PROC - - /* Initialize GL state */ - glClearColor(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 1.0f); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_SCISSOR_TEST); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); + renderer = SDL_CreateRenderer(window, NULL); + SDL_SetRenderDrawColor(renderer, 114, 144, 154, 255); /* ImGui setup */ - UI_Init( - SDLK_TAB, - SDL_SCANCODE_LEFT, - SDL_SCANCODE_RIGHT, - SDL_SCANCODE_UP, - SDL_SCANCODE_DOWN, - SDL_SCANCODE_PAGEUP, - SDL_SCANCODE_PAGEDOWN, - SDL_SCANCODE_HOME, - SDL_SCANCODE_END, - SDLK_DELETE, - SDLK_BACKSPACE, - SDLK_RETURN, - SDLK_ESCAPE, - SDLK_a, - SDLK_c, - SDLK_v, - SDLK_x, - SDLK_y, - SDLK_z, - &pixels, - &tw, - &th - ); - glGenTextures(1, &fontTexture); - glBindTexture(GL_TEXTURE_2D, fontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_ALPHA, + imContext = ImGui::CreateContext(NULL); + ImGui::SetCurrentContext(imContext); + ImGuiIO& io = ImGui::GetIO(); + io.BackendRendererUserData = (void*) renderer; + + /* Keyboard */ + io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; + io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; + io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN; + io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP; + io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; + io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; + io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; + io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; + io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; + io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE; + io.KeyMap[ImGuiKey_A] = SDLK_A; + io.KeyMap[ImGuiKey_C] = SDLK_C; + io.KeyMap[ImGuiKey_V] = SDLK_V; + io.KeyMap[ImGuiKey_X] = SDLK_X; + io.KeyMap[ImGuiKey_Y] = SDLK_Y; + io.KeyMap[ImGuiKey_Z] = SDLK_Z; + + /* Callbacks */ + io.RenderDrawListsFn = RenderDrawLists; + io.GetClipboardTextFn = GetClipboardText; + io.SetClipboardTextFn = SetClipboardText; + + /* Create texture for text rendering */ + io.Fonts->GetTexDataAsRGBA32(&pixels, &tw, &th); + fontTexture = SDL_CreateTexture( + renderer, + SDL_PIXELFORMAT_RGBA32, /* FIXME: GL_ALPHA? */ + SDL_TEXTUREACCESS_STATIC, tw, - th, - 0, - GL_ALPHA, - GL_UNSIGNED_BYTE, - pixels + th ); - UI_SetFontTexture((void*) (intptr_t) fontTexture); + SDL_UpdateTexture(fontTexture, NULL, pixels, 4 * tw); + SDL_SetTextureBlendMode(fontTexture, SDL_BLENDMODE_BLEND); + io.Fonts->TexID = (void*) fontTexture; while (run) { while (SDL_PollEvent(&evt) == 1) { - if (evt.type == SDL_QUIT) + if (evt.type == SDL_EVENT_QUIT) { run = 0; } - else if ( evt.type == SDL_KEYDOWN || - evt.type == SDL_KEYUP ) + else if ( evt.type == SDL_EVENT_KEY_DOWN || + evt.type == SDL_EVENT_KEY_UP ) { kmod = SDL_GetModState(); - UI_SubmitKey( - evt.key.keysym.sym & ~SDLK_SCANCODE_MASK, - evt.type == SDL_KEYDOWN, - (kmod & KMOD_SHIFT) != 0, - (kmod & KMOD_CTRL) != 0, - (kmod & KMOD_ALT) != 0, - (kmod & KMOD_GUI) != 0 - ); + io.KeysDown[ + evt.key.key & ~SDLK_SCANCODE_MASK + ] = evt.type == SDL_EVENT_KEY_DOWN; + io.KeyShift = (kmod & SDL_KMOD_SHIFT) != 0; + io.KeyCtrl = (kmod & SDL_KMOD_CTRL) != 0; + io.KeyAlt = (kmod & SDL_KMOD_ALT) != 0; + io.KeySuper = (kmod & SDL_KMOD_GUI) != 0; } - else if (evt.type == SDL_MOUSEBUTTONDOWN) + else if (evt.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { if (evt.button.button < 4) { mouseClicked[evt.button.button - 1] = 1; } } - else if (evt.type == SDL_MOUSEWHEEL) + else if (evt.type == SDL_EVENT_MOUSE_WHEEL) { if (evt.wheel.y > 0) mouseWheel = 1; if (evt.wheel.y < 0) mouseWheel = -1; } - else if (evt.type == SDL_TEXTINPUT) + else if (evt.type == SDL_EVENT_TEXT_INPUT) { - UI_SubmitText(evt.text.text); + io.AddInputCharactersUTF8(evt.text.text); } } /* SDL-related updates */ SDL_GetWindowSize(window, &ww, &wh); - SDL_GL_GetDrawableSize(window, &dw, &dh); + SDL_GetWindowSizeInPixels(window, &dw, &dh); mouseState = SDL_GetMouseState(&mx, &my); /* TODO: Focus */ - mouseClicked[0] |= (mouseState * SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; - mouseClicked[1] |= (mouseState * SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; - mouseClicked[2] |= (mouseState * SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; + mouseClicked[0] |= (mouseState * SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0; + mouseClicked[1] |= (mouseState * SDL_BUTTON_MASK(SDL_BUTTON_MIDDLE)) != 0; + mouseClicked[2] |= (mouseState * SDL_BUTTON_MASK(SDL_BUTTON_RIGHT)) != 0; tCur = SDL_GetTicks(); - /* Update ImGui input, prep for the new frame */ - SDL_ShowCursor(UI_Update( - ww, wh, dw, dh, - mx, my, - mouseClicked[0], - mouseClicked[1], - mouseClicked[2], - mouseWheel, - (tCur - tLast) / 1000.0f - ) ? 0 : 1); + /* Set these every frame, we have a resizable window! */ + io.DisplaySize = ImVec2((float) ww, (float) wh); + io.DisplayFramebufferScale = ImVec2( + ww > 0 ? ((float) dw / ww) : 0, + wh > 0 ? ((float) dh / wh) : 0 + ); + + /* Time update */ + io.DeltaTime = (tCur - tLast) / 1000.0f; + if (io.DeltaTime == 0.0f) + { + io.DeltaTime = 0.01f; + } + + /* Input updates not done via UI_Submit*() */ + io.MousePos = ImVec2((float) mx, (float) my); + io.MouseDown[0] = mouseClicked[0]; + io.MouseDown[1] = mouseClicked[1]; + io.MouseDown[2] = mouseClicked[2]; + io.MouseWheel = mouseWheel; + + /* BEGIN */ + ImGui::NewFrame(); /* Reset some things now that input's updated */ + if (io.MouseDrawCursor) + { + SDL_ShowCursor(); + } + else + { + SDL_HideCursor(); + } tLast = tCur; mouseClicked[0] = 0; mouseClicked[1] = 0; @@ -354,21 +284,18 @@ int main(int argc, char **argv) FAudioTool_Update(); /* Draw, draw, draw! */ - glDisable(GL_SCISSOR_TEST); - glClear(GL_COLOR_BUFFER_BIT); - glEnable(GL_SCISSOR_TEST); - UI_Render(); - SDL_GL_SwapWindow(window); + SDL_RenderClear(renderer); + ImGui::Render(); + SDL_RenderPresent(renderer); } /* Clean up if we need to */ FAudioTool_Quit(); /* Clean up. We out. */ - UI_Quit(); - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &fontTexture); - SDL_GL_DeleteContext(context); + ImGui::DestroyContext(imContext); + SDL_DestroyTexture(fontTexture); + SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; diff --git a/utils/uicommon/FAudioUI_ui.cpp b/utils/uicommon/FAudioUI_ui.cpp deleted file mode 100644 index d9530f49fd..0000000000 --- a/utils/uicommon/FAudioUI_ui.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* FAudio - XAudio Reimplementation for FNA - * - * Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source distribution. - * - * Ethan "flibitijibibo" Lee - * - */ - -/* Unless you're trying to do ImGui interop work, you probably don't want this! - * Go to the other folders to look at the actual tools. - * -flibit - */ - -#include -#include "imgui.h" - -/* FAudioUI_main.cpp */ - -extern const char* main_getclipboardtext(void* userdata); -extern void main_setclipboardtext(void* userdata, const char *text); -extern void main_setupviewport(int fbw, int fbh, float dw, float dh); -extern void main_setupvertexattribs( - int stride, - const void *vtx, - const void *txc, - const void *clr -); -extern void main_draw( - void *texture, - int sx, - int sy, - int sw, - int sh, - int count, - int idxSize, - const void *idx -); - -/* ImGui Callbacks */ - -void UI_RenderDrawLists(ImDrawData *draw_data) -{ - ImGuiIO& io = ImGui::GetIO(); - - /* Set up viewport/scissor rects (based on display size/scale */ - int fb_width = (int) (io.DisplaySize.x * io.DisplayFramebufferScale.x); - int fb_height = (int) (io.DisplaySize.y * io.DisplayFramebufferScale.y); - if (fb_width == 0 || fb_height == 0) - { - /* No point in rendering to nowhere... */ - return; - } - draw_data->ScaleClipRects(io.DisplayFramebufferScale); - main_setupviewport( - fb_width, - fb_height, - io.DisplaySize.x, - io.DisplaySize.y - ); - - /* Submit draw commands */ - #define OFFSETOF(TYPE, ELEMENT) ((size_t) &(((TYPE*) NULL)->ELEMENT)) - for (int cmd_l = 0; cmd_l < draw_data->CmdListsCount; cmd_l += 1) - { - const ImDrawList* cmd_list = draw_data->CmdLists[cmd_l]; - const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; - const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; - - main_setupvertexattribs( - sizeof(ImDrawVert), - ((const char*) vtx_buffer + OFFSETOF(ImDrawVert, pos)), - ((const char*) vtx_buffer + OFFSETOF(ImDrawVert, uv)), - ((const char*) vtx_buffer + OFFSETOF(ImDrawVert, col)) - ); - - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i += 1) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - main_draw( - pcmd->TextureId, - (int) pcmd->ClipRect.x, - (int) (fb_height - pcmd->ClipRect.w), - (int) (pcmd->ClipRect.z - pcmd->ClipRect.x), - (int) (pcmd->ClipRect.w - pcmd->ClipRect.y), - pcmd->ElemCount, - sizeof(ImDrawIdx), - idx_buffer - ); - idx_buffer += pcmd->ElemCount; - } - } - #undef OFFSETOF -} - -/* Public API */ - -static ImGuiContext *imContext = NULL; - -void UI_Init( - int tab, - int left, - int right, - int up, - int down, - int pgup, - int pgdown, - int home, - int end, - int del, - int backspace, - int enter, - int escape, - int a, - int c, - int v, - int x, - int y, - int z, - unsigned char **pixels, - int *tw, - int *th -) { - imContext = ImGui::CreateContext(NULL); - ImGui::SetCurrentContext(imContext); - - ImGuiIO& io = ImGui::GetIO(); - - /* Keyboard */ - io.KeyMap[ImGuiKey_Tab] = tab; - io.KeyMap[ImGuiKey_LeftArrow] = left; - io.KeyMap[ImGuiKey_RightArrow] = right; - io.KeyMap[ImGuiKey_UpArrow] = up; - io.KeyMap[ImGuiKey_DownArrow] = down; - io.KeyMap[ImGuiKey_PageUp] = pgup; - io.KeyMap[ImGuiKey_PageDown] = pgdown; - io.KeyMap[ImGuiKey_Home] = home; - io.KeyMap[ImGuiKey_End] = end; - io.KeyMap[ImGuiKey_Delete] = del; - io.KeyMap[ImGuiKey_Backspace] = backspace; - io.KeyMap[ImGuiKey_Enter] = enter; - io.KeyMap[ImGuiKey_Escape] = escape; - io.KeyMap[ImGuiKey_A] = a; - io.KeyMap[ImGuiKey_C] = c; - io.KeyMap[ImGuiKey_V] = v; - io.KeyMap[ImGuiKey_X] = x; - io.KeyMap[ImGuiKey_Y] = y; - io.KeyMap[ImGuiKey_Z] = z; - - /* Callbacks */ - io.RenderDrawListsFn = UI_RenderDrawLists; - io.GetClipboardTextFn = main_getclipboardtext; - io.SetClipboardTextFn = main_setclipboardtext; - - /* Create texture for text rendering */ - io.Fonts->GetTexDataAsAlpha8(pixels, tw, th); -} - -uint8_t UI_Update( - int ww, - int wh, - int dw, - int dh, - int mx, - int my, - uint8_t mouse1, - uint8_t mouse2, - uint8_t mouse3, - int8_t wheel, - float deltaTime -) { - ImGuiIO& io = ImGui::GetIO(); - - /* Set these every frame, we have a resizable window! */ - io.DisplaySize = ImVec2((float) ww, (float) wh); - io.DisplayFramebufferScale = ImVec2( - ww > 0 ? ((float) dw / ww) : 0, - wh > 0 ? ((float) dh / wh) : 0 - ); - - /* Time update */ - io.DeltaTime = deltaTime; - if (io.DeltaTime == 0.0f) - { - io.DeltaTime = 0.01f; - } - - /* Input updates not done via UI_Submit*() */ - io.MousePos = ImVec2((float) mx, (float) my); - io.MouseDown[0] = mouse1; - io.MouseDown[1] = mouse2; - io.MouseDown[2] = mouse3; - io.MouseWheel = wheel; - - /* BEGIN */ - ImGui::NewFrame(); - return io.MouseDrawCursor; -} - -void UI_Quit() -{ - ImGui::DestroyContext(imContext); -} - -void UI_Render() -{ - ImGui::Render(); -} - -void UI_SubmitKey( - int key, - uint8_t down, - uint8_t shift, - uint8_t ctrl, - uint8_t alt, - uint8_t gui -) { - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = shift; - io.KeyCtrl = ctrl; - io.KeyAlt = alt; - io.KeySuper = gui; -} - -void UI_SubmitText(char *text) -{ - ImGui::GetIO().AddInputCharactersUTF8(text); -} - -void UI_SetFontTexture(void *texture) -{ - ImGui::GetIO().Fonts->TexID = texture; -} diff --git a/utils/uicommon/glfuncs.h b/utils/uicommon/glfuncs.h deleted file mode 100644 index 22c07177a6..0000000000 --- a/utils/uicommon/glfuncs.h +++ /dev/null @@ -1,22 +0,0 @@ -GL_PROC(void, glViewport, (GLint a, GLint b, GLsizei c, GLsizei d)) -GL_PROC(void, glLoadIdentity, (void)) -GL_PROC(void, glOrtho, (GLdouble a, GLdouble b, GLdouble c, GLdouble d, GLdouble e, GLdouble f)) -GL_PROC(void, glVertexPointer, (GLint a, GLenum b, GLsizei c, const GLvoid* d)) -GL_PROC(void, glTexCoordPointer, (GLint a, GLenum b, GLsizei c, const GLvoid* d)) -GL_PROC(void, glColorPointer, (GLint a, GLenum b, GLsizei c, const GLvoid* d)) -GL_PROC(void, glBindTexture, (GLenum a, GLuint b)) -GL_PROC(void, glScissor, (GLint a, GLint b, GLsizei c, GLsizei d)) -GL_PROC(void, glDrawElements, (GLenum a, GLsizei b, GLenum c, const GLvoid* d)) -GL_PROC(void, glClearColor, (GLclampf a, GLclampf b, GLclampf c, GLclampf d)) -GL_PROC(void, glEnable, (GLenum a)) -GL_PROC(void, glBlendFunc, (GLenum a, GLenum b)) -GL_PROC(void, glPolygonMode, (GLenum a, GLenum b)) -GL_PROC(void, glEnableClientState, (GLenum a)) -GL_PROC(void, glMatrixMode, (GLenum a)) -GL_PROC(void, glGenTextures, (GLsizei a, GLuint *b)) -GL_PROC(void, glTexParameteri, (GLenum a, GLenum b, GLint c)) -GL_PROC(void, glPixelStorei, (GLenum a, GLint b)) -GL_PROC(void, glTexImage2D, (GLenum a, GLint b, GLint c, GLsizei d, GLsizei e, GLint f, GLenum g, GLenum h, const GLvoid *i)) -GL_PROC(void, glDisable, (GLenum a)) -GL_PROC(void, glClear, (GLbitfield a)) -GL_PROC(void, glDeleteTextures, (GLsizei a, const GLuint *b)) diff --git a/utils/uicommon/glmacros.h b/utils/uicommon/glmacros.h deleted file mode 100644 index 8004ecf0a5..0000000000 --- a/utils/uicommon/glmacros.h +++ /dev/null @@ -1,22 +0,0 @@ -#define glViewport INTERNAL_glViewport -#define glLoadIdentity INTERNAL_glLoadIdentity -#define glOrtho INTERNAL_glOrtho -#define glVertexPointer INTERNAL_glVertexPointer -#define glTexCoordPointer INTERNAL_glTexCoordPointer -#define glColorPointer INTERNAL_glColorPointer -#define glBindTexture INTERNAL_glBindTexture -#define glScissor INTERNAL_glScissor -#define glDrawElements INTERNAL_glDrawElements -#define glClearColor INTERNAL_glClearColor -#define glEnable INTERNAL_glEnable -#define glBlendFunc INTERNAL_glBlendFunc -#define glPolygonMode INTERNAL_glPolygonMode -#define glEnableClientState INTERNAL_glEnableClientState -#define glMatrixMode INTERNAL_glMatrixMode -#define glGenTextures INTERNAL_glGenTextures -#define glTexParameteri INTERNAL_glTexParameteri -#define glPixelStorei INTERNAL_glPixelStorei -#define glTexImage2D INTERNAL_glTexImage2D -#define glDisable INTERNAL_glDisable -#define glClear INTERNAL_glClear -#define glDeleteTextures INTERNAL_glDeleteTextures diff --git a/utils/voicepool/voicepool.cpp b/utils/voicepool/voicepool.cpp new file mode 100644 index 0000000000..0ee8dd7f48 --- /dev/null +++ b/utils/voicepool/voicepool.cpp @@ -0,0 +1,203 @@ +#include +#include +#include "../uicommon/imgui.h" +#include "../wavcommon/wavs.h" +#include +#include /* free */ + +/* UI Vars */ +const char *TOOL_NAME = "Voice Pool"; +int TOOL_WIDTH = 320; +int TOOL_HEIGHT = 190; + +/* Engine Vars */ +static bool loaded = false; +static FAudio *faudio = NULL; +static FAudioMasteringVoice *master = NULL; +static std::vector monoPool; +static std::vector stereoPool; +static std::vector monoPoolRate; +static std::vector stereoPoolRate; +static float *sounds[6]; +static drwav_uint64 soundLength[6]; +static unsigned int soundRate[6]; + +void FAudioTool_Quit() +{ + if (loaded) + { + for (size_t i = 0; i < monoPool.size(); i += 1) + { + FAudioVoice_DestroyVoice(monoPool[i]); + } + monoPool.clear(); + monoPoolRate.clear(); + for (size_t i = 0; i < stereoPool.size(); i += 1) + { + FAudioVoice_DestroyVoice(stereoPool[i]); + } + stereoPool.clear(); + stereoPoolRate.clear(); + + FAudioVoice_DestroyVoice(master); + FAudio_Release(faudio); + + for (size_t i = 0; i < 6; i += 1) + { + free(sounds[i]); + } + + loaded = false; + } +} + +void FAudioTool_Update() +{ + bool play_wave = false; + + static int wave_index = (int) AudioWave_SnareDrum01; + static bool wave_stereo = false; + + /* UI Work */ + + ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); + ImGui::SetNextWindowSize(ImVec2(640.0f, 125.0f)); + ImGui::Begin("Wave file to play"); + ImGui::RadioButton("Snare Drum (Forte)", &wave_index, (int) AudioWave_SnareDrum01); + ImGui::RadioButton("Snare Drum (Fortissimo)", &wave_index, (int) AudioWave_SnareDrum02); + ImGui::RadioButton("Snare Drum (Mezzo-Forte)", &wave_index, (int) AudioWave_SnareDrum03); + + play_wave = ImGui::Button("Play"); + ImGui::SameLine(); + ImGui::Checkbox("Stereo", &wave_stereo); + ImGui::End(); + + ImGui::SetNextWindowPos(ImVec2(0.0f, 125.0f)); + ImGui::SetNextWindowSize(ImVec2(640.0f, 65.0f)); + ImGui::Begin("Current pool stats"); + ImGui::Text("Mono Voices: %d", monoPool.size()); + ImGui::Text("Stereo Voices: %d", stereoPool.size()); + ImGui::End(); + + /* Engine Work */ + + if (!loaded) + { + uint32_t hr = FAudioCreate(&faudio, 0, FAUDIO_DEFAULT_PROCESSOR); + SDL_assert(hr == 0); + hr = FAudio_CreateMasteringVoice( + faudio, + &master, + FAUDIO_DEFAULT_CHANNELS, + FAUDIO_DEFAULT_SAMPLERATE, + 0, + 0, + NULL + ); + SDL_assert(hr == 0); + + unsigned int channels; + sounds[0] = WAVS_Open(AudioWave_SnareDrum01, false, &channels, &soundRate[0], &soundLength[0]); + SDL_assert(sounds[0] != NULL); + SDL_assert(channels == 1); + sounds[1] = WAVS_Open(AudioWave_SnareDrum02, false, &channels, &soundRate[1], &soundLength[1]); + SDL_assert(sounds[1] != NULL); + SDL_assert(channels == 1); + sounds[2] = WAVS_Open(AudioWave_SnareDrum03, false, &channels, &soundRate[2], &soundLength[2]); + SDL_assert(sounds[2] != NULL); + SDL_assert(channels == 1); + sounds[3] = WAVS_Open(AudioWave_SnareDrum01, true, &channels, &soundRate[3], &soundLength[3]); + SDL_assert(sounds[3] != NULL); + SDL_assert(channels == 2); + sounds[4] = WAVS_Open(AudioWave_SnareDrum02, true, &channels, &soundRate[4], &soundLength[4]); + SDL_assert(sounds[4] != NULL); + SDL_assert(channels == 2); + sounds[5] = WAVS_Open(AudioWave_SnareDrum03, true, &channels, &soundRate[5], &soundLength[5]); + SDL_assert(sounds[5] != NULL); + SDL_assert(channels == 2); + + loaded = true; + } + + if (play_wave) + { + FAudioSourceVoice *src; + unsigned int rate; + size_t index = wave_index + (wave_stereo ? 3 : 0); + + bool found = false; + const std::vector& pool = wave_stereo ? stereoPool : monoPool; + const std::vector& poolRate = wave_stereo ? stereoPoolRate : monoPoolRate; + for (size_t i = 0; i < pool.size(); i += 1) + { + FAudioVoiceState state; + FAudioSourceVoice_GetState(pool[i], &state, FAUDIO_VOICE_NOSAMPLESPLAYED); + if (state.BuffersQueued == 0) + { + /* Nothing is queued, reuse this voice! */ + src = pool[i]; + rate = poolRate[i]; + found = true; + break; + } + } + if (found) + { + /* At most we can change the sample rate, can't change channel count */ + if (soundRate[index] != rate) + { + FAudioSourceVoice_SetSourceSampleRate(src, soundRate[index]); + } + } + else + { + /* Pool didn't have anything left, make a new voice */ + FAudioWaveFormatEx waveFormat; + waveFormat.wFormatTag = 3; + waveFormat.nChannels = wave_stereo ? 2 : 1; + waveFormat.nSamplesPerSec = soundRate[index]; + waveFormat.nBlockAlign = waveFormat.nChannels * sizeof(float); + waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + waveFormat.wBitsPerSample = sizeof(float) * 8; + waveFormat.cbSize = 0; + + uint32_t hr = FAudio_CreateSourceVoice( + faudio, + &src, + &waveFormat, + 0, + FAUDIO_DEFAULT_FREQ_RATIO, + NULL, + NULL, + NULL + ); + + /* Just start this now, let the buffer call "play" instead */ + FAudioSourceVoice_Start(src, 0, FAUDIO_COMMIT_NOW); + + if (wave_stereo) + { + stereoPool.push_back(src); + stereoPoolRate.push_back(soundRate[index]); + } + else + { + monoPool.push_back(src); + monoPoolRate.push_back(soundRate[index]); + } + } + + /* Buffer and play, finally */ + FAudioBuffer buffer; + buffer.Flags = FAUDIO_END_OF_STREAM; + buffer.AudioBytes = soundLength[index] * sizeof(float); + buffer.pAudioData = (uint8_t*) sounds[index]; + buffer.PlayBegin = 0; + buffer.PlayLength = soundLength[index] / (wave_stereo ? 2 : 1); + buffer.LoopBegin = 0; + buffer.LoopLength = 0; + buffer.LoopCount = 0; + buffer.pContext = NULL; + FAudioSourceVoice_SubmitSourceBuffer(src, &buffer, NULL); + } +} diff --git a/visualc-gdk/FAudio.sln b/visualc-gdk/FAudio.sln new file mode 100644 index 0000000000..953be57a98 --- /dev/null +++ b/visualc-gdk/FAudio.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32630.194 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudio", "FAudio.vcxproj", "{35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3", "..\..\SDL\VisualC-GDK\SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Gaming.Xbox.Scarlett.x64 = Debug|Gaming.Xbox.Scarlett.x64 + Debug|Gaming.Xbox.XboxOne.x64 = Debug|Gaming.Xbox.XboxOne.x64 + Profile|Gaming.Xbox.Scarlett.x64 = Profile|Gaming.Xbox.Scarlett.x64 + Profile|Gaming.Xbox.XboxOne.x64 = Profile|Gaming.Xbox.XboxOne.x64 + Release|Gaming.Xbox.Scarlett.x64 = Release|Gaming.Xbox.Scarlett.x64 + Release|Gaming.Xbox.XboxOne.x64 = Release|Gaming.Xbox.XboxOne.x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Debug|Gaming.Xbox.Scarlett.x64.ActiveCfg = Debug|Gaming.Xbox.Scarlett.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Debug|Gaming.Xbox.Scarlett.x64.Build.0 = Debug|Gaming.Xbox.Scarlett.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Debug|Gaming.Xbox.XboxOne.x64.ActiveCfg = Debug|Gaming.Xbox.XboxOne.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Debug|Gaming.Xbox.XboxOne.x64.Build.0 = Debug|Gaming.Xbox.XboxOne.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Profile|Gaming.Xbox.Scarlett.x64.ActiveCfg = Profile|Gaming.Xbox.Scarlett.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Profile|Gaming.Xbox.Scarlett.x64.Build.0 = Profile|Gaming.Xbox.Scarlett.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Profile|Gaming.Xbox.XboxOne.x64.ActiveCfg = Profile|Gaming.Xbox.XboxOne.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Profile|Gaming.Xbox.XboxOne.x64.Build.0 = Profile|Gaming.Xbox.XboxOne.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Release|Gaming.Xbox.Scarlett.x64.ActiveCfg = Release|Gaming.Xbox.Scarlett.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Release|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Release|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64 + {35B0FB4B-F0C2-4D70-9B2D-136C8A3F68D1}.Release|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.Scarlett.x64.ActiveCfg = Debug|Gaming.Xbox.Scarlett.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.Scarlett.x64.Build.0 = Debug|Gaming.Xbox.Scarlett.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.XboxOne.x64.ActiveCfg = Debug|Gaming.Xbox.XboxOne.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|Gaming.Xbox.XboxOne.x64.Build.0 = Debug|Gaming.Xbox.XboxOne.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.Scarlett.x64.ActiveCfg = Release|Gaming.Xbox.Scarlett.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Profile|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.Scarlett.x64.ActiveCfg = Release|Gaming.Xbox.Scarlett.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.Scarlett.x64.Build.0 = Release|Gaming.Xbox.Scarlett.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.XboxOne.x64.ActiveCfg = Release|Gaming.Xbox.XboxOne.x64 + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|Gaming.Xbox.XboxOne.x64.Build.0 = Release|Gaming.Xbox.XboxOne.x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7B59FC6A-2675-4ADB-BA67-7B6F0E01A600} + EndGlobalSection +EndGlobal diff --git a/visualc-gdk/FAudio.vcxproj b/visualc-gdk/FAudio.vcxproj new file mode 100644 index 0000000000..d04241732a --- /dev/null +++ b/visualc-gdk/FAudio.vcxproj @@ -0,0 +1,311 @@ + + + + + Debug + Gaming.Xbox.Scarlett.x64 + + + Profile + Gaming.Xbox.Scarlett.x64 + + + Release + Gaming.Xbox.Scarlett.x64 + + + Release + Gaming.Xbox.XboxOne.x64 + + + Profile + Gaming.Xbox.XboxOne.x64 + + + Debug + Gaming.Xbox.XboxOne.x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} + + + + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} + + + + FAudio + {35b0fb4b-f0c2-4d70-9b2d-136c8a3f68d1} + en-US + Win32Proj + + 15.0 + Native + x64 + + + + DynamicLibrary + false + true + Unicode + false + false + $(DefaultPlatformToolset) + + + DynamicLibrary + false + true + Unicode + false + false + $(DefaultPlatformToolset) + + + DynamicLibrary + false + true + Unicode + false + false + $(DefaultPlatformToolset) + + + DynamicLibrary + false + true + Unicode + false + false + $(DefaultPlatformToolset) + + + DynamicLibrary + true + Unicode + false + false + $(DefaultPlatformToolset) + + + DynamicLibrary + true + Unicode + false + false + $(DefaultPlatformToolset) + + + + + + + + + + + + + + + + + + + + + + + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + ..\..\SDL\include;..\..\..\..\SDL\include;..\include;$(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + ..\..\SDL\include;..\..\..\..\SDL\include;..\include;$(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + ..\..\SDL\include;..\..\..\..\SDL\include;..\include;$(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + ..\..\SDL\include;..\..\..\..\SDL\include;..\include;$(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) + false + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + ..\..\SDL\include;..\..\..\..\SDL\include;..\include;$(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) + true + + + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + $(Console_SdkLibPath) + $(Console_SdkLibPath);$(Console_SdkWindowsMetadataPath) + ..\..\SDL\include;..\..\..\..\SDL\include;..\include;$(Console_SdkIncludeRoot) + $(Console_SdkRoot)bin;$(Console_SdkToolPath);$(ExecutablePath) + true + + + + $(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) + true + Windows + true + true + + + MaxSpeed + FAUDIO_SDL3_PLATFORM;FAUDIO_DISABLE_DEBUGCONFIGURATION;NDEBUG;_LIB;%(PreprocessorDefinitions) + Level4 + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + + + $(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) + true + Windows + true + true + + + MaxSpeed + FAUDIO_SDL3_PLATFORM;FAUDIO_DISABLE_DEBUGCONFIGURATION;NDEBUG;_LIB;%(PreprocessorDefinitions) + Level4 + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + + + $(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) + true + Windows + true + true + + + MaxSpeed + FAUDIO_SDL3_PLATFORM;FAUDIO_DISABLE_DEBUGCONFIGURATION;NDEBUG;_LIB;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + + + $(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) + true + Windows + true + true + + + MaxSpeed + FAUDIO_SDL3_PLATFORM;FAUDIO_DISABLE_DEBUGCONFIGURATION;NDEBUG;_LIB;PROFILE;%(PreprocessorDefinitions) + Level4 + true + true + true + /Zc:__cplusplus %(AdditionalOptions) + + + + + $(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) + Windows + true + + + false + Level4 + Disabled + FAUDIO_SDL3_PLATFORM;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + /Zc:__cplusplus %(AdditionalOptions) + + + + + $(Console_Libs);%(XboxExtensionsDependencies);%(AdditionalDependencies) + Windows + true + + + false + Level4 + Disabled + FAUDIO_SDL3_PLATFORM;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + /Zc:__cplusplus %(AdditionalOptions) + + + + + + \ No newline at end of file diff --git a/visualc-winrt/FAudio.sln b/visualc-winrt/FAudio.sln deleted file mode 100644 index e833bbc415..0000000000 --- a/visualc-winrt/FAudio.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2008 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudio", "FAudio.vcxproj", "{208F0A10-10FE-4C43-990F-3569169B1083}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {208F0A10-10FE-4C43-990F-3569169B1083}.Debug|x64.ActiveCfg = Debug|x64 - {208F0A10-10FE-4C43-990F-3569169B1083}.Debug|x64.Build.0 = Debug|x64 - {208F0A10-10FE-4C43-990F-3569169B1083}.Release|x64.ActiveCfg = Release|x64 - {208F0A10-10FE-4C43-990F-3569169B1083}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {6B531C65-9FF2-4E6A-95D7-EEB3D9D46633} - EndGlobalSection -EndGlobal diff --git a/visualc-winrt/FAudio.vcxproj b/visualc-winrt/FAudio.vcxproj deleted file mode 100644 index 49e25b0202..0000000000 --- a/visualc-winrt/FAudio.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {208f0a10-10fe-4c43-990f-3569169b1083} - DynamicLibrary - FAudio - en-US - 14.0 - true - Windows Store - 10.0.10240.0 - 10.0.10240.0 - 10.0 - - - - DynamicLibrary - true - v141 - - - DynamicLibrary - false - true - v141 - - - - - - - - - - - - - - - - false - false - ..\..\SDL2\include;..\include;$(IncludePath) - ..\..\SDL2\VisualC-WinRT\UWP_VS2015\$(Platform)\$(Configuration)\SDL-UWP;$(LibraryPath) - - - false - false - ..\..\SDL2\include;..\include;$(IncludePath) - ..\..\SDL2\VisualC-WinRT\UWP_VS2015\$(Platform)\$(Configuration)\SDL-UWP;$(LibraryPath) - - - - NotUsing - false - _WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - - - Console - false - false - WindowsApp.lib;SDL2.lib;%(AdditionalDependencies) - - - - - NotUsing - false - _WINDLL;_CRT_SECURE_NO_WARNINGS;FAUDIO_DISABLE_DEBUGCONFIGURATION;%(PreprocessorDefinitions) - - - Console - false - false - WindowsApp.lib;SDL2.lib;%(AdditionalDependencies) - - - - - - diff --git a/visualc-winrt/README b/visualc-winrt/README deleted file mode 100644 index b27d7fa36b..0000000000 --- a/visualc-winrt/README +++ /dev/null @@ -1,19 +0,0 @@ -Building FAudio for UWP ------------------------ -FAudio uses Visual Studio 2017 to build on Xbox One. - -Dependencies ------------- -Before building, download SDL2's source code from SDL's website: - -http://libsdl.org/download-2.0.php - -Extract the ZIP file's SDL2 directory (called something like 'SDL2-2.0.8') as -a sibling to your FAudio checkout and rename it to 'SDL2', so that you have -directories named 'FAudio' and 'SDL2' next to each other. - -Compiling ---------- -1. Build SDL2/VisualC-WinRT/UWP_VS2015/SDL-UWP.sln -2. Build FAudio.sln -3. Grab FAudio.dll and SDL2.dll, ship it!