Reenable and fix tests
- Add ASAN workflows - Remove flag messages from configure; these are misleading as they exclude `COMPILE_OPTIONS` - Fix non-working tests - Fix WavPack file loading on Windows - Fix ASAN traps in LoFi code due to a SIMD `loadu` call in HIIR resamplers - Add tests for st_audiofile -
This commit is contained in:
parent
507c61d458
commit
1e771a45e7
14 changed files with 228 additions and 105 deletions
90
.github/workflows/build.yml
vendored
90
.github/workflows/build.yml
vendored
|
|
@ -20,13 +20,8 @@ env:
|
||||||
# shell: pwsh on windows, bash all the rest
|
# shell: pwsh on windows, bash all the rest
|
||||||
# working-directory: ${{ github.workspace }}
|
# working-directory: ${{ github.workspace }}
|
||||||
|
|
||||||
# FIXME:
|
|
||||||
# Tests disabled (again); they were working one day and broken the day after
|
|
||||||
# without changes: ./build/tests/sfizz_tests: No such file or directory
|
|
||||||
# It didn't work either by specifying the full path (that was OK in previous builds)
|
|
||||||
jobs:
|
jobs:
|
||||||
clang_tidy:
|
clang_tidy:
|
||||||
# if: ${{ false }}
|
|
||||||
name: Clang Tidy
|
name: Clang Tidy
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -39,8 +34,57 @@ jobs:
|
||||||
- name: Run
|
- name: Run
|
||||||
run: ./scripts/run_clang_tidy.sh
|
run: ./scripts/run_clang_tidy.sh
|
||||||
|
|
||||||
|
test_with_asan:
|
||||||
|
name: ASAN
|
||||||
|
runs-on: ubuntu-22.04 # abseil (libabsl) is not available in 20.04 repository
|
||||||
|
env:
|
||||||
|
install_name: sfizz-${{ github.ref_name }}-linux
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
build_type: [Debug, RelWithDebInfo]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update && sudo apt-get install \
|
||||||
|
ninja-build \
|
||||||
|
libjack-jackd2-dev \
|
||||||
|
libabsl-dev \
|
||||||
|
libabsl20210324
|
||||||
|
- name: Configure CMake
|
||||||
|
run: |
|
||||||
|
options=(
|
||||||
|
-G Ninja
|
||||||
|
-B build
|
||||||
|
-S .
|
||||||
|
-D CMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||||
|
-D SFIZZ_TESTS=ON
|
||||||
|
-D SFIZZ_USE_SYSTEM_ABSEIL=ON
|
||||||
|
-D SFIZZ_ASAN=ON
|
||||||
|
)
|
||||||
|
cmake "${options[@]}"
|
||||||
|
- name: Build tests
|
||||||
|
run: |
|
||||||
|
options=(
|
||||||
|
--build build
|
||||||
|
--config ${{ matrix.build_type }}
|
||||||
|
--parallel 2
|
||||||
|
--target sfizz_tests
|
||||||
|
)
|
||||||
|
cmake "${options[@]}"
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
options=(
|
||||||
|
--build-config ${{ matrix.build_type }}
|
||||||
|
--output-on-failure
|
||||||
|
--test-dir build
|
||||||
|
)
|
||||||
|
ctest "${options[@]}"
|
||||||
|
|
||||||
build_for_linux:
|
build_for_linux:
|
||||||
# if: ${{ false }}
|
|
||||||
name: Linux Ubuntu 22.04
|
name: Linux Ubuntu 22.04
|
||||||
runs-on: ubuntu-22.04 # abseil (libabsl) is not available in 20.04 repository
|
runs-on: ubuntu-22.04 # abseil (libabsl) is not available in 20.04 repository
|
||||||
env:
|
env:
|
||||||
|
|
@ -83,7 +127,6 @@ jobs:
|
||||||
echo "-- github.workspace: ${{ github.workspace }}"
|
echo "-- github.workspace: ${{ github.workspace }}"
|
||||||
echo "-- runner.workspace: ${{ runner.workspace }}"
|
echo "-- runner.workspace: ${{ runner.workspace }}"
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
options=(
|
options=(
|
||||||
--build build
|
--build build
|
||||||
|
|
@ -94,15 +137,10 @@ jobs:
|
||||||
)
|
)
|
||||||
cmake "${options[@]}"
|
cmake "${options[@]}"
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
./build/tests/sfizz_tests
|
|
||||||
options=(
|
options=(
|
||||||
--build-config ${{ env.build_type }}
|
--build-config ${{ env.build_type }}
|
||||||
--debug
|
|
||||||
--extra-verbose
|
|
||||||
--output-on-failure
|
--output-on-failure
|
||||||
--parallel 2
|
|
||||||
--test-dir build
|
--test-dir build
|
||||||
)
|
)
|
||||||
ctest "${options[@]}"
|
ctest "${options[@]}"
|
||||||
|
|
@ -129,7 +167,6 @@ jobs:
|
||||||
path: "${{ github.workspace }}/${{ env.install_name }}.tar.gz"
|
path: "${{ github.workspace }}/${{ env.install_name }}.tar.gz"
|
||||||
|
|
||||||
build_for_macos:
|
build_for_macos:
|
||||||
# if: ${{ false }}
|
|
||||||
name: macOS 11
|
name: macOS 11
|
||||||
runs-on: macos-11
|
runs-on: macos-11
|
||||||
env:
|
env:
|
||||||
|
|
@ -161,7 +198,6 @@ jobs:
|
||||||
echo "-- runner.workspace: ${{ runner.workspace }}"
|
echo "-- runner.workspace: ${{ runner.workspace }}"
|
||||||
echo "-- github.workspace: ${{ github.workspace }}"
|
echo "-- github.workspace: ${{ github.workspace }}"
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
options=(
|
options=(
|
||||||
--build build
|
--build build
|
||||||
|
|
@ -172,15 +208,10 @@ jobs:
|
||||||
)
|
)
|
||||||
cmake "${options[@]}"
|
cmake "${options[@]}"
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
./build/tests/sfizz_tests
|
|
||||||
options=(
|
options=(
|
||||||
--build-config ${{ env.build_type }}
|
--build-config ${{ env.build_type }}
|
||||||
--debug
|
|
||||||
--extra-verbose
|
|
||||||
--output-on-failure
|
--output-on-failure
|
||||||
--parallel 2
|
|
||||||
--test-dir build
|
--test-dir build
|
||||||
)
|
)
|
||||||
ctest "${options[@]}"
|
ctest "${options[@]}"
|
||||||
|
|
@ -207,7 +238,6 @@ jobs:
|
||||||
path: "${{ github.workspace }}/${{ env.install_name }}.tar.gz"
|
path: "${{ github.workspace }}/${{ env.install_name }}.tar.gz"
|
||||||
|
|
||||||
build_for_windows:
|
build_for_windows:
|
||||||
# if: ${{ false }}
|
|
||||||
name: Windows 2019
|
name: Windows 2019
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
strategy:
|
strategy:
|
||||||
|
|
@ -235,12 +265,10 @@ jobs:
|
||||||
-A "${{ matrix.release_arch }}" `
|
-A "${{ matrix.release_arch }}" `
|
||||||
-B build `
|
-B build `
|
||||||
-S . `
|
-S . `
|
||||||
-D CMAKE_BUILD_TYPE=${{ env.build_type }} `
|
|
||||||
-D SFIZZ_TESTS=ON
|
-D SFIZZ_TESTS=ON
|
||||||
echo "-- runner.workspace: ${{ runner.workspace }}"
|
echo "-- runner.workspace: ${{ runner.workspace }}"
|
||||||
echo "-- github.workspace: ${{ github.workspace }}"
|
echo "-- github.workspace: ${{ github.workspace }}"
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
cmake `
|
cmake `
|
||||||
--build build `
|
--build build `
|
||||||
|
|
@ -249,15 +277,10 @@ jobs:
|
||||||
--target sfizz_tests `
|
--target sfizz_tests `
|
||||||
--verbose `
|
--verbose `
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
.\build\tests\${{ env.build_type }}\sfizz_tests.exe
|
|
||||||
ctest `
|
ctest `
|
||||||
--build-config ${{ env.build_type }} `
|
--build-config ${{ env.build_type }} `
|
||||||
--debug `
|
|
||||||
--extra-verbose `
|
|
||||||
--output-on-failure `
|
--output-on-failure `
|
||||||
--parallel 2 `
|
|
||||||
--test-dir build `
|
--test-dir build `
|
||||||
- name: Build all
|
- name: Build all
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -277,7 +300,6 @@ jobs:
|
||||||
path: "${{ github.workspace }}/${{ env.install_name }}.zip"
|
path: "${{ github.workspace }}/${{ env.install_name }}.zip"
|
||||||
|
|
||||||
archive_source_code:
|
archive_source_code:
|
||||||
# if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
if: ${{ github.ref_type == 'tag' }}
|
if: ${{ github.ref_type == 'tag' }}
|
||||||
name: Source code archive
|
name: Source code archive
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
|
@ -304,7 +326,6 @@ jobs:
|
||||||
path: "${{ github.workspace }}/${{ env.install_name }}.tar.gz"
|
path: "${{ github.workspace }}/${{ env.install_name }}.tar.gz"
|
||||||
|
|
||||||
build_with_libsndfile:
|
build_with_libsndfile:
|
||||||
# if: ${{ false }}
|
|
||||||
name: Linux libsndfile
|
name: Linux libsndfile
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -332,7 +353,6 @@ jobs:
|
||||||
)
|
)
|
||||||
cmake "${options[@]}"
|
cmake "${options[@]}"
|
||||||
- name: Build tests
|
- name: Build tests
|
||||||
if: ${{ false }}
|
|
||||||
run: |
|
run: |
|
||||||
options=(
|
options=(
|
||||||
--build build
|
--build build
|
||||||
|
|
@ -343,11 +363,15 @@ jobs:
|
||||||
)
|
)
|
||||||
cmake "${options[@]}"
|
cmake "${options[@]}"
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
if: ${{ false }}
|
run: |
|
||||||
run: ./build/tests/sfizz_tests
|
options=(
|
||||||
|
--build-config ${{ env.build_type }}
|
||||||
|
--output-on-failure
|
||||||
|
--test-dir build
|
||||||
|
)
|
||||||
|
ctest "${options[@]}"
|
||||||
|
|
||||||
build_with_makefile:
|
build_with_makefile:
|
||||||
# if: ${{ false }}
|
|
||||||
name: Linux makefile
|
name: Linux makefile
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -26,3 +26,4 @@ clients/sfzprint
|
||||||
*.code-*
|
*.code-*
|
||||||
.kak.tags.namecache
|
.kak.tags.namecache
|
||||||
.clangd
|
.clangd
|
||||||
|
venv
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ option_ex(SFIZZ_USE_SYSTEM_CATCH "Use Catch libraries preinstalled on system"
|
||||||
option_ex(SFIZZ_RELEASE_ASSERTS "Forced assertions in release builds" OFF)
|
option_ex(SFIZZ_RELEASE_ASSERTS "Forced assertions in release builds" OFF)
|
||||||
option_ex(SFIZZ_PROFILE_BUILD "Profile the build time" OFF)
|
option_ex(SFIZZ_PROFILE_BUILD "Profile the build time" OFF)
|
||||||
option_ex(SFIZZ_SNDFILE_STATIC "Link the sndfile library statically" OFF)
|
option_ex(SFIZZ_SNDFILE_STATIC "Link the sndfile library statically" OFF)
|
||||||
|
option_ex(SFIZZ_ASAN "Use address sanitizer on all sfizz targets" OFF)
|
||||||
|
|
||||||
# Continuous Controller count (0 to 511)
|
# Continuous Controller count (0 to 511)
|
||||||
set(MIDI_CC_COUNT 512 CACHE STRING "Maximum number of managed Control Change messages")
|
set(MIDI_CC_COUNT 512 CACHE STRING "Maximum number of managed Control Change messages")
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,11 @@ function(sfizz_enable_fast_math NAME)
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(sfizz_enable_release_asserts NAME)
|
||||||
|
target_compile_definitions("${NAME}" PUBLIC "SFIZZ_ENABLE_RELEASE_ASSERT=1")
|
||||||
|
target_compile_definitions("${NAME}" PUBLIC "SFIZZ_ENABLE_RELEASE_DBG=1")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# If we build with Clang, optionally use libc++. Enabled by default on Apple OS.
|
# If we build with Clang, optionally use libc++. Enabled by default on Apple OS.
|
||||||
cmake_dependent_option(USE_LIBCPP "Use libc++ with clang" "${APPLE}"
|
cmake_dependent_option(USE_LIBCPP "Use libc++ with clang" "${APPLE}"
|
||||||
"CMAKE_CXX_COMPILER_ID MATCHES Clang" OFF)
|
"CMAKE_CXX_COMPILER_ID MATCHES Clang" OFF)
|
||||||
|
|
@ -133,6 +138,13 @@ else()
|
||||||
set(PROJECT_IS_MAIN FALSE)
|
set(PROJECT_IS_MAIN FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(SFIZZ_ASAN)
|
||||||
|
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-fsanitize=address>)
|
||||||
|
add_link_options($<$<COMPILE_LANGUAGE:C,CXX>:-fsanitize=address>)
|
||||||
|
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-fno-omit-frame-pointer>)
|
||||||
|
add_link_options($<$<COMPILE_LANGUAGE:C,CXX>:-fno-omit-frame-pointer>)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Don't show build information when building a different project
|
# Don't show build information when building a different project
|
||||||
function(show_build_info_if_needed)
|
function(show_build_info_if_needed)
|
||||||
if(PROJECT_IS_MAIN)
|
if(PROJECT_IS_MAIN)
|
||||||
|
|
@ -155,6 +167,7 @@ Statically link sndfile: ${SFIZZ_SNDFILE_STATIC}
|
||||||
|
|
||||||
Use clang libc++: ${USE_LIBCPP}
|
Use clang libc++: ${USE_LIBCPP}
|
||||||
Release asserts: ${SFIZZ_RELEASE_ASSERTS}
|
Release asserts: ${SFIZZ_RELEASE_ASSERTS}
|
||||||
|
Use ASAN: ${SFIZZ_ASAN}
|
||||||
|
|
||||||
Use system abseil-cpp: ${SFIZZ_USE_SYSTEM_ABSEIL}
|
Use system abseil-cpp: ${SFIZZ_USE_SYSTEM_ABSEIL}
|
||||||
Use system catch: ${SFIZZ_USE_SYSTEM_CATCH}
|
Use system catch: ${SFIZZ_USE_SYSTEM_CATCH}
|
||||||
|
|
@ -182,11 +195,6 @@ VST3 destination directory: ${VST3_PLUGIN_INSTALL_DIR}")
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "
|
message(STATUS "
|
||||||
Install prefix: ${CMAKE_INSTALL_PREFIX}
|
Install prefix: ${CMAKE_INSTALL_PREFIX}
|
||||||
|
|
||||||
CXX Debug flags: ${CMAKE_CXX_FLAGS_DEBUG}
|
|
||||||
CXX Release flags: ${CMAKE_CXX_FLAGS_RELEASE}
|
|
||||||
CXX MinSize flags: ${CMAKE_CXX_FLAGS_MINSIZEREL}
|
|
||||||
CXX RelWithDebInfo flags: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}
|
|
||||||
")
|
")
|
||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
||||||
15
external/st_audiofile/src/st_audiofile.c
vendored
15
external/st_audiofile/src/st_audiofile.c
vendored
|
|
@ -9,6 +9,9 @@
|
||||||
#include "st_audiofile_libs.h"
|
#include "st_audiofile_libs.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
#define WAVPACK_MEMORY_ASSUMED_VERSION 5
|
#define WAVPACK_MEMORY_ASSUMED_VERSION 5
|
||||||
|
|
||||||
struct st_audio_file {
|
struct st_audio_file {
|
||||||
|
|
@ -179,10 +182,18 @@ static st_audio_file* st_generic_open_file(const void* filename, int widepath)
|
||||||
|
|
||||||
// Try WV
|
// Try WV
|
||||||
{
|
{
|
||||||
af->wv =
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
WavpackOpenFileInput((const char*)filename, NULL, OPEN_FILE_UTF8, 0);
|
// WavPack expects an UTF8 input and has no widechar api, so we convert the filename back...
|
||||||
|
unsigned wsize = wcslen(filename);
|
||||||
|
unsigned size = WideCharToMultiByte(CP_UTF8, 0, filename, wsize, NULL, 0, NULL, NULL);
|
||||||
|
char *buffer = (char*)malloc((size+1) * sizeof(char));
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, filename, wsize, buffer, size, NULL, NULL);
|
||||||
|
buffer[size] = '\0';
|
||||||
|
af->wv =
|
||||||
|
WavpackOpenFileInput(buffer, NULL, OPEN_FILE_UTF8, 0);
|
||||||
|
free(buffer);
|
||||||
#else
|
#else
|
||||||
|
af->wv =
|
||||||
WavpackOpenFileInput((const char*)filename, NULL, 0, 0);
|
WavpackOpenFileInput((const char*)filename, NULL, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
if (af->wv) {
|
if (af->wv) {
|
||||||
|
|
|
||||||
8
external/st_audiofile/src/st_audiofile.hpp
vendored
8
external/st_audiofile/src/st_audiofile.hpp
vendored
|
|
@ -60,13 +60,13 @@ inline ST_AudioFile::~ST_AudioFile() noexcept
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_AudioFile::ST_AudioFile(ST_AudioFile&& other) noexcept
|
inline ST_AudioFile::ST_AudioFile(ST_AudioFile&& other) noexcept
|
||||||
: af_(other.af_)
|
: af_(other.af_)
|
||||||
{
|
{
|
||||||
other.af_ = nullptr;
|
other.af_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_AudioFile& ST_AudioFile::operator=(ST_AudioFile&& other) noexcept
|
inline ST_AudioFile& ST_AudioFile::operator=(ST_AudioFile&& other) noexcept
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
if (af_)
|
if (af_)
|
||||||
|
|
@ -91,14 +91,14 @@ inline void ST_AudioFile::reset(st_audio_file* new_af) noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ST_AudioFile::open_file(const char* filename)
|
inline bool ST_AudioFile::open_file(const char* filename)
|
||||||
{
|
{
|
||||||
st_audio_file* new_af = st_open_file(filename);
|
st_audio_file* new_af = st_open_file(filename);
|
||||||
reset(new_af);
|
reset(new_af);
|
||||||
return new_af != nullptr;
|
return new_af != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ST_AudioFile::open_memory(const void* memory, size_t length)
|
inline bool ST_AudioFile::open_memory(const void* memory, size_t length)
|
||||||
{
|
{
|
||||||
st_audio_file* new_af = st_open_memory(memory, length);
|
st_audio_file* new_af = st_open_memory(memory, length);
|
||||||
reset(new_af);
|
reset(new_af);
|
||||||
|
|
|
||||||
|
|
@ -231,9 +231,7 @@ target_include_directories(sfizz_parser PUBLIC sfizz)
|
||||||
target_link_libraries(sfizz_parser
|
target_link_libraries(sfizz_parser
|
||||||
PUBLIC sfizz::filesystem sfizz::simde absl::strings
|
PUBLIC sfizz::filesystem sfizz::simde absl::strings
|
||||||
PRIVATE absl::flat_hash_map)
|
PRIVATE absl::flat_hash_map)
|
||||||
if(SFIZZ_RELEASE_ASSERTS)
|
sfizz_enable_release_asserts(sfizz_parser)
|
||||||
target_compile_definitions(sfizz_parser PUBLIC "SFIZZ_ENABLE_RELEASE_ASSERT=1")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# OSC messaging library
|
# OSC messaging library
|
||||||
set(SFIZZ_MESSAGING_HEADERS
|
set(SFIZZ_MESSAGING_HEADERS
|
||||||
|
|
@ -250,9 +248,8 @@ target_sources(sfizz_messaging PRIVATE
|
||||||
${SFIZZ_MESSAGING_HEADERS} ${SFIZZ_MESSAGING_SOURCES})
|
${SFIZZ_MESSAGING_HEADERS} ${SFIZZ_MESSAGING_SOURCES})
|
||||||
target_include_directories(sfizz_messaging PUBLIC ".")
|
target_include_directories(sfizz_messaging PUBLIC ".")
|
||||||
target_link_libraries(sfizz_messaging PUBLIC absl::strings)
|
target_link_libraries(sfizz_messaging PUBLIC absl::strings)
|
||||||
if(SFIZZ_RELEASE_ASSERTS)
|
sfizz_enable_release_asserts(sfizz_messaging)
|
||||||
target_compile_definitions(sfizz_messaging PUBLIC "SFIZZ_ENABLE_RELEASE_ASSERT=1")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Import library
|
# Import library
|
||||||
set(SFIZZ_IMPORT_HEADERS
|
set(SFIZZ_IMPORT_HEADERS
|
||||||
|
|
@ -303,9 +300,8 @@ if(SFIZZ_USE_SNDFILE)
|
||||||
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")
|
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")
|
||||||
target_link_libraries(sfizz_internal PUBLIC st_audiofile)
|
target_link_libraries(sfizz_internal PUBLIC st_audiofile)
|
||||||
endif()
|
endif()
|
||||||
if(SFIZZ_RELEASE_ASSERTS)
|
sfizz_enable_release_asserts(sfizz_internal)
|
||||||
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_ENABLE_RELEASE_ASSERT=1")
|
|
||||||
endif()
|
|
||||||
if(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT)
|
if(SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT)
|
||||||
target_compile_definitions(sfizz_internal PRIVATE "SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT=1")
|
target_compile_definitions(sfizz_internal PRIVATE "SFIZZ_IMPLEMENT_CXX17_ALIGNED_NEW_SUPPORT=1")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,7 @@ void sfz::FilePool::loadingJob(const QueuedFileData& data) noexcept
|
||||||
AudioReaderPtr reader = createAudioReader(file, id->isReverse(), &readError);
|
AudioReaderPtr reader = createAudioReader(file, id->isReverse(), &readError);
|
||||||
|
|
||||||
if (readError) {
|
if (readError) {
|
||||||
DBG("[sfizz] libsndfile errored for " << *id << " with message " << readError.message());
|
DBG("[sfizz] reading the file errored for " << *id << " with code " << readError << ": " << readError.message());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1069,6 +1069,10 @@ void Voice::Impl::fillWithData(AudioSpan<float> buffer) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
auto source = currentPromise_->getData();
|
auto source = currentPromise_->getData();
|
||||||
|
if (source.getNumFrames() == 0) {
|
||||||
|
DBG("[Voice] Empty source in promise");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BufferPool& bufferPool = resources_.getBufferPool();
|
BufferPool& bufferPool = resources_.getBufferPool();
|
||||||
const CurveSet& curves = resources_.getCurves();
|
const CurveSet& curves = resources_.getCurves();
|
||||||
|
|
|
||||||
|
|
@ -128,13 +128,13 @@ namespace fx {
|
||||||
|
|
||||||
const float steps = (1.0f + (100.0f - fDepth)) * 0.75f;
|
const float steps = (1.0f + (100.0f - fDepth)) * 0.75f;
|
||||||
const float invSteps = 1.0f / steps;
|
const float invSteps = 1.0f / steps;
|
||||||
|
float y2x[4] { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
for (uint32_t i = 0; i < nframes; ++i) {
|
for (uint32_t i = 0; i < nframes; ++i) {
|
||||||
float x = in[i];
|
float x = in[i];
|
||||||
|
|
||||||
float y = std::copysign((int)(0.5f + std::fabs(x * steps)), x) * invSteps; // NOLINT
|
float y = std::copysign((int)(0.5f + std::fabs(x * steps)), x) * invSteps; // NOLINT
|
||||||
|
|
||||||
float y2x[2];
|
|
||||||
y2x[0] = (y != lastValue) ? (0.5f * (y + lastValue)) : y;
|
y2x[0] = (y != lastValue) ? (0.5f * (y + lastValue)) : y;
|
||||||
y2x[1] = y;
|
y2x[1] = y;
|
||||||
|
|
||||||
|
|
@ -185,6 +185,7 @@ namespace fx {
|
||||||
|
|
||||||
float phase = fPhase;
|
float phase = fPhase;
|
||||||
float lastValue = fLastValue;
|
float lastValue = fLastValue;
|
||||||
|
float y2x[4] { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
for (uint32_t i = 0; i < nframes; ++i) {
|
for (uint32_t i = 0; i < nframes; ++i) {
|
||||||
float x = in[i];
|
float x = in[i];
|
||||||
|
|
@ -193,7 +194,6 @@ namespace fx {
|
||||||
float y = (phase > 1.0f) ? x : lastValue;
|
float y = (phase > 1.0f) ? x : lastValue;
|
||||||
phase -= static_cast<float>(static_cast<int>(phase));
|
phase -= static_cast<float>(static_cast<int>(phase));
|
||||||
|
|
||||||
float y2x[2];
|
|
||||||
y2x[0] = (y != lastValue) ? (0.5f * (y + lastValue)) : y;
|
y2x[0] = (y != lastValue) ? (0.5f * (y + lastValue)) : y;
|
||||||
y2x[1] = y;
|
y2x[1] = y;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,63 +9,137 @@
|
||||||
#include "sfizz/Synth.h"
|
#include "sfizz/Synth.h"
|
||||||
#include "TestHelpers.h"
|
#include "TestHelpers.h"
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
|
#include "st_audiofile.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace Catch::literals;
|
using namespace Catch::literals;
|
||||||
|
|
||||||
TEST_CASE("[AudioFiles] No leakage on right")
|
void compareFiles(const fs::path& lFile, const fs::path& rFile)
|
||||||
{
|
{
|
||||||
sfz::Synth synth;
|
auto l_file = ST_AudioFile();
|
||||||
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
|
auto r_file = ST_AudioFile();
|
||||||
std::vector<float> zeros(synth.getSamplesPerBlock(), 0);
|
#if defined(_WIN32)
|
||||||
sfz::AudioSpan<float> span { buffer };
|
l_file.open_file_w(lFile.wstring().c_str());
|
||||||
synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"(
|
r_file.open_file_w(rFile.wstring().c_str());
|
||||||
<region> sample=kick.wav key=60 pan=-100
|
#else
|
||||||
)");
|
l_file.open_file(lFile.string().c_str());
|
||||||
synth.noteOn(0, 60, 127);
|
r_file.open_file(rFile.string().c_str());
|
||||||
synth.renderBlock(buffer);
|
#endif
|
||||||
REQUIRE( numPlayingVoices(synth) == 1 );
|
CHECK(l_file.get_channels() == 1);
|
||||||
REQUIRE( approxEqual(span.getConstSpan(1), absl::MakeConstSpan(zeros), 1e-2f) );
|
CHECK(r_file.get_channels() == 1);
|
||||||
while (numPlayingVoices(synth) > 0) {
|
std::vector<float> wav (l_file.get_frame_count());
|
||||||
synth.renderBlock(buffer);
|
std::vector<float> flac (r_file.get_frame_count());
|
||||||
REQUIRE( approxEqual(span.getConstSpan(1), absl::MakeConstSpan(zeros), 1e-2f) );
|
l_file.read_f32(wav.data(), l_file.get_frame_count());
|
||||||
|
r_file.read_f32(flac.data(), r_file.get_frame_count());
|
||||||
|
REQUIRE( approxEqual<float>(wav, flac) );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[AudioFiles] Compare Flac and WAV")
|
||||||
|
{
|
||||||
|
compareFiles(fs::current_path() / "tests/TestFiles/kick.wav",
|
||||||
|
fs::current_path() / "tests/TestFiles/kick.flac");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(SFIZZ_USE_SNDFILE)
|
||||||
|
TEST_CASE("[AudioFiles] Compare WV and WAV")
|
||||||
|
{
|
||||||
|
compareFiles(fs::current_path() / "tests/TestFiles/kick.wav",
|
||||||
|
fs::current_path() / "tests/TestFiles/kick.wv");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct CompareOutputOpts
|
||||||
|
{
|
||||||
|
int note { 60 };
|
||||||
|
int delay { 0 };
|
||||||
|
int velocity { 127 };
|
||||||
|
float sampleRate { 48000.0f };
|
||||||
|
int samplesPerBlock { 1024 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compare the outputs of 2 sfz files with a given set of options, for a single note pressed.
|
||||||
|
*
|
||||||
|
* @param lFile
|
||||||
|
* @param rFile
|
||||||
|
* @param opts
|
||||||
|
*/
|
||||||
|
void compareOutputs(const std::string& lFile, const std::string& rFile, CompareOutputOpts opts)
|
||||||
|
{
|
||||||
|
sfz::Synth lSynth;
|
||||||
|
sfz::Synth rSynth;
|
||||||
|
lSynth.enableFreeWheeling();
|
||||||
|
rSynth.enableFreeWheeling();
|
||||||
|
lSynth.setSampleRate(opts.sampleRate);
|
||||||
|
rSynth.setSampleRate(opts.sampleRate);
|
||||||
|
lSynth.setSamplesPerBlock(opts.samplesPerBlock);
|
||||||
|
rSynth.setSamplesPerBlock(opts.samplesPerBlock);
|
||||||
|
sfz::AudioBuffer<float> lBuffer { 2, static_cast<unsigned>(lSynth.getSamplesPerBlock()) };
|
||||||
|
sfz::AudioBuffer<float> rBuffer { 2, static_cast<unsigned>(rSynth.getSamplesPerBlock()) };
|
||||||
|
sfz::AudioSpan<float> lSpan { lBuffer };
|
||||||
|
sfz::AudioSpan<float> rSpan { rBuffer };
|
||||||
|
lSynth.loadSfzString(fs::current_path() / "tests/TestFiles/l.sfz", lFile);
|
||||||
|
rSynth.loadSfzString(fs::current_path() / "tests/TestFiles/r.sfz", rFile);
|
||||||
|
lSynth.noteOn(opts.delay, opts.note, opts.velocity);
|
||||||
|
rSynth.noteOn(opts.delay, opts.note, opts.velocity);
|
||||||
|
lSynth.renderBlock(lSpan);
|
||||||
|
rSynth.renderBlock(rSpan);
|
||||||
|
REQUIRE( numPlayingVoices(lSynth) == 1 );
|
||||||
|
REQUIRE( numPlayingVoices(rSynth) == 1 );
|
||||||
|
REQUIRE( approxEqual(lSpan.getConstSpan(0), rSpan.getConstSpan(0)) );
|
||||||
|
REQUIRE( approxEqual(lSpan.getConstSpan(1), rSpan.getConstSpan(1)) );
|
||||||
|
while (numPlayingVoices(lSynth) == 1) {
|
||||||
|
REQUIRE( numPlayingVoices(rSynth) == 1 );
|
||||||
|
lSynth.renderBlock(lSpan);
|
||||||
|
rSynth.renderBlock(rSpan);
|
||||||
|
REQUIRE( approxEqual(lSpan.getConstSpan(0), rSpan.getConstSpan(0)) );
|
||||||
|
REQUIRE( approxEqual(lSpan.getConstSpan(1), rSpan.getConstSpan(1)) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[AudioFiles] WavPack file")
|
TEST_CASE("[AudioFiles] Sanity check (native sample rate)")
|
||||||
{
|
{
|
||||||
sfz::Synth synth;
|
std::string lFile = "<region> sample=kick.wav key=60";
|
||||||
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
|
std::string rFile = "<region> sample=kick.wav key=60";
|
||||||
sfz::AudioSpan<float> span { buffer };
|
CompareOutputOpts opts;
|
||||||
synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"(
|
opts.sampleRate = 44100.0f;
|
||||||
<region> sample=kick.wav key=60 pan=-100
|
compareOutputs(lFile, rFile, opts);
|
||||||
<region> sample=kick.wv key=60 pan=100
|
|
||||||
)");
|
|
||||||
synth.noteOn(0, 60, 127);
|
|
||||||
synth.renderBlock(buffer);
|
|
||||||
REQUIRE( numPlayingVoices(synth) == 2 );
|
|
||||||
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
|
||||||
while (numPlayingVoices(synth) > 0) {
|
|
||||||
synth.renderBlock(buffer);
|
|
||||||
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[AudioFiles] Flac file")
|
#if !defined(SFIZZ_USE_SNDFILE)
|
||||||
|
TEST_CASE("[AudioFiles] Wavpack file (native sample rate)")
|
||||||
{
|
{
|
||||||
sfz::Synth synth;
|
std::string lFile = "<region> sample=kick.wav key=60";
|
||||||
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
|
std::string rFile = "<region> sample=kick.wv key=60";
|
||||||
sfz::AudioSpan<float> span { buffer };
|
CompareOutputOpts opts;
|
||||||
synth.loadSfzString(fs::current_path() / "tests/TestFiles/wavpack.sfz", R"(
|
opts.sampleRate = 44100.0f;
|
||||||
<region> sample=kick.wav key=60 pan=-100
|
compareOutputs(lFile, rFile, opts);
|
||||||
<region> sample=kick.flac key=60 pan=100
|
}
|
||||||
)");
|
|
||||||
synth.noteOn(0, 60, 127);
|
TEST_CASE("[AudioFiles] Wavpack file (resampled)")
|
||||||
synth.renderBlock(buffer);
|
{
|
||||||
REQUIRE( numPlayingVoices(synth) == 2 );
|
std::string lFile = "<region> sample=kick.wav key=60";
|
||||||
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
std::string rFile = "<region> sample=kick.wv key=60";
|
||||||
while (numPlayingVoices(synth) > 0) {
|
CompareOutputOpts opts;
|
||||||
synth.renderBlock(buffer);
|
opts.sampleRate = 48000.0f;
|
||||||
REQUIRE( approxEqual(span.getConstSpan(0), span.getConstSpan(1)) );
|
compareOutputs(lFile, rFile, opts);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("[AudioFiles] Flac file (native sample rate)")
|
||||||
|
{
|
||||||
|
std::string lFile = "<region> sample=kick.wav key=60";
|
||||||
|
std::string rFile = "<region> sample=kick.flac key=60";
|
||||||
|
CompareOutputOpts opts;
|
||||||
|
opts.sampleRate = 44100.0f;
|
||||||
|
compareOutputs(lFile, rFile, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[AudioFiles] Flac file (resampled)")
|
||||||
|
{
|
||||||
|
std::string lFile = "<region> sample=kick.wav key=60";
|
||||||
|
std::string rFile = "<region> sample=kick.flac key=60";
|
||||||
|
CompareOutputOpts opts;
|
||||||
|
opts.sampleRate = 48000.0f;
|
||||||
|
compareOutputs(lFile, rFile, opts);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ set(SFIZZ_TEST_SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(sfizz_tests ${SFIZZ_TEST_SOURCES})
|
add_executable(sfizz_tests ${SFIZZ_TEST_SOURCES})
|
||||||
target_link_libraries(sfizz_tests PRIVATE sfizz::internal sfizz::static sfizz::spin_mutex sfizz::jsl sfizz::filesystem)
|
target_link_libraries(sfizz_tests PRIVATE sfizz::internal sfizz::static sfizz::spin_mutex sfizz::jsl sfizz::filesystem st_audiofile)
|
||||||
if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "10.12")
|
if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "10.12")
|
||||||
# workaround for incomplete C++17 runtime on macOS
|
# workaround for incomplete C++17 runtime on macOS
|
||||||
target_compile_definitions(sfizz_tests PRIVATE "CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS")
|
target_compile_definitions(sfizz_tests PRIVATE "CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS")
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,10 @@ TEST_CASE("[Messaging] Type-safe client API")
|
||||||
REQUIRE(args[index++].f == f);
|
REQUIRE(args[index++].f == f);
|
||||||
REQUIRE(args[index++].d == d);
|
REQUIRE(args[index++].d == d);
|
||||||
REQUIRE(!strcmp(args[index++].s, s));
|
REQUIRE(!strcmp(args[index++].s, s));
|
||||||
|
#if !defined(__SANITIZE_ADDRESS__)
|
||||||
REQUIRE(args[index ].b->data == b.data);
|
REQUIRE(args[index ].b->data == b.data);
|
||||||
REQUIRE(args[index++].b->size == b.size);
|
REQUIRE(args[index++].b->size == b.size);
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
client.receive<'i', 'm', 'h', 'f', 'd', 's', 'b', 'T', 'F', 'N', 'I'>(
|
client.receive<'i', 'm', 'h', 'f', 'd', 's', 'b', 'T', 'F', 'N', 'I'>(
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,10 @@ std::string createModulationDotGraph(std::vector<std::string> lines);
|
||||||
template <class Type>
|
template <class Type>
|
||||||
bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs, Type eps = 1e-3)
|
||||||
{
|
{
|
||||||
if (lhs.size() != rhs.size())
|
if (lhs.size() != rhs.size()) {
|
||||||
|
std::cerr << "Span size are different: "<< lhs.size() << " != " << rhs.size() << '\n';
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool different = false;
|
bool different = false;
|
||||||
for (size_t i = 0; i < rhs.size(); ++i)
|
for (size_t i = 0; i < rhs.size(); ++i)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue