Merge branch 'develop'
This commit is contained in:
commit
3bda904fe6
741 changed files with 68872 additions and 31378 deletions
65
.appveyor.yml
Normal file
65
.appveyor.yml
Normal file
File diff suppressed because one or more lines are too long
35
.gitattributes
vendored
35
.gitattributes
vendored
|
|
@ -1,3 +1,38 @@
|
|||
.* export-ignore
|
||||
.*/** export-ignore
|
||||
appveyor.yml export-ignore
|
||||
/scripts/appveyor/** export-ignore
|
||||
|
||||
/vst/external/VST_SDK/VST3_SDK/**/CMakeLists.txt export-ignore
|
||||
/vst/external/VST_SDK/VST3_SDK/public.sdk/samples export-ignore
|
||||
/vst/external/VST_SDK/VST3_SDK/public.sdk/source/vst/*wrapper/** export-ignore
|
||||
/vst/external/VST_SDK/VST3_SDK/public.sdk/source/vst/interappaudio/** export-ignore
|
||||
/vst/external/VST_SDK/VST3_SDK/public.sdk/source/vst/testsuite/** export-ignore
|
||||
/vst/external/VST_SDK/VST3_SDK/public.sdk/source/vst/utility/test/** export-ignore
|
||||
|
||||
/editor/external/vstgui4/**/CMakeLists.txt export-ignore
|
||||
/editor/external/vstgui4/vstgui/Documentation/** export-ignore
|
||||
/editor/external/vstgui4/vstgui/doxygen/** export-ignore
|
||||
/editor/external/vstgui4/vstgui/standalone/** export-ignore
|
||||
/editor/external/vstgui4/vstgui/tests/** export-ignore
|
||||
/editor/external/vstgui4/vstgui/tools/** export-ignore
|
||||
/editor/external/vstgui4/vstgui/uidescription/** export-ignore
|
||||
/editor/external/vstgui4/vstgui/uidescription/icontroller.h -export-ignore
|
||||
/editor/external/vstgui4/vstgui/vstgui_standalone* export-ignore
|
||||
/editor/external/vstgui4/vstgui/vstgui_uidescription* export-ignore
|
||||
|
||||
/external/st_audiofile/thirdparty/dr_libs/old/** export-ignore
|
||||
/external/st_audiofile/thirdparty/dr_libs/tests/** export-ignore
|
||||
|
||||
/external/filesystem/test/** export-ignore
|
||||
|
||||
/external/abseil-cpp/conanfile.py export-ignore
|
||||
/external/abseil-cpp/**/BUILD.bazel export-ignore
|
||||
/external/abseil-cpp/ci/** export-ignore
|
||||
|
||||
/external/simde/docker/** export-ignore
|
||||
/external/simde/test/** export-ignore
|
||||
/external/simde/meson* export-ignore
|
||||
/external/simde/*.py export-ignore
|
||||
/external/simde/*.yml export-ignore
|
||||
/external/simde/*.toml export-ignore
|
||||
|
|
|
|||
458
.github/workflows/build.yml
vendored
Normal file
458
.github/workflows/build.yml
vendored
Normal file
|
|
@ -0,0 +1,458 @@
|
|||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
tags:
|
||||
- '[0-9]*'
|
||||
- 'v[0-9]*'
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
clang_tidy:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up dependencies
|
||||
run: |
|
||||
sudo apt-get update && \
|
||||
sudo apt-get install \
|
||||
clang-tidy \
|
||||
libsndfile1-dev
|
||||
- name: Clang Tidy
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: cd "$GITHUB_WORKSPACE" && scripts/run_clang_tidy.sh
|
||||
|
||||
build_for_linux:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo "install_ref=${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
echo "install_name=sfizz-${GITHUB_REF##*/}-linux" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up dependencies
|
||||
run: |
|
||||
sudo apt-get update && \
|
||||
sudo apt-get install \
|
||||
libjack-jackd2-dev \
|
||||
libsndfile1-dev \
|
||||
libcairo2-dev \
|
||||
libpango1.0-dev \
|
||||
libfontconfig1-dev \
|
||||
libx11-xcb-dev \
|
||||
libxcb-util-dev \
|
||||
libxcb-cursor-dev \
|
||||
libxcb-xkb-dev \
|
||||
libxkbcommon-dev \
|
||||
libxkbcommon-x11-dev \
|
||||
libxcb-keysyms1-dev
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: |
|
||||
cmake "$GITHUB_WORKSPACE" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DSFIZZ_JACK=ON \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_LV2_UI=ON \
|
||||
-DSFIZZ_TESTS=ON \
|
||||
-DSFIZZ_SHARED=OFF \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=OFF \
|
||||
-DSFIZZ_LV2=ON \
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
- name: Build tests
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config "$BUILD_TYPE" -j 2 --target sfizz_tests
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: ${{runner.workspace}}/build/tests/sfizz_tests
|
||||
- name: Build all
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config "$BUILD_TYPE" -j 2
|
||||
- name: Install
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: |
|
||||
DESTDIR="$(pwd)/$install_name" cmake --build . --config "$BUILD_TYPE" --target install
|
||||
tar czvf "$install_name".tar.gz "$install_name"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Linux tarball
|
||||
path: ${{runner.workspace}}/build/${{env.install_name}}.tar.gz
|
||||
|
||||
build_for_mod:
|
||||
runs-on: ubuntu-18.04
|
||||
container:
|
||||
image: jpcima/mod-plugin-builder
|
||||
options: --user 0
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo "install_ref=${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
echo "install_name=sfizz-${GITHUB_REF##*/}-moddevices" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Fix up MOD environment
|
||||
shell: bash
|
||||
run: ln -sf /home/builder/mod-workdir ~/mod-workdir
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: mod-plugin-builder /usr/local/bin/cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: |
|
||||
mod-plugin-builder /usr/local/bin/cmake "$GITHUB_WORKSPACE" \
|
||||
-DSFIZZ_SYSTEM_PROCESSOR=armv7-a \
|
||||
-DCMAKE_BUILD_TYPE=Release -DSFIZZ_JACK=OFF -DSFIZZ_VST=OFF -DSFIZZ_LV2_UI=OFF
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: mod-plugin-builder /usr/local/bin/cmake --build . --config "$BUILD_TYPE" -- -j 2
|
||||
- name: Install
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: |
|
||||
DESTDIR="$(pwd)/$install_name" mod-plugin-builder /usr/local/bin/cmake --build . --config "$BUILD_TYPE" --target install
|
||||
tar czvf "$install_name".tar.gz "$install_name"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: MOD devices tarball
|
||||
path: ${{runner.workspace}}/build/${{env.install_name}}.tar.gz
|
||||
|
||||
build_for_win32:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo platform=x86 >> "${Env:GITHUB_ENV}"
|
||||
echo release_arch=Win32 >> "${Env:GITHUB_ENV}"
|
||||
echo "install_ref=$(${Env:GITHUB_REF}.split('/')[-1])" >> "${Env:GITHUB_ENV}"
|
||||
echo "install_name=sfizz-$(${Env:GITHUB_REF}.split('/')[-1])-win32" >> "${Env:GITHUB_ENV}"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Create Build Environment
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: |
|
||||
cmake "${Env:GITHUB_WORKSPACE}" -G"Visual Studio 16 2019" -A"${Env:release_arch}" -DCMAKE_BUILD_TYPE="${Env:BUILD_TYPE}" -DCMAKE_CXX_STANDARD=17 -DSFIZZ_TESTS=ON -DSFIZZ_VST=ON -DSFIZZ_LV2=ON
|
||||
- name: Build tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2 --target sfizz_tests
|
||||
- name: Test
|
||||
run: ${{runner.workspace}}/build/tests/Release/sfizz_tests
|
||||
- name: Build all
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2
|
||||
- name: Create installer
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: iscc /O"." /F"${Env:install_name}" /dARCH="${Env:platform}" innosetup.iss
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Win32 installer
|
||||
path: ${{runner.workspace}}/build/${{env.install_name}}.exe
|
||||
|
||||
build_for_win64:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo platform=x64 >> "${Env:GITHUB_ENV}"
|
||||
echo release_arch=x64 >> "${Env:GITHUB_ENV}"
|
||||
echo "install_ref=$(${Env:GITHUB_REF}.split('/')[-1])" >> "${Env:GITHUB_ENV}"
|
||||
echo "install_name=sfizz-$(${Env:GITHUB_REF}.split('/')[-1])-win64" >> "${Env:GITHUB_ENV}"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Create Build Environment
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: |
|
||||
cmake "${Env:GITHUB_WORKSPACE}" -G"Visual Studio 16 2019" -A"${Env:release_arch}" -DCMAKE_BUILD_TYPE="${Env:BUILD_TYPE}" -DCMAKE_CXX_STANDARD=17 -DSFIZZ_TESTS=ON -DSFIZZ_VST=ON -DSFIZZ_LV2=ON
|
||||
- name: Build tests
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2 --target sfizz_tests
|
||||
- name: Test
|
||||
run: ${{runner.workspace}}/build/tests/Release/sfizz_tests
|
||||
- name: Build all
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2
|
||||
- name: Install pluginval
|
||||
run: |
|
||||
Invoke-WebRequest https://github.com/Tracktion/pluginval/releases/download/latest_release/pluginval_Windows.zip -OutFile pluginval.zip
|
||||
Expand-Archive pluginval.zip -DestinationPath pluginval
|
||||
echo "$(Get-Location)\pluginval" | Out-File -FilePath ${Env:GITHUB_PATH} -Encoding utf8 -Append
|
||||
pluginval\pluginval --version
|
||||
- name: Validate VST3
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: pluginval --validate-in-process --validate sfizz.vst3
|
||||
- name: Create installer
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: iscc /O"." /F"${Env:install_name}" /dARCH="${Env:platform}" innosetup.iss
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Win64 installer
|
||||
path: ${{runner.workspace}}/build/${{env.install_name}}.exe
|
||||
|
||||
build_for_mingw32:
|
||||
runs-on: ubuntu-18.04
|
||||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo "install_ref=${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
echo "install_name=sfizz-${GITHUB_REF##*/}-mingw32" >> "$GITHUB_ENV"
|
||||
- name: Configure pacman repositories
|
||||
shell: bash
|
||||
run: |
|
||||
cat >>/etc/pacman.conf <<EOF
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
[mingw-w64]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://github.com/jpcima/arch-mingw-w64/releases/download/repo.\$arch/
|
||||
EOF
|
||||
- name: Set up dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
pacman -Sqyu --noconfirm
|
||||
pacman -Sq --needed --noconfirm base-devel git wget mingw-w64-cmake mingw-w64-gcc mingw-w64-pkg-config mingw-w64-libsndfile
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Fix MinGW headers
|
||||
shell: bash
|
||||
run: |
|
||||
cp -vf "$GITHUB_WORKSPACE"/scripts/mingw_dwrite_3.h \
|
||||
/usr/i686-w64-mingw32/include/dwrite_3.h
|
||||
- name: Fix VST sources
|
||||
shell: bash
|
||||
# need to convert some includes to lower case (as of VST 3.7.1)
|
||||
run: |
|
||||
find "$GITHUB_WORKSPACE"/plugins/vst/external/VST_SDK -type d -name source -exec \
|
||||
find {} -type f -name '*.[hc]' -o -name '*.[hc]pp' -print0 \; | \
|
||||
xargs -0 sed -i 's/<Windows.h>/<windows.h>/'
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: |
|
||||
i686-w64-mingw32-cmake "$GITHUB_WORKSPACE" \
|
||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DENABLE_LTO=OFF \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: i686-w64-mingw32-cmake --build . --config "$BUILD_TYPE" -j 2
|
||||
- name: Install
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: |
|
||||
DESTDIR="$(pwd)/$install_name" i686-w64-mingw32-cmake --build . --config "$BUILD_TYPE" --target install
|
||||
tar czvf "$install_name".tar.gz "$install_name"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Win32 MinGW tarball
|
||||
path: ${{runner.workspace}}/build/${{env.install_name}}.tar.gz
|
||||
|
||||
build_for_mingw64:
|
||||
runs-on: ubuntu-18.04
|
||||
container:
|
||||
image: archlinux
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo "install_ref=${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
echo "install_name=sfizz-${GITHUB_REF##*/}-mingw64" >> "$GITHUB_ENV"
|
||||
- name: Configure pacman repositories
|
||||
shell: bash
|
||||
run: |
|
||||
cat >>/etc/pacman.conf <<EOF
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
[mingw-w64]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://github.com/jpcima/arch-mingw-w64/releases/download/repo.\$arch/
|
||||
EOF
|
||||
- name: Set up dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
pacman -Sqyu --noconfirm
|
||||
pacman -Sq --needed --noconfirm base-devel git wget mingw-w64-cmake mingw-w64-gcc mingw-w64-pkg-config mingw-w64-libsndfile
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Fix MinGW headers
|
||||
shell: bash
|
||||
run: |
|
||||
cp -vf "$GITHUB_WORKSPACE"/scripts/mingw_dwrite_3.h \
|
||||
/usr/x86_64-w64-mingw32/include/dwrite_3.h
|
||||
- name: Fix VST sources
|
||||
shell: bash
|
||||
# need to convert some includes to lower case (as of VST 3.7.1)
|
||||
run: |
|
||||
find "$GITHUB_WORKSPACE"/plugins/vst/external/VST_SDK -type d -name source -exec \
|
||||
find {} -type f -name '*.[hc]' -o -name '*.[hc]pp' -print0 \; | \
|
||||
xargs -0 sed -i 's/<Windows.h>/<windows.h>/'
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: |
|
||||
x86_64-w64-mingw32-cmake "$GITHUB_WORKSPACE" \
|
||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
|
||||
-DENABLE_LTO=OFF \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
- name: Build
|
||||
shell: bash
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
run: x86_64-w64-mingw32-cmake --build . --config "$BUILD_TYPE" -j 2
|
||||
- name: Install
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: |
|
||||
DESTDIR="$(pwd)/$install_name" x86_64-w64-mingw32-cmake --build . --config "$BUILD_TYPE" --target install
|
||||
tar czvf "$install_name".tar.gz "$install_name"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Win64 MinGW tarball
|
||||
path: ${{runner.workspace}}/build/${{env.install_name}}.tar.gz
|
||||
|
||||
build_with_makefile:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build with GNU make
|
||||
shell: bash
|
||||
run: make -C "$GITHUB_WORKSPACE" -f generic.mk -j2
|
||||
- name: Compile a simple program
|
||||
shell: bash
|
||||
run: |
|
||||
cat <<EOF > "$GITHUB_WORKSPACE"/simple.cpp
|
||||
#include <sfizz.hpp>
|
||||
int main() {
|
||||
sfz::Sfizz synth;
|
||||
synth.loadSfzString("", "");
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cat <<EOF > "$GITHUB_WORKSPACE"/simple.mk
|
||||
all: simple
|
||||
include generic.mk
|
||||
simple.o: simple.cpp
|
||||
\$(CXX) \$(CXXFLAGS) \$(SFIZZ_CXX_FLAGS) -c -o \$@ \$<
|
||||
simple: simple.o \$(SFIZZ_TARGET)
|
||||
\$(CXX) -o \$@ \$^ \$(SFIZZ_LINK_FLAGS) \$(LDFLAGS)
|
||||
EOF
|
||||
make -C "$GITHUB_WORKSPACE" -f simple.mk
|
||||
|
||||
archive_source_code:
|
||||
runs-on: ubuntu-18.04
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo "install_ref=${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
echo "install_name=sfizz-${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Set up dependencies
|
||||
run: |
|
||||
sudo apt-get update && \
|
||||
sudo apt-get install \
|
||||
python-pip
|
||||
sudo pip install git-archive-all
|
||||
- name: Archive source code
|
||||
shell: bash
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE" && \
|
||||
git-archive-all --prefix="${install_name}/" -9 "${{runner.workspace}}/${install_name}.tar.gz"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Source code tarball
|
||||
path: ${{runner.workspace}}/${{env.install_name}}.tar.gz
|
||||
|
||||
deploy:
|
||||
runs-on: ubuntu-18.04
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
needs:
|
||||
- build_for_linux
|
||||
- build_for_mod
|
||||
- build_for_mingw32
|
||||
- build_for_mingw64
|
||||
- archive_source_code
|
||||
steps:
|
||||
- name: Set install name
|
||||
run: |
|
||||
echo "install_ref=${GITHUB_REF##*/}" >> "$GITHUB_ENV"
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: Linux tarball
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: MOD devices tarball
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: Win32 MinGW tarball
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: Win64 MinGW tarball
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: Source code tarball
|
||||
- name: Display file information
|
||||
shell: bash
|
||||
run: ls -lR
|
||||
## Note: not using `actions/create-release@v1`
|
||||
## because it cannot update an existing release
|
||||
## see https://github.com/actions/create-release/issues/29
|
||||
- uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
with:
|
||||
tag_name: ${{env.install_ref}}
|
||||
name: Release ${{env.install_ref}}
|
||||
draft: false
|
||||
prerelease: false
|
||||
files: |
|
||||
sfizz-${{env.install_ref}}-*
|
||||
sfizz-${{env.install_ref}}.*
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
|
|
@ -1,4 +1,4 @@
|
|||
build*
|
||||
build*/*
|
||||
docs
|
||||
.vscode
|
||||
perf.data
|
||||
|
|
@ -11,7 +11,7 @@ CMakeFiles/
|
|||
cmake_install.cmake
|
||||
compile_commands.json
|
||||
*.a
|
||||
*.txt.user
|
||||
*.user*
|
||||
*.autosave
|
||||
/Doxyfile
|
||||
.DS_Store
|
||||
|
|
@ -19,21 +19,12 @@ compile_commands.json
|
|||
clients/sfizz_jack
|
||||
clients/sfzprint
|
||||
|
||||
/vst/download/
|
||||
/plugins/vst/download/
|
||||
/plugins/vst/external/vstsdk2.4/
|
||||
/plugins/vst/external/CoreAudioUtilityClasses/
|
||||
|
||||
/editor/external/fluentui-system-icons/
|
||||
/plugins/editor/external/fluentui-system-icons/
|
||||
|
||||
# gh-pages unstaged files:
|
||||
_api/
|
||||
_site/
|
||||
.bundle/
|
||||
api/
|
||||
assets/
|
||||
node_modules/
|
||||
.jekyll-cache
|
||||
.jekyll-metadata
|
||||
.sass-cache
|
||||
*.lock
|
||||
*.sublime-*
|
||||
*.code-*
|
||||
.kak.tags.namecache
|
||||
|
|
|
|||
35
.gitmodules
vendored
35
.gitmodules
vendored
|
|
@ -4,18 +4,41 @@
|
|||
branch = lts_2020_02_25
|
||||
shallow = true
|
||||
[submodule "vst/external/VST_SDK/VST3_SDK/base"]
|
||||
path = vst/external/VST_SDK/VST3_SDK/base
|
||||
path = plugins/vst/external/VST_SDK/VST3_SDK/base
|
||||
url = https://github.com/steinbergmedia/vst3_base.git
|
||||
shallow = true
|
||||
[submodule "vst/external/VST_SDK/VST3_SDK/pluginterfaces"]
|
||||
path = vst/external/VST_SDK/VST3_SDK/pluginterfaces
|
||||
url = https://github.com/sfztools/vst3_pluginterfaces.git
|
||||
path = plugins/vst/external/VST_SDK/VST3_SDK/pluginterfaces
|
||||
url = https://github.com/steinbergmedia/vst3_pluginterfaces.git
|
||||
shallow = true
|
||||
[submodule "vst/external/VST_SDK/VST3_SDK/public.sdk"]
|
||||
path = vst/external/VST_SDK/VST3_SDK/public.sdk
|
||||
url = https://github.com/sfztools/vst3_public_sdk.git
|
||||
path = plugins/vst/external/VST_SDK/VST3_SDK/public.sdk
|
||||
url = https://github.com/steinbergmedia/vst3_public_sdk.git
|
||||
shallow = true
|
||||
[submodule "vst/external/VST_SDK/VST3_SDK/vstgui4"]
|
||||
path = editor/external/vstgui4
|
||||
path = plugins/editor/external/vstgui4
|
||||
url = https://github.com/sfztools/vstgui.git
|
||||
shallow = true
|
||||
[submodule "external/st_audiofile/thirdparty/dr_libs"]
|
||||
path = external/st_audiofile/thirdparty/dr_libs
|
||||
url = https://github.com/mackron/dr_libs.git
|
||||
shallow = true
|
||||
[submodule "external/st_audiofile/thirdparty/stb_vorbis"]
|
||||
path = external/st_audiofile/thirdparty/stb_vorbis
|
||||
url = https://github.com/sfztools/stb_vorbis.git
|
||||
shallow = true
|
||||
[submodule "external/st_audiofile/thirdparty/libaiff"]
|
||||
path = external/st_audiofile/thirdparty/libaiff
|
||||
url = https://github.com/sfztools/libaiff.git
|
||||
shallow = true
|
||||
[submodule "vst/external/sfzt_auwrapper"]
|
||||
path = plugins/vst/external/sfzt_auwrapper
|
||||
url = https://github.com/sfztools/sfzt_auwrapper.git
|
||||
shallow = true
|
||||
[submodule "external/filesystem"]
|
||||
path = external/filesystem
|
||||
url = https://github.com/gulrak/filesystem.git
|
||||
shallow = true
|
||||
[submodule "external/simde"]
|
||||
path = external/simde
|
||||
url = https://github.com/simd-everywhere/simde.git
|
||||
|
|
|
|||
146
.travis.yml
146
.travis.yml
|
|
@ -8,29 +8,7 @@ cache:
|
|||
|
||||
jobs:
|
||||
include:
|
||||
- name: "clang-tidy checks"
|
||||
stage: "Tests"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-tidy
|
||||
- wget
|
||||
- unzip
|
||||
- libsndfile-dev
|
||||
install: .travis/download_vst_sdk.sh
|
||||
script: scripts/run_clang_tidy.sh
|
||||
|
||||
- name: "Linux amd64 tests"
|
||||
arch: amd64
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libjack-jackd2-dev
|
||||
- libsndfile1-dev
|
||||
install: .travis/download_cmake.sh
|
||||
script: .travis/script_test.sh
|
||||
|
||||
- name: "Linux arm64 tests"
|
||||
- name: "Linux arm64 test and build"
|
||||
arch: arm64-graviton2
|
||||
group: edge
|
||||
virt: lxd
|
||||
|
|
@ -39,82 +17,17 @@ jobs:
|
|||
packages:
|
||||
- libjack-jackd2-dev
|
||||
- libsndfile1-dev
|
||||
- libcairo2-dev
|
||||
- libfontconfig1-dev
|
||||
- libx11-xcb-dev
|
||||
- libxcb-util-dev
|
||||
- libxcb-cursor-dev
|
||||
- libxcb-xkb-dev
|
||||
- libxkbcommon-dev
|
||||
- libxkbcommon-x11-dev
|
||||
- libxcb-keysyms1-dev
|
||||
install: .travis/download_cmake.sh
|
||||
script: .travis/script_test.sh
|
||||
|
||||
- name: "macOS"
|
||||
stage: "Build"
|
||||
os: osx
|
||||
osx_image: xcode11.3
|
||||
addons:
|
||||
homebrew:
|
||||
packages:
|
||||
- cmake
|
||||
- libsndfile
|
||||
- jack
|
||||
- dylibbundler
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
script: .travis/script_osx.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "MOD devices arm"
|
||||
env:
|
||||
- CONTAINER=jpcima/mod-plugin-builder
|
||||
- CROSS_COMPILE=moddevices-arm
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-moddevices"
|
||||
before_install: .travis/before_install_moddevices.sh
|
||||
install: .travis/install_moddevices.sh
|
||||
script: .travis/script_moddevices.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "Windows mingw32"
|
||||
env:
|
||||
- CROSS_COMPILE=mingw32
|
||||
- CONTAINER=archlinux
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-mingw32"
|
||||
before_install: .travis/before_install_mingw.sh
|
||||
install: .travis/install_mingw.sh
|
||||
script: .travis/script_mingw.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "Windows mingw64"
|
||||
env:
|
||||
- CROSS_COMPILE=mingw64
|
||||
- CONTAINER=archlinux
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-mingw64"
|
||||
before_install: .travis/before_install_mingw.sh
|
||||
install: .travis/install_mingw.sh
|
||||
script: .travis/script_mingw.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "Linux amd64 library"
|
||||
arch: amd64
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libjack-jackd2-dev
|
||||
- libsndfile1-dev
|
||||
install: .travis/download_cmake.sh
|
||||
script: .travis/script_library.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "Linux arm64 library"
|
||||
arch: arm64-graviton2
|
||||
group: edge
|
||||
virt: lxd
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libjack-jackd2-dev
|
||||
- libsndfile1-dev
|
||||
install: .travis/download_cmake.sh
|
||||
script: .travis/script_library.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
script: .travis/script_test_and_build.sh
|
||||
|
||||
- name: "Linux arm64 static plugins"
|
||||
arch: arm64-graviton2
|
||||
|
|
@ -135,43 +48,6 @@ jobs:
|
|||
script: .travis/script_plugins.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "Linux amd64 static plugins"
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-plugins-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
- ENABLE_VST_PLUGIN=ON
|
||||
- ENABLE_LV2_UI=ON
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libjack-jackd2-dev
|
||||
- libsndfile1-dev
|
||||
- libcairo2-dev
|
||||
- libfontconfig1-dev
|
||||
- libx11-xcb-dev
|
||||
- libxcb-util-dev
|
||||
- libxcb-cursor-dev
|
||||
- libxcb-xkb-dev
|
||||
- libxkbcommon-dev
|
||||
- libxkbcommon-x11-dev
|
||||
- libxcb-keysyms1-dev
|
||||
install:
|
||||
- .travis/download_cmake.sh
|
||||
- .travis/download_static_libs.sh
|
||||
script: .travis/script_plugins.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- stage: "Deploy"
|
||||
name: "Source packaging"
|
||||
if: (tag =~ /^v?[0-9]/) AND (type = push)
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-src"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python-pip
|
||||
install: sudo pip install git-archive-all
|
||||
script: git-archive-all --prefix="sfizz-${TRAVIS_BRANCH}/" -9 "${INSTALL_DIR}.tar.gz"
|
||||
|
||||
- name: "Discord Webhook"
|
||||
install: skip
|
||||
script: bash ${TRAVIS_BUILD_DIR}/.travis/discord_webhook.sh success
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
. .travis/docker_container.sh
|
||||
|
||||
buildenv bash -c "echo Hello from container" # ensure to start the container
|
||||
docker cp "$container":/etc/pacman.conf pacman.conf
|
||||
cat >>pacman.conf <<EOF
|
||||
[multilib]
|
||||
Include = /etc/pacman.d/mirrorlist
|
||||
|
||||
[mingw-w64]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = https://github.com/jpcima/arch-mingw-w64/releases/download/repo.\$arch/
|
||||
EOF
|
||||
docker cp pacman.conf "$container":/etc/pacman.conf
|
||||
rm -f pacman.conf
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
. .travis/docker_container.sh
|
||||
|
||||
buildenv bash -c "echo Hello from container" # ensure to start the container
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ -z "$CONTAINER" ]; then
|
||||
echo "The variable CONTAINER is not set."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
buildenv() {
|
||||
setup_container "$CONTAINER"
|
||||
docker exec -w "$(pwd)" -u "$(id -u)" -i -t "$container" "$@"
|
||||
}
|
||||
|
||||
buildenv_as_root() {
|
||||
setup_container "$CONTAINER"
|
||||
docker exec -w "$(pwd)" -u 0 -i -t "$container" "$@"
|
||||
}
|
||||
|
||||
setup_container() {
|
||||
if [ -f ${TRAVIS_BUILD_DIR}/docker-container-id ]; then
|
||||
container=$(cat ${TRAVIS_BUILD_DIR}/docker-container-id)
|
||||
else
|
||||
container=$(docker run -d -i -t -v /home/travis:/home/travis "$1" /bin/bash)
|
||||
echo "$container" > ${TRAVIS_BUILD_DIR}/docker-container-id
|
||||
fi
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
vst_download_prefix="vst/download"
|
||||
vst_sdk_archive="vst-sdk_3.6.14_build-24_2019-11-29.zip"
|
||||
mkdir -p ${vst_download_prefix}
|
||||
if ! [[ -f "${vst_download_prefix}/${vst_sdk_archive}" ]]; then
|
||||
wget -P ${vst_download_prefix} "https://download.steinberg.net/sdk_downloads/${vst_sdk_archive}"
|
||||
fi
|
||||
mkdir -p vst/external
|
||||
unzip -ouq "${vst_download_prefix}/${vst_sdk_archive}" -d "vst/external"
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
. .travis/docker_container.sh
|
||||
|
||||
buildenv_as_root pacman -Sqyu --noconfirm
|
||||
buildenv_as_root pacman -Sq --noconfirm base-devel wget mingw-w64-cmake mingw-w64-gcc mingw-w64-pkg-config mingw-w64-libsndfile
|
||||
buildenv i686-w64-mingw32-gcc -v && buildenv i686-w64-mingw32-g++ -v && buildenv i686-w64-mingw32-cmake --version
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
. .travis/docker_container.sh
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
buildenv() {
|
||||
"$@"
|
||||
}
|
||||
|
|
@ -2,18 +2,12 @@
|
|||
|
||||
set -ex
|
||||
|
||||
if ! [ -z "$CONTAINER" ]; then
|
||||
. .travis/docker_container.sh
|
||||
else
|
||||
. .travis/no_container.sh
|
||||
fi
|
||||
|
||||
cd build
|
||||
buildenv make DESTDIR=${PWD}/${INSTALL_DIR} install
|
||||
make DESTDIR=${PWD}/${INSTALL_DIR} install
|
||||
tar -zcvf "${INSTALL_DIR}.tar.gz" ${INSTALL_DIR}
|
||||
|
||||
# Only release a tarball if there is a tag
|
||||
if [[ ${TRAVIS_TAG} != "" ]]; then
|
||||
if [[ ${TRAVIS_TAG} != "" ]] && [[ ${DEPLOY_BUILD} ]]; then
|
||||
mv "${INSTALL_DIR}.tar.gz" ${TRAVIS_BUILD_DIR}
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
. .travis/docker_container.sh
|
||||
|
||||
mkdir -p build/${INSTALL_DIR} && cd build
|
||||
if [[ ${CROSS_COMPILE} == "mingw32" ]]; then
|
||||
buildenv i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DENABLE_LTO=OFF \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
buildenv make -j2
|
||||
elif [[ ${CROSS_COMPILE} == "mingw64" ]]; then
|
||||
buildenv x86_64-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DENABLE_LTO=OFF \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
buildenv make -j2
|
||||
fi
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
. .travis/docker_container.sh
|
||||
|
||||
mkdir -p build/${INSTALL_DIR} && cd build
|
||||
|
||||
buildenv mod-plugin-builder /usr/local/bin/cmake \
|
||||
-DSFIZZ_SYSTEM_PROCESSOR=armv7-a \
|
||||
-DCMAKE_BUILD_TYPE=Release -DSFIZZ_JACK=OFF -DSFIZZ_LV2_UI=OFF ..
|
||||
buildenv mod-plugin-builder make -j2
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
mkdir -p build/${INSTALL_DIR} && cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_AU=ON \
|
||||
-DSFIZZ_TESTS=OFF \
|
||||
-DCMAKE_CXX_STANDARD=14 \
|
||||
-DLV2PLUGIN_INSTALL_DIR=/Library/Audio/Plug-Ins/LV2 \
|
||||
-DVSTPLUGIN_INSTALL_DIR=/Library/Audio/Plug-Ins/VST3 \
|
||||
-DAUPLUGIN_INSTALL_DIR=/Library/Audio/Plug-Ins/Components \
|
||||
..
|
||||
make -j$(sysctl -n hw.ncpu)
|
||||
# Xcode not currently supported, see https://gitlab.kitware.com/cmake/cmake/issues/18088
|
||||
# xcodebuild -project sfizz.xcodeproj -alltargets -configuration Debug build
|
||||
|
|
@ -3,12 +3,19 @@ set -ex
|
|||
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_JACK=ON \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_LV2_UI=ON \
|
||||
-DSFIZZ_TESTS=ON \
|
||||
-DSFIZZ_SHARED=OFF \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=OFF \
|
||||
-DSFIZZ_LV2=OFF \
|
||||
-DSFIZZ_LV2=ON \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
make -j2 sfizz_tests
|
||||
tests/sfizz_tests
|
||||
make -j2 sfizz_jack
|
||||
make -j2 sfizz_render
|
||||
make -j2 sfizz_lv2
|
||||
make -j2 sfizz_lv2_ui
|
||||
make -j2 sfizz_vst3
|
||||
|
|
@ -10,3 +10,4 @@ Contributors to `sfizz`, in chronologic order:
|
|||
- Tobiasz "unfa" Karoń (2020)
|
||||
- Kinwie (2020)
|
||||
- Atsushi Eno (2020)
|
||||
- Dominique Würtz (2021)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
project (sfizz VERSION 0.5.1 LANGUAGES CXX C)
|
||||
project (sfizz VERSION 1.0.0 LANGUAGES CXX C)
|
||||
set (PROJECT_DESCRIPTION "A library to load SFZ description files and use them to render music.")
|
||||
|
||||
# External configuration CMake scripts
|
||||
|
|
@ -16,24 +16,36 @@ set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
|||
include (BuildType)
|
||||
|
||||
# Build Options
|
||||
include (OptionEx)
|
||||
|
||||
set (BUILD_TESTING OFF CACHE BOOL "Disable Abseil's tests [default: OFF]")
|
||||
|
||||
option (ENABLE_LTO "Enable Link Time Optimization [default: ON]" ON)
|
||||
option (SFIZZ_JACK "Enable JACK stand-alone build [default: ON]" ON)
|
||||
option (SFIZZ_RENDER "Enable renderer of SMF files [default: ON]" ON)
|
||||
option (SFIZZ_LV2 "Enable LV2 plug-in build [default: ON]" ON)
|
||||
option (SFIZZ_LV2_UI "Enable LV2 plug-in user interface [default: ON]" ON)
|
||||
option (SFIZZ_VST "Enable VST plug-in build [default: OFF]" OFF)
|
||||
option (SFIZZ_AU "Enable AU plug-in build [default: OFF]" OFF)
|
||||
option (SFIZZ_BENCHMARKS "Enable benchmarks build [default: OFF]" OFF)
|
||||
option (SFIZZ_TESTS "Enable tests build [default: OFF]" OFF)
|
||||
option (SFIZZ_DEVTOOLS "Enable developer tools build [default: OFF]" OFF)
|
||||
option (SFIZZ_SHARED "Enable shared library build [default: ON]" ON)
|
||||
option (SFIZZ_USE_VCPKG "Assume that sfizz is build using vcpkg [default: OFF]" OFF)
|
||||
option (SFIZZ_STATIC_DEPENDENCIES "Link dependencies statically [default: OFF]" OFF)
|
||||
option (SFIZZ_RELEASE_ASSERTS "Forced assertions in release builds [default: OFF]" OFF)
|
||||
option_ex (ENABLE_LTO "Enable Link Time Optimization" ON)
|
||||
option_ex (SFIZZ_JACK "Enable JACK stand-alone build" CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
option_ex (SFIZZ_RENDER "Enable renderer of SMF files" ON)
|
||||
option_ex (SFIZZ_LV2 "Enable LV2 plug-in build" ON)
|
||||
option_ex (SFIZZ_LV2_UI "Enable LV2 plug-in user interface" ON)
|
||||
option_ex (SFIZZ_VST "Enable VST plug-in build" ON)
|
||||
option_ex (SFIZZ_AU "Enable AU plug-in build" APPLE)
|
||||
option_ex (SFIZZ_VST2 "Enable VST2 plug-in build (unsupported)" OFF)
|
||||
option_ex (SFIZZ_BENCHMARKS "Enable benchmarks build" OFF)
|
||||
option_ex (SFIZZ_TESTS "Enable tests build" OFF)
|
||||
option_ex (SFIZZ_DEMOS "Enable feature demos build" OFF)
|
||||
option_ex (SFIZZ_DEVTOOLS "Enable developer tools build" OFF)
|
||||
option_ex (SFIZZ_SHARED "Enable shared library build" ON)
|
||||
option_ex (SFIZZ_USE_SNDFILE "Enable use of the sndfile library" OFF)
|
||||
option_ex (SFIZZ_USE_VCPKG "Assume that sfizz is build using vcpkg" OFF)
|
||||
option_ex (SFIZZ_USE_SYSTEM_ABSEIL "Use Abseil libraries preinstalled on system" OFF)
|
||||
option_ex (SFIZZ_USE_SYSTEM_SIMDE "Use SIMDe libraries preinstalled on system" OFF)
|
||||
option_ex (SFIZZ_STATIC_DEPENDENCIES "Link dependencies statically" OFF)
|
||||
option_ex (SFIZZ_RELEASE_ASSERTS "Forced assertions in release builds" OFF)
|
||||
|
||||
# The fixed number of controller parameters
|
||||
set(SFIZZ_NUM_CCS 512)
|
||||
|
||||
include (SfizzConfig)
|
||||
include (SfizzDeps)
|
||||
include (SfizzFaust)
|
||||
|
||||
# Don't use IPO in non Release builds
|
||||
include (CheckIPO)
|
||||
|
|
@ -41,39 +53,26 @@ include (CheckIPO)
|
|||
# Dylib bunder for macOS
|
||||
include (BundleDylibs)
|
||||
|
||||
# Add Abseil
|
||||
add_subdirectory (external/abseil-cpp EXCLUDE_FROM_ALL)
|
||||
|
||||
# Add the static library targets and sources
|
||||
add_subdirectory (src)
|
||||
|
||||
# Optional targets
|
||||
add_subdirectory (clients)
|
||||
|
||||
if ((SFIZZ_LV2 AND SFIZZ_LV2_UI) OR SFIZZ_VST)
|
||||
add_subdirectory (editor)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_LV2)
|
||||
add_subdirectory (lv2)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_VST)
|
||||
add_subdirectory (vst)
|
||||
else()
|
||||
if (SFIZZ_AU)
|
||||
message(WARNING "Audio Unit requires VST to be enabled")
|
||||
endif()
|
||||
endif()
|
||||
add_subdirectory (plugins)
|
||||
|
||||
if (SFIZZ_BENCHMARKS)
|
||||
add_subdirectory (benchmarks)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_TESTS)
|
||||
enable_testing ()
|
||||
add_subdirectory (tests)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_DEMOS)
|
||||
add_subdirectory (demos)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_DEVTOOLS)
|
||||
add_subdirectory (devtools)
|
||||
endif()
|
||||
|
|
|
|||
28
README.md
28
README.md
|
|
@ -37,27 +37,51 @@ We invite you to check out the [GOVERNANCE](GOVERNANCE.md) file to see how the o
|
|||
## Dependencies and licenses
|
||||
|
||||
The sfizz library makes primary use of:
|
||||
|
||||
- [libsndfile], licensed under the GNU Lesser General Public License v2.1
|
||||
- [Abseil], licensed under the Apache License 2.0
|
||||
- [atomic_queue] by Maxim Egorushkin, licensed under the MIT license
|
||||
- [filesystem] by Steffen Schümann, licensed under the BSD 3-Clause license
|
||||
- [hiir] by Laurent de Soras, licensed under the WTFPL v2 license
|
||||
- [KISS FFT] by Mark Borgerding, licensed under the BSD 3-Clause license
|
||||
- [Surge tuning] by Paul Walker, licensed under the MIT license
|
||||
- [pugixml] by Arseny Kapoulkine, licensed under the MIT license
|
||||
- [cephes] by Stephen Moshier, licensed under the BSD 3-Clause license
|
||||
- [cpuid] by Steinwurf ApS, licensed under the BSD 3-Clause license
|
||||
- [faust-libraries] by GRAME, Julius O. Smith III and Eric Tarr, licensed under the STK-4.3 license and a permissive variant of the LGPL license
|
||||
|
||||
The sfizz library also uses in some subprojects:
|
||||
|
||||
- [Catch2], licensed under the Boost Software License 1.0
|
||||
- [benchmark], licensed under the Apache License 2.0
|
||||
- [LV2], licensed under the ISC license
|
||||
- [JACK], licensed under the GNU Lesser General Public License v2.1
|
||||
- [cxxopts] by Jarryd Beck, licensed under the MIT license
|
||||
- [fmidi] by Jean Pierre Cimalando, licensed under the Boost Software License 1.0
|
||||
- [libsamplerate], licensed under the BSD 2-Clause license
|
||||
- [GLSL-Color-Spaces] by tobspr, licensed under the MIT license
|
||||
- [stb_image] by Sean Barrett, licensed as public domain or MIT license
|
||||
|
||||
[Abseil]: https://github.com/abseil/abseil-cpp
|
||||
[Abseil]: https://abseil.io/
|
||||
[atomic_queue]: https://github.com/max0x7ba/atomic_queue
|
||||
[benchmark]: https://github.com/google/benchmark
|
||||
[Catch2]: https://github.com/catchorg/Catch2
|
||||
[filesystem]: https://github.com/gulrak/filesystem
|
||||
[Surge tuning]: https://surge-synth-team.org/tuning-library/
|
||||
[pugixml]: https://pugixml.org/
|
||||
[cephes]: https://www.netlib.org/cephes/
|
||||
[cpuid]: https://github.com/steinwurf/cpuid
|
||||
[faust-libraries]: https://github.com/grame-cncm/faustlibraries
|
||||
[hiir]: http://ldesoras.free.fr/prod.html#src_hiir
|
||||
[KISS FFT]: http://kissfft.sourceforge.net/
|
||||
[JACK]: https://github.com/jackaudio/jack2
|
||||
[libsndfile]: https://github.com/erikd/libsndfile/
|
||||
[cxxopts]: https://github.com/jarro2783/cxxopts
|
||||
[fmidi]: https://github.com/jpcima/fmidi
|
||||
[libsamplerate]: http://www.mega-nerd.com/SRC/
|
||||
[libsndfile]: http://www.mega-nerd.com/libsndfile/
|
||||
[LV2]: https://lv2plug.in/
|
||||
[GLSL-Color-Spaces]: https://github.com/tobspr/GLSL-Color-Spaces
|
||||
[stb_image]: https://github.com/nothings/stb
|
||||
[our website]: https://sfz.tools/sfizz
|
||||
[releases]: https://github.com/sfztools/sfizz/releases
|
||||
[Carla]: https://kx.studio/Applications:Carla
|
||||
|
|
|
|||
53
appveyor.yml
53
appveyor.yml
|
|
@ -1,53 +0,0 @@
|
|||
version: build-{build}
|
||||
image: Visual Studio 2019
|
||||
configuration: Release
|
||||
platform:
|
||||
- Win32
|
||||
- x64
|
||||
cache:
|
||||
- c:\tools\vcpkg\installed\ -> appveyor.yml
|
||||
|
||||
install:
|
||||
- cmd: choco install -y innosetup
|
||||
- cmd: set PATH=C:\Program Files (x86)\Inno Setup 6;%PATH%
|
||||
- cmd: if %platform%==Win32 set VCPKG_TRIPLET=x86-windows-static
|
||||
- cmd: if %platform%==x64 set VCPKG_TRIPLET=x64-windows-static
|
||||
# - cmd: cd c:\tools\vcpkg\
|
||||
# - cmd: git pull
|
||||
# - cmd: .\bootstrap-vcpkg.bat
|
||||
# - cmd: cd %APPVEYOR_BUILD_FOLDER%
|
||||
- cmd: vcpkg install libsndfile:%VCPKG_TRIPLET%
|
||||
|
||||
before_build:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- cmd: mkdir CMakeBuild
|
||||
- cmd: cd CMakeBuild
|
||||
- cmd: cmake .. -G"Visual Studio 16 2019" -A"%platform%" -DSFIZZ_JACK=OFF -DSFIZZ_BENCHMARKS=OFF -DSFIZZ_TESTS=OFF -DSFIZZ_LV2=ON -DSFIZZ_VST=ON -DCMAKE_BUILD_TYPE=Release -DVCPKG_TARGET_TRIPLET=%VCPKG_TRIPLET% -DCMAKE_TOOLCHAIN_FILE=C:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
|
||||
build_script:
|
||||
- cmd: cmake --build . --config Release -j
|
||||
|
||||
after_build:
|
||||
- cmd: if %platform%==Win32 set RELEASE_ARCH=x86
|
||||
- cmd: if %platform%==x64 set RELEASE_ARCH=x64
|
||||
- cmd: 7z a sfizz-lv2-%APPVEYOR_REPO_TAG_NAME%-%RELEASE_ARCH%-msvc.zip sfizz.lv2
|
||||
- cmd: 7z a sfizz-vst3-%APPVEYOR_REPO_TAG_NAME%-%RELEASE_ARCH%-msvc.zip sfizz.vst3
|
||||
- cmd: 7z a sfizz-lib-%APPVEYOR_REPO_TAG_NAME%-%RELEASE_ARCH%-msvc.zip src/Release/sfizz*
|
||||
- cmd: iscc.exe /dARCH=%RELEASE_ARCH% innosetup.iss
|
||||
|
||||
artifacts:
|
||||
- name: Packages
|
||||
path: 'CMakeBuild/sfizz-*-msvc*'
|
||||
|
||||
# Deploy to GitHub Releases
|
||||
# See https://www.appveyor.com/docs/deployment/github/
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
auth_token:
|
||||
secure: xOugGAynvnZdc0DXaL3rlgMf4CICFLkdO8JxoRfLQMKJhkj/kZ4d8h7NCFneDzXG
|
||||
artifact: Packages
|
||||
draft: false
|
||||
prerelease: false
|
||||
force_update: true
|
||||
on:
|
||||
appveyor_repo_tag: true
|
||||
|
|
@ -35,24 +35,11 @@ public:
|
|||
}
|
||||
|
||||
sfz::MidiState midiState;
|
||||
sfz::Region region{0, midiState};
|
||||
sfz::ADSREnvelope<float> envelope;
|
||||
sfz::Region region{0};
|
||||
sfz::ADSREnvelope envelope;
|
||||
std::vector<float> output;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(EnvelopeFixture, Scalar)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
envelope.reset(region.amplitudeEG, region, midiState, 0, 0, sampleRate);
|
||||
envelope.startRelease(releaseTime);
|
||||
for (int offset = 0; offset < envelopeSize; offset += static_cast<int>(state.range(0)))
|
||||
for (auto& out: output)
|
||||
out = envelope.getNextValue();
|
||||
benchmark::DoNotOptimize(output);
|
||||
}
|
||||
state.counters["Blocks"] = benchmark::Counter(envelopeSize / static_cast<double>(state.range(0)), benchmark::Counter::kIsIterationInvariantRate);
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(EnvelopeFixture, Block)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
|
|
@ -66,6 +53,5 @@ BENCHMARK_DEFINE_F(EnvelopeFixture, Block)(benchmark::State& state)
|
|||
state.counters["Blocks"] = benchmark::Counter(envelopeSize / static_cast<double>(state.range(0)), benchmark::Counter::kIsIterationInvariantRate);
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(EnvelopeFixture, Scalar)->RangeMultiplier(2)->Range((2 << 6), (2 << 11));
|
||||
BENCHMARK_REGISTER_F(EnvelopeFixture, Block)->RangeMultiplier(2)->Range((2 << 6), (2 << 11));
|
||||
BENCHMARK_MAIN();
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "SIMDHelpers.h"
|
||||
#include "Macros.h"
|
||||
#include "utility/Macros.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
class AddArray : public benchmark::Fixture {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "SIMDHelpers.h"
|
||||
#include "Macros.h"
|
||||
#include "utility/Macros.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
class WithinArray : public benchmark::Fixture {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ public:
|
|||
|
||||
static TemporaryFile fileWav;
|
||||
static TemporaryFile fileFlac;
|
||||
static TemporaryFile fileAiff;
|
||||
static TemporaryFile fileOgg;
|
||||
|
||||
std::vector<float> workBuffer;
|
||||
|
|
@ -101,6 +102,7 @@ public:
|
|||
|
||||
TemporaryFile AudioReaderFixture::fileWav = createAudioFile(SF_FORMAT_WAV|SF_FORMAT_PCM_16);
|
||||
TemporaryFile AudioReaderFixture::fileFlac = createAudioFile(SF_FORMAT_FLAC|SF_FORMAT_PCM_16);
|
||||
TemporaryFile AudioReaderFixture::fileAiff = createAudioFile(SF_FORMAT_AIFF|SF_FORMAT_PCM_16);
|
||||
TemporaryFile AudioReaderFixture::fileOgg = createAudioFile(SF_FORMAT_OGG|SF_FORMAT_VORBIS);
|
||||
|
||||
TemporaryFile AudioReaderFixture::createAudioFile(int format)
|
||||
|
|
@ -146,16 +148,12 @@ static void doReaderBenchmark(const fs::path& path, std::vector<float> &buffer,
|
|||
|
||||
static void doEntireRead(const fs::path& path)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
SndfileHandle handle(path.c_str());
|
||||
#else
|
||||
SndfileHandle handle(path.wstring().c_str());
|
||||
#endif
|
||||
if (handle.error())
|
||||
throw std::runtime_error("cannot open sound file for reading");
|
||||
sfz::AudioReaderPtr reader = sfz::createAudioReader(path, false);
|
||||
if (!reader)
|
||||
return;
|
||||
|
||||
std::vector<float> buffer(static_cast<size_t>(2 * handle.frames()));
|
||||
handle.read(buffer.data(), buffer.size());
|
||||
std::vector<float> buffer(static_cast<size_t>(2 * reader->frames()));
|
||||
reader->readNextBlock(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, EntireWav)(benchmark::State& state)
|
||||
|
|
@ -200,6 +198,27 @@ BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseFlac)(benchmark::State& state)
|
|||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, EntireAiff)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doEntireRead(fileAiff.path());
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ForwardAiff)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileAiff.path(), workBuffer, sfz::AudioReaderType::Forward);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseAiff)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileAiff.path(), workBuffer, sfz::AudioReaderType::Reverse);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, EntireOgg)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
|
|
@ -214,12 +233,14 @@ BENCHMARK_DEFINE_F(AudioReaderFixture, ForwardOgg)(benchmark::State& state)
|
|||
}
|
||||
}
|
||||
|
||||
//BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseOgg)(benchmark::State& state)
|
||||
//{
|
||||
// for (auto _ : state) {
|
||||
// doReaderBenchmark(fileOgg.path(), workBuffer, sfz::AudioReaderType::Reverse);
|
||||
// }
|
||||
//}
|
||||
#if !defined(ST_AUDIO_FILE_USE_SNDFILE)
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseOgg)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileOgg.path(), workBuffer, sfz::AudioReaderType::Reverse);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ForwardWav)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseWav)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
|
|
@ -227,7 +248,12 @@ BENCHMARK_REGISTER_F(AudioReaderFixture, EntireWav)->Range(1, 1);
|
|||
BENCHMARK_REGISTER_F(AudioReaderFixture, ForwardFlac)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseFlac)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, EntireFlac)->Range(1, 1);
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ForwardAiff)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseAiff)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, EntireAiff)->Range(1, 1);
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ForwardOgg)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
//BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseOgg)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
#if !defined(ST_AUDIO_FILE_USE_SNDFILE)
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseOgg)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
#endif
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, EntireOgg)->Range(1, 1);
|
||||
BENCHMARK_MAIN();
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "SIMDHelpers.h"
|
||||
#include "Macros.h"
|
||||
#include "utility/Macros.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
class ClampArray : public benchmark::Fixture {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@
|
|||
|
||||
class Interpolators : public benchmark::Fixture {
|
||||
public:
|
||||
Interpolators()
|
||||
{
|
||||
sfz::initializeInterpolators();
|
||||
}
|
||||
|
||||
void SetUp(const ::benchmark::State& state)
|
||||
{
|
||||
std::random_device rd { };
|
||||
|
|
@ -55,33 +60,27 @@ static void doInterpolation(absl::Span<const float> input, absl::Span<float> out
|
|||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(Interpolators, Linear)(benchmark::State& state)
|
||||
{
|
||||
ScopedFTZ ftz;
|
||||
#define ADD_INTERPOLATOR_BENCHMARK(Type) \
|
||||
BENCHMARK_DEFINE_F(Interpolators, Type)(benchmark::State& state) \
|
||||
{ \
|
||||
ScopedFTZ ftz; \
|
||||
for (auto _ : state) { \
|
||||
absl::Span<float> span = absl::MakeSpan(output); \
|
||||
doInterpolation<sfz::kInterpolator##Type>(input, span); \
|
||||
} \
|
||||
} \
|
||||
BENCHMARK_REGISTER_F(Interpolators, Type) \
|
||||
->RangeMultiplier(4)->Range(1 << 4, 1 << 12);
|
||||
|
||||
for (auto _ : state) {
|
||||
doInterpolation<sfz::kInterpolatorLinear>(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(Interpolators, Hermite3)(benchmark::State& state)
|
||||
{
|
||||
ScopedFTZ ftz;
|
||||
|
||||
for (auto _ : state) {
|
||||
doInterpolation<sfz::kInterpolatorHermite3>(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(Interpolators, Bspline3)(benchmark::State& state)
|
||||
{
|
||||
ScopedFTZ ftz;
|
||||
|
||||
for (auto _ : state) {
|
||||
doInterpolation<sfz::kInterpolatorBspline3>(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(Interpolators, Linear)->RangeMultiplier(4)->Range(1 << 4, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(Interpolators, Hermite3)->RangeMultiplier(4)->Range(1 << 4, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(Interpolators, Bspline3)->RangeMultiplier(4)->Range(1 << 4, 1 << 12);
|
||||
ADD_INTERPOLATOR_BENCHMARK(Nearest)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Linear)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Hermite3)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Bspline3)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc8)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc12)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc16)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc24)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc36)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc48)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc60)
|
||||
ADD_INTERPOLATOR_BENCHMARK(Sinc72)
|
||||
|
|
|
|||
|
|
@ -1,191 +0,0 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "SIMDHelpers.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <sndfile.hh>
|
||||
#include "ghc/filesystem.hpp"
|
||||
#include "Oversampler.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "absl/memory/memory.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
constexpr std::array<double, 12> coeffsStage2x {
|
||||
0.036681502163648017,
|
||||
0.13654762463195771,
|
||||
0.27463175937945411,
|
||||
0.42313861743656667,
|
||||
0.56109869787919475,
|
||||
0.67754004997416162,
|
||||
0.76974183386322659,
|
||||
0.83988962484963803,
|
||||
0.89226081800387891,
|
||||
0.9315419599631839,
|
||||
0.96209454837808395,
|
||||
0.98781637073289708
|
||||
};
|
||||
|
||||
constexpr std::array<double, 4> coeffsStage4x {
|
||||
0.042448989488488006,
|
||||
0.17072114107630679,
|
||||
0.39329183835224008,
|
||||
0.74569514831986694
|
||||
};
|
||||
|
||||
constexpr std::array<double, 3> coeffsStage8x {
|
||||
0.055748680811302048,
|
||||
0.24305119574153092,
|
||||
0.6466991311926823
|
||||
};
|
||||
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
#include "hiir/Upsampler2xSse.h"
|
||||
using Upsampler2x = hiir::Upsampler2xSse<coeffsStage2x.size()>;
|
||||
using Upsampler4x = hiir::Upsampler2xSse<coeffsStage4x.size()>;
|
||||
using Upsampler8x = hiir::Upsampler2xSse<coeffsStage8x.size()>;
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
#include "hiir/Upsampler2xNeon.h"
|
||||
using Upsampler2x = hiir::Upsampler2xNeon<coeffsStage2x.size()>;
|
||||
using Upsampler4x = hiir::Upsampler2xNeon<coeffsStage4x.size()>;
|
||||
using Upsampler8x = hiir::Upsampler2xNeon<coeffsStage8x.size()>;
|
||||
#else
|
||||
#include "hiir/Upsampler2xFpu.h"
|
||||
using Upsampler2x = hiir::Upsampler2xFpu<coeffsStage2x.size()>;
|
||||
using Upsampler4x = hiir::Upsampler2xFpu<coeffsStage4x.size()>;
|
||||
using Upsampler8x = hiir::Upsampler2xFpu<coeffsStage8x.size()>;
|
||||
#endif
|
||||
|
||||
|
||||
class FileFixture : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& /* state */) {
|
||||
rootPath = getPath() / "sample1.flac";
|
||||
if (!ghc::filesystem::exists(rootPath)) {
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "Can't find path" << '\n';
|
||||
#endif
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
sndfile = SndfileHandle(rootPath.c_str());
|
||||
numFrames = static_cast<size_t>(sndfile.frames());
|
||||
output = absl::make_unique<sfz::AudioBuffer<float>>(sndfile.channels(), numFrames * 4);
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */) {
|
||||
}
|
||||
|
||||
ghc::filesystem::path getPath()
|
||||
{
|
||||
#ifdef __linux__
|
||||
char buf[PATH_MAX + 1];
|
||||
if (readlink("/proc/self/exe", buf, sizeof(buf) - 1) == -1)
|
||||
return {};
|
||||
std::string str { buf };
|
||||
return str.substr(0, str.rfind('/'));
|
||||
#elif _WIN32
|
||||
return ghc::filesystem::current_path();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<sfz::AudioBuffer<float>> output;
|
||||
SndfileHandle sndfile;
|
||||
ghc::filesystem::path rootPath;
|
||||
size_t numFrames { 0 };
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(FileFixture, NoResampling)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::Buffer<float> buffer { numFrames * sndfile.channels() };
|
||||
sndfile.readf(buffer.data(), sndfile.frames());
|
||||
sfz::readInterleaved(buffer, output->getSpan(0), output->getSpan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(FileFixture, ResampleAtOnce)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::Buffer<float> buffer { numFrames * sndfile.channels() };
|
||||
sfz::Buffer<float> temp { numFrames * 4 };
|
||||
|
||||
Upsampler2x upsampler2x;
|
||||
Upsampler4x upsampler4x;
|
||||
upsampler2x.set_coefs(coeffsStage2x.data());
|
||||
upsampler4x.set_coefs(coeffsStage4x.data());
|
||||
|
||||
sndfile.readf(buffer.data(), numFrames);
|
||||
sfz::readInterleaved(buffer, output->getSpan(0), output->getSpan(1));
|
||||
|
||||
upsampler2x.process_block(temp.data(), output->channelReader(0), static_cast<long>(numFrames));
|
||||
upsampler4x.process_block(output->channelWriter(0), temp.data(), static_cast<long>(numFrames * 2));
|
||||
|
||||
upsampler2x.clear_buffers();
|
||||
upsampler4x.clear_buffers();
|
||||
|
||||
upsampler2x.process_block(temp.data(), output->channelReader(1), static_cast<long>(numFrames));
|
||||
upsampler4x.process_block(output->channelWriter(1), temp.data(), static_cast<long>(numFrames * 2));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(FileFixture, ResampleInChunks)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
auto chunkSize = static_cast<size_t>(state.range(0));
|
||||
sfz::Buffer<float> buffer { numFrames * sndfile.channels() };
|
||||
|
||||
sfz::Buffer<float> leftInput { chunkSize };
|
||||
sfz::Buffer<float> rightInput { chunkSize };
|
||||
sfz::Buffer<float> chunk { chunkSize * 2 };
|
||||
|
||||
sndfile.readf(buffer.data(), numFrames);
|
||||
|
||||
auto bufferSpan = absl::MakeSpan(buffer);
|
||||
auto leftSpan = absl::MakeSpan(leftInput);
|
||||
auto rightSpan = absl::MakeSpan(rightInput);
|
||||
auto chunkSpan = absl::MakeSpan(chunk);
|
||||
|
||||
Upsampler2x upsampler2xLeft;
|
||||
Upsampler2x upsampler2xRight;
|
||||
Upsampler4x upsampler4xLeft;
|
||||
Upsampler4x upsampler4xRight;
|
||||
upsampler2xLeft.set_coefs(coeffsStage2x.data());
|
||||
upsampler2xRight.set_coefs(coeffsStage2x.data());
|
||||
upsampler4xLeft.set_coefs(coeffsStage4x.data());
|
||||
upsampler4xRight.set_coefs(coeffsStage4x.data());
|
||||
|
||||
size_t inputFrameCounter { 0 };
|
||||
size_t outputFrameCounter { 0 };
|
||||
while(inputFrameCounter < numFrames)
|
||||
{
|
||||
// std::cout << "Input frames: " << inputFrameCounter << "/" << numFrames << '\n';
|
||||
const auto thisChunkSize = std::min(chunkSize, numFrames - inputFrameCounter);
|
||||
const auto bufferChunk = bufferSpan.subspan(
|
||||
inputFrameCounter * sndfile.channels(),
|
||||
thisChunkSize * sndfile.channels()
|
||||
);
|
||||
|
||||
sfz::readInterleaved(bufferChunk, leftSpan, rightSpan);
|
||||
|
||||
upsampler2xLeft.process_block(chunkSpan.data(), leftSpan.data(), static_cast<long>(thisChunkSize));
|
||||
upsampler4xLeft.process_block(output->channelWriter(0) + outputFrameCounter, chunkSpan.data(), static_cast<long>(thisChunkSize * 2));
|
||||
|
||||
upsampler2xRight.process_block(chunkSpan.data(), rightSpan.data(), static_cast<long>(thisChunkSize));
|
||||
upsampler4xRight.process_block(output->channelWriter(1) + outputFrameCounter, chunkSpan.data(), static_cast<long>(thisChunkSize * 2));
|
||||
|
||||
inputFrameCounter += chunkSize;
|
||||
outputFrameCounter += chunkSize * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(FileFixture, NoResampling);
|
||||
BENCHMARK_REGISTER_F(FileFixture, ResampleAtOnce);
|
||||
BENCHMARK_REGISTER_F(FileFixture, ResampleInChunks)->RangeMultiplier(4)->Range((1 << 4), (1 << 16));
|
||||
BENCHMARK_MAIN();
|
||||
|
|
@ -34,24 +34,24 @@ public:
|
|||
std::vector<float> output;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(SmootherFixture, Linear) (benchmark::State& state)
|
||||
BENCHMARK_DEFINE_F(SmootherFixture, OnePole) (benchmark::State& state)
|
||||
{
|
||||
sfz::Smoother smoother;
|
||||
sfz::OnePoleSmoother smoother;
|
||||
smoother.setSmoothing(10, sfz::config::defaultSampleRate);
|
||||
for (auto _ : state) {
|
||||
smoother.process(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
// BENCHMARK_DEFINE_F(SmootherFixture, Multiplicative)(benchmark::State& state) {
|
||||
// sfz::MultiplicativeSmoother smoother;
|
||||
// smoother.setSmoothing(10, sfz::config::defaultSampleRate);
|
||||
// for (auto _ : state)
|
||||
// {
|
||||
// smoother.process(input, absl::MakeSpan(output));
|
||||
// }
|
||||
// }
|
||||
BENCHMARK_DEFINE_F(SmootherFixture, Linear) (benchmark::State& state)
|
||||
{
|
||||
sfz::LinearSmoother smoother;
|
||||
smoother.setSmoothing(10, sfz::config::defaultSampleRate);
|
||||
for (auto _ : state) {
|
||||
smoother.process(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(SmootherFixture, OnePole)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(SmootherFixture, Linear)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
// BENCHMARK_REGISTER_F(SmootherFixture, Multiplicative)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "Macros.h"
|
||||
#include "ScopedFTZ.h"
|
||||
#include "MathHelpers.h"
|
||||
#include "SIMDConfig.h"
|
||||
#include "utility/Macros.h"
|
||||
#include "effects/impl/ResonantArray.h"
|
||||
#include "effects/impl/ResonantArraySSE.h"
|
||||
#include "effects/impl/ResonantArrayAVX.h"
|
||||
|
|
|
|||
|
|
@ -1,38 +1,13 @@
|
|||
project(sfizz)
|
||||
|
||||
# Check SIMD
|
||||
include (SfizzSIMDSourceFiles)
|
||||
set(BENCHMARK_SIMD_SOURCES)
|
||||
sfizz_add_simd_sources(BENCHMARK_SIMD_SOURCES "../src")
|
||||
find_package(benchmark CONFIG REQUIRED)
|
||||
|
||||
# Check libsamplerate
|
||||
find_library(SAMPLERATE_LIBRARY "samplerate")
|
||||
find_path(SAMPLERATE_INCLUDE_DIR "samplerate.h")
|
||||
message(STATUS "Checking samplerate library: ${SAMPLERATE_LIBRARY}")
|
||||
message(STATUS "Checking samplerate includes: ${SAMPLERATE_INCLUDE_DIR}")
|
||||
if(SAMPLERATE_LIBRARY AND SAMPLERATE_INCLUDE_DIR)
|
||||
add_library(sfizz-samplerate INTERFACE)
|
||||
target_include_directories(sfizz-samplerate INTERFACE "${SAMPLERATE_INCLUDE_DIR}")
|
||||
target_link_libraries(sfizz-samplerate INTERFACE "${SAMPLERATE_LIBRARY}")
|
||||
endif()
|
||||
|
||||
add_library(bm_simd STATIC ${BENCHMARK_SIMD_SOURCES})
|
||||
target_link_libraries(bm_simd PRIVATE absl::span sfizz-cpuid)
|
||||
target_include_directories(bm_simd PRIVATE ../src/external)
|
||||
add_library(bm_ftz STATIC ../src/sfizz/ScopedFTZ.cpp)
|
||||
|
||||
macro(sfizz_add_benchmark TARGET)
|
||||
add_executable("${TARGET}" ${ARGN})
|
||||
target_link_libraries("${TARGET}"
|
||||
PRIVATE absl::span absl::algorithm
|
||||
PRIVATE benchmark::benchmark benchmark::benchmark_main
|
||||
PRIVATE bm_simd bm_ftz)
|
||||
if (LIBATOMIC_FOUND)
|
||||
target_link_libraries ("${TARGET}" PRIVATE atomic)
|
||||
if (NOT TARGET sfizz_benchmarks)
|
||||
add_custom_target(sfizz_benchmarks)
|
||||
endif()
|
||||
target_include_directories("${TARGET}" PRIVATE ../src/sfizz ../src/external)
|
||||
sfizz_enable_fast_math("${TARGET}")
|
||||
add_executable("${TARGET}" ${ARGN})
|
||||
add_dependencies(sfizz_benchmarks "${TARGET}")
|
||||
target_link_libraries("${TARGET}"
|
||||
PRIVATE sfizz::internal sfizz::filesystem absl::span absl::algorithm
|
||||
PRIVATE benchmark::benchmark benchmark::benchmark_main)
|
||||
sfizz_enable_fast_math("${TARGET}")
|
||||
endmacro()
|
||||
|
||||
sfizz_add_benchmark(bm_opf_high_vs_low BM_OPF_high_vs_low.cpp)
|
||||
|
|
@ -44,7 +19,6 @@ sfizz_add_benchmark(bm_gain BM_gain.cpp)
|
|||
sfizz_add_benchmark(bm_divide BM_divide.cpp)
|
||||
sfizz_add_benchmark(bm_ramp BM_ramp.cpp)
|
||||
sfizz_add_benchmark(bm_ADSR BM_ADSR.cpp)
|
||||
target_link_libraries(bm_ADSR PRIVATE sfizz::sfizz)
|
||||
|
||||
sfizz_add_benchmark(bm_add BM_add.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyAdd BM_multiplyAdd.cpp)
|
||||
|
|
@ -66,91 +40,44 @@ sfizz_add_benchmark(bm_clamp BM_clamp.cpp)
|
|||
sfizz_add_benchmark(bm_allWithin BM_allWithin.cpp)
|
||||
|
||||
sfizz_add_benchmark(bm_logger BM_logger.cpp)
|
||||
target_link_libraries(bm_logger PRIVATE sfizz::sfizz)
|
||||
sfizz_add_benchmark(bm_smoothers BM_smoothers.cpp)
|
||||
target_link_libraries(bm_smoothers PRIVATE sfizz::sfizz)
|
||||
sfizz_add_benchmark(bm_powerFollower BM_powerFollower.cpp)
|
||||
target_link_libraries(bm_powerFollower PRIVATE sfizz::sfizz)
|
||||
|
||||
if (TARGET sfizz-samplerate)
|
||||
if(TARGET sfizz::samplerate)
|
||||
sfizz_add_benchmark(bm_resample BM_resample.cpp ${BENCHMARK_SIMD_SOURCES})
|
||||
target_link_libraries(bm_resample PRIVATE sfizz-samplerate sfizz-sndfile sfizz-cpuid)
|
||||
target_link_libraries(bm_resample PRIVATE sfizz::samplerate sfizz::sndfile sfizz::hiir)
|
||||
endif()
|
||||
|
||||
sfizz_add_benchmark(bm_envelopes BM_envelopes.cpp)
|
||||
|
||||
sfizz_add_benchmark(bm_wavfile BM_wavfile.cpp)
|
||||
target_link_libraries(bm_wavfile PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_wavfile PRIVATE sfizz::sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_flacfile BM_flacfile.cpp)
|
||||
target_link_libraries(bm_flacfile PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_flacfile PRIVATE sfizz::sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_audioReaders BM_audioReaders.cpp ../src/sfizz/AudioReader.cpp)
|
||||
target_link_libraries(bm_audioReaders PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_audioReaders PRIVATE st_audiofile sfizz::sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_readChunk BM_readChunk.cpp)
|
||||
target_link_libraries(bm_readChunk PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_readChunk PRIVATE sfizz::sndfile)
|
||||
sfizz_add_benchmark(bm_readChunkFlac BM_readChunkFlac.cpp)
|
||||
target_link_libraries(bm_readChunkFlac PRIVATE sfizz-sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_resampleChunk BM_resampleChunk.cpp)
|
||||
target_link_libraries(bm_resampleChunk PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_readChunkFlac PRIVATE sfizz::sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_interpolators BM_interpolators.cpp)
|
||||
|
||||
sfizz_add_benchmark(bm_filterModulation BM_filterModulation.cpp ../src/sfizz/SfzFilter.cpp)
|
||||
target_link_libraries(bm_filterModulation PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_filterModulation PRIVATE sfizz::sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_filterStereoMono BM_filterStereoMono.cpp ../src/sfizz/SfzFilter.cpp)
|
||||
target_link_libraries(bm_filterStereoMono PRIVATE sfizz-sndfile)
|
||||
target_link_libraries(bm_filterStereoMono PRIVATE sfizz::sndfile)
|
||||
|
||||
sfizz_add_benchmark(bm_stringResonator BM_stringResonator.cpp
|
||||
../src/sfizz/effects/impl/ResonantArray.cpp
|
||||
../src/sfizz/effects/impl/ResonantArraySSE.cpp
|
||||
../src/sfizz/effects/impl/ResonantArrayAVX.cpp
|
||||
../src/sfizz/effects/impl/ResonantString.cpp
|
||||
../src/sfizz/effects/impl/ResonantStringSSE.cpp
|
||||
../src/sfizz/effects/impl/ResonantStringAVX.cpp)
|
||||
target_link_libraries(bm_stringResonator PRIVATE sfizz-sndfile)
|
||||
sfizz_add_benchmark(bm_stringResonator BM_stringResonator.cpp)
|
||||
target_link_libraries(bm_stringResonator PRIVATE sfizz::sndfile)
|
||||
|
||||
add_custom_target(sfizz_benchmarks)
|
||||
add_dependencies(sfizz_benchmarks
|
||||
bm_opf_high_vs_low
|
||||
bm_write
|
||||
bm_clock
|
||||
bm_pointerIterationOrOffsets
|
||||
bm_read
|
||||
bm_mean
|
||||
bm_meanSquared
|
||||
bm_cumsum
|
||||
bm_diff
|
||||
bm_mathfuns
|
||||
bm_gain
|
||||
bm_divide
|
||||
bm_ramp
|
||||
bm_ADSR
|
||||
bm_add
|
||||
bm_logger
|
||||
bm_subtract
|
||||
bm_multiplyAdd
|
||||
bm_readChunk
|
||||
bm_resampleChunk
|
||||
bm_envelopes
|
||||
bm_wavfile
|
||||
bm_flacfile
|
||||
bm_filterModulation
|
||||
bm_filterStereoMono
|
||||
bm_stringResonator
|
||||
)
|
||||
|
||||
if (TARGET bm_resample)
|
||||
add_dependencies(sfizz_benchmarks bm_resample)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_SYSTEM_PROCESSOR MATCHES "armv7l")
|
||||
if(SFIZZ_SYSTEM_PROCESSOR MATCHES "armv7l")
|
||||
sfizz_add_benchmark(bm_pan_arm BM_pan_arm.cpp ../src/sfizz/Panning.cpp)
|
||||
target_link_libraries(bm_pan_arm PRIVATE sfizz-jsl)
|
||||
add_dependencies(sfizz_benchmarks bm_pan_arm)
|
||||
target_link_libraries(bm_pan_arm PRIVATE sfizz::jsl)
|
||||
endif()
|
||||
|
||||
configure_file("sample.wav" "${CMAKE_BINARY_DIR}/benchmarks/sample1.wav" COPYONLY)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,14 @@
|
|||
project (sfizz)
|
||||
|
||||
if (SFIZZ_JACK)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(JACK "jack" REQUIRED)
|
||||
link_directories (${JACK_LIBRARY_DIRS})
|
||||
|
||||
add_executable (sfizz_jack MidiHelpers.h jack_client.cpp)
|
||||
target_include_directories (sfizz_jack PRIVATE ${JACK_INCLUDE_DIRS})
|
||||
target_link_libraries (sfizz_jack PRIVATE sfizz::sfizz absl::flags_parse ${JACK_LIBRARIES})
|
||||
sfizz_enable_lto_if_needed (sfizz_jack)
|
||||
install (TARGETS sfizz_jack DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
if(SFIZZ_JACK)
|
||||
add_executable(sfizz_jack MidiHelpers.h jack_client.cpp)
|
||||
target_link_libraries(sfizz_jack PRIVATE sfizz::sfizz sfizz::jack sfizz::spin_mutex absl::flags_parse)
|
||||
sfizz_enable_lto_if_needed(sfizz_jack)
|
||||
install(TARGETS sfizz_jack DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT "jack" OPTIONAL)
|
||||
endif()
|
||||
|
||||
if (SFIZZ_RENDER)
|
||||
add_library(sfizz-fmidi STATIC
|
||||
"external/fmidi/sources/fmidi/fmidi.h"
|
||||
"external/fmidi/sources/fmidi/fmidi_mini.cpp")
|
||||
target_include_directories(sfizz-fmidi PUBLIC "external/fmidi/sources")
|
||||
target_compile_definitions(sfizz-fmidi PUBLIC "FMIDI_STATIC=1" "FMIDI_DISABLE_DESCRIBE_API=1")
|
||||
|
||||
if(SFIZZ_RENDER)
|
||||
add_executable(sfizz_render MidiHelpers.h sfizz_render.cpp)
|
||||
target_link_libraries(sfizz_render PRIVATE sfizz::sfizz sfizz-fmidi sfizz-sndfile)
|
||||
sfizz_enable_lto_if_needed (sfizz_render)
|
||||
install (TARGETS sfizz_render DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT "render" OPTIONAL)
|
||||
target_link_libraries(sfizz_render PRIVATE sfizz::internal sfizz::fmidi sfizz::cxxopts st_audiofile_formats)
|
||||
sfizz_enable_lto_if_needed(sfizz_render)
|
||||
install(TARGETS sfizz_render DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT "render" OPTIONAL)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <absl/flags/parse.h>
|
||||
#include <absl/flags/flag.h>
|
||||
#include <absl/types/span.h>
|
||||
#include <SpinMutex.h>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <ios>
|
||||
|
|
@ -38,11 +39,14 @@
|
|||
#include <string_view>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
|
||||
static jack_port_t* midiInputPort;
|
||||
static jack_port_t* outputPort1;
|
||||
static jack_port_t* outputPort2;
|
||||
static jack_client_t* client;
|
||||
static SpinMutex processMutex;
|
||||
|
||||
int process(jack_nframes_t numFrames, void* arg)
|
||||
{
|
||||
|
|
@ -51,6 +55,16 @@ int process(jack_nframes_t numFrames, void* arg)
|
|||
auto* buffer = jack_port_get_buffer(midiInputPort, numFrames);
|
||||
assert(buffer);
|
||||
|
||||
auto* leftOutput = reinterpret_cast<float*>(jack_port_get_buffer(outputPort1, numFrames));
|
||||
auto* rightOutput = reinterpret_cast<float*>(jack_port_get_buffer(outputPort2, numFrames));
|
||||
|
||||
std::unique_lock<SpinMutex> lock { processMutex, std::try_to_lock };
|
||||
if (!lock.owns_lock()) {
|
||||
std::fill_n(leftOutput, numFrames, 0.0f);
|
||||
std::fill_n(rightOutput, numFrames, 0.0f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto numMidiEvents = jack_midi_get_event_count(buffer);
|
||||
jack_midi_event_t event;
|
||||
|
||||
|
|
@ -64,41 +78,34 @@ int process(jack_nframes_t numFrames, void* arg)
|
|||
|
||||
switch (midi::status(event.buffer[0])) {
|
||||
case midi::noteOff: noteoff:
|
||||
// DBG("[MIDI] Note " << +event.buffer[1] << " OFF at time " << event.time);
|
||||
synth->noteOff(event.time, event.buffer[1], event.buffer[2]);
|
||||
break;
|
||||
case midi::noteOn:
|
||||
if (event.buffer[2] == 0)
|
||||
goto noteoff;
|
||||
// DBG("[MIDI] Note " << +event.buffer[1] << " ON at time " << event.time);
|
||||
synth->noteOn(event.time, event.buffer[1], event.buffer[2]);
|
||||
break;
|
||||
case midi::polyphonicPressure:
|
||||
// DBG("[MIDI] Polyphonic pressure on at time " << event.time);
|
||||
synth->polyAftertouch(event.time, event.buffer[1], event.buffer[2]);
|
||||
break;
|
||||
case midi::controlChange:
|
||||
// DBG("[MIDI] CC " << +event.buffer[1] << " at time " << event.time);
|
||||
synth->cc(event.time, event.buffer[1], event.buffer[2]);
|
||||
break;
|
||||
case midi::programChange:
|
||||
// DBG("[MIDI] Program change at time " << event.time);
|
||||
// Not implemented
|
||||
break;
|
||||
case midi::channelPressure:
|
||||
// DBG("[MIDI] Channel pressure at time " << event.time);
|
||||
synth->channelAftertouch(event.time, event.buffer[1]);
|
||||
break;
|
||||
case midi::pitchBend:
|
||||
synth->pitchWheel(event.time, midi::buildAndCenterPitch(event.buffer[1], event.buffer[2]));
|
||||
// DBG("[MIDI] Pitch bend at time " << event.time);
|
||||
break;
|
||||
case midi::systemMessage:
|
||||
// DBG("[MIDI] System message at time " << event.time);
|
||||
// Not implemented
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto* leftOutput = reinterpret_cast<float*>(jack_port_get_buffer(outputPort1, numFrames));
|
||||
auto* rightOutput = reinterpret_cast<float*>(jack_port_get_buffer(outputPort2, numFrames));
|
||||
|
||||
float* stereoOutput[] = { leftOutput, rightOutput };
|
||||
synth->renderBlock(stereoOutput, numFrames);
|
||||
|
||||
|
|
@ -112,6 +119,7 @@ int sampleBlockChanged(jack_nframes_t nframes, void* arg)
|
|||
|
||||
auto* synth = reinterpret_cast<sfz::Sfizz*>(arg);
|
||||
// DBG("Sample per block changed to " << nframes);
|
||||
std::lock_guard<SpinMutex> lock { processMutex };
|
||||
synth->setSamplesPerBlock(nframes);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -123,6 +131,7 @@ int sampleRateChanged(jack_nframes_t nframes, void* arg)
|
|||
|
||||
auto* synth = reinterpret_cast<sfz::Sfizz*>(arg);
|
||||
// DBG("Sample rate changed to " << nframes);
|
||||
std::lock_guard<SpinMutex> lock { processMutex };
|
||||
synth->setSampleRate(nframes);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
#include <sndfile.hh>
|
||||
#include "sfizz/Synth.h"
|
||||
#include "sfizz/MathHelpers.h"
|
||||
#include "sfizz/SfzHelpers.h"
|
||||
#include "sfizz/SIMDHelpers.h"
|
||||
#include "MidiHelpers.h"
|
||||
#include "cxxopts.hpp"
|
||||
#include <st_audiofile_libs.h>
|
||||
#include <cxxopts.hpp>
|
||||
#include <fmidi/fmidi.h>
|
||||
#include <iostream>
|
||||
|
||||
|
|
@ -66,7 +66,6 @@ int main(int argc, char** argv)
|
|||
bool help { false };
|
||||
bool useEOT { false };
|
||||
int quality { 2 };
|
||||
int oversampling { 1 };
|
||||
|
||||
options.add_options()
|
||||
("sfz", "SFZ file", cxxopts::value<std::string>())
|
||||
|
|
@ -74,7 +73,6 @@ int main(int argc, char** argv)
|
|||
("wav", "Output wav file", cxxopts::value<std::string>())
|
||||
("b,blocksize", "Block size for the sfizz callbacks", cxxopts::value(blockSize))
|
||||
("s,samplerate", "Output sample rate", cxxopts::value(sampleRate))
|
||||
("oversampling", "Internal oversampling factor", cxxopts::value(oversampling))
|
||||
("q,quality", "Resampling quality", cxxopts::value(quality))
|
||||
("v,verbose", "Verbose output", cxxopts::value(verbose))
|
||||
("log", "Produce logs", cxxopts::value<std::string>())
|
||||
|
|
@ -126,23 +124,6 @@ int main(int argc, char** argv)
|
|||
if (params.count("log") > 0)
|
||||
synth.enableLogging(params["log"].as<std::string>());
|
||||
|
||||
const auto osFactor = [oversampling] {
|
||||
switch (oversampling){
|
||||
case 1:
|
||||
return sfz::Oversampling::x1;
|
||||
case 2:
|
||||
return sfz::Oversampling::x2;
|
||||
case 4:
|
||||
return sfz::Oversampling::x4;
|
||||
case 5:
|
||||
return sfz::Oversampling::x8;
|
||||
default:
|
||||
LOG_ERROR("Bad oversampling factor: " << oversampling);
|
||||
std::exit(-1);
|
||||
}
|
||||
}();
|
||||
synth.setOversamplingFactor(osFactor);
|
||||
|
||||
ERROR_IF(!synth.loadSfzFile(sfzPath), "There was an error loading the SFZ file.");
|
||||
LOG_INFO(synth.getNumRegions() << " regions in the SFZ.");
|
||||
|
||||
|
|
@ -158,14 +139,27 @@ int main(int argc, char** argv)
|
|||
LOG_INFO("-- Cutting the rendering at the last MIDI End of Track message");
|
||||
}
|
||||
|
||||
SndfileHandle outputFile (outputPath.u8string(), SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 2, sampleRate);
|
||||
ERROR_IF(outputFile.error() != 0, "Error writing out the wav file: " << outputFile.strError());
|
||||
drwav outputFile;
|
||||
drwav_data_format outputFormat {};
|
||||
outputFormat.container = drwav_container_riff;
|
||||
outputFormat.format = DR_WAVE_FORMAT_PCM;
|
||||
outputFormat.channels = 2;
|
||||
outputFormat.sampleRate = sampleRate;
|
||||
outputFormat.bitsPerSample = 16;
|
||||
|
||||
#if !defined(_WIN32)
|
||||
drwav_bool32 outputFileOk = drwav_init_file_write(&outputFile, outputPath.c_str(), &outputFormat, nullptr);
|
||||
#else
|
||||
drwav_bool32 outputFileOk = drwav_init_file_write_w(&outputFile, outputPath.c_str(), &outputFormat, nullptr);
|
||||
#endif
|
||||
ERROR_IF(!outputFileOk, "Error opening the wav file for writing");
|
||||
|
||||
auto sampleRateDouble = static_cast<double>(sampleRate);
|
||||
const double increment { 1.0 / sampleRateDouble };
|
||||
int numFramesWritten { 0 };
|
||||
uint64_t numFramesWritten { 0 };
|
||||
sfz::AudioBuffer<float> audioBuffer { 2, blockSize };
|
||||
sfz::Buffer<float> interleavedBuffer { 2 * blockSize };
|
||||
sfz::Buffer<int16_t> interleavedPcm { 2 * blockSize };
|
||||
|
||||
fmidi_player_u midiPlayer { fmidi_player_new(midiFile.get()) };
|
||||
CallbackData callbackData { synth, 0, false };
|
||||
|
|
@ -178,7 +172,8 @@ int main(int argc, char** argv)
|
|||
fmidi_player_tick(midiPlayer.get(), increment);
|
||||
synth.renderBlock(audioBuffer);
|
||||
sfz::writeInterleaved(audioBuffer.getConstSpan(0), audioBuffer.getConstSpan(1), absl::MakeSpan(interleavedBuffer));
|
||||
numFramesWritten += outputFile.writef(interleavedBuffer.data(), blockSize);
|
||||
drwav_f32_to_s16(interleavedPcm.data(), interleavedBuffer.data(), 2 * blockSize);
|
||||
numFramesWritten += drwav_write_pcm_frames(&outputFile, blockSize, interleavedPcm.data());
|
||||
}
|
||||
|
||||
if (!useEOT) {
|
||||
|
|
@ -186,12 +181,13 @@ int main(int argc, char** argv)
|
|||
while (averagePower > 1e-12f) {
|
||||
synth.renderBlock(audioBuffer);
|
||||
sfz::writeInterleaved(audioBuffer.getConstSpan(0), audioBuffer.getConstSpan(1), absl::MakeSpan(interleavedBuffer));
|
||||
numFramesWritten += outputFile.writef(interleavedBuffer.data(), blockSize);
|
||||
drwav_f32_to_s16(interleavedPcm.data(), interleavedBuffer.data(), 2 * blockSize);
|
||||
numFramesWritten += drwav_write_pcm_frames(&outputFile, blockSize, interleavedPcm.data());
|
||||
averagePower = sfz::meanSquared<float>(interleavedBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
outputFile.writeSync();
|
||||
drwav_uninit(&outputFile);
|
||||
LOG_INFO("Wrote " << numFramesWritten << " frames of sound data in" << outputPath.string());
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ function(bundle_dylibs NAME PATH)
|
|||
return()
|
||||
endif()
|
||||
|
||||
set(_relative_libdir "../libs")
|
||||
set(_relative_libdir "../Frameworks")
|
||||
|
||||
get_filename_component(_dir "${PATH}" DIRECTORY)
|
||||
set(_dir "${_dir}/${_relative_libdir}")
|
||||
|
|
|
|||
|
|
@ -1,37 +1,37 @@
|
|||
# Added in CMake 3.9
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS 3.9)
|
||||
message (WARNING "\nIPO checks are only available on CMake 3.9 and later.")
|
||||
if(CMAKE_VERSION VERSION_LESS 3.9)
|
||||
message(WARNING "\nIPO checks are only available on CMake 3.9 and later.")
|
||||
|
||||
set(ENABLE_LTO OFF CACHE BOOL "" FORCE)
|
||||
|
||||
function (SFIZZ_ENABLE_LTO_IF_NEEDED TARGET)
|
||||
function(SFIZZ_ENABLE_LTO_IF_NEEDED TARGET)
|
||||
endfunction()
|
||||
|
||||
return()
|
||||
endif()
|
||||
|
||||
include (CheckIPOSupported)
|
||||
check_ipo_supported (RESULT result OUTPUT output)
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT result OUTPUT output)
|
||||
|
||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
|
||||
set(ENABLE_LTO OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
if (result AND ENABLE_LTO AND CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
message (STATUS "\nLTO enabled.")
|
||||
if(result AND ENABLE_LTO AND CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
message(STATUS "\nLTO enabled.")
|
||||
else()
|
||||
if (${output})
|
||||
message (WARNING "\nIPO disabled: ${output}")
|
||||
if(${output})
|
||||
message(WARNING "\nIPO disabled: ${output}")
|
||||
else()
|
||||
message (WARNING "\nIPO was disabled or not in a Release build.")
|
||||
message(WARNING "\nIPO was disabled or not in a Release build.")
|
||||
endif()
|
||||
set(ENABLE_LTO OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
function (SFIZZ_ENABLE_LTO_IF_NEEDED TARGET)
|
||||
if (${ENABLE_LTO})
|
||||
function(SFIZZ_ENABLE_LTO_IF_NEEDED TARGET)
|
||||
if(${ENABLE_LTO})
|
||||
message(STATUS "Enabling LTO on ${TARGET}")
|
||||
set_property (TARGET ${TARGET} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
|
||||
set_property(TARGET ${TARGET} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
|
|||
94
cmake/GNUWarnings.cmake
Normal file
94
cmake/GNUWarnings.cmake
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# A CMake module to use GNU warning flags with C and C++
|
||||
# and detect their availability.
|
||||
#
|
||||
# Usage:
|
||||
# gw_warn(<Wflag>...)
|
||||
# gw_warn_c(<Wflag>...)
|
||||
# gw_warn_cxx(<Wflag>...)
|
||||
# gw_target_warn(<target> <PUBLIC|PRIVATE|INTERFACE> <Wflag>...)
|
||||
# gw_target_warn_c(<target> <PUBLIC|PRIVATE|INTERFACE> <Wflag>...)
|
||||
# gw_target_warn_cxx(<target> <PUBLIC|PRIVATE|INTERFACE> <Wflag>...)
|
||||
#
|
||||
# Copyright 2020, Jean Pierre Cimalando <jp-dev@inbox.ru>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
function(gw_warn)
|
||||
gw_warn_c(${ARGN})
|
||||
gw_warn_cxx(${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(gw_warn_c)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
|
||||
foreach(flag ${ARGN})
|
||||
_gw_check_c_flag_is_silent("${flag}")
|
||||
if("${GNUWARNINGS_C_FLAG_${flag}_SILENT}")
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:C>:${flag}>")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(gw_warn_cxx)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
foreach(flag ${ARGN})
|
||||
_gw_check_cxx_flag_is_silent("${flag}")
|
||||
if("${GNUWARNINGS_CXX_FLAG_${flag}_SILENT}")
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:${flag}>")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(gw_target_warn TARGET DOMAIN)
|
||||
gw_target_warn_c("${TARGET}" "${DOMAIN}" ${ARGN})
|
||||
gw_target_warn_cxx("${TARGET}" "${DOMAIN}" ${ARGN})
|
||||
endfunction()
|
||||
|
||||
function(gw_target_warn_c TARGET DOMAIN)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
|
||||
foreach(flag ${ARGN})
|
||||
_gw_check_c_flag_is_silent("${flag}")
|
||||
if("${GNUWARNINGS_C_FLAG_${flag}_SILENT}")
|
||||
target_compile_options("${TARGET}" "${DOMAIN}" "$<$<COMPILE_LANGUAGE:C>:${flag}>")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(gw_target_warn_cxx TARGET DOMAIN)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
foreach(flag ${ARGN})
|
||||
_gw_check_cxx_flag_is_silent("${flag}")
|
||||
if("${GNUWARNINGS_CXX_FLAG_${flag}_SILENT}")
|
||||
target_compile_options("${TARGET}" "${DOMAIN}" "$<$<COMPILE_LANGUAGE:CXX>:${flag}>")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_gw_check_c_flag_is_silent FLAG)
|
||||
if(NOT DEFINED "GNUWARNINGS_C_FLAG_${FLAG}_SILENT")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.c" "")
|
||||
_gw_check_command_succeeds_silently(_result "${CMAKE_C_COMPILER}" "${FLAG}" "-c" "-o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.c")
|
||||
message(STATUS "Have C warning ${flag}: ${_result}")
|
||||
set("GNUWARNINGS_C_FLAG_${FLAG}_SILENT" "${_result}" CACHE INTERNAL "Have C warning ${flag}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_gw_check_cxx_flag_is_silent FLAG)
|
||||
if(NOT DEFINED "GNUWARNINGS_CXX_FLAG_${FLAG}_SILENT")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.cpp" "")
|
||||
_gw_check_command_succeeds_silently(_result "${CMAKE_CXX_COMPILER}" "${FLAG}" "-c" "-o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.o" "${CMAKE_CURRENT_BINARY_DIR}/CheckGNUWarning.cpp")
|
||||
message(STATUS "Have C++ warning ${flag}: ${_result}")
|
||||
set("GNUWARNINGS_CXX_FLAG_${FLAG}_SILENT" "${_result}" CACHE INTERNAL "Have C++ warning ${flag}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(_gw_check_command_succeeds_silently RESULT_VARIABLE)
|
||||
execute_process(COMMAND ${ARGN} RESULT_VARIABLE _result OUTPUT_VARIABLE _output ERROR_VARIABLE _error OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE)
|
||||
if(_result EQUAL 0 AND _output STREQUAL "" AND _error STREQUAL "")
|
||||
set("${RESULT_VARIABLE}" TRUE PARENT_SCOPE)
|
||||
else()
|
||||
set("${RESULT_VARIABLE}" FALSE PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
|
@ -1,17 +1,20 @@
|
|||
# This option is for MIDI CC support in absence of host midi:binding support
|
||||
option(SFIZZ_LV2_PSA "Enable plugin-side MIDI automations" OFF)
|
||||
|
||||
# Configuration for this plugin
|
||||
# TODO: generate version from git
|
||||
set (LV2PLUGIN_VERSION_MINOR 6)
|
||||
set (LV2PLUGIN_VERSION_MICRO 0)
|
||||
set (LV2PLUGIN_NAME "sfizz")
|
||||
set (LV2PLUGIN_COMMENT "SFZ sampler")
|
||||
set (LV2PLUGIN_URI "http://sfztools.github.io/sfizz")
|
||||
set (LV2PLUGIN_REPOSITORY "https://github.com/sfztools/sfizz")
|
||||
set (LV2PLUGIN_AUTHOR "SFZTools")
|
||||
set (LV2PLUGIN_EMAIL "paul@ferrand.cc")
|
||||
if (SFIZZ_USE_VCPKG)
|
||||
set (LV2PLUGIN_SPDX_LICENSE_ID "LGPL-3.0-only")
|
||||
set(LV2PLUGIN_VERSION_MINOR 8)
|
||||
set(LV2PLUGIN_VERSION_MICRO 0)
|
||||
set(LV2PLUGIN_NAME "sfizz")
|
||||
set(LV2PLUGIN_COMMENT "SFZ sampler")
|
||||
set(LV2PLUGIN_URI "http://sfztools.github.io/sfizz")
|
||||
set(LV2PLUGIN_REPOSITORY "https://github.com/sfztools/sfizz")
|
||||
set(LV2PLUGIN_AUTHOR "SFZTools")
|
||||
set(LV2PLUGIN_EMAIL "paul@ferrand.cc")
|
||||
if(SFIZZ_USE_VCPKG)
|
||||
set(LV2PLUGIN_SPDX_LICENSE_ID "LGPL-3.0-only")
|
||||
else()
|
||||
set (LV2PLUGIN_SPDX_LICENSE_ID "ISC")
|
||||
set(LV2PLUGIN_SPDX_LICENSE_ID "ISC")
|
||||
endif()
|
||||
|
||||
if(SFIZZ_LV2_UI)
|
||||
|
|
@ -30,13 +33,69 @@ else()
|
|||
set(LV2_UI_TYPE "X11UI")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set (LV2PLUGIN_INSTALL_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/LV2" CACHE STRING
|
||||
if(APPLE)
|
||||
set(LV2PLUGIN_INSTALL_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/LV2" CACHE STRING
|
||||
"Install destination for LV2 bundle [default: $ENV{HOME}/Library/Audio/Plug-Ins/LV2]")
|
||||
elseif (MSVC)
|
||||
set (LV2PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lv2" CACHE STRING
|
||||
elseif(MSVC)
|
||||
set(LV2PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lv2" CACHE STRING
|
||||
"Install destination for LV2 bundle [default: ${CMAKE_INSTALL_PREFIX}/lv2]")
|
||||
else()
|
||||
set (LV2PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/lv2" CACHE STRING
|
||||
set(LV2PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/lv2" CACHE STRING
|
||||
"Install destination for LV2 bundle [default: ${CMAKE_INSTALL_PREFIX}/lib/lv2]")
|
||||
endif()
|
||||
|
||||
include(StringUtility)
|
||||
|
||||
function(sfizz_lv2_generate_controllers_ttl FILE)
|
||||
file(WRITE "${FILE}" "# LV2 parameters for SFZ controllers
|
||||
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
|
||||
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
|
||||
@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
|
||||
@prefix patch: <http://lv2plug.in/ns/ext/patch#> .
|
||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
||||
@prefix sfizz: <${LV2PLUGIN_URI}#> .
|
||||
")
|
||||
math(EXPR _j "${SFIZZ_NUM_CCS}-1")
|
||||
foreach(_i RANGE "${_j}")
|
||||
string_left_pad(_i "${_i}" 3 0)
|
||||
file(APPEND "${FILE}" "
|
||||
sfizz:cc${_i}
|
||||
a lv2:Parameter ;
|
||||
rdfs:label \"Controller ${_i}\" ;
|
||||
rdfs:range atom:Float")
|
||||
|
||||
if(_i LESS 128 AND NOT SFIZZ_LV2_PSA)
|
||||
math(EXPR _digit1 "${_i}>>4")
|
||||
math(EXPR _digit2 "${_i}&15")
|
||||
string(SUBSTRING "0123456789ABCDEF" "${_digit1}" 1 _digit1)
|
||||
string(SUBSTRING "0123456789ABCDEF" "${_digit2}" 1 _digit2)
|
||||
file(APPEND "${FILE}" " ;
|
||||
midi:binding \"B0${_digit1}${_digit2}00\"^^midi:MidiEvent .
|
||||
")
|
||||
else()
|
||||
file(APPEND "${FILE}" " .
|
||||
")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(APPEND "${FILE}" "
|
||||
<${LV2PLUGIN_URI}>
|
||||
a lv2:Plugin ;
|
||||
")
|
||||
|
||||
file(APPEND "${FILE}" " patch:readable sfizz:cc000")
|
||||
foreach(_i RANGE 1 "${_j}")
|
||||
string_left_pad(_i "${_i}" 3 0)
|
||||
file(APPEND "${FILE}" ", sfizz:cc${_i}")
|
||||
endforeach()
|
||||
file(APPEND "${FILE}" " ;
|
||||
")
|
||||
|
||||
file(APPEND "${FILE}" " patch:writable sfizz:cc000")
|
||||
foreach(_i RANGE 1 "${_j}")
|
||||
string_left_pad(_i "${_i}" 3 0)
|
||||
file(APPEND "${FILE}" ", sfizz:cc${_i}")
|
||||
endforeach()
|
||||
file(APPEND "${FILE}" " .
|
||||
")
|
||||
endfunction()
|
||||
|
|
|
|||
19
cmake/OptionEx.cmake
Normal file
19
cmake/OptionEx.cmake
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
# This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
# license. You should have receive a LICENSE.md file along with the code.
|
||||
# If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
# Macro: option_ex(OPTION DOC [CONDITION])
|
||||
# Defines an option, with these characteristics:
|
||||
# - A suffix [default: ON/OFF] is appended to the documentation
|
||||
# - The value is interpreted like a conditional expression
|
||||
macro(option_ex option doc)
|
||||
if(${ARGN})
|
||||
set(_value ON)
|
||||
else()
|
||||
set(_value OFF)
|
||||
endif()
|
||||
option("${option}" "${doc} [default: ${_value}]" "${_value}")
|
||||
unset(_value)
|
||||
endmacro()
|
||||
|
|
@ -1,51 +1,51 @@
|
|||
include(CMakeDependentOption)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(GNUWarnings)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to be used")
|
||||
set(CMAKE_C_STANDARD 99 CACHE STRING "C standard to be used")
|
||||
|
||||
# Export the compile_commands.json file
|
||||
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Only install what's explicitely said
|
||||
set (CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
|
||||
set (CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set (CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set (CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
|
||||
# Set C++ compatibility level
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" AND CMAKE_CXX_STANDARD LESS 17)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
elseif((SFIZZ_LV2_UI OR SFIZZ_VST OR SFIZZ_AU OR SFIZZ_VST2) AND CMAKE_CXX_STANDARD LESS 14)
|
||||
# if the UI is part of the build, make it 14
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
|
||||
# Process sources as UTF-8
|
||||
if(MSVC)
|
||||
add_compile_options("/utf-8")
|
||||
endif()
|
||||
|
||||
# Set Windows compatibility level to 7
|
||||
if (WIN32)
|
||||
if(WIN32)
|
||||
add_compile_definitions(_WIN32_WINNT=0x601)
|
||||
endif()
|
||||
|
||||
# Set macOS compatibility level
|
||||
if (APPLE)
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")
|
||||
endif()
|
||||
|
||||
# Do not define macros `min` and `max`
|
||||
if (WIN32)
|
||||
if(WIN32)
|
||||
add_compile_definitions(NOMINMAX)
|
||||
endif()
|
||||
|
||||
# Find macOS system libraries
|
||||
if(APPLE)
|
||||
find_library(APPLE_COREFOUNDATION_LIBRARY "CoreFoundation")
|
||||
find_library(APPLE_FOUNDATION_LIBRARY "Foundation")
|
||||
find_library(APPLE_COCOA_LIBRARY "Cocoa")
|
||||
find_library(APPLE_CARBON_LIBRARY "Carbon")
|
||||
find_library(APPLE_OPENGL_LIBRARY "OpenGL")
|
||||
find_library(APPLE_ACCELERATE_LIBRARY "Accelerate")
|
||||
find_library(APPLE_QUARTZCORE_LIBRARY "QuartzCore")
|
||||
find_library(APPLE_AUDIOTOOLBOX_LIBRARY "AudioToolbox")
|
||||
find_library(APPLE_AUDIOUNIT_LIBRARY "AudioUnit")
|
||||
find_library(APPLE_COREAUDIO_LIBRARY "CoreAudio")
|
||||
find_library(APPLE_COREMIDI_LIBRARY "CoreMIDI")
|
||||
endif()
|
||||
|
||||
# The variable CMAKE_SYSTEM_PROCESSOR is incorrect on Visual studio...
|
||||
# see https://gitlab.kitware.com/cmake/cmake/issues/15170
|
||||
|
||||
if (NOT SFIZZ_SYSTEM_PROCESSOR)
|
||||
if(NOT SFIZZ_SYSTEM_PROCESSOR)
|
||||
if(MSVC)
|
||||
set(SFIZZ_SYSTEM_PROCESSOR "${MSVC_CXX_ARCHITECTURE_ID}")
|
||||
else()
|
||||
|
|
@ -54,109 +54,61 @@ if (NOT SFIZZ_SYSTEM_PROCESSOR)
|
|||
endif()
|
||||
|
||||
# Add required flags for the builds
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
add_compile_options(-Wall)
|
||||
add_compile_options(-Wextra)
|
||||
add_compile_options(-Wno-multichar)
|
||||
add_compile_options(-Werror=return-type)
|
||||
if (SFIZZ_SYSTEM_PROCESSOR MATCHES "^(i.86|x86_64)$")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
gw_warn(-Wall -Wextra -Wno-multichar -Werror=return-type)
|
||||
if(SFIZZ_SYSTEM_PROCESSOR MATCHES "^(i.86|x86_64)$")
|
||||
add_compile_options(-msse2)
|
||||
elseif(SFIZZ_SYSTEM_PROCESSOR MATCHES "^(arm.*)$")
|
||||
add_compile_options(-mfpu=neon)
|
||||
if (NOT ANDROID)
|
||||
if(NOT ANDROID)
|
||||
add_compile_options(-mfloat-abi=hard)
|
||||
endif()
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
add_compile_options(/Zc:__cplusplus)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
function(sfizz_enable_fast_math NAME)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
target_compile_options("${NAME}" PRIVATE "-ffast-math")
|
||||
elseif(MSVC)
|
||||
target_compile_options("${NAME}" PRIVATE "/fp:fast")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# The sndfile library
|
||||
add_library(sfizz-sndfile INTERFACE)
|
||||
|
||||
# The jsl utility library for C++
|
||||
add_library(sfizz-jsl INTERFACE)
|
||||
target_include_directories(sfizz-jsl INTERFACE "external/jsl/include")
|
||||
|
||||
if (SFIZZ_USE_VCPKG OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
find_package(SndFile CONFIG REQUIRED)
|
||||
find_path(SNDFILE_INCLUDE_DIR sndfile.hh)
|
||||
target_include_directories(sfizz-sndfile INTERFACE "${SNDFILE_INCLUDE_DIR}")
|
||||
target_link_libraries(sfizz-sndfile INTERFACE SndFile::sndfile)
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SNDFILE "sndfile" REQUIRED)
|
||||
target_include_directories(sfizz-sndfile INTERFACE ${SNDFILE_INCLUDE_DIRS})
|
||||
if (SFIZZ_STATIC_DEPENDENCIES)
|
||||
target_link_libraries(sfizz-sndfile INTERFACE ${SNDFILE_STATIC_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(sfizz-sndfile INTERFACE ${SNDFILE_LIBRARIES})
|
||||
endif()
|
||||
link_directories(${SNDFILE_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
|
||||
# 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_CXX_COMPILER_ID MATCHES Clang" OFF)
|
||||
if (USE_LIBCPP)
|
||||
if(USE_LIBCPP)
|
||||
add_compile_options(-stdlib=libc++)
|
||||
# Presumably need the above for linking too, maybe other options missing as well
|
||||
add_link_options(-stdlib=libc++) # New command on CMake master, not in 3.12 release
|
||||
add_link_options(-lc++abi) # New command on CMake master, not in 3.12 release
|
||||
endif()
|
||||
|
||||
add_library(sfizz-pugixml STATIC "src/external/pugixml/src/pugixml.cpp")
|
||||
target_include_directories(sfizz-pugixml PUBLIC "src/external/pugixml/src")
|
||||
|
||||
add_library(sfizz-spline STATIC "src/external/spline/spline/spline.cpp")
|
||||
target_include_directories(sfizz-spline PUBLIC "src/external/spline")
|
||||
|
||||
add_library(sfizz-tunings STATIC "src/external/tunings/src/Tunings.cpp")
|
||||
target_include_directories(sfizz-tunings PUBLIC "src/external/tunings/include")
|
||||
|
||||
include (CheckLibraryExists)
|
||||
add_library (sfizz-atomic INTERFACE)
|
||||
if (UNIX AND NOT APPLE)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic/check_libatomic.c" "int main() { return 0; }")
|
||||
try_compile(SFIZZ_LINK_LIBATOMIC "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic"
|
||||
SOURCES "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic/check_libatomic.c"
|
||||
LINK_LIBRARIES "atomic")
|
||||
if (SFIZZ_LINK_LIBATOMIC)
|
||||
target_link_libraries (sfizz-atomic INTERFACE "atomic")
|
||||
endif()
|
||||
else()
|
||||
set(SFIZZ_LINK_LIBATOMIC FALSE)
|
||||
endif()
|
||||
|
||||
# Don't show build information when building a different project
|
||||
function (show_build_info_if_needed)
|
||||
if (CMAKE_PROJECT_NAME STREQUAL "sfizz")
|
||||
message (STATUS "
|
||||
function(show_build_info_if_needed)
|
||||
if(CMAKE_PROJECT_NAME STREQUAL "sfizz")
|
||||
message(STATUS "
|
||||
Project name: ${PROJECT_NAME}
|
||||
Build type: ${CMAKE_BUILD_TYPE}
|
||||
Build processor: ${SFIZZ_SYSTEM_PROCESSOR}
|
||||
Build using LTO: ${ENABLE_LTO}
|
||||
Build as shared library: ${SFIZZ_SHARED}
|
||||
Build JACK stand-alone client: ${SFIZZ_JACK}
|
||||
Build render client: ${SFIZZ_RENDER}
|
||||
Build LV2 plug-in: ${SFIZZ_LV2}
|
||||
Build LV2 user interface: ${SFIZZ_LV2_UI}
|
||||
Build VST plug-in: ${SFIZZ_VST}
|
||||
Build AU plug-in: ${SFIZZ_AU}
|
||||
Build benchmarks: ${SFIZZ_BENCHMARKS}
|
||||
Build tests: ${SFIZZ_TESTS}
|
||||
Build demos: ${SFIZZ_DEMOS}
|
||||
Build devtools: ${SFIZZ_DEVTOOLS}
|
||||
Use sndfile: ${SFIZZ_USE_SNDFILE}
|
||||
Use vcpkg: ${SFIZZ_USE_VCPKG}
|
||||
Statically link dependencies: ${SFIZZ_STATIC_DEPENDENCIES}
|
||||
Link libatomic: ${SFIZZ_LINK_LIBATOMIC}
|
||||
Use clang libc++: ${USE_LIBCPP}
|
||||
Release asserts: ${SFIZZ_RELEASE_ASSERTS}
|
||||
|
||||
|
|
@ -169,5 +121,3 @@ Compiler CXX min size flags: ${CMAKE_CXX_FLAGS_MINSIZEREL}
|
|||
")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
find_package (Threads REQUIRED)
|
||||
|
|
|
|||
261
cmake/SfizzDeps.cmake
Normal file
261
cmake/SfizzDeps.cmake
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
# Find system threads
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
# Find OpenMP
|
||||
find_package(OpenMP)
|
||||
if(OPENMP_FOUND)
|
||||
add_library(sfizz_openmp INTERFACE)
|
||||
add_library(sfizz::openmp ALIAS sfizz_openmp)
|
||||
|
||||
# OpenMP flags are provided as a space-separated string, we need a list
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.9)
|
||||
separate_arguments(SFIZZ_OpenMP_C_OPTIONS NATIVE_COMMAND "${OpenMP_C_FLAGS}")
|
||||
separate_arguments(SFIZZ_OpenMP_CXX_OPTIONS NATIVE_COMMAND "${OpenMP_CXX_FLAGS}")
|
||||
elseif(CMAKE_HOST_WIN32)
|
||||
separate_arguments(SFIZZ_OpenMP_C_OPTIONS WINDOWS_COMMAND "${OpenMP_C_FLAGS}")
|
||||
separate_arguments(SFIZZ_OpenMP_CXX_OPTIONS WINDOWS_COMMAND "${OpenMP_CXX_FLAGS}")
|
||||
else()
|
||||
separate_arguments(SFIZZ_OpenMP_C_OPTIONS UNIX_COMMAND "${OpenMP_C_FLAGS}")
|
||||
separate_arguments(SFIZZ_OpenMP_CXX_OPTIONS UNIX_COMMAND "${OpenMP_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
target_compile_options(sfizz_openmp INTERFACE
|
||||
$<$<COMPILE_LANGUAGE:C>:${SFIZZ_OpenMP_C_OPTIONS}>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:${SFIZZ_OpenMP_CXX_OPTIONS}>)
|
||||
endif()
|
||||
|
||||
# Find macOS system libraries
|
||||
if(APPLE)
|
||||
find_library(APPLE_COREFOUNDATION_LIBRARY "CoreFoundation")
|
||||
find_library(APPLE_FOUNDATION_LIBRARY "Foundation")
|
||||
find_library(APPLE_COCOA_LIBRARY "Cocoa")
|
||||
find_library(APPLE_CARBON_LIBRARY "Carbon")
|
||||
find_library(APPLE_OPENGL_LIBRARY "OpenGL")
|
||||
find_library(APPLE_ACCELERATE_LIBRARY "Accelerate")
|
||||
find_library(APPLE_QUARTZCORE_LIBRARY "QuartzCore")
|
||||
find_library(APPLE_AUDIOTOOLBOX_LIBRARY "AudioToolbox")
|
||||
find_library(APPLE_AUDIOUNIT_LIBRARY "AudioUnit")
|
||||
find_library(APPLE_COREAUDIO_LIBRARY "CoreAudio")
|
||||
find_library(APPLE_COREMIDI_LIBRARY "CoreMIDI")
|
||||
endif()
|
||||
|
||||
# Set up macOS library paths
|
||||
if(APPLE)
|
||||
# See https://stackoverflow.com/a/54103956
|
||||
# and https://stackoverflow.com/a/21692023
|
||||
# Apparently this is not needed in Travis CI using addons
|
||||
# but it is in Appveyor instead
|
||||
list(APPEND CMAKE_PREFIX_PATH /usr/local)
|
||||
endif()
|
||||
|
||||
# Add Abseil
|
||||
if(SFIZZ_USE_SYSTEM_ABSEIL)
|
||||
find_package(absl REQUIRED)
|
||||
else()
|
||||
function(sfizz_add_vendor_abseil)
|
||||
set(BUILD_SHARED_LIBS OFF) # only changed at local scope
|
||||
add_subdirectory("external/abseil-cpp" EXCLUDE_FROM_ALL)
|
||||
endfunction()
|
||||
sfizz_add_vendor_abseil()
|
||||
endif()
|
||||
|
||||
# The jsl utility library for C++
|
||||
add_library(sfizz_jsl INTERFACE)
|
||||
add_library(sfizz::jsl ALIAS sfizz_jsl)
|
||||
target_include_directories(sfizz_jsl INTERFACE "external/jsl/include")
|
||||
|
||||
# The cxxopts library
|
||||
add_library(sfizz_cxxopts INTERFACE)
|
||||
add_library(sfizz::cxxopts ALIAS sfizz_cxxopts)
|
||||
target_include_directories(sfizz_cxxopts INTERFACE "external/cxxopts")
|
||||
|
||||
# The sndfile library
|
||||
if(SFIZZ_USE_SNDFILE OR SFIZZ_DEMOS OR SFIZZ_DEVTOOLS OR SFIZZ_BENCHMARKS)
|
||||
add_library(sfizz_sndfile INTERFACE)
|
||||
add_library(sfizz::sndfile ALIAS sfizz_sndfile)
|
||||
if(SFIZZ_USE_VCPKG OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
find_package(SndFile CONFIG REQUIRED)
|
||||
find_path(SNDFILE_INCLUDE_DIR "sndfile.hh")
|
||||
target_include_directories(sfizz_sndfile INTERFACE "${SNDFILE_INCLUDE_DIR}")
|
||||
target_link_libraries(sfizz_sndfile INTERFACE SndFile::sndfile)
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SNDFILE "sndfile" REQUIRED)
|
||||
target_include_directories(sfizz_sndfile INTERFACE ${SNDFILE_INCLUDE_DIRS})
|
||||
if(SFIZZ_STATIC_DEPENDENCIES)
|
||||
target_link_libraries(sfizz_sndfile INTERFACE ${SNDFILE_STATIC_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(sfizz_sndfile INTERFACE ${SNDFILE_LIBRARIES})
|
||||
endif()
|
||||
link_directories(${SNDFILE_LIBRARY_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The st_audiofile library
|
||||
if(SFIZZ_USE_SNDFILE)
|
||||
set(ST_AUDIO_FILE_USE_SNDFILE ON CACHE BOOL "" FORCE)
|
||||
set(ST_AUDIO_FILE_EXTERNAL_SNDFILE "sfizz::sndfile" CACHE STRING "" FORCE)
|
||||
else()
|
||||
set(ST_AUDIO_FILE_USE_SNDFILE OFF CACHE BOOL "" FORCE)
|
||||
set(ST_AUDIO_FILE_EXTERNAL_SNDFILE "" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
add_subdirectory("external/st_audiofile" EXCLUDE_FROM_ALL)
|
||||
|
||||
# The simde library
|
||||
add_library(sfizz_simde INTERFACE)
|
||||
add_library(sfizz::simde ALIAS sfizz_simde)
|
||||
if(SFIZZ_USE_SYSTEM_SIMDE)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SIMDE "simde" REQUIRED)
|
||||
target_include_directories(sfizz_simde INTERFACE "${SIMDE_INCLUDE_DIRS}")
|
||||
if(NOT SIMDE_VERSION OR SIMDE_VERSION VERSION_LESS_EQUAL "0.7.2")
|
||||
message(WARNING "The version of SIMDe on this system has known issues. \
|
||||
It is recommended to either update if a newer version is available, or use the \
|
||||
version bundled with this package. Refer to following issues: \
|
||||
simd-everywhere/simde#704, simd-everywhere/simde#706")
|
||||
endif()
|
||||
else()
|
||||
target_include_directories(sfizz_simde INTERFACE "external/simde")
|
||||
endif()
|
||||
if(TARGET sfizz::openmp)
|
||||
target_link_libraries(sfizz_simde INTERFACE sfizz::openmp)
|
||||
endif()
|
||||
|
||||
# The pugixml library
|
||||
add_library(sfizz_pugixml STATIC "src/external/pugixml/src/pugixml.cpp")
|
||||
add_library(sfizz::pugixml ALIAS sfizz_pugixml)
|
||||
target_include_directories(sfizz_pugixml PUBLIC "src/external/pugixml/src")
|
||||
|
||||
# The spline library
|
||||
add_library(sfizz_spline STATIC "src/external/spline/spline/spline.cpp")
|
||||
add_library(sfizz::spline ALIAS sfizz_spline)
|
||||
target_include_directories(sfizz_spline PUBLIC "src/external/spline")
|
||||
|
||||
# The tunings library
|
||||
add_library(sfizz_tunings STATIC "src/external/tunings/src/Tunings.cpp")
|
||||
add_library(sfizz::tunings ALIAS sfizz_tunings)
|
||||
target_include_directories(sfizz_tunings PUBLIC "src/external/tunings/include")
|
||||
|
||||
# The hiir library
|
||||
add_library(sfizz_hiir INTERFACE)
|
||||
add_library(sfizz::hiir ALIAS sfizz_hiir)
|
||||
target_include_directories(sfizz_hiir INTERFACE "src/external/hiir")
|
||||
|
||||
# The hiir filter designer
|
||||
add_library(sfizz_hiir_polyphase_iir2designer STATIC
|
||||
"src/external/hiir/hiir/PolyphaseIir2Designer.cpp")
|
||||
add_library(sfizz::hiir_polyphase_iir2designer ALIAS sfizz_hiir_polyphase_iir2designer)
|
||||
target_link_libraries(sfizz_hiir_polyphase_iir2designer PUBLIC sfizz::hiir)
|
||||
|
||||
# The kissfft library
|
||||
add_library(sfizz_kissfft STATIC
|
||||
"src/external/kiss_fft/kiss_fft.c"
|
||||
"src/external/kiss_fft/tools/kiss_fftr.c")
|
||||
add_library(sfizz::kissfft ALIAS sfizz_kissfft)
|
||||
target_include_directories(sfizz_kissfft
|
||||
PUBLIC "src/external/kiss_fft"
|
||||
PUBLIC "src/external/kiss_fft/tools")
|
||||
|
||||
# The cephes library
|
||||
add_library(sfizz_cephes STATIC
|
||||
"external/cephes/src/chbevl.c"
|
||||
"external/cephes/src/i0.c")
|
||||
add_library(sfizz::cephes ALIAS sfizz_cephes)
|
||||
|
||||
# The cpuid library
|
||||
add_library(sfizz_cpuid STATIC
|
||||
"src/external/cpuid/src/cpuid/cpuinfo.cpp"
|
||||
"src/external/cpuid/src/cpuid/version.cpp")
|
||||
add_library(sfizz::cpuid ALIAS sfizz_cpuid)
|
||||
set_property(TARGET sfizz_cpuid PROPERTY CXX_STANDARD 11)
|
||||
target_include_directories(sfizz_cpuid
|
||||
PUBLIC "src/external/cpuid/src"
|
||||
PRIVATE "src/external/cpuid/platform/src")
|
||||
|
||||
# The threadpool library
|
||||
add_library(sfizz_threadpool INTERFACE)
|
||||
add_library(sfizz::threadpool ALIAS sfizz_threadpool)
|
||||
target_include_directories(sfizz_threadpool INTERFACE "external/threadpool")
|
||||
|
||||
# The atomic_queue library
|
||||
add_library(sfizz_atomic_queue INTERFACE)
|
||||
add_library(sfizz::atomic_queue ALIAS sfizz_atomic_queue)
|
||||
target_include_directories(sfizz_atomic_queue INTERFACE "external/atomic_queue/include")
|
||||
|
||||
# The ghc::filesystem library
|
||||
add_library(sfizz_filesystem INTERFACE)
|
||||
add_library(sfizz::filesystem ALIAS sfizz_filesystem)
|
||||
target_include_directories(sfizz_filesystem INTERFACE "external/filesystem/include")
|
||||
|
||||
# The atomic library
|
||||
add_library(sfizz_atomic INTERFACE)
|
||||
add_library(sfizz::atomic ALIAS sfizz_atomic)
|
||||
if(UNIX AND NOT APPLE)
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic/check_libatomic.c" "int main() { return 0; }")
|
||||
try_compile(SFIZZ_LINK_LIBATOMIC "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic"
|
||||
SOURCES "${CMAKE_CURRENT_BINARY_DIR}/check_libatomic/check_libatomic.c"
|
||||
LINK_LIBRARIES "atomic")
|
||||
if(SFIZZ_LINK_LIBATOMIC)
|
||||
target_link_libraries(sfizz_atomic INTERFACE "atomic")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The jack library
|
||||
if(SFIZZ_JACK)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(JACK "jack" REQUIRED)
|
||||
elseif()
|
||||
find_package(PkgConfig)
|
||||
if(PKGCONFIG_FOUND)
|
||||
pkg_check_modules(JACK "jack")
|
||||
endif()
|
||||
endif()
|
||||
if(JACK_FOUND)
|
||||
add_library(sfizz_jacklib INTERFACE)
|
||||
add_library(sfizz::jack ALIAS sfizz_jacklib)
|
||||
target_include_directories(sfizz_jacklib INTERFACE ${JACK_INCLUDE_DIRS})
|
||||
target_link_libraries(sfizz_jacklib INTERFACE ${JACK_LIBRARIES})
|
||||
link_directories(${JACK_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
# The Qt library
|
||||
find_package(Qt5 COMPONENTS Widgets)
|
||||
|
||||
# The fmidi library
|
||||
add_library(sfizz_fmidi STATIC
|
||||
"external/fmidi/sources/fmidi/fmidi.h"
|
||||
"external/fmidi/sources/fmidi/fmidi_mini.cpp")
|
||||
add_library(sfizz::fmidi ALIAS sfizz_fmidi)
|
||||
target_include_directories(sfizz_fmidi PUBLIC "external/fmidi/sources")
|
||||
target_compile_definitions(sfizz_fmidi PUBLIC "FMIDI_STATIC=1" "FMIDI_DISABLE_DESCRIBE_API=1")
|
||||
|
||||
# The samplerate library
|
||||
find_package(PkgConfig)
|
||||
if(PKGCONFIG_FOUND)
|
||||
pkg_check_modules(SAMPLERATE "samplerate")
|
||||
if(SAMPLERATE_FOUND)
|
||||
add_library(sfizz_samplerate INTERFACE)
|
||||
add_library(sfizz::samplerate ALIAS sfizz_samplerate)
|
||||
target_include_directories(sfizz_samplerate INTERFACE ${SAMPLERATE_INCLUDE_DIRS})
|
||||
target_link_libraries(sfizz_samplerate INTERFACE ${SAMPLERATE_LIBRARIES})
|
||||
link_directories(${SAMPLERATE_LIBRARY_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
if(NOT TARGET sfizz::samplerate)
|
||||
find_library(SAMPLERATE_LIBRARY "samplerate")
|
||||
find_path(SAMPLERATE_INCLUDE_DIR "samplerate.h")
|
||||
message(STATUS "Checking samplerate library: ${SAMPLERATE_LIBRARY}")
|
||||
message(STATUS "Checking samplerate includes: ${SAMPLERATE_INCLUDE_DIR}")
|
||||
if(SAMPLERATE_LIBRARY AND SAMPLERATE_INCLUDE_DIR)
|
||||
add_library(sfizz_samplerate INTERFACE)
|
||||
add_library(sfizz::samplerate ALIAS sfizz_samplerate)
|
||||
target_include_directories(sfizz_samplerate INTERFACE "${SAMPLERATE_INCLUDE_DIR}")
|
||||
target_link_libraries(sfizz_samplerate INTERFACE "${SAMPLERATE_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The benchmark library
|
||||
if(SFIZZ_BENCHMARKS)
|
||||
find_package(benchmark CONFIG REQUIRED)
|
||||
endif()
|
||||
72
cmake/SfizzFaust.cmake
Normal file
72
cmake/SfizzFaust.cmake
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
include(CMakeParseArguments)
|
||||
|
||||
option(SFIZZ_RECOMPILE_FAUST "Recompile faust sources" OFF)
|
||||
|
||||
if(SFIZZ_RECOMPILE_FAUST)
|
||||
find_program(RDMD "rdmd")
|
||||
if(NOT RDMD)
|
||||
message(FATAL_ERROR "rdmd is missing, it is required for regenerating faust sources.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(add_faust_command INPUT OUTPUT)
|
||||
set(_options ONE_SAMPLE DOUBLE IN_PLACE VECTORIZE MATH_APPROXIMATION)
|
||||
set(_one_args PROCESS_NAME CLASS_NAME SUPERCLASS_NAME)
|
||||
set(_multi_args IMPORT_DIRS)
|
||||
cmake_parse_arguments(_FAUST "${_options}" "${_one_args}" "${_multi_args}" ${ARGN})
|
||||
if(NOT SFIZZ_RECOMPILE_FAUST)
|
||||
return()
|
||||
endif()
|
||||
if(NOT RDMD)
|
||||
return()
|
||||
endif()
|
||||
if(NOT INPUT)
|
||||
message(FATAL_ERROR "No input file given.")
|
||||
endif()
|
||||
if(NOT OUTPUT)
|
||||
message(FATAL_ERROR "No output file given.")
|
||||
endif()
|
||||
set(_cmd "${RDMD}" "${PROJECT_SOURCE_DIR}/scripts/faustwrap.d")
|
||||
if(NOT IS_ABSOLUTE "${INPUT}")
|
||||
set(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT}")
|
||||
endif()
|
||||
if(NOT IS_ABSOLUTE "${OUTPUT}")
|
||||
set(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT}")
|
||||
endif()
|
||||
get_filename_component(_output_dir "${OUTPUT}" DIRECTORY)
|
||||
file(MAKE_DIRECTORY "${_output_dir}")
|
||||
list(APPEND _cmd "-o" "${OUTPUT}" "${INPUT}")
|
||||
if(_FAUST_ONE_SAMPLE)
|
||||
list(APPEND _cmd "--os")
|
||||
endif()
|
||||
if(_FAUST_DOUBLE)
|
||||
list(APPEND _cmd "--double")
|
||||
endif()
|
||||
if(_FAUST_IN_PLACE)
|
||||
list(APPEND _cmd "--inpl")
|
||||
endif()
|
||||
if(_FAUST_VECTORIZE)
|
||||
list(APPEND _cmd "--vec")
|
||||
endif()
|
||||
if(_FAUST_MATH_APPROXIMATION)
|
||||
list(APPEND _cmd "--mapp")
|
||||
endif()
|
||||
if(_FAUST_PROCESS_NAME)
|
||||
list(APPEND _cmd "--pn" "${_FAUST_PROCESS_NAME}")
|
||||
endif()
|
||||
if(_FAUST_CLASS_NAME)
|
||||
list(APPEND _cmd "--cn" "${_FAUST_CLASS_NAME}")
|
||||
endif()
|
||||
if(_FAUST_SUPERCLASS_NAME)
|
||||
list(APPEND _cmd "--scn" "${_FAUST_SUPERCLASS_NAME}")
|
||||
endif()
|
||||
if (_FAUST_IMPORT_DIRS)
|
||||
foreach(_dir IN LISTS _FAUST_IMPORT_DIRS)
|
||||
if(NOT IS_ABSOLUTE "${_dir}")
|
||||
set(_dir "${CMAKE_CURRENT_SOURCE_DIR}/${_dir}")
|
||||
endif()
|
||||
list(APPEND _cmd "--import-dir" "${_dir}")
|
||||
endforeach()
|
||||
endif()
|
||||
add_custom_command(OUTPUT "${OUTPUT}" COMMAND ${_cmd} DEPENDS "${INPUT}")
|
||||
endfunction()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
macro(sfizz_add_simd_sources SOURCES_VAR PREFIX)
|
||||
# It needs a macro, otherwise the source properties cannot take effect.
|
||||
|
||||
list (APPEND ${SOURCES_VAR}
|
||||
list(APPEND ${SOURCES_VAR}
|
||||
${PREFIX}/sfizz/SIMDHelpers.cpp
|
||||
${PREFIX}/sfizz/simd/HelpersNEON.cpp
|
||||
${PREFIX}/sfizz/simd/HelpersSSE.cpp
|
||||
|
|
@ -9,10 +9,10 @@ macro(sfizz_add_simd_sources SOURCES_VAR PREFIX)
|
|||
|
||||
# For CPU-dispatched X86 sources
|
||||
# Always build them for all X86 targets.
|
||||
if (SFIZZ_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64|x64|X64|i.86|x86|X86)$")
|
||||
if(SFIZZ_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64|x64|X64|i.86|x86|X86)$")
|
||||
# on GCC, it requires to set ISA support flags on individual files
|
||||
# to be able to use the intrinsics
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set_source_files_properties(
|
||||
${PREFIX}/sfizz/effects/impl/ResonantStringAVX.cpp
|
||||
${PREFIX}/sfizz/effects/impl/ResonantArrayAVX.cpp
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ if(NOT TARGET uninstall)
|
|||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/MakeUninstall.cmake)
|
||||
|
||||
if (SFIZZ_LV2 AND LV2PLUGIN_INSTALL_DIR)
|
||||
if(SFIZZ_LV2 AND LV2PLUGIN_INSTALL_DIR)
|
||||
add_custom_command(TARGET uninstall
|
||||
COMMAND rm -rv "${LV2PLUGIN_INSTALL_DIR}/${PROJECT_NAME}.lv2")
|
||||
endif()
|
||||
|
||||
if (SFIZZ_VST AND VSTPLUGIN_INSTALL_DIR)
|
||||
if(SFIZZ_VST AND VSTPLUGIN_INSTALL_DIR)
|
||||
add_custom_command(TARGET uninstall
|
||||
COMMAND rm -rv "${VSTPLUGIN_INSTALL_DIR}/${PROJECT_NAME}.vst3")
|
||||
endif()
|
||||
|
|
|
|||
11
cmake/StringUtility.cmake
Normal file
11
cmake/StringUtility.cmake
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
function(string_left_pad VAR INPUT LENGTH FILLCHAR)
|
||||
set(_output "${INPUT}")
|
||||
string(LENGTH "${_output}" _length)
|
||||
while(_length LESS "${LENGTH}")
|
||||
set(_output "${FILLCHAR}${_output}")
|
||||
string(LENGTH "${_output}" _length)
|
||||
endwhile()
|
||||
set("${VAR}" "${_output}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
set (VSTPLUGIN_NAME "sfizz")
|
||||
set (VSTPLUGIN_VENDOR "Paul Ferrand")
|
||||
set (VSTPLUGIN_URL "http://sfztools.github.io/sfizz")
|
||||
set (VSTPLUGIN_EMAIL "paul@ferrand.cc")
|
||||
set(VSTPLUGIN_NAME "sfizz")
|
||||
set(VSTPLUGIN_VENDOR "Paul Ferrand")
|
||||
set(VSTPLUGIN_URL "http://sfztools.github.io/sfizz")
|
||||
set(VSTPLUGIN_EMAIL "paul@ferrand.cc")
|
||||
|
||||
if (APPLE)
|
||||
set (VSTPLUGIN_INSTALL_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3" CACHE STRING
|
||||
if(APPLE)
|
||||
set(VSTPLUGIN_INSTALL_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/VST3" CACHE STRING
|
||||
"Install destination for VST bundle [default: $ENV{HOME}/Library/Audio/Plug-Ins/VST3]")
|
||||
set (AUPLUGIN_INSTALL_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components" CACHE STRING
|
||||
set(AUPLUGIN_INSTALL_DIR "$ENV{HOME}/Library/Audio/Plug-Ins/Components" CACHE STRING
|
||||
"Install destination for AudioUnit bundle [default: $ENV{HOME}/Library/Audio/Plug-Ins/Components]")
|
||||
elseif (MSVC)
|
||||
set (VSTPLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/vst3" CACHE STRING
|
||||
elseif(MSVC)
|
||||
set(VSTPLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/vst3" CACHE STRING
|
||||
"Install destination for VST bundle [default: ${CMAKE_INSTALL_PREFIX}/vst3]")
|
||||
else()
|
||||
set (VSTPLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/vst3" CACHE STRING
|
||||
set(VSTPLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/vst3" CACHE STRING
|
||||
"Install destination for VST bundle [default: ${CMAKE_INSTALL_PREFIX}/lib/vst3]")
|
||||
endif()
|
||||
|
||||
if (NOT VST3_SYSTEM_PROCESSOR)
|
||||
if(NOT VST3_SYSTEM_PROCESSOR)
|
||||
set(VST3_SYSTEM_PROCESSOR "${SFIZZ_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
|
|
|
|||
110
common.mk
110
common.mk
|
|
@ -4,6 +4,10 @@ ifndef SFIZZ_DIR
|
|||
$(error sfizz: The source directory must be set before including)
|
||||
endif
|
||||
|
||||
### Options
|
||||
|
||||
SFIZZ_USE_SNDFILE ?= 0
|
||||
|
||||
###
|
||||
|
||||
SFIZZ_MACHINE := $(shell $(CC) -dumpmachine)
|
||||
|
|
@ -44,7 +48,9 @@ SFIZZ_CXX_FLAGS = $(SFIZZ_C_FLAGS)
|
|||
SFIZZ_SOURCES = \
|
||||
src/sfizz/ADSREnvelope.cpp \
|
||||
src/sfizz/AudioReader.cpp \
|
||||
src/sfizz/BeatClock.cpp \
|
||||
src/sfizz/Curve.cpp \
|
||||
src/sfizz/Defaults.cpp \
|
||||
src/sfizz/effects/Apan.cpp \
|
||||
src/sfizz/Effects.cpp \
|
||||
src/sfizz/modulations/ModId.cpp \
|
||||
|
|
@ -52,6 +58,8 @@ SFIZZ_SOURCES = \
|
|||
src/sfizz/modulations/ModKeyHash.cpp \
|
||||
src/sfizz/modulations/ModMatrix.cpp \
|
||||
src/sfizz/modulations/sources/ADSREnvelope.cpp \
|
||||
src/sfizz/modulations/sources/ChannelAftertouch.cpp \
|
||||
src/sfizz/modulations/sources/PolyAftertouch.cpp \
|
||||
src/sfizz/modulations/sources/Controller.cpp \
|
||||
src/sfizz/modulations/sources/FlexEnvelope.cpp \
|
||||
src/sfizz/modulations/sources/LFO.cpp \
|
||||
|
|
@ -81,16 +89,18 @@ SFIZZ_SOURCES = \
|
|||
src/sfizz/FilterPool.cpp \
|
||||
src/sfizz/FlexEGDescription.cpp \
|
||||
src/sfizz/FlexEnvelope.cpp \
|
||||
src/sfizz/FloatEnvelopes.cpp \
|
||||
src/sfizz/Interpolators.cpp \
|
||||
src/sfizz/Layer.cpp \
|
||||
src/sfizz/Logger.cpp \
|
||||
src/sfizz/LFO.cpp \
|
||||
src/sfizz/LFODescription.cpp \
|
||||
src/sfizz/Messaging.cpp \
|
||||
src/sfizz/Metronome.cpp \
|
||||
src/sfizz/MidiState.cpp \
|
||||
src/sfizz/OpcodeCleanup.cpp \
|
||||
src/sfizz/Opcode.cpp \
|
||||
src/sfizz/Oversampler.cpp \
|
||||
src/sfizz/Panning.cpp \
|
||||
src/sfizz/Parser.cpp \
|
||||
src/sfizz/parser/Parser.cpp \
|
||||
src/sfizz/parser/ParserPrivate.cpp \
|
||||
src/sfizz/PolyphonyGroup.cpp \
|
||||
|
|
@ -102,22 +112,26 @@ SFIZZ_SOURCES = \
|
|||
src/sfizz/sfizz.cpp \
|
||||
src/sfizz/sfizz_wrapper.cpp \
|
||||
src/sfizz/SfzFilter.cpp \
|
||||
src/sfizz/SfzHelpers.cpp \
|
||||
src/sfizz/SIMDHelpers.cpp \
|
||||
src/sfizz/simd/HelpersSSE.cpp \
|
||||
src/sfizz/simd/HelpersAVX.cpp \
|
||||
src/sfizz/Smoothers.cpp \
|
||||
src/sfizz/Synth.cpp \
|
||||
src/sfizz/SynthMessaging.cpp \
|
||||
src/sfizz/Tuning.cpp \
|
||||
src/sfizz/utility/SpinMutex.cpp \
|
||||
src/sfizz/utility/spin_mutex/SpinMutex.cpp \
|
||||
src/sfizz/Voice.cpp \
|
||||
src/sfizz/VoiceManager.cpp \
|
||||
src/sfizz/VoiceStealing.cpp \
|
||||
src/sfizz/Wavetables.cpp
|
||||
src/sfizz/Wavetables.cpp \
|
||||
src/sfizz/WindowedSinc.cpp
|
||||
|
||||
### Other internal
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/sfizz
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/src/sfizz \
|
||||
-I$(SFIZZ_DIR)/src/sfizz/utility/bit_array \
|
||||
-I$(SFIZZ_DIR)/src/sfizz/utility/spin_mutex
|
||||
|
||||
# Pkg-config dependency
|
||||
|
||||
|
|
@ -125,13 +139,69 @@ SFIZZ_PKG_CONFIG ?= pkg-config
|
|||
|
||||
# Sndfile dependency
|
||||
|
||||
ifeq ($(SFIZZ_USE_SNDFILE),1)
|
||||
SFIZZ_SNDFILE_C_FLAGS ?= $(shell $(SFIZZ_PKG_CONFIG) --cflags sndfile)
|
||||
SFIZZ_SNDFILE_CXX_FLAGS ?= $(SFIZZ_SNDFILE_C_FLAGS)
|
||||
SFIZZ_SNDFILE_LINK_FLAGS ?= $(shell $(SFIZZ_PKG_CONFIG) --libs sndfile)
|
||||
|
||||
SFIZZ_C_FLAGS += $(SFIZZ_SNDFILE_C_FLAGS)
|
||||
SFIZZ_CXX_FLAGS += $(SFIZZ_SNDFILE_CXX_FLAGS)
|
||||
SFIZZ_C_FLAGS += -DSFIZZ_USE_SNDFILE=1
|
||||
SFIZZ_CXX_FLAGS += -DSFIZZ_USE_SNDFILE=1
|
||||
endif
|
||||
|
||||
# st_audiofile dependency
|
||||
|
||||
SFIZZ_SOURCES += \
|
||||
external/st_audiofile/src/st_audiofile.c \
|
||||
external/st_audiofile/src/st_audiofile_common.c \
|
||||
external/st_audiofile/src/st_audiofile_libs.c \
|
||||
external/st_audiofile/src/st_audiofile_sndfile.c
|
||||
|
||||
ifneq ($(SFIZZ_USE_SNDFILE),1)
|
||||
SFIZZ_SOURCES += \
|
||||
external/st_audiofile/src/st_audiofile_libs.c
|
||||
endif
|
||||
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/src \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/thirdparty/dr_libs \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/thirdparty/stb_vorbis
|
||||
SFIZZ_CXX_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/src \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/thirdparty/dr_libs \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/thirdparty/stb_vorbis
|
||||
|
||||
ifeq ($(SFIZZ_USE_SNDFILE),1)
|
||||
SFIZZ_C_FLAGS += $(SFIZZ_SNDFILE_C_FLAGS) -DST_AUDIO_FILE_USE_SNDFILE=1
|
||||
SFIZZ_CXX_FLAGS += $(SFIZZ_SNDFILE_CXX_FLAGS) -DST_AUDIO_FILE_USE_SNDFILE=1
|
||||
SFIZZ_LINK_FLAGS += $(SFIZZ_SNDFILE_LINK_FLAGS)
|
||||
endif
|
||||
|
||||
# libaiff dependency
|
||||
|
||||
ifneq ($(SFIZZ_USE_SNDFILE),1)
|
||||
SFIZZ_SOURCES += \
|
||||
external/st_audiofile/thirdparty/libaiff/libaiff.all.c
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/thirdparty/libaiff
|
||||
SFIZZ_CXX_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/st_audiofile/thirdparty/libaiff
|
||||
endif
|
||||
|
||||
# hiir dependency
|
||||
|
||||
SFIZZ_CXX_FLAGS += -I$(SFIZZ_DIR)/src/external/hiir
|
||||
|
||||
# threadpool dependency
|
||||
|
||||
SFIZZ_CXX_FLAGS += -I$(SFIZZ_DIR)/external/threadpool
|
||||
|
||||
# atomic_queue dependency
|
||||
|
||||
SFIZZ_CXX_FLAGS += -I$(SFIZZ_DIR)/external/atomic_queue/include
|
||||
|
||||
# ghc::filesystem dependency
|
||||
|
||||
SFIZZ_CXX_FLAGS += -I$(SFIZZ_DIR)/external/filesystem/include
|
||||
|
||||
### Abseil dependency
|
||||
|
||||
|
|
@ -146,9 +216,6 @@ SFIZZ_SOURCES += \
|
|||
# absl::exponential_biased
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/exponential_biased.cc
|
||||
# absl::dynamic_annotations
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/dynamic_annotations.cc
|
||||
# absl::malloc_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/low_level_alloc.cc
|
||||
|
|
@ -233,6 +300,9 @@ SFIZZ_SOURCES += \
|
|||
# absl::city
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/hash/internal/city.cc
|
||||
# absl::wyhash
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/hash/internal/wyhash.cc
|
||||
# absl::int128
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/numeric/int128.cc
|
||||
|
|
@ -255,6 +325,10 @@ SFIZZ_SOURCES += \
|
|||
src/external/cpuid/src/cpuid/cpuinfo.cpp \
|
||||
src/external/cpuid/src/cpuid/version.cpp
|
||||
|
||||
### simde dependency
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/simde
|
||||
|
||||
### Pugixml dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/pugixml/src
|
||||
|
|
@ -281,6 +355,12 @@ SFIZZ_SOURCES += \
|
|||
SFIZZ_CXX_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/jsl/include
|
||||
|
||||
### cephes dependency
|
||||
|
||||
SFIZZ_SOURCES += \
|
||||
external/cephes/src/chbevl.c \
|
||||
external/cephes/src/i0.c
|
||||
|
||||
### math dependency
|
||||
|
||||
ifdef SFIZZ_OS_LINUX
|
||||
|
|
@ -294,3 +374,9 @@ SFIZZ_C_FLAGS += -pthread
|
|||
SFIZZ_CXX_FLAGS += -pthread
|
||||
SFIZZ_LINK_FLAGS += -pthread
|
||||
endif
|
||||
|
||||
### OpenMP dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -fopenmp
|
||||
SFIZZ_CXX_FLAGS += -fopenmp
|
||||
SFIZZ_LINK_FLAGS += -fopenmp
|
||||
|
|
|
|||
51
demos/CMakeLists.txt
Normal file
51
demos/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
if(TARGET Qt5::Widgets AND TARGET sfizz::jack)
|
||||
add_executable(sfizz_demo_filters DemoFilters.cpp)
|
||||
target_link_libraries(sfizz_demo_filters PRIVATE sfizz::internal sfizz::jack Qt5::Widgets)
|
||||
set_target_properties(sfizz_demo_filters PROPERTIES AUTOUIC ON)
|
||||
|
||||
add_executable(sfizz_demo_smooth DemoSmooth.cpp)
|
||||
target_link_libraries(sfizz_demo_smooth PRIVATE sfizz::internal sfizz::jack Qt5::Widgets)
|
||||
set_target_properties(sfizz_demo_smooth PROPERTIES AUTOUIC ON)
|
||||
|
||||
add_executable(sfizz_demo_stereo DemoStereo.cpp)
|
||||
target_link_libraries(sfizz_demo_stereo PRIVATE sfizz::internal sfizz::jack Qt5::Widgets)
|
||||
set_target_properties(sfizz_demo_stereo PROPERTIES AUTOUIC ON)
|
||||
|
||||
add_executable(sfizz_demo_wavetables DemoWavetables.cpp)
|
||||
target_link_libraries(sfizz_demo_wavetables PRIVATE sfizz::internal sfizz::jack Qt5::Widgets)
|
||||
set_target_properties(sfizz_demo_wavetables PROPERTIES AUTOUIC ON)
|
||||
endif()
|
||||
|
||||
if(TARGET Qt5::Widgets)
|
||||
add_executable(sfizz_demo_parser DemoParser.cpp)
|
||||
target_link_libraries(sfizz_demo_parser PRIVATE sfizz::parser Qt5::Widgets)
|
||||
set_target_properties(sfizz_demo_parser PROPERTIES AUTOUIC ON)
|
||||
|
||||
add_executable(sfizz_demo_stretch_tuning DemoStretchTuning.cpp)
|
||||
target_link_libraries(sfizz_demo_stretch_tuning PRIVATE sfizz::internal Qt5::Widgets)
|
||||
set_target_properties(sfizz_demo_stretch_tuning PROPERTIES AUTOUIC ON)
|
||||
endif()
|
||||
|
||||
add_executable(eq_apply EQ.cpp)
|
||||
target_link_libraries(eq_apply PRIVATE sfizz::internal sfizz::sndfile sfizz::cxxopts sfizz::filesystem)
|
||||
|
||||
add_executable(filter_apply Filter.cpp)
|
||||
target_link_libraries(filter_apply PRIVATE sfizz::internal sfizz::sndfile sfizz::cxxopts sfizz::filesystem)
|
||||
|
||||
add_executable(sfizz_plot_curve PlotCurve.cpp)
|
||||
target_link_libraries(sfizz_plot_curve PRIVATE sfizz::internal)
|
||||
|
||||
add_executable(sfizz_plot_wavetables PlotWavetables.cpp)
|
||||
target_link_libraries(sfizz_plot_wavetables PRIVATE sfizz::internal)
|
||||
|
||||
add_executable(sfizz_plot_lfo PlotLFO.cpp)
|
||||
target_link_libraries(sfizz_plot_lfo PRIVATE sfizz::internal sfizz::sndfile sfizz::cxxopts)
|
||||
|
||||
add_executable(sfizz_file_instrument FileInstrument.cpp)
|
||||
target_link_libraries(sfizz_file_instrument PRIVATE sfizz::internal sfizz::sndfile)
|
||||
|
||||
add_executable(sfizz_file_wavetable FileWavetable.cpp)
|
||||
target_link_libraries(sfizz_file_wavetable PRIVATE sfizz::internal)
|
||||
|
||||
add_executable(sfizz_tuning Tuning.cpp)
|
||||
target_link_libraries(sfizz_tuning PRIVATE sfizz::internal sfizz::cxxopts)
|
||||
|
|
@ -247,7 +247,7 @@ void DemoApp::initWindow()
|
|||
grpMode->setExclusive(true);
|
||||
|
||||
connect(
|
||||
grpMode, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this,
|
||||
grpMode, &QButtonGroup::idToggled, this,
|
||||
[this](int id, bool toggled) {
|
||||
if (toggled)
|
||||
valueChangedFilterMode(id);
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
#include "sfizz/SfzFilter.h"
|
||||
#include "sfizz/Buffer.h"
|
||||
#include "sfizz/SIMDHelpers.h"
|
||||
#include "ghc/filesystem.hpp"
|
||||
#include "cxxopts.hpp"
|
||||
#include "sfizz/StringViewHelpers.h"
|
||||
#include "sfizz/utility/StringViewHelpers.h"
|
||||
#include <sndfile.hh>
|
||||
#include <cxxopts.hpp>
|
||||
#include <ghc/fs_std.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
(void)argc;
|
||||
|
|
@ -12,20 +12,21 @@
|
|||
static const char* modeString(int mode, const char* valueFallback = nullptr)
|
||||
{
|
||||
switch (mode) {
|
||||
case SF_LOOP_NONE:
|
||||
case sfz::LoopNone:
|
||||
return "none";
|
||||
case SF_LOOP_FORWARD:
|
||||
case sfz::LoopForward:
|
||||
return "forward";
|
||||
case SF_LOOP_BACKWARD:
|
||||
case sfz::LoopBackward:
|
||||
return "backward";
|
||||
case SF_LOOP_ALTERNATING:
|
||||
case sfz::LoopAlternating:
|
||||
return "alternating";
|
||||
default:
|
||||
return valueFallback;
|
||||
}
|
||||
}
|
||||
|
||||
static void printInstrument(const SF_INSTRUMENT& ins)
|
||||
template <class Instrument>
|
||||
static void printInstrument(const Instrument& ins)
|
||||
{
|
||||
printf("Gain: %d\n", ins.gain);
|
||||
printf("Base note: %d\n", ins.basenote);
|
||||
|
|
@ -34,7 +35,7 @@ static void printInstrument(const SF_INSTRUMENT& ins)
|
|||
printf("Key: %d:%d\n", ins.key_lo, ins.key_hi);
|
||||
printf("Loop count: %d\n", ins.loop_count);
|
||||
|
||||
for (int i = 0; i < ins.loop_count; ++i) {
|
||||
for (unsigned i = 0, n = ins.loop_count; i < n; ++i) {
|
||||
printf("\nLoop %d:\n", i + 1);
|
||||
printf("\tMode: %s\n", modeString(ins.loops[i].mode, "(unknown)"));
|
||||
printf("\tStart: %u\n", ins.loops[i].start);
|
||||
|
|
@ -83,18 +84,18 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
SF_INSTRUMENT ins {};
|
||||
|
||||
if (method == kMethodRiff) {
|
||||
sfz::FileMetadataReader reader;
|
||||
if (!reader.open(path)) {
|
||||
fprintf(stderr, "Cannot open file\n");
|
||||
return 1;
|
||||
}
|
||||
if (!reader.extractRiffInstrument(ins)) {
|
||||
sfz::InstrumentInfo ins {};
|
||||
if (!reader.extractInstrument(ins)) {
|
||||
fprintf(stderr, "Cannot get instrument\n");
|
||||
return 1;
|
||||
}
|
||||
printInstrument(ins);
|
||||
}
|
||||
else {
|
||||
SndfileHandle sndFile(path);
|
||||
|
|
@ -102,13 +103,13 @@ int main(int argc, char *argv[])
|
|||
fprintf(stderr, "Cannot open file\n");
|
||||
return 1;
|
||||
}
|
||||
SF_INSTRUMENT ins {};
|
||||
if (sndFile.command(SFC_GET_INSTRUMENT, &ins, sizeof(ins)) != 1) {
|
||||
fprintf(stderr, "Cannot get instrument\n");
|
||||
return 1;
|
||||
}
|
||||
printInstrument(ins);
|
||||
}
|
||||
|
||||
printInstrument(ins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
#include "sfizz/SfzFilter.h"
|
||||
#include "sfizz/Buffer.h"
|
||||
#include "sfizz/SIMDHelpers.h"
|
||||
#include "ghc/filesystem.hpp"
|
||||
#include "cxxopts.hpp"
|
||||
#include "sfizz/StringViewHelpers.h"
|
||||
#include "sfizz/utility/StringViewHelpers.h"
|
||||
#include <sndfile.hh>
|
||||
#include <cxxopts.hpp>
|
||||
#include <ghc/fs_std.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
(void)argc;
|
||||
|
|
@ -17,12 +17,14 @@
|
|||
|
||||
#include "sfizz/Synth.h"
|
||||
#include "sfizz/LFO.h"
|
||||
#include "sfizz/Region.h"
|
||||
#include "sfizz/LFODescription.h"
|
||||
#include "sfizz/MathHelpers.h"
|
||||
#include "cxxopts.hpp"
|
||||
#include <absl/types/span.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cmath>
|
||||
#ifdef _WIN32
|
||||
#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
|
||||
|
|
@ -107,25 +109,34 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
constexpr size_t bufferSize = 1024;
|
||||
sfz::Resources resources;
|
||||
resources.setSamplesPerBlock(bufferSize);
|
||||
|
||||
size_t numLfos = desc.size();
|
||||
std::vector<sfz::LFO> lfos(numLfos);
|
||||
std::vector<std::unique_ptr<sfz::LFO>> lfos(numLfos);
|
||||
|
||||
for (size_t l = 0; l < numLfos; ++l) {
|
||||
lfos[l].setSampleRate(sampleRate);
|
||||
lfos[l].configure(&desc[l]);
|
||||
sfz::LFO* lfo = new sfz::LFO(resources);
|
||||
lfos[l].reset(lfo);
|
||||
lfo->setSampleRate(sampleRate);
|
||||
lfo->configure(&desc[l]);
|
||||
}
|
||||
|
||||
size_t numFrames = (size_t)std::ceil(sampleRate * duration);
|
||||
std::vector<float> outputMemory(numLfos * numFrames);
|
||||
|
||||
for (size_t l = 0; l < numLfos; ++l) {
|
||||
lfos[l].start(0);
|
||||
lfos[l]->start(0);
|
||||
}
|
||||
|
||||
std::vector<absl::Span<float>> lfoOutputs(numLfos);
|
||||
for (size_t l = 0; l < numLfos; ++l) {
|
||||
lfoOutputs[l] = absl::MakeSpan(&outputMemory[l * numFrames], numFrames);
|
||||
lfos[l].process(lfoOutputs[l]);
|
||||
for (size_t i = 0, currentFrames; i < numFrames; i += currentFrames) {
|
||||
currentFrames = std::min(numFrames - i, bufferSize);
|
||||
lfos[l]->process(lfoOutputs[l].subspan(i, currentFrames));
|
||||
}
|
||||
}
|
||||
|
||||
if (saveFlac) {
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
###############################
|
||||
# Developer tools
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(PKGCONFIG_FOUND)
|
||||
pkg_check_modules(JACK "jack")
|
||||
endif()
|
||||
find_package(Qt5 COMPONENTS Widgets)
|
||||
|
||||
if(JACK_FOUND AND TARGET Qt5::Widgets)
|
||||
if(TARGET sfizz::jack AND TARGET Qt5::Widgets)
|
||||
add_executable(sfizz_capture_eg CaptureEG.h CaptureEG.cpp)
|
||||
target_include_directories(sfizz_capture_eg PRIVATE . ${JACK_INCLUDE_DIRS})
|
||||
target_link_libraries(sfizz_capture_eg PRIVATE sfizz-sndfile Qt5::Widgets ${JACK_LIBRARIES})
|
||||
target_include_directories(sfizz_capture_eg PRIVATE .)
|
||||
target_link_libraries(sfizz_capture_eg PRIVATE sfizz::sndfile Qt5::Widgets sfizz::jack)
|
||||
set_target_properties(sfizz_capture_eg PROPERTIES AUTOUIC ON)
|
||||
endif()
|
||||
|
||||
add_executable(sfizz_preprocessor Preprocessor.cpp)
|
||||
target_link_libraries(sfizz_preprocessor sfizz_parser)
|
||||
target_link_libraries(sfizz_preprocessor PRIVATE sfizz::parser sfizz::pugixml sfizz::cxxopts)
|
||||
|
||||
add_executable(sfizz_importer Importer.cpp)
|
||||
target_link_libraries(sfizz_importer PRIVATE sfizz::import)
|
||||
|
||||
add_executable(sfizz_hiir_designer HIIRDesigner.cpp)
|
||||
target_link_libraries(sfizz_hiir_designer PRIVATE sfizz::hiir_polyphase_iir2designer)
|
||||
|
|
|
|||
420
devtools/HIIRDesigner.cpp
Normal file
420
devtools/HIIRDesigner.cpp
Normal file
|
|
@ -0,0 +1,420 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include <hiir/PolyphaseIir2Designer.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
using FD = hiir::PolyphaseIir2Designer;
|
||||
|
||||
struct Stage {
|
||||
int factor;
|
||||
double tbw;
|
||||
int nbr_coefs;
|
||||
std::unique_ptr<double[]> coefs;
|
||||
};
|
||||
|
||||
static std::vector<Stage> calculate_stages(int oversampling, double attenuation, double transition);
|
||||
static void generate_cpp_prologue(int argc, char *argv[]);
|
||||
static void generate_cpp_epilogue();
|
||||
static void generate_cpp_coefs(const Stage *stages, int num_stages);
|
||||
static void generate_cpp_upsampler(const Stage *stages, int num_stages);
|
||||
static void generate_cpp_downsampler(const Stage *stages, int num_stages);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
double attenuation = 0.0;
|
||||
double transition = 0.0;
|
||||
int oversampling = 16;
|
||||
bool have_a = false;
|
||||
bool have_t = false;
|
||||
|
||||
for (int argi = 1; argi < argc; ++argi) {
|
||||
const char *arg = argv[argi];
|
||||
if (!strcmp(arg, "-a")) {
|
||||
if (++argi >= argc) {
|
||||
fprintf(stderr, "The option %s expects a value.\n", arg);
|
||||
return 1;
|
||||
}
|
||||
arg = argv[argi];
|
||||
attenuation = atof(arg);
|
||||
have_a = true;
|
||||
}
|
||||
else if (!strcmp(arg, "-t")) {
|
||||
if (++argi >= argc) {
|
||||
fprintf(stderr, "The option %s expects a value.\n", arg);
|
||||
return 1;
|
||||
}
|
||||
arg = argv[argi];
|
||||
transition = atof(arg);
|
||||
have_t = true;
|
||||
}
|
||||
else if (!strcmp(arg, "-o")) {
|
||||
if (++argi >= argc) {
|
||||
fprintf(stderr, "The option %s expects a value.\n", arg);
|
||||
return 1;
|
||||
}
|
||||
arg = argv[argi];
|
||||
oversampling = atoi(arg);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Unrecognized argument: %s\n", arg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_a) {
|
||||
fprintf(stderr, "No attenuation given (-a)\n");
|
||||
return 1;
|
||||
}
|
||||
if (!have_t) {
|
||||
fprintf(stderr, "No transition bandwidth given (-t)\n");
|
||||
return 1;
|
||||
}
|
||||
else if (attenuation < 0.0) {
|
||||
fprintf(stderr, "Invalid attenuation\n");
|
||||
return 1;
|
||||
}
|
||||
else if (transition <= 0.0 || transition >= 0.5) {
|
||||
fprintf(stderr, "Invalid transition bandwidth\n");
|
||||
return 1;
|
||||
}
|
||||
else if (oversampling < 2) {
|
||||
fprintf(stderr, "Invalid oversampling\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<Stage> stages = calculate_stages(oversampling, attenuation, transition);
|
||||
int num_stages = (int)stages.size();
|
||||
|
||||
// generate the coeffs
|
||||
generate_cpp_prologue(argc, argv);
|
||||
printf("\n");
|
||||
generate_cpp_coefs(stages.data(), num_stages);
|
||||
printf("\n");
|
||||
generate_cpp_upsampler(stages.data(), num_stages);
|
||||
printf("\n");
|
||||
generate_cpp_downsampler(stages.data(), num_stages);
|
||||
printf("\n");
|
||||
generate_cpp_epilogue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::vector<Stage> calculate_stages(int oversampling, double attenuation, double transition)
|
||||
{
|
||||
std::vector<Stage> stages;
|
||||
stages.reserve(8);
|
||||
|
||||
bool done = false;
|
||||
for (int num_stage = 0; !done; ++num_stage) {
|
||||
if (num_stage > 0)
|
||||
printf("\n");
|
||||
|
||||
Stage stage;
|
||||
stage.factor = 2 << num_stage;
|
||||
stage.tbw = transition *
|
||||
std::pow(0.5, num_stage) + 0.5 * (1 - std::pow(0.5, num_stage));
|
||||
|
||||
stage.nbr_coefs = FD::compute_nbr_coefs_from_proto(attenuation, stage.tbw);
|
||||
double *coefs = new double[stage.nbr_coefs]{};
|
||||
stage.coefs.reset(coefs);
|
||||
|
||||
FD::compute_coefs(coefs, attenuation, stage.tbw);
|
||||
|
||||
done = stage.factor >= oversampling;
|
||||
|
||||
stages.push_back(std::move(stage));
|
||||
}
|
||||
|
||||
return stages;
|
||||
}
|
||||
|
||||
static void generate_cpp_prologue(int argc, char *argv[])
|
||||
{
|
||||
printf("//------------------------------------------------------------------------------\n");
|
||||
printf("// This is generated by the Sfizz HIIR designer\n");
|
||||
printf("// Using options:");
|
||||
for (int i = 1; i < argc; ++i)
|
||||
printf(" %s", argv[i]);
|
||||
printf("\n");
|
||||
printf("//------------------------------------------------------------------------------\n");
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf(
|
||||
"#pragma once\n"
|
||||
"#include \"OversamplerHelpers.h\"\n"
|
||||
"#include \"MathHelpers\"\n"
|
||||
"\n"
|
||||
"namespace sfz {\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void generate_cpp_epilogue()
|
||||
{
|
||||
printf("} // namespace sfz\n");
|
||||
}
|
||||
|
||||
static void generate_cpp_coefs(const Stage *stages, int num_stages)
|
||||
{
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
const double *coefs = stage.coefs.get();
|
||||
printf("// %dx <-> %dx: TBW = %g\n", stage.factor, stage.factor / 2, stage.tbw);
|
||||
printf("static constexpr double OSCoeffs%dx[%d] = {\n", stage.factor, stage.nbr_coefs);
|
||||
for (int i = 0; i < stage.nbr_coefs; ++i) {
|
||||
printf("\t" "%.18f,\n", coefs[i]);
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_cpp_upsampler(const Stage *stages, int num_stages)
|
||||
{
|
||||
printf("class Upsampler {\n");
|
||||
printf("public:\n");
|
||||
|
||||
printf("\t" "Upsampler()\n");
|
||||
printf("\t" "{\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
printf("\t\t" "up%d_.set_coefs(OSCoeffs%dx);\n", stage.factor, stage.factor);
|
||||
}
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "void clear()\n");
|
||||
printf("\t" "{\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
printf("\t\t" "up%d_.clear_buffers();\n", stage.factor);
|
||||
}
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "static int recommendedBuffer(int factor, int spl)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "switch (factor) {\n");
|
||||
printf("\t\t" "case 2:\n");
|
||||
printf("\t\t\t" "return 0;\n");
|
||||
printf("\t\t" "case 4:\n");
|
||||
printf("\t\t\t" "return 2 * spl;\n");
|
||||
printf("\t\t" "default:\n");
|
||||
printf("\t\t\t" "return factor * spl;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "static unsigned conversionFactor(double sourceRate, double targetRate)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "int factor = static_cast<int>(std::ceil(targetRate / sourceRate));\n");
|
||||
printf("\t\t" "factor = (factor > 1) ? factor : 1;\n");
|
||||
printf("\t\t" "factor = (factor < 128) ? factor : 128;\n");
|
||||
printf("\t\t" "return nextPow2(factor);\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "static bool canProcess(int factor)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "switch (factor) {\n");
|
||||
printf("\t\t" "case 1:\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
printf("\t\t" "case %d:\n", stage.factor);
|
||||
}
|
||||
printf("\t\t\t" "return true;\n");
|
||||
printf("\t\t" "default:\n");
|
||||
printf("\t\t\t" "return false;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "void process(int factor, const float *in, float *out, int spl, float *temp, int ntemp)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "switch (factor) {\n");
|
||||
printf("\t\t" "case 1:\n");
|
||||
printf("\t\t\t" "if (in != out) std::memcpy(out, in, spl * sizeof(float));\n");
|
||||
printf("\t\t\t" "break;\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
printf("\t\t" "case %d:\n", stage.factor);
|
||||
printf("\t\t\t" "process%dx(in, out, spl, temp, ntemp);\n", stage.factor);
|
||||
printf("\t\t\t" "break;\n");
|
||||
}
|
||||
printf("\t\t" "default:\n");
|
||||
printf("\t\t\t" "ASSERTFALSE;\n");
|
||||
printf("\t\t\t" "break;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
for (int n = 1; n <= num_stages; ++n) {
|
||||
// special case factor=2, buffer not required
|
||||
if (stages[n - 1].factor == 2) {
|
||||
printf("\t" "void process2x(const float *in, float *out, int spl, float * = nullptr, int = 0)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "up2_.process_block(out, in, spl);\n");
|
||||
printf("\t" "}\n");
|
||||
continue;
|
||||
}
|
||||
printf("\t" "void process%dx(const float *in, float *out, int spl, float *temp, int ntemp)\n", stages[n - 1].factor);
|
||||
printf("\t" "{\n");
|
||||
// special case factor=4, only 1 buffer required
|
||||
if (stages[n - 1].factor > 4)
|
||||
printf("\t\t" "int maxspl = ntemp / %d;\n", stages[n - 1].factor);
|
||||
else
|
||||
printf("\t\t" "int maxspl = ntemp / %d;\n", stages[n - 1].factor / 2);
|
||||
printf("\t\t" "ASSERT(maxspl > 0);\n");
|
||||
printf("\t\t" "float *t1 = temp;\n");
|
||||
if (stages[n - 1].factor > 4)
|
||||
printf("\t\t" "float *t2 = temp + %d * maxspl;\n", stages[n - 1].factor / 2);
|
||||
printf("\t\t" "while (spl > 0) {\n");
|
||||
printf("\t\t\t" "int curspl = (spl < maxspl) ? spl : maxspl;\n");
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
const char *tempnames[] = {"t1", "t2"};
|
||||
const char *outname = tempnames[i & 1];
|
||||
const char *inname = tempnames[1 - (i & 1)];
|
||||
if (i == 0)
|
||||
inname = "in";
|
||||
if (i + 1 == n)
|
||||
outname = "out";
|
||||
printf("\t\t\t" "up%d_.process_block(%s, %s, %d * curspl);\n", stage.factor, outname, inname, stage.factor / 2);
|
||||
}
|
||||
printf("\t\t\t" "in += curspl;\n");
|
||||
printf("\t\t\t" "out += curspl;\n");
|
||||
printf("\t\t\t" "spl -= curspl;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
}
|
||||
|
||||
printf("private:\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
printf("\t" "hiir::Upsampler2x<%d> up%d_;\n", stage.nbr_coefs, stage.factor);
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static void generate_cpp_downsampler(const Stage *stages, int num_stages)
|
||||
{
|
||||
printf("class Downsampler {\n");
|
||||
printf("public:\n");
|
||||
|
||||
printf("\t" "Downsampler()\n");
|
||||
printf("\t" "{\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[num_stages - 1 - i];
|
||||
printf("\t\t" "down%d_.set_coefs(OSCoeffs%dx);\n", stage.factor, stage.factor);
|
||||
}
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "void clear()\n");
|
||||
printf("\t" "{\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[num_stages - 1 - i];
|
||||
printf("\t\t" "down%d_.clear_buffers();\n", stage.factor);
|
||||
}
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "static int recommendedBuffer(int factor, int spl)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "switch (factor) {\n");
|
||||
printf("\t\t" "case 2:\n");
|
||||
printf("\t\t\t" "return 0;\n");
|
||||
printf("\t\t" "case 4:\n");
|
||||
printf("\t\t\t" "return 2 * spl;\n");
|
||||
printf("\t\t" "default:\n");
|
||||
printf("\t\t\t" "return factor * spl;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "static unsigned conversionFactor(double sourceRate, double targetRate)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "int factor = static_cast<int>(std::ceil(targetRate / sourceRate));\n");
|
||||
printf("\t\t" "factor = (factor > 1) ? factor : 1;\n");
|
||||
printf("\t\t" "factor = (factor < 128) ? factor : 128;\n");
|
||||
printf("\t\t" "return nextPow2(factor);\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "static bool canProcess(int factor)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "switch (factor) {\n");
|
||||
printf("\t\t" "case 1:\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[i];
|
||||
printf("\t\t" "case %d:\n", stage.factor);
|
||||
}
|
||||
printf("\t\t\t" "return true;\n");
|
||||
printf("\t\t" "default:\n");
|
||||
printf("\t\t\t" "return false;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
printf("\t" "void process(int factor, const float *in, float *out, int spl, float *temp, int ntemp)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "switch (factor) {\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[num_stages - 1 - i];
|
||||
printf("\t\t" "case %d:\n", stage.factor);
|
||||
printf("\t\t\t" "process%dx(in, out, spl, temp, ntemp);\n", stage.factor);
|
||||
printf("\t\t\t" "break;\n");
|
||||
}
|
||||
printf("\t\t" "case 1:\n");
|
||||
printf("\t\t\t" "if (in != out) std::memcpy(out, in, spl * sizeof(float));\n");
|
||||
printf("\t\t\t" "break;\n");
|
||||
printf("\t\t" "default:\n");
|
||||
printf("\t\t\t" "ASSERTFALSE;\n");
|
||||
printf("\t\t\t" "break;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
|
||||
for (int n = 1; n <= num_stages; ++n) {
|
||||
// special case factor=2, buffer not required
|
||||
if (stages[n - 1].factor == 2) {
|
||||
printf("\t" "void process2x(const float *in, float *out, int spl, float * = nullptr, int = 0)\n");
|
||||
printf("\t" "{\n");
|
||||
printf("\t\t" "down2_.process_block(out, in, spl);\n");
|
||||
printf("\t" "}\n");
|
||||
continue;
|
||||
}
|
||||
printf("\t" "void process%dx(const float *in, float *out, int spl, float *temp, int ntemp)\n", stages[n - 1].factor);
|
||||
printf("\t" "{\n");
|
||||
// special case factor=4, only 1 buffer required
|
||||
if (stages[n - 1].factor > 4)
|
||||
printf("\t\t" "int maxspl = ntemp / %d;\n", stages[n - 1].factor);
|
||||
else
|
||||
printf("\t\t" "int maxspl = ntemp / %d;\n", stages[n - 1].factor / 2);
|
||||
printf("\t\t" "ASSERT(maxspl > 0);\n");
|
||||
printf("\t\t" "float *t1 = temp;\n");
|
||||
if (stages[n - 1].factor > 4)
|
||||
printf("\t\t" "float *t2 = temp + %d * maxspl;\n", stages[n - 1].factor / 2);
|
||||
printf("\t\t" "while (spl > 0) {\n");
|
||||
printf("\t\t\t" "int curspl = (spl < maxspl) ? spl : maxspl;\n");
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const Stage &stage = stages[n - 1 - i];
|
||||
const char *tempnames[] = {"t1", "t2"};
|
||||
const char *outname = tempnames[i & 1];
|
||||
const char *inname = tempnames[1 - (i & 1)];
|
||||
if (i == 0)
|
||||
inname = "in";
|
||||
if (i + 1 == n)
|
||||
outname = "out";
|
||||
printf("\t\t\t" "down%d_.process_block(%s, %s, %d * curspl);\n", stage.factor, outname, inname, stage.factor / 2);
|
||||
}
|
||||
printf("\t\t\t" "in += curspl;\n");
|
||||
printf("\t\t\t" "out += curspl;\n");
|
||||
printf("\t\t\t" "spl -= curspl;\n");
|
||||
printf("\t\t" "}\n");
|
||||
printf("\t" "}\n");
|
||||
}
|
||||
|
||||
printf("private:\n");
|
||||
for (int i = 0; i < num_stages; ++i) {
|
||||
const Stage &stage = stages[num_stages - 1 - i];
|
||||
printf("\t" "hiir::Downsampler2x<%d> down%d_;\n", stage.nbr_coefs, stage.factor);
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
39
devtools/Importer.cpp
Normal file
39
devtools/Importer.cpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include "sfizz/import/ForeignInstrument.h"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const sfz::InstrumentFormatRegistry& formatRegistry = sfz::InstrumentFormatRegistry::getInstance();
|
||||
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: sfizz_importer <foreign-instrument>\n";
|
||||
std::cerr << "--\n" "Supported formats:\n";
|
||||
for (const sfz::InstrumentFormat* format : formatRegistry.getAllFormats())
|
||||
std::cerr << " * " << format->name() << '\n';
|
||||
return 1;
|
||||
}
|
||||
|
||||
const fs::path foreignPath = fs::u8path(argv[1]);
|
||||
|
||||
const sfz::InstrumentFormat* format = formatRegistry.getMatchingFormat(foreignPath);
|
||||
|
||||
if (!format) {
|
||||
std::cerr << "There is no support for files of this format.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto importer = format->createImporter();
|
||||
std::string text = importer->convertToSfz(foreignPath);
|
||||
|
||||
if (text.empty()) {
|
||||
std::cerr << "The conversion has failed.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << text;
|
||||
if (text.back() != '\n')
|
||||
std::cout << '\n';
|
||||
std::cout << std::flush;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -13,10 +13,18 @@
|
|||
*/
|
||||
|
||||
#include "parser/Parser.h"
|
||||
#include "../tests/cxxopts.hpp"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include <pugixml.hpp>
|
||||
#include <cxxopts.hpp>
|
||||
#include <absl/strings/string_view.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
enum Mode { OutputSFZ, OutputXML };
|
||||
Mode g_mode = OutputSFZ;
|
||||
|
||||
pugi::xml_document g_xml_doc;
|
||||
}
|
||||
|
||||
class MyParserListener : public sfz::Parser::Listener {
|
||||
public:
|
||||
explicit MyParserListener(sfz::Parser& parser)
|
||||
|
|
@ -27,10 +35,20 @@ public:
|
|||
protected:
|
||||
void onParseFullBlock(const std::string& header, const std::vector<sfz::Opcode>& opcodes) override
|
||||
{
|
||||
std::cout << '\n';
|
||||
std::cout << '<' << header << '>' << '\n';
|
||||
for (const sfz::Opcode& opc : opcodes)
|
||||
std::cout << opc.opcode << '=' << opc.value << '\n';
|
||||
if (g_mode == OutputSFZ) {
|
||||
std::cout << '\n';
|
||||
std::cout << '<' << header << '>' << '\n';
|
||||
for (const sfz::Opcode& opc : opcodes)
|
||||
std::cout << opc.name << '=' << opc.value << '\n';
|
||||
}
|
||||
else if (g_mode == OutputXML) {
|
||||
pugi::xml_node block_node = g_xml_doc.append_child(header.c_str());
|
||||
for (const sfz::Opcode& opc : opcodes) {
|
||||
pugi::xml_node opcode_node = block_node.append_child("opcode");
|
||||
opcode_node.append_attribute("name").set_value(opc.name.c_str());
|
||||
opcode_node.append_attribute("value").set_value(opc.value.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onParseError(const sfz::SourceRange& range, const std::string& message) override
|
||||
|
|
@ -58,6 +76,7 @@ int main(int argc, char *argv[])
|
|||
options.add_options()
|
||||
("D,define", "Add external definition", cxxopts::value<std::vector<std::string>>())
|
||||
("i,input", "Input SFZ file", cxxopts::value<std::string>())
|
||||
("m,mode", "Mode of operation (sfz, xml)", cxxopts::value<std::string>())
|
||||
("h,help", "Print usage");
|
||||
|
||||
options.parse_positional({"input"});
|
||||
|
|
@ -81,6 +100,18 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (result.count("mode")) {
|
||||
const std::string& modeString = result["mode"].as<std::string>();
|
||||
if (modeString == "sfz")
|
||||
g_mode = OutputSFZ;
|
||||
else if (modeString == "xml")
|
||||
g_mode = OutputXML;
|
||||
else {
|
||||
std::cerr << "Unknown mode of operation: " << modeString << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const fs::path sfzFilePath { result["input"].as<std::string>() };
|
||||
|
||||
sfz::Parser parser;
|
||||
|
|
@ -106,5 +137,8 @@ int main(int argc, char *argv[])
|
|||
if (parser.getErrorCount() > 0)
|
||||
return 1;
|
||||
|
||||
if (g_mode == OutputXML)
|
||||
g_xml_doc.save(std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
set(VSTGUI_BASEDIR "${CMAKE_CURRENT_SOURCE_DIR}/external/vstgui4")
|
||||
include("cmake/Vstgui.cmake")
|
||||
|
||||
set(EDITOR_RESOURCES
|
||||
logo.png
|
||||
logo_text.png
|
||||
logo_text_white.png
|
||||
logo_text@2x.png
|
||||
logo_text_white@2x.png
|
||||
background.png
|
||||
background@2x.png
|
||||
icon_white.png
|
||||
icon_white@2x.png
|
||||
knob48.png
|
||||
knob48@2x.png
|
||||
Fonts/sfizz-fluentui-system-r20.ttf
|
||||
Fonts/Roboto-Regular.ttf
|
||||
PARENT_SCOPE)
|
||||
|
||||
function(copy_editor_resources SOURCE_DIR DESTINATION_DIR)
|
||||
foreach(res ${EDITOR_RESOURCES})
|
||||
get_filename_component(_dir "${res}" DIRECTORY)
|
||||
file(MAKE_DIRECTORY "${DESTINATION_DIR}/${_dir}")
|
||||
file(COPY "${SOURCE_DIR}/${res}" DESTINATION "${DESTINATION_DIR}/${_dir}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# editor
|
||||
add_library(sfizz_editor STATIC EXCLUDE_FROM_ALL
|
||||
src/editor/EditIds.h
|
||||
src/editor/EditIds.cpp
|
||||
src/editor/Editor.h
|
||||
src/editor/Editor.cpp
|
||||
src/editor/EditorController.h
|
||||
src/editor/GUIComponents.h
|
||||
src/editor/GUIComponents.cpp
|
||||
src/editor/GUIPiano.h
|
||||
src/editor/GUIPiano.cpp
|
||||
src/editor/NativeHelpers.h
|
||||
src/editor/NativeHelpers.cpp
|
||||
src/editor/layout/main.hpp
|
||||
src/editor/utility/vstgui_after.h
|
||||
src/editor/utility/vstgui_before.h)
|
||||
target_include_directories(sfizz_editor PUBLIC "src")
|
||||
target_link_libraries(sfizz_editor PRIVATE sfizz-vstgui)
|
||||
target_link_libraries(sfizz_editor PUBLIC absl::strings)
|
||||
if(APPLE)
|
||||
find_library(APPLE_APPKIT_LIBRARY "AppKit")
|
||||
find_library(APPLE_CORESERVICES_LIBRARY "CoreServices")
|
||||
find_library(APPLE_FOUNDATION_LIBRARY "Foundation")
|
||||
target_sources(sfizz_editor PRIVATE
|
||||
src/editor/NativeHelpers.mm)
|
||||
target_link_libraries(sfizz_editor PRIVATE
|
||||
"${APPLE_APPKIT_LIBRARY}"
|
||||
"${APPLE_CORESERVICES_LIBRARY}"
|
||||
"${APPLE_FOUNDATION_LIBRARY}")
|
||||
target_compile_options(sfizz_editor PRIVATE "-fobjc-arc")
|
||||
endif()
|
||||
|
||||
# dependencies
|
||||
if(WIN32)
|
||||
#
|
||||
elseif(APPLE)
|
||||
#
|
||||
else()
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(sfizz-gio "gio-2.0" REQUIRED)
|
||||
target_include_directories(sfizz_editor PRIVATE ${sfizz-gio_INCLUDE_DIRS})
|
||||
target_link_libraries(sfizz_editor PRIVATE ${sfizz-gio_LIBRARIES})
|
||||
endif()
|
||||
target_include_directories(sfizz_editor PRIVATE "../src/external") # ghc::filesystem
|
||||
|
||||
# layout tool
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
add_executable(layout-maker
|
||||
"tools/layout-maker/sources/layout.h"
|
||||
"tools/layout-maker/sources/reader.cpp"
|
||||
"tools/layout-maker/sources/reader.h"
|
||||
"tools/layout-maker/sources/main.cpp")
|
||||
target_link_libraries(layout-maker PRIVATE absl::strings)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/editor/layout/main.hpp"
|
||||
COMMAND "$<TARGET_FILE:layout-maker>"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/layout/main.fl"
|
||||
> "${CMAKE_CURRENT_SOURCE_DIR}/src/editor/layout/main.hpp"
|
||||
DEPENDS layout-maker "${CMAKE_CURRENT_SOURCE_DIR}/layout/main.fl")
|
||||
endif()
|
||||
1
editor/external/vstgui4
vendored
1
editor/external/vstgui4
vendored
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 055cbcc9ae858f0b07d5d86c205a1111e2fba7a4
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#pragma once
|
||||
#include <cassert>
|
||||
|
||||
enum class EditId : int {
|
||||
SfzFile,
|
||||
Volume,
|
||||
Polyphony,
|
||||
Oversampling,
|
||||
PreloadSize,
|
||||
ScalaFile,
|
||||
ScalaRootKey,
|
||||
TuningFrequency,
|
||||
StretchTuning,
|
||||
UINumCurves,
|
||||
UINumMasters,
|
||||
UINumGroups,
|
||||
UINumRegions,
|
||||
UINumPreloadedSamples,
|
||||
UINumActiveVoices,
|
||||
UIActivePanel,
|
||||
};
|
||||
|
||||
struct EditRange {
|
||||
float def = 0.0;
|
||||
float min = 0.0;
|
||||
float max = 1.0;
|
||||
constexpr EditRange() = default;
|
||||
constexpr EditRange(float def, float min, float max)
|
||||
: def(def), min(min), max(max) {}
|
||||
static EditRange get(EditId id);
|
||||
};
|
||||
|
|
@ -1,495 +0,0 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "GUIComponents.h"
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
|
||||
#include "utility/vstgui_before.h"
|
||||
#include "vstgui/lib/cdrawcontext.h"
|
||||
#include "vstgui/lib/cgraphicspath.h"
|
||||
#include "vstgui/lib/cframe.h"
|
||||
#include "utility/vstgui_after.h"
|
||||
|
||||
///
|
||||
SBoxContainer::SBoxContainer(const CRect& size)
|
||||
: CViewContainer(size)
|
||||
{
|
||||
CViewContainer::setBackgroundColor(CColor(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
void SBoxContainer::setCornerRadius(CCoord radius)
|
||||
{
|
||||
cornerRadius_ = radius;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SBoxContainer::setBackgroundColor(const CColor& color)
|
||||
{
|
||||
backgroundColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
CColor SBoxContainer::getBackgroundColor() const
|
||||
{
|
||||
return backgroundColor_;
|
||||
}
|
||||
|
||||
void SBoxContainer::drawRect(CDrawContext* dc, const CRect& updateRect)
|
||||
{
|
||||
CRect bounds = getViewSize();
|
||||
|
||||
dc->setDrawMode(kAntiAliasing);
|
||||
|
||||
SharedPointer<CGraphicsPath> path = owned(dc->createGraphicsPath());
|
||||
path->addRoundRect(bounds, cornerRadius_);
|
||||
|
||||
dc->setFillColor(backgroundColor_);
|
||||
dc->drawGraphicsPath(path.get(), CDrawContext::kPathFilled);
|
||||
|
||||
CViewContainer::drawRect(dc, updateRect);
|
||||
}
|
||||
|
||||
///
|
||||
STitleContainer::STitleContainer(const CRect& size, UTF8StringPtr text)
|
||||
: SBoxContainer(size), text_(text ? text : ""), titleFont_(kNormalFont)
|
||||
{
|
||||
}
|
||||
|
||||
void STitleContainer::setTitleFont(CFontRef font)
|
||||
{
|
||||
titleFont_ = font;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void STitleContainer::setTitleFontColor(CColor color)
|
||||
{
|
||||
titleFontColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void STitleContainer::setTitleBackgroundColor(CColor color)
|
||||
{
|
||||
titleBackgroundColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void STitleContainer::drawRect(CDrawContext* dc, const CRect& updateRect)
|
||||
{
|
||||
SBoxContainer::drawRect(dc, updateRect);
|
||||
|
||||
CRect bounds = getViewSize();
|
||||
CCoord cornerRadius = cornerRadius_;
|
||||
|
||||
dc->setDrawMode(kAntiAliasing);
|
||||
|
||||
CCoord fontHeight = titleFont_->getSize();
|
||||
CCoord titleHeight = fontHeight + 8.0;
|
||||
|
||||
CRect titleBounds = bounds;
|
||||
titleBounds.bottom = titleBounds.top + titleHeight;
|
||||
|
||||
SharedPointer<CGraphicsPath> path = owned(dc->createGraphicsPath());
|
||||
path->beginSubpath(titleBounds.getBottomRight());
|
||||
path->addLine(titleBounds.getBottomLeft());
|
||||
path->addArc(CRect(titleBounds.left, titleBounds.top, titleBounds.left + 2.0 * cornerRadius, titleBounds.top + 2.0 * cornerRadius), 180., 270., true);
|
||||
path->addArc(CRect(titleBounds.right - 2.0 * cornerRadius, titleBounds.top, titleBounds.right, titleBounds.top + 2.0 * cornerRadius), 270., 360., true);
|
||||
path->closeSubpath();
|
||||
|
||||
dc->setFillColor(titleBackgroundColor_);
|
||||
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
|
||||
|
||||
dc->setFont(titleFont_);
|
||||
dc->setFontColor(titleFontColor_);
|
||||
dc->drawString(text_.c_str(), titleBounds, kCenterText);
|
||||
}
|
||||
|
||||
///
|
||||
void SFileDropTarget::setFileDropFunction(FileDropFunction f)
|
||||
{
|
||||
dropFunction_ = std::move(f);
|
||||
}
|
||||
|
||||
DragOperation SFileDropTarget::onDragEnter(DragEventData data)
|
||||
{
|
||||
op_ = isFileDrop(data.drag) ?
|
||||
DragOperation::Copy : DragOperation::None;
|
||||
return op_;
|
||||
}
|
||||
|
||||
DragOperation SFileDropTarget::onDragMove(DragEventData data)
|
||||
{
|
||||
(void)data;
|
||||
return op_;
|
||||
}
|
||||
|
||||
void SFileDropTarget::onDragLeave(DragEventData data)
|
||||
{
|
||||
(void)data;
|
||||
op_ = DragOperation::None;
|
||||
}
|
||||
|
||||
bool SFileDropTarget::onDrop(DragEventData data)
|
||||
{
|
||||
if (op_ != DragOperation::Copy || !isFileDrop(data.drag))
|
||||
return false;
|
||||
|
||||
IDataPackage::Type type;
|
||||
const void* bytes;
|
||||
uint32_t size = data.drag->getData(0, bytes, type);
|
||||
std::string path(reinterpret_cast<const char*>(bytes), size);
|
||||
|
||||
if (dropFunction_)
|
||||
dropFunction_(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SFileDropTarget::isFileDrop(IDataPackage* package)
|
||||
{
|
||||
return package->getCount() == 1 &&
|
||||
package->getDataType(0) == IDataPackage::kFilePath;
|
||||
}
|
||||
|
||||
///
|
||||
SValueMenu::SValueMenu(const CRect& bounds, IControlListener* listener, int32_t tag)
|
||||
: CParamDisplay(bounds), menuListener_(owned(new MenuListener(*this)))
|
||||
{
|
||||
setListener(listener);
|
||||
setTag(tag);
|
||||
}
|
||||
|
||||
CMenuItem* SValueMenu::addEntry(CMenuItem* item, float value, int32_t index)
|
||||
{
|
||||
if (index < 0 || index > getNbEntries()) {
|
||||
menuItems_.emplace_back(owned(item));
|
||||
menuItemValues_.emplace_back(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
menuItems_.insert(menuItems_.begin() + index, owned(item));
|
||||
menuItemValues_.insert(menuItemValues_.begin() + index, value);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
CMenuItem* SValueMenu::addEntry(const UTF8String& title, float value, int32_t index, int32_t itemFlags)
|
||||
{
|
||||
if (title == "-")
|
||||
return addSeparator(index);
|
||||
CMenuItem* item = new CMenuItem(title, nullptr, 0, nullptr, itemFlags);
|
||||
return addEntry(item, value, index);
|
||||
}
|
||||
|
||||
CMenuItem* SValueMenu::addSeparator(int32_t index)
|
||||
{
|
||||
CMenuItem* item = new CMenuItem("", nullptr, 0, nullptr, CMenuItem::kSeparator);
|
||||
return addEntry(item, 0.0f, index);
|
||||
}
|
||||
|
||||
int32_t SValueMenu::getNbEntries() const
|
||||
{
|
||||
return static_cast<int32_t>(menuItems_.size());
|
||||
}
|
||||
|
||||
CMouseEventResult SValueMenu::onMouseDown(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
(void)where;
|
||||
|
||||
if (buttons & (kLButton|kRButton|kApple)) {
|
||||
CFrame* frame = getFrame();
|
||||
CRect bounds = getViewSize();
|
||||
|
||||
CPoint frameWhere = bounds.getBottomLeft();
|
||||
this->localToFrame(frameWhere);
|
||||
|
||||
auto self = shared(this);
|
||||
frame->doAfterEventProcessing([self, frameWhere]() {
|
||||
if (CFrame* frame = self->getFrame()) {
|
||||
SharedPointer<COptionMenu> menu = owned(new COptionMenu(CRect(), self->menuListener_, -1, nullptr, nullptr, COptionMenu::kPopupStyle));
|
||||
for (const SharedPointer<CMenuItem>& item : self->menuItems_) {
|
||||
menu->addEntry(item);
|
||||
item->remember(); // above call does not increment refcount
|
||||
}
|
||||
menu->setFont(self->getFont());
|
||||
menu->setFontColor(self->getFontColor());
|
||||
menu->setBackColor(self->getBackColor());
|
||||
menu->popup(frame, frameWhere + CPoint(0.0, 1.0));
|
||||
}
|
||||
});
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
|
||||
return kMouseEventNotHandled;
|
||||
}
|
||||
|
||||
void SValueMenu::onItemClicked(int32_t index)
|
||||
{
|
||||
float oldValue = getValue();
|
||||
setValue(menuItemValues_[index]);
|
||||
if (getValue() != oldValue)
|
||||
valueChanged();
|
||||
}
|
||||
|
||||
///
|
||||
SActionMenu::SActionMenu(const CRect& bounds, IControlListener* listener)
|
||||
: CParamDisplay(bounds), menuListener_(owned(new MenuListener(*this)))
|
||||
{
|
||||
setListener(listener);
|
||||
|
||||
auto toString = [](float, std::string& result, CParamDisplay* display) {
|
||||
result = static_cast<SActionMenu*>(display)->getTitle();
|
||||
return true;
|
||||
};
|
||||
|
||||
setValueToStringFunction2(toString);
|
||||
}
|
||||
|
||||
void SActionMenu::setTitle(std::string title)
|
||||
{
|
||||
title_ = std::move(title);
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SActionMenu::setHoverColor(const CColor& color)
|
||||
{
|
||||
hoverColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
CMenuItem* SActionMenu::addEntry(CMenuItem* item, int32_t tag, int32_t index)
|
||||
{
|
||||
if (index < 0 || index > getNbEntries()) {
|
||||
menuItems_.emplace_back(owned(item));
|
||||
menuItemTags_.emplace_back(tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
menuItems_.insert(menuItems_.begin() + index, owned(item));
|
||||
menuItemTags_.insert(menuItemTags_.begin() + index, tag);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
CMenuItem* SActionMenu::addEntry(const UTF8String& title, int32_t tag, int32_t index, int32_t itemFlags)
|
||||
{
|
||||
if (title == "-")
|
||||
return addSeparator(index);
|
||||
CMenuItem* item = new CMenuItem(title, nullptr, 0, nullptr, itemFlags);
|
||||
return addEntry(item, tag, index);
|
||||
}
|
||||
|
||||
CMenuItem* SActionMenu::addSeparator(int32_t index)
|
||||
{
|
||||
CMenuItem* item = new CMenuItem("", nullptr, 0, nullptr, CMenuItem::kSeparator);
|
||||
return addEntry(item, 0.0f, index);
|
||||
}
|
||||
|
||||
int32_t SActionMenu::getNbEntries() const
|
||||
{
|
||||
return static_cast<int32_t>(menuItems_.size());
|
||||
}
|
||||
|
||||
void SActionMenu::draw(CDrawContext* dc)
|
||||
{
|
||||
CColor backupColor = fontColor;
|
||||
if (hovered_)
|
||||
fontColor = hoverColor_;
|
||||
CParamDisplay::draw(dc);
|
||||
if (hovered_)
|
||||
fontColor = backupColor;
|
||||
}
|
||||
|
||||
CMouseEventResult SActionMenu::onMouseEntered(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
hovered_ = true;
|
||||
invalid();
|
||||
return CParamDisplay::onMouseEntered(where, buttons);
|
||||
}
|
||||
|
||||
CMouseEventResult SActionMenu::onMouseExited(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
hovered_ = false;
|
||||
invalid();
|
||||
return CParamDisplay::onMouseExited(where, buttons);
|
||||
}
|
||||
|
||||
CMouseEventResult SActionMenu::onMouseDown(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
(void)where;
|
||||
|
||||
if (buttons & (kLButton|kRButton|kApple)) {
|
||||
CFrame* frame = getFrame();
|
||||
CRect bounds = getViewSize();
|
||||
|
||||
CPoint frameWhere = bounds.getBottomLeft();
|
||||
this->localToFrame(frameWhere);
|
||||
|
||||
auto self = shared(this);
|
||||
frame->doAfterEventProcessing([self, frameWhere]() {
|
||||
if (CFrame* frame = self->getFrame()) {
|
||||
SharedPointer<COptionMenu> menu = owned(new COptionMenu(CRect(), self->menuListener_, -1, nullptr, nullptr, COptionMenu::kPopupStyle));
|
||||
for (const SharedPointer<CMenuItem>& item : self->menuItems_) {
|
||||
menu->addEntry(item);
|
||||
item->remember(); // above call does not increment refcount
|
||||
}
|
||||
menu->setFont(self->getFont());
|
||||
menu->setFontColor(self->getFontColor());
|
||||
menu->setBackColor(self->getBackColor());
|
||||
menu->popup(frame, frameWhere + CPoint(0.0, 1.0));
|
||||
}
|
||||
});
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
|
||||
return kMouseEventNotHandled;
|
||||
}
|
||||
|
||||
void SActionMenu::onItemClicked(int32_t index)
|
||||
{
|
||||
setTag(menuItemTags_[index]);
|
||||
setValue(1.0f);
|
||||
if (listener)
|
||||
listener->valueChanged(this);
|
||||
setValue(0.0f);
|
||||
if (listener)
|
||||
listener->valueChanged(this);
|
||||
}
|
||||
|
||||
///
|
||||
void STextButton::setHoverColor(const CColor& color)
|
||||
{
|
||||
hoverColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void STextButton::setInactiveColor(const CColor& color)
|
||||
{
|
||||
inactiveColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void STextButton::setInactive(bool b)
|
||||
{
|
||||
inactive_ = b;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void STextButton::draw(CDrawContext* context)
|
||||
{
|
||||
CColor backupColor = textColor;
|
||||
if (hovered_)
|
||||
textColor = hoverColor_; // textColor is protected
|
||||
else if (inactive_)
|
||||
textColor = inactiveColor_;
|
||||
CTextButton::draw(context);
|
||||
textColor = backupColor;
|
||||
}
|
||||
|
||||
|
||||
CMouseEventResult STextButton::onMouseEntered (CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
hovered_ = true;
|
||||
invalid();
|
||||
return CTextButton::onMouseEntered(where, buttons);
|
||||
}
|
||||
|
||||
CMouseEventResult STextButton::onMouseExited (CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
hovered_ = false;
|
||||
invalid();
|
||||
return CTextButton::onMouseExited(where, buttons);
|
||||
}
|
||||
|
||||
///
|
||||
SStyledKnob::SStyledKnob(const CRect& size, IControlListener* listener, int32_t tag)
|
||||
: CKnobBase(size, listener, tag, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void SStyledKnob::setActiveTrackColor(const CColor& color)
|
||||
{
|
||||
if (activeTrackColor_ == color)
|
||||
return;
|
||||
activeTrackColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SStyledKnob::setInactiveTrackColor(const CColor& color)
|
||||
{
|
||||
if (inactiveTrackColor_ == color)
|
||||
return;
|
||||
inactiveTrackColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SStyledKnob::setLineIndicatorColor(const CColor& color)
|
||||
{
|
||||
if (lineIndicatorColor_ == color)
|
||||
return;
|
||||
lineIndicatorColor_ = color;
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SStyledKnob::draw(CDrawContext* dc)
|
||||
{
|
||||
const CCoord lineWidth = 4.0;
|
||||
const CCoord indicatorLineLength = 10.0;
|
||||
const CCoord angleSpread = 250.0;
|
||||
const CCoord angle1 = 270.0 - 0.5 * angleSpread;
|
||||
const CCoord angle2 = 270.0 + 0.5 * angleSpread;
|
||||
|
||||
dc->setDrawMode(kAntiAliasing);
|
||||
|
||||
const CRect bounds = getViewSize();
|
||||
|
||||
// compute inner bounds
|
||||
CRect rect(bounds);
|
||||
rect.setWidth(std::min(rect.getWidth(), rect.getHeight()));
|
||||
rect.setHeight(rect.getWidth());
|
||||
rect.centerInside(bounds);
|
||||
rect.extend(-lineWidth, -lineWidth);
|
||||
|
||||
SharedPointer<CGraphicsPath> path;
|
||||
|
||||
// inactive track
|
||||
path = owned(dc->createGraphicsPath());
|
||||
path->addArc(rect, angle1, angle2, true);
|
||||
|
||||
dc->setFrameColor(inactiveTrackColor_);
|
||||
dc->setLineWidth(lineWidth);
|
||||
dc->setLineStyle(kLineSolid);
|
||||
dc->drawGraphicsPath(path, CDrawContext::kPathStroked);
|
||||
|
||||
// active track
|
||||
const CCoord v = getValueNormalized();
|
||||
const CCoord vAngle = angle1 + v * angleSpread;
|
||||
path = owned(dc->createGraphicsPath());
|
||||
path->addArc(rect, angle1, vAngle, true);
|
||||
|
||||
dc->setFrameColor(activeTrackColor_);
|
||||
dc->setLineWidth(lineWidth + 0.5);
|
||||
dc->setLineStyle(kLineSolid);
|
||||
dc->drawGraphicsPath(path, CDrawContext::kPathStroked);
|
||||
|
||||
// indicator line
|
||||
{
|
||||
CCoord module1 = 0.5 * rect.getWidth() - indicatorLineLength;
|
||||
CCoord module2 = 0.5 * rect.getWidth();
|
||||
std::complex<CCoord> c1 = std::polar(module1, vAngle * (M_PI / 180.0));
|
||||
std::complex<CCoord> c2 = std::polar(module2, vAngle * (M_PI / 180.0));
|
||||
|
||||
CPoint p1(c1.real(), c1.imag());
|
||||
CPoint p2(c2.real(), c2.imag());
|
||||
p1.offset(rect.getCenter());
|
||||
p2.offset(rect.getCenter());
|
||||
|
||||
dc->setFrameColor(lineIndicatorColor_);
|
||||
dc->setLineWidth(1.0);
|
||||
dc->setLineStyle(kLineSolid);
|
||||
dc->drawLine(p1, p2);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "GUIPiano.h"
|
||||
#include "utility/vstgui_before.h"
|
||||
#include "vstgui/lib/cdrawcontext.h"
|
||||
#include "vstgui/lib/cgraphicspath.h"
|
||||
#include "utility/vstgui_after.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
static constexpr CCoord keyoffs[12] = {0, 0.6, 1, 1.8, 2, 3,
|
||||
3.55, 4, 4.7, 5, 5.85, 6};
|
||||
static constexpr bool black[12] = {0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0};
|
||||
|
||||
SPiano::SPiano(CRect bounds)
|
||||
: CView(bounds)
|
||||
{
|
||||
setNumOctaves(10);
|
||||
}
|
||||
|
||||
void SPiano::setFont(CFontRef font)
|
||||
{
|
||||
font_ = font;
|
||||
getDimensions(true);
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SPiano::setNumOctaves(unsigned octs)
|
||||
{
|
||||
keyval_.resize(octs * 12);
|
||||
octs_ = std::max(1u, octs);
|
||||
getDimensions(true);
|
||||
invalid();
|
||||
}
|
||||
|
||||
void SPiano::draw(CDrawContext* dc)
|
||||
{
|
||||
const Dimensions dim = getDimensions(false);
|
||||
const unsigned octs = octs_;
|
||||
const unsigned keyCount = octs * 12;
|
||||
|
||||
dc->setDrawMode(kAntiAliasing);
|
||||
|
||||
if (backgroundFill_.alpha > 0) {
|
||||
SharedPointer<CGraphicsPath> path;
|
||||
path = owned(dc->createGraphicsPath());
|
||||
path->addRoundRect(dim.bounds, backgroundRadius_);
|
||||
dc->setFillColor(CColor(0xca, 0xca, 0xca));
|
||||
dc->drawGraphicsPath(path, CDrawContext::kPathFilled);
|
||||
}
|
||||
|
||||
for (unsigned key = 0; key < keyCount; ++key) {
|
||||
if (!black[key % 12]) {
|
||||
CRect rect = keyRect(key);
|
||||
CColor keycolor = whiteFill_;
|
||||
if (keyval_[key])
|
||||
keycolor = pressedFill_;
|
||||
dc->setFillColor(keycolor);
|
||||
dc->drawRect(rect, kDrawFilled);
|
||||
}
|
||||
}
|
||||
|
||||
dc->setFrameColor(outline_);
|
||||
dc->drawLine(dim.keyBounds.getTopLeft(), dim.keyBounds.getBottomLeft());
|
||||
for (unsigned key = 0; key < keyCount; ++key) {
|
||||
if (!black[key % 12]) {
|
||||
CRect rect = keyRect(key);
|
||||
dc->drawLine(rect.getTopRight(), rect.getBottomRight());
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned key = 0; key < keyCount; ++key) {
|
||||
if (black[key % 12]) {
|
||||
CRect rect = keyRect(key);
|
||||
CColor keycolor = blackFill_;
|
||||
if (keyval_[key])
|
||||
keycolor = pressedFill_;
|
||||
dc->setFillColor(keycolor);
|
||||
dc->drawRect(rect, kDrawFilled);
|
||||
dc->setFrameColor(outline_);
|
||||
dc->drawRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
if (const CFontRef& font = font_) {
|
||||
for (unsigned o = 0; o < octs; ++o) {
|
||||
CRect rect = keyRect(o * 12);
|
||||
CRect textRect(
|
||||
rect.left, dim.labelBounds.top,
|
||||
rect.right, dim.labelBounds.bottom);
|
||||
dc->setFont(font);
|
||||
dc->setFontColor(labelStroke_);
|
||||
std::string text = std::to_string(static_cast<int>(o) - 1);
|
||||
dc->drawString(text.c_str(), textRect, kCenterText);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
dc->setFrameColor(outline_);
|
||||
dc->drawLine(dim.keyBounds.getTopLeft(), dim.keyBounds.getTopRight());
|
||||
dc->setFrameColor(shadeOutline_);
|
||||
dc->drawLine(dim.keyBounds.getBottomLeft(), dim.keyBounds.getBottomRight());
|
||||
}
|
||||
|
||||
dc->setFrameColor(outline_);
|
||||
}
|
||||
|
||||
CMouseEventResult SPiano::onMouseDown(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
unsigned key = keyAtPos(where);
|
||||
if (key != ~0u) {
|
||||
keyval_[key] = 1;
|
||||
mousePressedKey_ = key;
|
||||
if (onKeyPressed)
|
||||
onKeyPressed(key, mousePressVelocity(key, where.y));
|
||||
invalid();
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
return CView::onMouseDown(where, buttons);
|
||||
}
|
||||
|
||||
CMouseEventResult SPiano::onMouseUp(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
unsigned key = mousePressedKey_;
|
||||
if (key != ~0u) {
|
||||
keyval_[key] = 0;
|
||||
if (onKeyReleased)
|
||||
onKeyReleased(key, mousePressVelocity(key, where.y));
|
||||
mousePressedKey_ = ~0u;
|
||||
invalid();
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
return CView::onMouseUp(where, buttons);
|
||||
}
|
||||
|
||||
CMouseEventResult SPiano::onMouseMoved(CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
if (mousePressedKey_ != ~0u) {
|
||||
unsigned key = keyAtPos(where);
|
||||
if (mousePressedKey_ != key) {
|
||||
keyval_[mousePressedKey_] = 0;
|
||||
if (onKeyReleased)
|
||||
onKeyReleased(mousePressedKey_, mousePressVelocity(key, where.y));
|
||||
// mousePressedKey_ = ~0u;
|
||||
if (key != ~0u) {
|
||||
keyval_[key] = 1;
|
||||
mousePressedKey_ = key;
|
||||
if (onKeyPressed)
|
||||
onKeyPressed(key, mousePressVelocity(key, where.y));
|
||||
}
|
||||
invalid();
|
||||
}
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
return CView::onMouseMoved(where, buttons);
|
||||
}
|
||||
|
||||
const SPiano::Dimensions& SPiano::getDimensions(bool forceUpdate) const
|
||||
{
|
||||
if (!forceUpdate && dim_.bounds == getViewSize())
|
||||
return dim_;
|
||||
|
||||
Dimensions dim;
|
||||
dim.bounds = getViewSize();
|
||||
dim.paddedBounds = CRect(dim.bounds)
|
||||
.extend(-2 * innerPaddingX_, -2 * innerPaddingY_);
|
||||
CCoord keyHeight = std::floor(dim.paddedBounds.getHeight());
|
||||
CCoord fontHeight = font_ ? font_->getSize() : 0.0;
|
||||
keyHeight -= spacingY_ + fontHeight;
|
||||
dim.keyBounds = CRect(dim.paddedBounds)
|
||||
.setHeight(keyHeight);
|
||||
dim.keyWidth = static_cast<unsigned>(
|
||||
dim.paddedBounds.getWidth() / octs_ / 7.0);
|
||||
dim.keyBounds.setWidth(dim.keyWidth * octs_ * 7.0);
|
||||
dim.keyBounds.offset(
|
||||
std::floor(0.5 * (dim.paddedBounds.getWidth() - dim.keyBounds.getWidth())), 0.0);
|
||||
|
||||
if (!font_)
|
||||
dim.labelBounds = CRect();
|
||||
else
|
||||
dim.labelBounds = CRect(
|
||||
dim.keyBounds.left, dim.keyBounds.bottom + spacingY_,
|
||||
dim.keyBounds.right, dim.keyBounds.bottom + spacingY_ + fontHeight);
|
||||
|
||||
dim_ = dim;
|
||||
return dim_;
|
||||
}
|
||||
|
||||
CRect SPiano::keyRect(const Dimensions& dim, unsigned key)
|
||||
{
|
||||
unsigned oct = key / 12;
|
||||
unsigned note = key % 12;
|
||||
unsigned keyw = dim.keyWidth;
|
||||
unsigned keyh = static_cast<unsigned>(dim.keyBounds.getHeight());
|
||||
CCoord octwidth = (keyoffs[11] + 1.0) * keyw;
|
||||
CCoord octx = octwidth * oct;
|
||||
CCoord notex = octx + keyoffs[note] * keyw;
|
||||
CCoord notew = black[note] ? (0.6 * keyw) : keyw;
|
||||
CCoord noteh = black[note] ? (0.6 * keyh) : keyh;
|
||||
return CRect(notex, 0.0, notex + notew, noteh).offset(dim.keyBounds.getTopLeft());
|
||||
}
|
||||
|
||||
CRect SPiano::keyRect(unsigned key) const
|
||||
{
|
||||
return keyRect(getDimensions(false), key);
|
||||
}
|
||||
|
||||
unsigned SPiano::keyAtPos(CPoint pos) const
|
||||
{
|
||||
const unsigned octs = octs_;
|
||||
|
||||
for (unsigned key = 0; key < octs * 12; ++key) {
|
||||
if (black[key % 12]) {
|
||||
if (keyRect(key).pointInside(pos))
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned key = 0; key < octs * 12; ++key) {
|
||||
if (!black[key % 12]) {
|
||||
if (keyRect(key).pointInside(pos))
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
float SPiano::mousePressVelocity(unsigned key, CCoord posY)
|
||||
{
|
||||
const CRect rect = keyRect(key);
|
||||
CCoord value = (posY - rect.top) / rect.getHeight();
|
||||
return std::max(0.0f, std::min(1.0f, static_cast<float>(value)));
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "NativeHelpers.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "ghc/fs_std.hpp"
|
||||
#include <windows.h>
|
||||
#include <cstring>
|
||||
|
||||
bool openFileInExternalEditor(const char *filename)
|
||||
{
|
||||
std::wstring path = fs::u8path(filename).wstring();
|
||||
|
||||
SHELLEXECUTEINFOW info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
info.cbSize = sizeof(info);
|
||||
info.fMask = SEE_MASK_CLASSNAME;
|
||||
info.lpVerb = L"open";
|
||||
info.lpFile = path.c_str();
|
||||
info.lpClass = L"txtfile";
|
||||
info.nShow = SW_SHOW;
|
||||
|
||||
return ShellExecuteExW(&info);
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
// implemented in NativeHelpers.mm
|
||||
#else
|
||||
#include <gio/gio.h>
|
||||
|
||||
bool openFileInExternalEditor(const char *filename)
|
||||
{
|
||||
GAppInfo* appinfo = g_app_info_get_default_for_type("text/plain", FALSE);
|
||||
if (!appinfo)
|
||||
return 1;
|
||||
|
||||
GList* files = nullptr;
|
||||
GFile* file = g_file_new_for_path(filename);
|
||||
files = g_list_append(files, file);
|
||||
gboolean success = g_app_info_launch(appinfo, files, nullptr, nullptr);
|
||||
g_object_unref(file);
|
||||
g_list_free(files);
|
||||
g_object_unref(appinfo);
|
||||
return success == TRUE;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
// This code is part of the sfizz library and is licensed under a BSD 2-clause
|
||||
// license. You should have receive a LICENSE.md file along with the code.
|
||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#include "NativeHelpers.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <CoreServices/CoreServices.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
bool openFileInExternalEditor(const char *fileNameUTF8)
|
||||
{
|
||||
BOOL wasOpened = NO;
|
||||
|
||||
NSURL* applicationURL = (__bridge_transfer NSURL*)LSCopyDefaultApplicationURLForContentType(
|
||||
kUTTypePlainText, kLSRolesEditor, nil);
|
||||
if (!applicationURL)
|
||||
return false;
|
||||
if ([applicationURL isFileURL]) {
|
||||
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
|
||||
NSString* fileName = [NSString stringWithUTF8String:fileNameUTF8];
|
||||
wasOpened = [workspace openFile:fileName withApplication:[applicationURL path]];
|
||||
}
|
||||
|
||||
return wasOpened == YES;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/* This file is generated by the layout maker tool. */
|
||||
LogicalGroup* const view__0 = createLogicalGroup(CRect(0, 0, 800, 475), -1, "", kCenterText, 14);
|
||||
mainView = view__0;
|
||||
Background* const view__1 = createBackground(CRect(190, 110, 790, 390), -1, "", kCenterText, 14);
|
||||
view__0->addView(view__1);
|
||||
enterTheme(darkTheme);
|
||||
LogicalGroup* const view__2 = createLogicalGroup(CRect(0, 0, 800, 110), -1, "", kCenterText, 14);
|
||||
view__0->addView(view__2);
|
||||
RoundedGroup* const view__3 = createRoundedGroup(CRect(5, 4, 180, 105), -1, "", kCenterText, 14);
|
||||
view__2->addView(view__3);
|
||||
SfizzMainButton* const view__4 = createSfizzMainButton(CRect(30, 5, 150, 65), kTagFirstChangePanel+kPanelGeneral, "", kCenterText, 14);
|
||||
view__3->addView(view__4);
|
||||
HomeButton* const view__5 = createHomeButton(CRect(44, 69, 69, 94), kTagFirstChangePanel+kPanelGeneral, "", kCenterText, 24);
|
||||
view__3->addView(view__5);
|
||||
CCButton* const view__6 = createCCButton(CRect(76, 69, 101, 94), kTagFirstChangePanel+kPanelControls, "", kCenterText, 24);
|
||||
view__3->addView(view__6);
|
||||
SettingsButton* const view__7 = createSettingsButton(CRect(107, 69, 132, 94), kTagFirstChangePanel+kPanelSettings, "", kCenterText, 24);
|
||||
view__3->addView(view__7);
|
||||
RoundedGroup* const view__8 = createRoundedGroup(CRect(185, 5, 565, 105), -1, "", kCenterText, 14);
|
||||
view__2->addView(view__8);
|
||||
HLine* const view__9 = createHLine(CRect(10, 36, 370, 41), -1, "", kCenterText, 14);
|
||||
view__8->addView(view__9);
|
||||
HLine* const view__10 = createHLine(CRect(10, 68, 370, 73), -1, "", kCenterText, 14);
|
||||
view__8->addView(view__10);
|
||||
ClickableLabel* const view__11 = createClickableLabel(CRect(10, 6, 260, 37), kTagLoadSfzFile, "DefaultInstrument.sfz", kLeftText, 20);
|
||||
sfzFileLabel_ = view__11;
|
||||
view__8->addView(view__11);
|
||||
Label* const view__12 = createLabel(CRect(10, 39, 260, 69), -1, "Key switch:", kLeftText, 20);
|
||||
view__8->addView(view__12);
|
||||
Label* const view__13 = createLabel(CRect(10, 71, 70, 96), -1, "Voices:", kRightText, 12);
|
||||
view__8->addView(view__13);
|
||||
PreviousFileButton* const view__14 = createPreviousFileButton(CRect(295, 9, 320, 34), kTagPreviousSfzFile, "", kCenterText, 24);
|
||||
view__8->addView(view__14);
|
||||
NextFileButton* const view__15 = createNextFileButton(CRect(320, 9, 345, 34), kTagNextSfzFile, "", kCenterText, 24);
|
||||
view__8->addView(view__15);
|
||||
ChevronDropDown* const view__16 = createChevronDropDown(CRect(345, 9, 370, 34), kTagFileOperations, "", kCenterText, 24);
|
||||
fileOperationsMenu_ = view__16;
|
||||
view__8->addView(view__16);
|
||||
Label* const view__17 = createLabel(CRect(75, 71, 125, 96), -1, "", kCenterText, 12);
|
||||
infoVoicesLabel_ = view__17;
|
||||
view__8->addView(view__17);
|
||||
Label* const view__18 = createLabel(CRect(130, 71, 190, 96), -1, "Max:", kRightText, 12);
|
||||
view__8->addView(view__18);
|
||||
Label* const view__19 = createLabel(CRect(195, 71, 245, 96), -1, "", kCenterText, 12);
|
||||
numVoicesLabel_ = view__19;
|
||||
view__8->addView(view__19);
|
||||
Label* const view__20 = createLabel(CRect(250, 71, 310, 96), -1, "Memory:", kRightText, 12);
|
||||
view__8->addView(view__20);
|
||||
Label* const view__21 = createLabel(CRect(315, 71, 365, 96), -1, "", kCenterText, 12);
|
||||
memoryLabel_ = view__21;
|
||||
view__8->addView(view__21);
|
||||
RoundedGroup* const view__22 = createRoundedGroup(CRect(570, 5, 795, 105), -1, "", kCenterText, 14);
|
||||
view__2->addView(view__22);
|
||||
Knob48* const view__23 = createKnob48(CRect(45, 15, 93, 63), -1, "", kCenterText, 14);
|
||||
view__22->addView(view__23);
|
||||
view__23->setVisible(false);
|
||||
ValueLabel* const view__24 = createValueLabel(CRect(40, 65, 100, 70), -1, "Center", kCenterText, 12);
|
||||
view__22->addView(view__24);
|
||||
view__24->setVisible(false);
|
||||
StyledKnob* const view__25 = createStyledKnob(CRect(110, 15, 158, 63), kTagSetVolume, "", kCenterText, 14);
|
||||
volumeSlider_ = view__25;
|
||||
view__22->addView(view__25);
|
||||
ValueLabel* const view__26 = createValueLabel(CRect(105, 65, 165, 87), -1, "0.0 dB", kCenterText, 12);
|
||||
volumeLabel_ = view__26;
|
||||
view__22->addView(view__26);
|
||||
VMeter* const view__27 = createVMeter(CRect(175, 15, 210, 70), -1, "", kCenterText, 14);
|
||||
view__22->addView(view__27);
|
||||
enterTheme(defaultTheme);
|
||||
LogicalGroup* const view__28 = createLogicalGroup(CRect(5, 110, 796, 395), -1, "", kCenterText, 14);
|
||||
subPanels_[kPanelGeneral] = view__28;
|
||||
view__0->addView(view__28);
|
||||
RoundedGroup* const view__29 = createRoundedGroup(CRect(0, 0, 175, 280), -1, "", kCenterText, 14);
|
||||
view__28->addView(view__29);
|
||||
Label* const view__30 = createLabel(CRect(15, 10, 75, 35), -1, "Curves:", kLeftText, 14);
|
||||
view__29->addView(view__30);
|
||||
Label* const view__31 = createLabel(CRect(15, 35, 75, 60), -1, "Masters:", kLeftText, 14);
|
||||
view__29->addView(view__31);
|
||||
Label* const view__32 = createLabel(CRect(15, 60, 75, 85), -1, "Groups:", kLeftText, 14);
|
||||
view__29->addView(view__32);
|
||||
Label* const view__33 = createLabel(CRect(15, 85, 75, 110), -1, "Regions:", kLeftText, 14);
|
||||
view__29->addView(view__33);
|
||||
Label* const view__34 = createLabel(CRect(15, 110, 75, 135), -1, "Samples:", kLeftText, 14);
|
||||
view__29->addView(view__34);
|
||||
Label* const view__35 = createLabel(CRect(115, 10, 155, 35), -1, "0", kCenterText, 14);
|
||||
infoCurvesLabel_ = view__35;
|
||||
view__29->addView(view__35);
|
||||
Label* const view__36 = createLabel(CRect(115, 35, 155, 60), -1, "0", kCenterText, 14);
|
||||
infoMastersLabel_ = view__36;
|
||||
view__29->addView(view__36);
|
||||
Label* const view__37 = createLabel(CRect(115, 60, 155, 85), -1, "0", kCenterText, 14);
|
||||
infoGroupsLabel_ = view__37;
|
||||
view__29->addView(view__37);
|
||||
Label* const view__38 = createLabel(CRect(115, 85, 155, 110), -1, "0", kCenterText, 14);
|
||||
infoRegionsLabel_ = view__38;
|
||||
view__29->addView(view__38);
|
||||
Label* const view__39 = createLabel(CRect(115, 110, 155, 135), -1, "0", kCenterText, 14);
|
||||
infoSamplesLabel_ = view__39;
|
||||
view__29->addView(view__39);
|
||||
LogicalGroup* const view__40 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
|
||||
subPanels_[kPanelControls] = view__40;
|
||||
view__0->addView(view__40);
|
||||
view__40->setVisible(false);
|
||||
RoundedGroup* const view__41 = createRoundedGroup(CRect(0, 0, 790, 285), -1, "", kCenterText, 14);
|
||||
view__40->addView(view__41);
|
||||
Label* const view__42 = createLabel(CRect(0, 0, 790, 285), -1, "Controls not available", kCenterText, 40);
|
||||
view__41->addView(view__42);
|
||||
LogicalGroup* const view__43 = createLogicalGroup(CRect(5, 109, 795, 395), -1, "", kCenterText, 14);
|
||||
subPanels_[kPanelSettings] = view__43;
|
||||
view__0->addView(view__43);
|
||||
view__43->setVisible(false);
|
||||
TitleGroup* const view__44 = createTitleGroup(CRect(255, 26, 535, 126), -1, "Engine", kCenterText, 12);
|
||||
view__43->addView(view__44);
|
||||
ValueMenu* const view__45 = createValueMenu(CRect(25, 60, 85, 85), kTagSetNumVoices, "", kCenterText, 12);
|
||||
numVoicesSlider_ = view__45;
|
||||
view__44->addView(view__45);
|
||||
ValueLabel* const view__46 = createValueLabel(CRect(15, 20, 95, 45), -1, "Polyphony", kCenterText, 12);
|
||||
view__44->addView(view__46);
|
||||
ValueMenu* const view__47 = createValueMenu(CRect(110, 60, 170, 85), kTagSetOversampling, "", kCenterText, 12);
|
||||
oversamplingSlider_ = view__47;
|
||||
view__44->addView(view__47);
|
||||
ValueLabel* const view__48 = createValueLabel(CRect(100, 20, 180, 45), -1, "Oversampling", kCenterText, 12);
|
||||
view__44->addView(view__48);
|
||||
ValueLabel* const view__49 = createValueLabel(CRect(185, 20, 265, 45), -1, "Preload size", kCenterText, 12);
|
||||
view__44->addView(view__49);
|
||||
ValueMenu* const view__50 = createValueMenu(CRect(195, 60, 255, 85), kTagSetPreloadSize, "", kCenterText, 12);
|
||||
preloadSizeSlider_ = view__50;
|
||||
view__44->addView(view__50);
|
||||
TitleGroup* const view__51 = createTitleGroup(CRect(200, 161, 590, 261), -1, "Tuning", kCenterText, 12);
|
||||
view__43->addView(view__51);
|
||||
ValueLabel* const view__52 = createValueLabel(CRect(125, 20, 205, 45), -1, "Root key", kCenterText, 12);
|
||||
view__51->addView(view__52);
|
||||
ValueMenu* const view__53 = createValueMenu(CRect(220, 60, 280, 85), kTagSetTuningFrequency, "", kCenterText, 12);
|
||||
tuningFrequencySlider_ = view__53;
|
||||
view__51->addView(view__53);
|
||||
ValueLabel* const view__54 = createValueLabel(CRect(210, 20, 290, 45), -1, "Frequency", kCenterText, 12);
|
||||
view__51->addView(view__54);
|
||||
StyledKnob* const view__55 = createStyledKnob(CRect(310, 45, 358, 93), kTagSetStretchedTuning, "", kCenterText, 14);
|
||||
stretchedTuningSlider_ = view__55;
|
||||
view__51->addView(view__55);
|
||||
ValueLabel* const view__56 = createValueLabel(CRect(295, 20, 375, 45), -1, "Stretch", kCenterText, 12);
|
||||
view__51->addView(view__56);
|
||||
ValueLabel* const view__57 = createValueLabel(CRect(20, 20, 120, 45), -1, "Scala file", kCenterText, 12);
|
||||
view__51->addView(view__57);
|
||||
ValueButton* const view__58 = createValueButton(CRect(20, 60, 120, 85), kTagLoadScalaFile, "DefaultScale", kCenterText, 12);
|
||||
scalaFileButton_ = view__58;
|
||||
view__51->addView(view__58);
|
||||
ValueMenu* const view__59 = createValueMenu(CRect(135, 60, 170, 85), kTagSetScalaRootKey, "", kCenterText, 12);
|
||||
scalaRootKeySlider_ = view__59;
|
||||
view__51->addView(view__59);
|
||||
ValueMenu* const view__60 = createValueMenu(CRect(170, 60, 200, 85), kTagSetScalaRootKey, "", kCenterText, 12);
|
||||
scalaRootOctaveSlider_ = view__60;
|
||||
view__51->addView(view__60);
|
||||
Piano* const view__61 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
|
||||
piano_ = view__61;
|
||||
view__0->addView(view__61);
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
#include "reader.h"
|
||||
#include <absl/strings/string_view.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef std::vector<std::string> TokenList;
|
||||
static bool read_file_tokens(const char *filename, TokenList &tokens);
|
||||
static Layout read_tokens_layout(TokenList::iterator &tok_it, TokenList::iterator tok_end);
|
||||
|
||||
Layout read_file_layout(const char *filename)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
if (!read_file_tokens(filename, tokens))
|
||||
throw std::runtime_error("Cannot read fluid design file.");
|
||||
|
||||
TokenList::iterator tok_it = tokens.begin();
|
||||
TokenList::iterator tok_end = tokens.end();
|
||||
return read_tokens_layout(tok_it, tok_end);
|
||||
}
|
||||
|
||||
static std::string consume_next_token(TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
if (tok_it == tok_end)
|
||||
throw file_format_error("Premature end of tokens");
|
||||
return *tok_it++;
|
||||
}
|
||||
|
||||
static bool try_consume_next_token(const char *text, TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
if (tok_it == tok_end)
|
||||
return false;
|
||||
|
||||
if (*tok_it != text)
|
||||
return false;
|
||||
|
||||
++tok_it;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ensure_next_token(const char *text, TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
std::string tok = consume_next_token(tok_it, tok_end);
|
||||
if (tok != text)
|
||||
throw file_format_error("Unexpected token: " + tok);
|
||||
}
|
||||
|
||||
static std::string consume_enclosed_string(TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
ensure_next_token("{", tok_it, tok_end);
|
||||
unsigned depth = 1;
|
||||
|
||||
std::string text;
|
||||
for (;;) {
|
||||
std::string part = consume_next_token(tok_it, tok_end);
|
||||
if (part == "}") {
|
||||
if (--depth == 0)
|
||||
return text;
|
||||
}
|
||||
else if (part == "{")
|
||||
++depth;
|
||||
if (!text.empty())
|
||||
text.push_back(' ');
|
||||
text.append(part);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static std::string consume_any_string(TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
if (tok_it != tok_end && *tok_it == "{")
|
||||
return consume_enclosed_string(tok_it, tok_end);
|
||||
else
|
||||
return consume_next_token(tok_it, tok_end);
|
||||
}
|
||||
|
||||
static int consume_int_token(TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
std::string text = consume_next_token(tok_it, tok_end);
|
||||
return std::stoi(text);
|
||||
}
|
||||
|
||||
static int consume_real_token(TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
std::string text = consume_next_token(tok_it, tok_end);
|
||||
return std::stod(text);
|
||||
}
|
||||
|
||||
static void consume_layout_item_properties(LayoutItem &item, TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
ensure_next_token("{", tok_it, tok_end);
|
||||
for (bool have = true; have;) {
|
||||
if (try_consume_next_token("open", tok_it, tok_end))
|
||||
; // skip
|
||||
else if (try_consume_next_token("selected", tok_it, tok_end))
|
||||
; // skip
|
||||
else if (try_consume_next_token("label", tok_it, tok_end))
|
||||
item.label = consume_any_string(tok_it, tok_end);
|
||||
else if (try_consume_next_token("xywh", tok_it, tok_end)) {
|
||||
ensure_next_token("{", tok_it, tok_end);
|
||||
item.x = consume_int_token(tok_it, tok_end);
|
||||
item.y = consume_int_token(tok_it, tok_end);
|
||||
item.w = consume_int_token(tok_it, tok_end);
|
||||
item.h = consume_int_token(tok_it, tok_end);
|
||||
ensure_next_token("}", tok_it, tok_end);
|
||||
}
|
||||
else if (try_consume_next_token("box", tok_it, tok_end))
|
||||
item.box = consume_next_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("down_box", tok_it, tok_end))
|
||||
item.down_box = consume_next_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("labelfont", tok_it, tok_end))
|
||||
item.labelfont = consume_int_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("labelsize", tok_it, tok_end))
|
||||
item.labelsize = consume_int_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("labeltype", tok_it, tok_end))
|
||||
item.labeltype = consume_any_string(tok_it, tok_end);
|
||||
else if (try_consume_next_token("textsize", tok_it, tok_end))
|
||||
item.textsize = consume_int_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("align", tok_it, tok_end))
|
||||
item.align = consume_int_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("type", tok_it, tok_end))
|
||||
item.type = consume_any_string(tok_it, tok_end);
|
||||
else if (try_consume_next_token("callback", tok_it, tok_end))
|
||||
item.callback = consume_any_string(tok_it, tok_end);
|
||||
else if (try_consume_next_token("class", tok_it, tok_end))
|
||||
item.classname = consume_any_string(tok_it, tok_end);
|
||||
else if (try_consume_next_token("value", tok_it, tok_end))
|
||||
item.value = consume_real_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("minimum", tok_it, tok_end))
|
||||
item.minimum = consume_real_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("maximum", tok_it, tok_end))
|
||||
item.maximum = consume_real_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("step", tok_it, tok_end))
|
||||
item.step = consume_real_token(tok_it, tok_end);
|
||||
else if (try_consume_next_token("image", tok_it, tok_end))
|
||||
item.image.filepath = consume_any_string(tok_it, tok_end);
|
||||
else if (try_consume_next_token("hide", tok_it, tok_end))
|
||||
item.hidden = true;
|
||||
else if (try_consume_next_token("visible", tok_it, tok_end))
|
||||
/* skip */;
|
||||
else if (try_consume_next_token("comment", tok_it, tok_end))
|
||||
item.comment = consume_any_string(tok_it, tok_end);
|
||||
else
|
||||
have = false;
|
||||
}
|
||||
ensure_next_token("}", tok_it, tok_end);
|
||||
}
|
||||
|
||||
static LayoutItem consume_layout_item(const std::string &classname, TokenList::iterator &tok_it, TokenList::iterator tok_end, bool anonymous = false)
|
||||
{
|
||||
LayoutItem item;
|
||||
item.classname = classname;
|
||||
if (!anonymous)
|
||||
item.id = consume_any_string(tok_it, tok_end);
|
||||
consume_layout_item_properties(item, tok_it, tok_end);
|
||||
if (tok_it != tok_end && *tok_it == "{") {
|
||||
consume_next_token(tok_it, tok_end);
|
||||
for (std::string text; (text = consume_next_token(tok_it, tok_end)) != "}";) {
|
||||
if (text == "decl") {
|
||||
consume_any_string(tok_it, tok_end);
|
||||
consume_any_string(tok_it, tok_end);
|
||||
}
|
||||
else if (text == "Function") {
|
||||
consume_any_string(tok_it, tok_end);
|
||||
consume_any_string(tok_it, tok_end);
|
||||
consume_any_string(tok_it, tok_end);
|
||||
}
|
||||
else
|
||||
item.items.push_back(consume_layout_item(text, tok_it, tok_end));
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
static Layout read_tokens_layout(TokenList::iterator &tok_it, TokenList::iterator tok_end)
|
||||
{
|
||||
Layout layout;
|
||||
|
||||
std::string version_name;
|
||||
std::string header_name;
|
||||
std::string code_name;
|
||||
|
||||
while (tok_it != tok_end) {
|
||||
std::string key = consume_next_token(tok_it, tok_end);
|
||||
|
||||
if (key == "version")
|
||||
version_name = consume_next_token(tok_it, tok_end);
|
||||
else if (key == "header_name") {
|
||||
ensure_next_token("{", tok_it, tok_end);
|
||||
header_name = consume_next_token(tok_it, tok_end);
|
||||
ensure_next_token("}", tok_it, tok_end);
|
||||
}
|
||||
else if (key == "code_name") {
|
||||
ensure_next_token("{", tok_it, tok_end);
|
||||
code_name = consume_next_token(tok_it, tok_end);
|
||||
ensure_next_token("}", tok_it, tok_end);
|
||||
}
|
||||
else if (key == "decl") {
|
||||
consume_any_string(tok_it, tok_end);
|
||||
consume_any_string(tok_it, tok_end);
|
||||
}
|
||||
else if (key == "widget_class") {
|
||||
key = consume_next_token(tok_it, tok_end);
|
||||
layout.items.push_back(consume_layout_item(key, tok_it, tok_end, true));
|
||||
layout.items.back().id = key;
|
||||
}
|
||||
else
|
||||
layout.items.push_back(consume_layout_item(key, tok_it, tok_end));
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
///
|
||||
class tokenizer {
|
||||
public:
|
||||
tokenizer(
|
||||
absl::string_view text,
|
||||
absl::string_view dropped_delims,
|
||||
absl::string_view kept_delims);
|
||||
|
||||
absl::string_view next();
|
||||
|
||||
private:
|
||||
absl::string_view text_;
|
||||
absl::string_view dropped_delims_;
|
||||
absl::string_view kept_delims_;
|
||||
};
|
||||
|
||||
tokenizer::tokenizer(
|
||||
absl::string_view text,
|
||||
absl::string_view dropped_delims,
|
||||
absl::string_view kept_delims)
|
||||
: text_(text), dropped_delims_(dropped_delims), kept_delims_(kept_delims)
|
||||
{
|
||||
}
|
||||
|
||||
absl::string_view tokenizer::next()
|
||||
{
|
||||
auto is_dropped = [this](char c) -> bool {
|
||||
return dropped_delims_.find(c) != dropped_delims_.npos;
|
||||
};
|
||||
auto is_kept = [this](char c) -> bool {
|
||||
return kept_delims_.find(c) != kept_delims_.npos;
|
||||
};
|
||||
auto is_delim = [this](char c) -> bool {
|
||||
return dropped_delims_.find(c) != dropped_delims_.npos ||
|
||||
kept_delims_.find(c) != kept_delims_.npos;
|
||||
};
|
||||
|
||||
absl::string_view text = text_;
|
||||
|
||||
while (!text.empty() && is_dropped(text[0]))
|
||||
text.remove_prefix(1);
|
||||
|
||||
if (text.empty())
|
||||
return {};
|
||||
|
||||
size_t pos;
|
||||
{
|
||||
auto it = std::find_if(text.begin(), text.end(), is_delim);
|
||||
if (it == text.end())
|
||||
pos = text.size();
|
||||
else {
|
||||
pos = std::distance(text.begin(), it);
|
||||
pos += is_kept(text[0]);
|
||||
}
|
||||
}
|
||||
|
||||
absl::string_view token = text.substr(0, pos);
|
||||
text_ = text.substr(pos);
|
||||
return token;
|
||||
}
|
||||
|
||||
///
|
||||
static bool read_file_tokens(const char *filename, TokenList &tokens)
|
||||
{
|
||||
std::ifstream stream(filename);
|
||||
std::string line;
|
||||
|
||||
std::string text;
|
||||
while (std::getline(stream, line)) {
|
||||
if (!line.empty() && line[0] != '#') {
|
||||
text.append(line);
|
||||
text.push_back('\n');
|
||||
}
|
||||
}
|
||||
|
||||
if (stream.bad())
|
||||
return false;
|
||||
|
||||
tokenizer tok(text, " \t\r\n", "{}");
|
||||
absl::string_view token;
|
||||
while (!(token = tok.next()).empty())
|
||||
tokens.emplace_back(token);
|
||||
|
||||
return !stream.bad();
|
||||
}
|
||||
2
external/abseil-cpp
vendored
2
external/abseil-cpp
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit df3ea785d8c30a9503321a3d35ee7d35808f190d
|
||||
Subproject commit 997aaf3a28308eba1b9156aa35ab7bca9688e9f6
|
||||
21
external/atomic_queue/LICENSE
vendored
Normal file
21
external/atomic_queue/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 Maxim Egorushkin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -55,15 +55,13 @@ struct GetIndexShuffleBits<false, array_size, elements_per_cache_line> {
|
|||
// the element within the cache line) with the next N bits (which are the index of the cache line)
|
||||
// of the element index.
|
||||
template<int BITS>
|
||||
constexpr unsigned remap_index_with_mix(unsigned index, unsigned mix)
|
||||
{
|
||||
constexpr unsigned remap_index_with_mix(unsigned index, unsigned mix) {
|
||||
return index ^ mix ^ (mix << BITS);
|
||||
}
|
||||
|
||||
template<int BITS>
|
||||
constexpr unsigned remap_index(unsigned index) noexcept {
|
||||
return remap_index_with_mix<BITS>(
|
||||
index, (index ^ (index >> BITS)) & ((1u << BITS) - 1));
|
||||
return remap_index_with_mix<BITS>(index, (index ^ (index >> BITS)) & ((1u << BITS) - 1));
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
@ -213,7 +211,7 @@ protected:
|
|||
else {
|
||||
for(;;) {
|
||||
unsigned char expected = STORED;
|
||||
if(ATOMIC_QUEUE_LIKELY(state.compare_exchange_strong(expected, LOADING, X, X))) {
|
||||
if(ATOMIC_QUEUE_LIKELY(state.compare_exchange_strong(expected, LOADING, A, X))) {
|
||||
T element{std::move(q_element)};
|
||||
state.store(EMPTY, R);
|
||||
return element;
|
||||
|
|
@ -238,7 +236,7 @@ protected:
|
|||
else {
|
||||
for(;;) {
|
||||
unsigned char expected = EMPTY;
|
||||
if(ATOMIC_QUEUE_LIKELY(state.compare_exchange_strong(expected, STORING, X, X))) {
|
||||
if(ATOMIC_QUEUE_LIKELY(state.compare_exchange_strong(expected, STORING, A, X))) {
|
||||
q_element = std::forward<U>(element);
|
||||
state.store(STORED, R);
|
||||
return;
|
||||
|
|
@ -318,11 +316,16 @@ public:
|
|||
}
|
||||
|
||||
bool was_empty() const noexcept {
|
||||
return static_cast<int>(head_.load(X) - tail_.load(X)) <= 0;
|
||||
return !was_size();
|
||||
}
|
||||
|
||||
bool was_full() const noexcept {
|
||||
return static_cast<int>(head_.load(X) - tail_.load(X)) >= static_cast<int>(static_cast<Derived const&>(*this).size_);
|
||||
return was_size() >= static_cast<int>(static_cast<Derived const&>(*this).size_);
|
||||
}
|
||||
|
||||
unsigned was_size() const noexcept {
|
||||
// tail_ can be greater than head_ because of consumers doing pop, rather that try_pop, when the queue is empty.
|
||||
return std::max(static_cast<int>(head_.load(X) - tail_.load(X)), 0);
|
||||
}
|
||||
|
||||
unsigned capacity() const noexcept {
|
||||
|
|
@ -16,7 +16,6 @@ static inline void spin_loop_pause() noexcept {
|
|||
}
|
||||
} // namespace atomic_queue
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
// TODO: These need to be verified as I do not have access to ARM platform.
|
||||
namespace atomic_queue {
|
||||
constexpr int CACHE_LINE_SIZE = 64;
|
||||
static inline void spin_loop_pause() noexcept {
|
||||
|
|
@ -48,9 +47,11 @@ namespace atomic_queue {
|
|||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define ATOMIC_QUEUE_LIKELY(expr) __builtin_expect(static_cast<bool>(expr), 1)
|
||||
#define ATOMIC_QUEUE_UNLIKELY(expr) __builtin_expect(static_cast<bool>(expr), 0)
|
||||
#define ATOMIC_QUEUE_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
#define ATOMIC_QUEUE_LIKELY(expr) expr
|
||||
#define ATOMIC_QUEUE_UNLIKELY(expr) expr
|
||||
#define ATOMIC_QUEUE_LIKELY(expr) (expr)
|
||||
#define ATOMIC_QUEUE_UNLIKELY(expr) (expr)
|
||||
#define ATOMIC_QUEUE_NOINLINE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
119
external/cephes/LICENSE.txt
vendored
Normal file
119
external/cephes/LICENSE.txt
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
==== NOTE ====
|
||||
The actual cephes library, shipped with and wrapped by this package, is available on The Netlib at http://www.netlib.org/cephes/ . It does not have any license specified. However, its original authors, Stephen Moshier, has kindly granted permission for inclusion in a BSD-licensed package. See email snippet below for reference.
|
||||
|
||||
Return-Path: <steve@moshier.net>
|
||||
X-Original-To: julien@cornebise.com
|
||||
Delivered-To: julien@cornebise.com
|
||||
Received: from atl4mhob11.myregisteredsite.com (atl4mhob11.myregisteredsite.com [209.17.115.49])
|
||||
by cornebise.com (Postfix) with ESMTP id D47B139FC0
|
||||
for <julien@cornebise.com>; Fri, 25 Oct 2013 16:32:40 +0200 (CEST)
|
||||
Received: from mailpod1.hostingplatform.com ([10.30.71.116])
|
||||
by atl4mhob11.myregisteredsite.com (8.14.4/8.14.4) with ESMTP id r9PEWcwQ003543
|
||||
for <julien@cornebise.com>; Fri, 25 Oct 2013 10:32:38 -0400
|
||||
Received: (qmail 11948 invoked by uid 0); 25 Oct 2013 12:36:20 -0000
|
||||
X-TCPREMOTEIP: 76.24.25.74
|
||||
X-Authenticated-UID: steve@moshier.net
|
||||
Received: from unknown (HELO d510.local) (steve@moshier.net@76.24.25.74)
|
||||
by 0 with ESMTPA; 25 Oct 2013 12:36:20 -0000
|
||||
Date: Fri, 25 Oct 2013 08:36:19 -0400 (EDT)
|
||||
From: Stephen Moshier <steve@moshier.net>
|
||||
X-X-Sender: steve@d510
|
||||
To: Julien Cornebise <julien@cornebise.com>
|
||||
Subject: Re: Cephes: permission to wrap+distribute for Lua
|
||||
In-Reply-To: <52653AD3.1010004@cornebise.com>
|
||||
Message-ID: <alpine.DEB.2.02.1310250827040.17646@d510>
|
||||
References: <52653AD3.1010004@cornebise.com>
|
||||
User-Agent: Alpine 2.02 (DEB 1266 2009-07-14)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed
|
||||
|
||||
|
||||
Julien, thank you for writing.
|
||||
BSD license is fine, modification is OK.
|
||||
There are more build scripts available in the web site distributions than
|
||||
there are on the Netlib. I think there is an update to Planck's radiation
|
||||
function that I haven't sent to Netlib yet. But Netlib is a more stable
|
||||
site, so it is better to cite that as a reference.
|
||||
|
||||
|
||||
On Mon, 21 Oct 2013, Julien Cornebise wrote:
|
||||
|
||||
> -----BEGIN PGP SIGNED MESSAGE-----
|
||||
> Hash: SHA1
|
||||
>
|
||||
> Dear Mr Moshier
|
||||
>
|
||||
> I am a researcher in mathematics and machine learning in London, and
|
||||
> am writing about your awesome Cephes library, whom I found at the
|
||||
> heart of Scipy.
|
||||
>
|
||||
> It is so useful that, with your permission, I would like to wrap it
|
||||
> for Lua and Torch (a machine learning overlay to Lua, specialized in
|
||||
> neural nets, see http://www.torch.ch). I would like to distribute it
|
||||
> as a package for Torch, including your source code along the wrapping
|
||||
> code.
|
||||
> This wouldbe a public package, distributed under BSD License. I have
|
||||
> put a first draft on github:
|
||||
> https://github.com/jucor/torch-cephes
|
||||
>
|
||||
> Hence my three questions, please:
|
||||
>
|
||||
> 1/ How would you like to be acknowledged, beyond the comments that are
|
||||
> already in your code? Do you have any standard header/disclaimer that
|
||||
> I could add to the documentation?
|
||||
>
|
||||
> 2/ At the moment, your code is left untouched. However, if I ever need
|
||||
> to modify bits of the code, what are the conditions/restrictions?
|
||||
> Nothing huge -- I definitely do not want to mess with it: I was
|
||||
> planning to use the natural completion of some functions on the
|
||||
> completed real line (e.g. CDF returing 1 when called with "infinity",
|
||||
> or quantiles returning -Infinity when called with 0), either natively
|
||||
> if supported, or by setting a specific flag via mtherr().
|
||||
>
|
||||
> 3/ I am currently using the source from Netlib. Do you recommend using
|
||||
> the source from your website instead ?
|
||||
>
|
||||
> Thank you very much for your attention,
|
||||
> and, more importantly, for the time and effort your poured into Cephes.
|
||||
>
|
||||
> Best regards,
|
||||
>
|
||||
> Julien Cornebise, Ph.D.
|
||||
> London, UK
|
||||
> http://www.cornebise.com/julien
|
||||
> -----BEGIN PGP SIGNATURE-----
|
||||
> Version: GnuPG v1.4.14 (Darwin)
|
||||
> Comment: GPGTools - http://gpgtools.org
|
||||
> Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
|
||||
>
|
||||
> iEYEARECAAYFAlJlOtEACgkQKYR3gC0rw/gIpQCfZKu6+iDh9ghhm6QfsLXnldKN
|
||||
> BuIAn2zZHu1c/IrRAevhjM7N7xGg0LHO
|
||||
> =WeP5
|
||||
> -----END PGP SIGNATURE-----
|
||||
|
||||
|
||||
==== LICENSE ====
|
||||
Copyright (c) 2013, Julien Cornebise
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the organization nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
82
external/cephes/src/chbevl.c
vendored
Normal file
82
external/cephes/src/chbevl.c
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* chbevl.c
|
||||
*
|
||||
* Evaluate Chebyshev series
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* int N;
|
||||
* double x, y, coef[N], chebevl();
|
||||
*
|
||||
* y = chbevl( x, coef, N );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Evaluates the series
|
||||
*
|
||||
* N-1
|
||||
* - '
|
||||
* y = > coef[i] T (x/2)
|
||||
* - i
|
||||
* i=0
|
||||
*
|
||||
* of Chebyshev polynomials Ti at argument x/2.
|
||||
*
|
||||
* Coefficients are stored in reverse order, i.e. the zero
|
||||
* order term is last in the array. Note N is the number of
|
||||
* coefficients, not the order.
|
||||
*
|
||||
* If coefficients are for the interval a to b, x must
|
||||
* have been transformed to x -> 2(2x - b - a)/(b-a) before
|
||||
* entering the routine. This maps x from (a, b) to (-1, 1),
|
||||
* over which the Chebyshev polynomials are defined.
|
||||
*
|
||||
* If the coefficients are for the inverted interval, in
|
||||
* which (a, b) is mapped to (1/b, 1/a), the transformation
|
||||
* required is x -> 2(2ab/x - b - a)/(b-a). If b is infinity,
|
||||
* this becomes x -> 4a/x - 1.
|
||||
*
|
||||
*
|
||||
*
|
||||
* SPEED:
|
||||
*
|
||||
* Taking advantage of the recurrence properties of the
|
||||
* Chebyshev polynomials, the routine requires one more
|
||||
* addition per loop than evaluating a nested polynomial of
|
||||
* the same degree.
|
||||
*
|
||||
*/
|
||||
/* chbevl.c */
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.0: April, 1987
|
||||
Copyright 1985, 1987 by Stephen L. Moshier
|
||||
Direct inquiries to 30 Frost Street, Cambridge, MA 02140
|
||||
*/
|
||||
|
||||
double chbevl( x, array, n )
|
||||
double x;
|
||||
double array[];
|
||||
int n;
|
||||
{
|
||||
double b0, b1, b2, *p;
|
||||
int i;
|
||||
|
||||
p = array;
|
||||
b0 = *p++;
|
||||
b1 = 0.0;
|
||||
i = n - 1;
|
||||
|
||||
do
|
||||
{
|
||||
b2 = b1;
|
||||
b1 = b0;
|
||||
b0 = x * b1 - b2 + *p++;
|
||||
}
|
||||
while( --i );
|
||||
|
||||
return( 0.5*(b0-b2) );
|
||||
}
|
||||
193
external/cephes/src/i0.c
vendored
Normal file
193
external/cephes/src/i0.c
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/* i0.c
|
||||
*
|
||||
* Modified Bessel function of order zero
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* double x, y, i0();
|
||||
*
|
||||
* y = i0( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns modified Bessel function of order zero of the
|
||||
* argument.
|
||||
*
|
||||
* The function is defined as i0(x) = j0( ix ).
|
||||
*
|
||||
* The range is partitioned into the two intervals [0,8] and
|
||||
* (8, infinity). Chebyshev polynomial expansions are employed
|
||||
* in each interval.
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* DEC 0,30 6000 8.2e-17 1.9e-17
|
||||
* IEEE 0,30 30000 5.8e-16 1.4e-16
|
||||
*
|
||||
*/
|
||||
/* i0e.c
|
||||
*
|
||||
* Modified Bessel function of order zero,
|
||||
* exponentially scaled
|
||||
*
|
||||
*
|
||||
*
|
||||
* SYNOPSIS:
|
||||
*
|
||||
* double x, y, i0e();
|
||||
*
|
||||
* y = i0e( x );
|
||||
*
|
||||
*
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* Returns exponentially scaled modified Bessel function
|
||||
* of order zero of the argument.
|
||||
*
|
||||
* The function is defined as i0e(x) = exp(-|x|) j0( ix ).
|
||||
*
|
||||
*
|
||||
*
|
||||
* ACCURACY:
|
||||
*
|
||||
* Relative error:
|
||||
* arithmetic domain # trials peak rms
|
||||
* IEEE 0,30 30000 5.4e-16 1.2e-16
|
||||
* See i0().
|
||||
*
|
||||
*/
|
||||
|
||||
/* i0.c */
|
||||
|
||||
|
||||
/*
|
||||
Cephes Math Library Release 2.8: June, 2000
|
||||
Copyright 1984, 1987, 2000 by Stephen L. Moshier
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* Chebyshev coefficients for exp(-x) I0(x)
|
||||
* in the interval [0,8].
|
||||
*
|
||||
* lim(x->0){ exp(-x) I0(x) } = 1.
|
||||
*/
|
||||
|
||||
static double A[] =
|
||||
{
|
||||
-4.41534164647933937950E-18,
|
||||
3.33079451882223809783E-17,
|
||||
-2.43127984654795469359E-16,
|
||||
1.71539128555513303061E-15,
|
||||
-1.16853328779934516808E-14,
|
||||
7.67618549860493561688E-14,
|
||||
-4.85644678311192946090E-13,
|
||||
2.95505266312963983461E-12,
|
||||
-1.72682629144155570723E-11,
|
||||
9.67580903537323691224E-11,
|
||||
-5.18979560163526290666E-10,
|
||||
2.65982372468238665035E-9,
|
||||
-1.30002500998624804212E-8,
|
||||
6.04699502254191894932E-8,
|
||||
-2.67079385394061173391E-7,
|
||||
1.11738753912010371815E-6,
|
||||
-4.41673835845875056359E-6,
|
||||
1.64484480707288970893E-5,
|
||||
-5.75419501008210370398E-5,
|
||||
1.88502885095841655729E-4,
|
||||
-5.76375574538582365885E-4,
|
||||
1.63947561694133579842E-3,
|
||||
-4.32430999505057594430E-3,
|
||||
1.05464603945949983183E-2,
|
||||
-2.37374148058994688156E-2,
|
||||
4.93052842396707084878E-2,
|
||||
-9.49010970480476444210E-2,
|
||||
1.71620901522208775349E-1,
|
||||
-3.04682672343198398683E-1,
|
||||
6.76795274409476084995E-1
|
||||
};
|
||||
|
||||
|
||||
/* Chebyshev coefficients for exp(-x) sqrt(x) I0(x)
|
||||
* in the inverted interval [8,infinity].
|
||||
*
|
||||
* lim(x->inf){ exp(-x) sqrt(x) I0(x) } = 1/sqrt(2pi).
|
||||
*/
|
||||
|
||||
static double B[] =
|
||||
{
|
||||
-7.23318048787475395456E-18,
|
||||
-4.83050448594418207126E-18,
|
||||
4.46562142029675999901E-17,
|
||||
3.46122286769746109310E-17,
|
||||
-2.82762398051658348494E-16,
|
||||
-3.42548561967721913462E-16,
|
||||
1.77256013305652638360E-15,
|
||||
3.81168066935262242075E-15,
|
||||
-9.55484669882830764870E-15,
|
||||
-4.15056934728722208663E-14,
|
||||
1.54008621752140982691E-14,
|
||||
3.85277838274214270114E-13,
|
||||
7.18012445138366623367E-13,
|
||||
-1.79417853150680611778E-12,
|
||||
-1.32158118404477131188E-11,
|
||||
-3.14991652796324136454E-11,
|
||||
1.18891471078464383424E-11,
|
||||
4.94060238822496958910E-10,
|
||||
3.39623202570838634515E-9,
|
||||
2.26666899049817806459E-8,
|
||||
2.04891858946906374183E-7,
|
||||
2.89137052083475648297E-6,
|
||||
6.88975834691682398426E-5,
|
||||
3.36911647825569408990E-3,
|
||||
8.04490411014108831608E-1
|
||||
};
|
||||
|
||||
|
||||
extern double chbevl ( double, void *, int );
|
||||
|
||||
double i0(x)
|
||||
double x;
|
||||
{
|
||||
double y;
|
||||
|
||||
if( x < 0 )
|
||||
x = -x;
|
||||
if( x <= 8.0 )
|
||||
{
|
||||
y = (x/2.0) - 2.0;
|
||||
return( exp(x) * chbevl( y, A, 30 ) );
|
||||
}
|
||||
|
||||
return( exp(x) * chbevl( 32.0/x - 2.0, B, 25 ) / sqrt(x) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
double i0e( x )
|
||||
double x;
|
||||
{
|
||||
double y;
|
||||
|
||||
if( x < 0 )
|
||||
x = -x;
|
||||
if( x <= 8.0 )
|
||||
{
|
||||
y = (x/2.0) - 2.0;
|
||||
return( chbevl( y, A, 30 ) );
|
||||
}
|
||||
|
||||
return( chbevl( 32.0/x - 2.0, B, 25 ) / sqrt(x) );
|
||||
|
||||
}
|
||||
19
external/cxxopts/LICENSE
vendored
Normal file
19
external/cxxopts/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 Jarryd Beck
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
653
clients/cxxopts.hpp → external/cxxopts/cxxopts.hpp
vendored
653
clients/cxxopts.hpp → external/cxxopts/cxxopts.hpp
vendored
File diff suppressed because it is too large
Load diff
1
external/filesystem
vendored
Submodule
1
external/filesystem
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 2a8b380f8d4e77b389c42a194ab9c70d8e3a0f1e
|
||||
7
external/jsl/include/jsl/allocator
vendored
7
external/jsl/include/jsl/allocator
vendored
|
|
@ -1,4 +1,11 @@
|
|||
// -*- C++ -*-
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// Copyright Jean Pierre Cimalando 2018-2020.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
// -*- C++ -*-
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// Copyright Jean Pierre Cimalando 2018-2020.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "../../allocator"
|
||||
#include <new>
|
||||
#if defined(_WIN32)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
// -*- C++ -*-
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// Copyright Jean Pierre Cimalando 2018-2020.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "../../allocator"
|
||||
#include <new>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
// -*- C++ -*-
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// Copyright Jean Pierre Cimalando 2018-2020.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
#include "../../allocator"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
|
|||
1
external/simde
vendored
Submodule
1
external/simde
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5c2f423b41c06228e4be0cce0010a252297da4e7
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue