Merge branch 'develop' into master
3
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.* export-ignore
|
||||
.*/** export-ignore
|
||||
appveyor.yml export-ignore
|
||||
2
.gitignore
vendored
|
|
@ -21,6 +21,8 @@ clients/sfzprint
|
|||
|
||||
/vst/download/
|
||||
|
||||
/editor/external/fluentui-system-icons/
|
||||
|
||||
# gh-pages unstaged files:
|
||||
_api/
|
||||
_site/
|
||||
|
|
|
|||
4
.gitmodules
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[submodule "external/abseil-cpp"]
|
||||
path = external/abseil-cpp
|
||||
url = https://github.com/abseil/abseil-cpp
|
||||
url = https://github.com/abseil/abseil-cpp.git
|
||||
branch = lts_2020_02_25
|
||||
shallow = true
|
||||
[submodule "vst/external/VST_SDK/VST3_SDK/base"]
|
||||
|
|
@ -16,6 +16,6 @@
|
|||
url = https://github.com/sfztools/vst3_public_sdk.git
|
||||
shallow = true
|
||||
[submodule "vst/external/VST_SDK/VST3_SDK/vstgui4"]
|
||||
path = vst/external/VST_SDK/VST3_SDK/vstgui4
|
||||
path = editor/external/vstgui4
|
||||
url = https://github.com/sfztools/vstgui.git
|
||||
shallow = true
|
||||
|
|
|
|||
61
.travis.yml
|
|
@ -40,8 +40,33 @@ jobs:
|
|||
install: .travis/download_cmake.sh
|
||||
script: .travis/script_test.sh
|
||||
|
||||
- name: "Windows mingw32"
|
||||
- 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_osx.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
|
||||
|
|
@ -92,6 +117,7 @@ jobs:
|
|||
env:
|
||||
- INSTALL_DIR="sfizz-plugins-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
- ENABLE_VST_PLUGIN=OFF
|
||||
- ENABLE_LV2_UI=OFF
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
|
|
@ -107,6 +133,7 @@ jobs:
|
|||
env:
|
||||
- INSTALL_DIR="sfizz-plugins-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
- ENABLE_VST_PLUGIN=ON
|
||||
- ENABLE_LV2_UI=ON
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
|
|
@ -127,28 +154,9 @@ jobs:
|
|||
script: .travis/script_plugins.sh
|
||||
after_success: .travis/prepare_tarball.sh
|
||||
|
||||
- name: "macOS"
|
||||
os: osx
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-${TRAVIS_OS_NAME}-${TRAVIS_CPU_ARCH}"
|
||||
install: .travis/install_osx.sh
|
||||
script: .travis/script_osx.sh
|
||||
after_success: .travis/prepare_osx.sh
|
||||
|
||||
- name: "MOD devices arm"
|
||||
stage: "Build"
|
||||
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
|
||||
|
||||
- stage: "Deploy"
|
||||
name: "Source packaging"
|
||||
if: (tag IS present) AND (branch = master) AND (type = push)
|
||||
if: (tag =~ /^v?[0-9]/) AND (type = push)
|
||||
env:
|
||||
- INSTALL_DIR="sfizz-${TRAVIS_BRANCH}-src"
|
||||
addons:
|
||||
|
|
@ -158,17 +166,6 @@ jobs:
|
|||
install: sudo pip install git-archive-all
|
||||
script: git-archive-all --prefix="sfizz-${TRAVIS_BRANCH}/" -9 "${INSTALL_DIR}.tar.gz"
|
||||
|
||||
- name: "Generate documentation"
|
||||
if: (tag IS present) AND (branch = master) AND (type = push)
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- doxygen
|
||||
- cmake
|
||||
- libsndfile-dev
|
||||
install: skip
|
||||
script: .travis/update_dox.sh
|
||||
|
||||
- name: "Discord Webhook"
|
||||
install: skip
|
||||
script: bash ${TRAVIS_BUILD_DIR}/.travis/discord_webhook.sh success
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
sudo ln -s /usr/local /opt/local
|
||||
brew update
|
||||
brew upgrade cmake
|
||||
brew install python || brew link --overwrite python
|
||||
brew install jack
|
||||
brew install dylibbundler
|
||||
|
|
@ -15,7 +15,8 @@ buildenv make DESTDIR=${PWD}/${INSTALL_DIR} install
|
|||
|
||||
# Bundle LV2 dependencies
|
||||
cd "${INSTALL_DIR}"/Library/Audio/Plug-Ins/LV2
|
||||
dylibbundler -od -b -x sfizz.lv2/sfizz.so -d sfizz.lv2/libs/ -p @loader_path/libs/
|
||||
dylibbundler -od -b -x sfizz.lv2/Contents/Binary/sfizz.so -d sfizz.lv2/Contents/libs/ -p @loader_path/../libs/
|
||||
dylibbundler -od -b -x sfizz.lv2/Contents/Binary/sfizz_ui.so -d sfizz.lv2/Contents/libs/ -p @loader_path/../libs/
|
||||
cd "${TRAVIS_BUILD_DIR}/build"
|
||||
|
||||
# Bundle VST3 dependencies
|
||||
|
|
|
|||
|
|
@ -8,4 +8,4 @@ cmake -DCMAKE_BUILD_TYPE=Release \
|
|||
-DSFIZZ_TESTS=OFF \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
make -j$(nproc)
|
||||
make -j2
|
||||
|
|
|
|||
|
|
@ -9,17 +9,17 @@ if [[ ${CROSS_COMPILE} == "mingw32" ]]; then
|
|||
-DENABLE_LTO=OFF \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_VST=ON \
|
||||
-DSFIZZ_STATIC_LIBSNDFILE=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
buildenv make -j$(nproc)
|
||||
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_LIBSNDFILE=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
buildenv make -j$(nproc)
|
||||
buildenv make -j2
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ 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 ..
|
||||
buildenv mod-plugin-builder make -j
|
||||
-DCMAKE_BUILD_TYPE=Release -DSFIZZ_JACK=OFF -DSFIZZ_LV2_UI=OFF ..
|
||||
buildenv mod-plugin-builder make -j2
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ mkdir -p build/${INSTALL_DIR} && cd build
|
|||
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_VST="$ENABLE_VST_PLUGIN" \
|
||||
-DSFIZZ_LV2_UI="$ENABLE_LV2_UI" \
|
||||
-DSFIZZ_TESTS=OFF \
|
||||
-DSFIZZ_SHARED=OFF \
|
||||
-DSFIZZ_STATIC_LIBSNDFILE=ON \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=ON \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
make -j$(nproc)
|
||||
make -j2
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ cmake -DCMAKE_BUILD_TYPE=Release \
|
|||
-DSFIZZ_JACK=OFF \
|
||||
-DSFIZZ_TESTS=ON \
|
||||
-DSFIZZ_SHARED=OFF \
|
||||
-DSFIZZ_STATIC_LIBSNDFILE=OFF \
|
||||
-DSFIZZ_STATIC_DEPENDENCIES=OFF \
|
||||
-DSFIZZ_LV2=OFF \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
..
|
||||
make -j$(nproc) sfizz_tests
|
||||
make -j2 sfizz_tests
|
||||
tests/sfizz_tests
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -x # No fail, we need to go back to the original branch at the end
|
||||
. .travis/environment.sh
|
||||
|
||||
mkdir build && cd build && cmake -DSFIZZ_JACK=OFF -DSFIZZ_SHARED=OFF -DSFIZZ_LV2=OFF .. && cd ..
|
||||
doxygen Doxyfile
|
||||
./doxygen/scripts/generate_api_index.sh
|
||||
git fetch --depth=1 https://github.com/${TRAVIS_REPO_SLUG}.git refs/heads/gh-pages:refs/remotes/origin/gh-pages
|
||||
git checkout origin/gh-pages
|
||||
git checkout -b gh-pages
|
||||
mv _api api/${TRAVIS_TAG}
|
||||
mv api_index.md api/index.md
|
||||
git add api && git commit -m "Release ${TRAVIS_TAG} (Travis build: ${TRAVIS_BUILD_NUMBER})"
|
||||
git remote add origin-pages https://${GITHUB_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git > /dev/null 2>&1
|
||||
git push --quiet --set-upstream origin-pages gh-pages
|
||||
git checkout ${TRAVIS_BRANCH}
|
||||
|
|
@ -8,3 +8,5 @@ Contributors to `sfizz`, in chronologic order:
|
|||
- Michael Willis (2020)
|
||||
- Jean-Pierre Cimalando (2020)
|
||||
- Tobiasz "unfa" Karoń (2020)
|
||||
- Kinwie (2020)
|
||||
- Atsushi Eno (2020)
|
||||
|
|
|
|||
|
|
@ -8,27 +8,21 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
project (sfizz VERSION 0.4.0 LANGUAGES CXX C)
|
||||
project (sfizz VERSION 0.5.0 LANGUAGES CXX C)
|
||||
set (PROJECT_DESCRIPTION "A library to load SFZ description files and use them to render music.")
|
||||
|
||||
# External configuration CMake scripts
|
||||
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include (BuildType)
|
||||
include (SfizzConfig)
|
||||
|
||||
# Build Options
|
||||
set (BUILD_TESTING OFF CACHE BOOL "Disable Abseil's tests [default: OFF]")
|
||||
|
||||
# On macOS add the needed directories for both library and jack client
|
||||
if (APPLE)
|
||||
include_directories (SYSTEM /usr/local/opt/libsndfile/include)
|
||||
link_directories (/usr/local/opt/libsndfile/lib)
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
|
@ -36,9 +30,11 @@ 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_LIBSNDFILE "Link libsndfile statically [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)
|
||||
|
||||
include (SfizzConfig)
|
||||
|
||||
# Don't use IPO in non Release builds
|
||||
include (CheckIPO)
|
||||
|
||||
|
|
@ -51,6 +47,10 @@ 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()
|
||||
|
|
|
|||
|
|
@ -47,4 +47,10 @@ It is the role of maintainers to best adapt the governance model to the evolutio
|
|||
3. Maintainers can be invited from regular contributors at any point in time; maintainers wishing to leave the governance of the project may inform the other maintainers.
|
||||
In both cases, updates to this document reflect the evolution of the governance team and rules.
|
||||
|
||||
## License for the GOVERNANCE.md file
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided that this notice
|
||||
is preserved. This file is offered as-is, without any warranty.
|
||||
|
||||
[Open-source Open Collective]: https://opencollective.com/sfztools
|
||||
|
|
|
|||
|
|
@ -3,12 +3,7 @@ BSD 2-Clause License
|
|||
The code is copyrighted by their respective authors, as indicated by the
|
||||
source control mechanism.
|
||||
|
||||
Contributors include:
|
||||
- Paul Ferrand (2019-) paul at ferrand dot cc
|
||||
- Andrea Zanellato (2019-)
|
||||
- Jean-Pierre Cimalando (2020-)
|
||||
- Michael Willis (2020-)
|
||||
- Alexander Mitchell (2020-)
|
||||
Please refer to AUTHORS.md for the list of contributors.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
[![Travis Build Status]](https://travis-ci.com/sfztools/sfizz)
|
||||
[![AppVeyor Build Status]](https://ci.appveyor.com/project/sfztools/sfizz)
|
||||
|
||||
SFZ library and LV2 plugin, please check [our website] for more details.
|
||||
[![Discord Badge Image]](https://discord.gg/3ArE9Mw)
|
||||
|
||||
SFZ parser and synth c++ library, providing AU / LV2 / VST3 plugins
|
||||
and JACK standalone client, please check [our website] for more details.
|
||||
|
||||

|
||||
|
||||
|
|
@ -64,3 +67,4 @@ The sfizz library also uses in some subprojects:
|
|||
[build from source]: https://sfz.tools/sfizz/development/build/
|
||||
[AppVeyor Build Status]: https://img.shields.io/appveyor/ci/sfztools/sfizz.svg?label=Windows&style=popout&logo=appveyor
|
||||
[Travis Build Status]: https://img.shields.io/travis/com/sfztools/sfizz.svg?label=Linux&style=popout&logo=travis
|
||||
[Discord Badge Image]: https://img.shields.io/discord/587748534321807416?label=discord&logo=discord
|
||||
|
|
|
|||
10
appveyor.yml
|
|
@ -1,5 +1,5 @@
|
|||
version: build-{build}
|
||||
image: Visual Studio 2017
|
||||
image: Visual Studio 2019
|
||||
configuration: Release
|
||||
platform:
|
||||
- Win32
|
||||
|
|
@ -12,20 +12,22 @@ install:
|
|||
- 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
|
||||
- cmd: mkdir CMakeBuild
|
||||
- cmd: cd CMakeBuild
|
||||
- cmd: cmake .. -G"Visual Studio 15 2017" -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
|
||||
- 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: cp sfizz.lv2/Release/sfizz.dll sfizz.lv2/
|
||||
- cmd: rm -rf sfizz.lv2/Release
|
||||
- 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
|
||||
|
|
|
|||
70
benchmarks/BM_allWithin.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// 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 "SIMDHelpers.h"
|
||||
#include "Macros.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class WithinArray : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
std::random_device rd { };
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 1, 10 };
|
||||
input = std::vector<float>(state.range(0));
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& state) {
|
||||
UNUSED(state);
|
||||
}
|
||||
|
||||
std::vector<float> input;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(WithinArray, ScalarFalse)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::allWithin, false);
|
||||
sfz::allWithin<float>(input, 1.2f, 3.8f);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(WithinArray, SIMDFalse)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::allWithin, true);
|
||||
sfz::allWithin<float>(input, 1.2f, 3.8f);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(WithinArray, ScalarTrue)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::allWithin, false);
|
||||
sfz::allWithin<float>(input, 0.0f, 11.0f);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(WithinArray, SIMDTrue)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::allWithin, true);
|
||||
sfz::allWithin<float>(input, 0.0f, 11.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_REGISTER_F(WithinArray, ScalarFalse)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(WithinArray, SIMDFalse)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(WithinArray, ScalarTrue)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(WithinArray, SIMDTrue)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
233
benchmarks/BM_audioReaders.cpp
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
// 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 "AudioReader.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <sndfile.hh>
|
||||
#include <ghc/fs_std.hpp>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
#include <stdexcept>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
///
|
||||
struct TemporaryFile {
|
||||
TemporaryFile();
|
||||
~TemporaryFile();
|
||||
|
||||
TemporaryFile(const TemporaryFile&) = delete;
|
||||
TemporaryFile& operator=(const TemporaryFile&) = delete;
|
||||
|
||||
TemporaryFile(TemporaryFile&&) = default;
|
||||
TemporaryFile& operator=(TemporaryFile&&) = default;
|
||||
|
||||
const fs::path& path() const { return path_; }
|
||||
|
||||
private:
|
||||
fs::path path_;
|
||||
static fs::path createTemporaryFile();
|
||||
};
|
||||
|
||||
TemporaryFile::TemporaryFile()
|
||||
: path_(createTemporaryFile())
|
||||
{
|
||||
}
|
||||
|
||||
TemporaryFile::~TemporaryFile()
|
||||
{
|
||||
std::error_code ec;
|
||||
fs::remove(path_, ec);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
fs::path TemporaryFile::createTemporaryFile()
|
||||
{
|
||||
char path[] = P_tmpdir "/sndXXXXXX";
|
||||
int fd = mkstemp(path);
|
||||
if (fd == -1)
|
||||
throw std::runtime_error("Cannot create temporary file.");
|
||||
close(fd);
|
||||
return path;
|
||||
}
|
||||
#else
|
||||
fs::path TemporaryFile::createTemporaryFile()
|
||||
{
|
||||
DWORD ret = GetTempPathW(0, buffer);
|
||||
std::unique_ptr<WCHAR[]> path;
|
||||
if (ret != 0) {
|
||||
path.reset(new WCHAR[ret + 8]{});
|
||||
ret = GetTempPathW(0, buffer);
|
||||
if (ret != 0)
|
||||
wcscat(path.get(), L"\\XXXXXX");
|
||||
}
|
||||
if (ret == 0 || !_wmktemp(path.get()))
|
||||
throw std::runtime_error("Cannot create temporary file.");
|
||||
return path.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
///
|
||||
class AudioReaderFixture : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) override
|
||||
{
|
||||
workBuffer.resize(2 * static_cast<size_t>(state.range(0)));
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */) override
|
||||
{
|
||||
}
|
||||
|
||||
static TemporaryFile createAudioFile(int format);
|
||||
|
||||
static TemporaryFile fileWav;
|
||||
static TemporaryFile fileFlac;
|
||||
static TemporaryFile fileOgg;
|
||||
|
||||
std::vector<float> workBuffer;
|
||||
};
|
||||
|
||||
TemporaryFile AudioReaderFixture::fileWav = createAudioFile(SF_FORMAT_WAV|SF_FORMAT_PCM_16);
|
||||
TemporaryFile AudioReaderFixture::fileFlac = createAudioFile(SF_FORMAT_FLAC|SF_FORMAT_PCM_16);
|
||||
TemporaryFile AudioReaderFixture::fileOgg = createAudioFile(SF_FORMAT_OGG|SF_FORMAT_VORBIS);
|
||||
|
||||
TemporaryFile AudioReaderFixture::createAudioFile(int format)
|
||||
{
|
||||
constexpr unsigned sampleRate = 44100;
|
||||
constexpr unsigned fileDuration = 10;
|
||||
constexpr unsigned fileFrames = sampleRate * fileDuration;
|
||||
|
||||
// synth 2 channels of arbitrary waveform
|
||||
std::unique_ptr<double[]> sndData { new double[2 * fileFrames] };
|
||||
double phase = 0.0;
|
||||
for (unsigned i = 0; i < fileFrames; ++i) {
|
||||
sndData[2 * i ] = std::sin(2.0 * M_PI * phase);
|
||||
sndData[2 * i + 1] = std::cos(2.0 * M_PI * phase);
|
||||
phase += 440.0 * (1.0 / sampleRate);
|
||||
phase -= static_cast<long>(phase);
|
||||
}
|
||||
|
||||
// create temp file
|
||||
TemporaryFile temp;
|
||||
fprintf(stderr, "* Temporary file: %s\n", temp.path().u8string().c_str());
|
||||
|
||||
// write to file
|
||||
#if !defined(_WIN32)
|
||||
SndfileHandle snd(temp.path().c_str(), SFM_WRITE, format, 2, sampleRate);
|
||||
#else
|
||||
SndfileHandle snd(temp.path().wstring().c_str(), SFM_WRITE, format, 2, sampleRate);
|
||||
#endif
|
||||
|
||||
if (snd.error())
|
||||
throw std::runtime_error("cannot open sound file for writing");
|
||||
snd.writef(sndData.get(), fileFrames);
|
||||
snd = SndfileHandle();
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void doReaderBenchmark(const fs::path& path, std::vector<float> &buffer, sfz::AudioReaderType type)
|
||||
{
|
||||
sfz::AudioReaderPtr reader = sfz::createExplicitAudioReader(path, type);
|
||||
while (reader->readNextBlock(buffer.data(), buffer.size() / 2) > 0);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
std::vector<float> buffer(static_cast<size_t>(2 * handle.frames()));
|
||||
handle.read(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, EntireWav)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doEntireRead(fileWav.path());
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ForwardWav)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileWav.path(), workBuffer, sfz::AudioReaderType::Forward);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseWav)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileWav.path(), workBuffer, sfz::AudioReaderType::Reverse);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, EntireFlac)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doEntireRead(fileFlac.path());
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ForwardFlac)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileFlac.path(), workBuffer, sfz::AudioReaderType::Forward);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseFlac)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileFlac.path(), workBuffer, sfz::AudioReaderType::Reverse);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, EntireOgg)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doEntireRead(fileOgg.path());
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(AudioReaderFixture, ForwardOgg)(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
doReaderBenchmark(fileOgg.path(), workBuffer, sfz::AudioReaderType::Forward);
|
||||
}
|
||||
}
|
||||
|
||||
//BENCHMARK_DEFINE_F(AudioReaderFixture, ReverseOgg)(benchmark::State& state)
|
||||
//{
|
||||
// for (auto _ : state) {
|
||||
// doReaderBenchmark(fileOgg.path(), workBuffer, sfz::AudioReaderType::Reverse);
|
||||
// }
|
||||
//}
|
||||
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ForwardWav)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseWav)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
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, ForwardOgg)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
//BENCHMARK_REGISTER_F(AudioReaderFixture, ReverseOgg)->RangeMultiplier(2)->Range((1 << 6), (1 << 10));
|
||||
BENCHMARK_REGISTER_F(AudioReaderFixture, EntireOgg)->Range(1, 1);
|
||||
BENCHMARK_MAIN();
|
||||
52
benchmarks/BM_clamp.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// 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 "SIMDHelpers.h"
|
||||
#include "Macros.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class ClampArray : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
std::random_device rd { };
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 0, 10 };
|
||||
input = std::vector<float>(state.range(0));
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& state) {
|
||||
UNUSED(state);
|
||||
}
|
||||
|
||||
std::vector<float> input;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(ClampArray, Scalar)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::clampAll, false);
|
||||
sfz::clampAll<float>(absl::MakeSpan(input), 1.2f, 3.8f);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(ClampArray, SIMD)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::clampAll, true);
|
||||
sfz::clampAll<float>(absl::MakeSpan(input), 1.2f, 3.8f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BENCHMARK_REGISTER_F(ClampArray, Scalar)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(ClampArray, SIMD)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
|
|
@ -20,7 +20,7 @@ constexpr float sampleRate { 48000.0f };
|
|||
|
||||
class FilterFixture : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
void SetUp(const ::benchmark::State& /* state */) {
|
||||
inputLeft = std::vector<float>(blockSize);
|
||||
inputRight = std::vector<float>(blockSize);
|
||||
outputLeft = std::vector<float>(blockSize);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
class FileFixture : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
void SetUp(const ::benchmark::State& /* state */) {
|
||||
filePath1 = getPath() / "sample1.flac";
|
||||
filePath2 = getPath() / "sample2.flac";
|
||||
filePath3 = getPath() / "sample3.flac";
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ BENCHMARK_DEFINE_F(MeanSquaredArray, Scalar)
|
|||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::meanSquared, false);
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::sumSquares, false);
|
||||
auto result = sfz::meanSquared<float>(input);
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ BENCHMARK_DEFINE_F(MeanSquaredArray, SIMD)
|
|||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::meanSquared, true);
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::sumSquares, true);
|
||||
auto result = sfz::meanSquared<float>(input);
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ BENCHMARK_DEFINE_F(MeanSquaredArray, Scalar_Unaligned)
|
|||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::meanSquared, false);
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::sumSquares, false);
|
||||
auto result = sfz::meanSquared<float>(absl::MakeSpan(input).subspan(1));
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ BENCHMARK_DEFINE_F(MeanSquaredArray, SIMD_Unaligned)
|
|||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::meanSquared, true);
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::sumSquares, true);
|
||||
auto result = sfz::meanSquared<float>(absl::MakeSpan(input).subspan(1));
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
|
|
|
|||
83
benchmarks/BM_multiplyMul.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
// 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 "SIMDHelpers.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class MultiplyMul : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
std::random_device rd { };
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 0.1f, 1.0f };
|
||||
input = std::vector<float>(state.range(0));
|
||||
output = std::vector<float>(state.range(0));
|
||||
gain = std::vector<float>(state.range(0));
|
||||
std::fill(output.begin(), output.end(), 2.0f );
|
||||
std::generate(gain.begin(), gain.end(), [&]() { return dist(gen); });
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<float> gain;
|
||||
std::vector<float> input;
|
||||
std::vector<float> output;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, Straight)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
for (int i = 0; i < state.range(0); ++i)
|
||||
output[i] *= gain[i] * input[i];
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, Scalar)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, false);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, SIMD)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, Scalar_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, false);
|
||||
sfz::multiplyMul<float>(absl::MakeSpan(gain).subspan(1), absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMul, SIMD_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul, true);
|
||||
sfz::multiplyMul<float>(absl::MakeSpan(gain).subspan(1), absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, Straight)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, Scalar)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, SIMD)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, Scalar_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMul, SIMD_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
88
benchmarks/BM_multiplyMulFixedGain.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// 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 "SIMDHelpers.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
class MultiplyMulFixedGain : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state)
|
||||
{
|
||||
std::random_device rd {};
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 0.1f, 1.0f };
|
||||
input = std::vector<float>(state.range(0));
|
||||
output = std::vector<float>(state.range(0));
|
||||
gain = dist(gen);
|
||||
std::fill(output.begin(), output.end(), 2.0f);
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */)
|
||||
{
|
||||
}
|
||||
|
||||
float gain = {};
|
||||
std::vector<float> input;
|
||||
std::vector<float> output;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, Straight)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
for (int i = 0; i < state.range(0); ++i)
|
||||
output[i] *= gain * input[i];
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, Scalar)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, false);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, SIMD)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, true);
|
||||
sfz::multiplyMul1<float>(gain, input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, Scalar_Unaligned)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, false);
|
||||
sfz::multiplyMul1<float>(gain, absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(MultiplyMulFixedGain, SIMD_Unaligned)
|
||||
(benchmark::State& state)
|
||||
{
|
||||
for (auto _ : state) {
|
||||
sfz::setSIMDOpStatus<float>(sfz::SIMDOps::multiplyMul1, true);
|
||||
sfz::multiplyMul1<float>(gain, absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, Straight)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, Scalar)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, SIMD)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, Scalar_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_REGISTER_F(MultiplyMulFixedGain, SIMD_Unaligned)->RangeMultiplier(4)->Range(1 << 2, 1 << 12);
|
||||
BENCHMARK_MAIN();
|
||||
134
benchmarks/BM_pan_arm.cpp
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// 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 "Panning.h"
|
||||
#include "simd/Common.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <random>
|
||||
#include <absl/algorithm/container.h>
|
||||
#include "absl/types/span.h"
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include <jsl/allocator>
|
||||
template <class T, std::size_t A = 16>
|
||||
using aligned_vector = std::vector<T, jsl::aligned_allocator<T, A>>;
|
||||
|
||||
// Number of elements in the table, odd for equal volume at center
|
||||
constexpr int panSize = 4095;
|
||||
|
||||
// Table of pan values for the left channel, extra element for safety
|
||||
static const auto panData = []()
|
||||
{
|
||||
std::array<float, panSize + 1> pan;
|
||||
int i = 0;
|
||||
|
||||
for (; i < panSize; ++i)
|
||||
pan[i] = std::cos(i * (piTwo<double>() / (panSize - 1)));
|
||||
|
||||
for (; i < static_cast<int>(pan.size()); ++i)
|
||||
pan[i] = pan[panSize - 1];
|
||||
|
||||
return pan;
|
||||
}();
|
||||
|
||||
float _panLookup(float pan)
|
||||
{
|
||||
// reduce range, round to nearest
|
||||
int index = lroundPositive(pan * (panSize - 1));
|
||||
return panData[index];
|
||||
}
|
||||
|
||||
void panScalar(const float* panEnvelope, float* leftBuffer, float* rightBuffer, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = panEnvelope + size;
|
||||
while (panEnvelope < sentinel) {
|
||||
auto p =(*panEnvelope + 1.0f) * 0.5f;
|
||||
p = clamp(p, 0.0f, 1.0f);
|
||||
*leftBuffer *= _panLookup(p);
|
||||
*rightBuffer *= _panLookup(1 - p);
|
||||
incrementAll(panEnvelope, leftBuffer, rightBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void panSIMD(const float* panEnvelope, float* leftBuffer, float* rightBuffer, unsigned size) noexcept
|
||||
{
|
||||
const auto sentinel = panEnvelope + size;
|
||||
int32_t indices[4];
|
||||
while (panEnvelope < sentinel) {
|
||||
float32x4_t mmPan = vld1q_f32(panEnvelope);
|
||||
mmPan = vaddq_f32(mmPan, vdupq_n_f32(1.0f));
|
||||
mmPan = vmulq_n_f32(mmPan, 0.5f * panSize);
|
||||
mmPan = vaddq_f32(mmPan, vdupq_n_f32(0.5f));
|
||||
mmPan = vminq_f32(mmPan, vdupq_n_f32(panSize));
|
||||
mmPan = vmaxq_f32(mmPan, vdupq_n_f32(0.0f));
|
||||
int32x4_t mmIdx = vcvtq_s32_f32(mmPan);
|
||||
vst1q_s32(indices, mmIdx);
|
||||
|
||||
leftBuffer[0] *= panData[indices[0]];
|
||||
rightBuffer[0] *= panData[panSize - indices[0] - 1];
|
||||
leftBuffer[1] *= panData[indices[1]];
|
||||
rightBuffer[1] *= panData[panSize - indices[1]- 1];
|
||||
leftBuffer[2] *= panData[indices[2]];
|
||||
rightBuffer[2] *= panData[panSize - indices[2]- 1];
|
||||
leftBuffer[3] *= panData[indices[3]];
|
||||
rightBuffer[3] *= panData[panSize - indices[3]- 1];
|
||||
|
||||
incrementAll<4>(panEnvelope, leftBuffer, rightBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
class PanFixture : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
std::random_device rd { };
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { -1.0f, 1.0f };
|
||||
pan.resize(state.range(0));
|
||||
right.resize(state.range(0));
|
||||
left.resize(state.range(0));
|
||||
|
||||
if (!willAlign<16>(pan.data(), left.data(), right.data()))
|
||||
std::cout << "Will not align!" << '\n';
|
||||
absl::c_generate(pan, [&]() { return dist(gen); });
|
||||
absl::c_generate(left, [&]() { return dist(gen); });
|
||||
absl::c_generate(right, [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */) {
|
||||
|
||||
}
|
||||
|
||||
aligned_vector<float> pan;
|
||||
aligned_vector<float> right;
|
||||
aligned_vector<float> left;
|
||||
};
|
||||
|
||||
BENCHMARK_DEFINE_F(PanFixture, PanScalar)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
panScalar(pan.data(), left.data(), right.data(), state.range(0));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(PanFixture, PanSIMD)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
panSIMD(pan.data(), left.data(), right.data(), state.range(0));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(PanFixture, PanSfizz)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::pan(pan.data(), left.data(), right.data(), state.range(0));
|
||||
}
|
||||
}
|
||||
|
||||
// Register the function as a benchmark
|
||||
BENCHMARK_REGISTER_F(PanFixture, PanScalar)->RangeMultiplier(4)->Range((1 << 4), (1 << 12));
|
||||
BENCHMARK_REGISTER_F(PanFixture, PanSIMD)->RangeMultiplier(4)->Range((1 << 4), (1 << 12));
|
||||
BENCHMARK_REGISTER_F(PanFixture, PanSfizz)->RangeMultiplier(4)->Range((1 << 4), (1 << 12));
|
||||
BENCHMARK_MAIN();
|
||||
125
benchmarks/BM_powerFollower.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
// 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 "PowerFollower.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "Config.h"
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <cmath>
|
||||
|
||||
class PowerFollowerFixture : public benchmark::Fixture {
|
||||
public:
|
||||
PowerFollowerFixture()
|
||||
{
|
||||
inputSignal_ = sfz::AudioBuffer<float>(2, numFrames);
|
||||
auto leftSignal = inputSignal_.getSpan(0);
|
||||
auto rightSignal = inputSignal_.getSpan(1);
|
||||
float phase = 0;
|
||||
for (size_t i = 0; i < numFrames; ++i) {
|
||||
constexpr float k2pi = 2.0 * M_PI;
|
||||
leftSignal[i] = std::sin(k2pi * phase);
|
||||
rightSignal[i] = std::cos(k2pi * phase);
|
||||
phase += 440.0f / sfz::config::defaultSampleRate;
|
||||
phase -= static_cast<int>(phase);
|
||||
}
|
||||
}
|
||||
|
||||
void SetUp(const ::benchmark::State& state)
|
||||
{
|
||||
auto blockSize = static_cast<size_t>(state.range(0));
|
||||
follower_.setSampleRate(sfz::config::defaultSampleRate);
|
||||
follower_.setSamplesPerBlock(blockSize);
|
||||
follower_.clear();
|
||||
|
||||
//
|
||||
refFollower_.init(sfz::config::defaultSampleRate);
|
||||
refFollower_.clear();
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */)
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr size_t numFrames = 65536;
|
||||
sfz::PowerFollower follower_;
|
||||
sfz::AudioBuffer<float> inputSignal_;
|
||||
|
||||
//
|
||||
struct ReferenceFollower {
|
||||
/*
|
||||
import("stdfaust.lib");
|
||||
process = (_, _) : + : an.amp_follower_ud(att, rel) with { att = 5e-3; rel = 200e-3; };
|
||||
*/
|
||||
|
||||
void init(float sampleRate)
|
||||
{
|
||||
fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(sampleRate)));
|
||||
fConst1 = std::exp((0.0f - (200.0f / fConst0)));
|
||||
fConst2 = (1.0f - fConst1);
|
||||
fConst3 = std::exp((0.0f - (5.0f / fConst0)));
|
||||
fConst4 = (1.0f - fConst3);
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
|
||||
fRec1[l0] = 0.0f;
|
||||
}
|
||||
for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
|
||||
fRec0[l1] = 0.0f;
|
||||
}
|
||||
}
|
||||
float process(float input0, float input1)
|
||||
{
|
||||
float fTemp0 = std::fabs((float(input0) + float(input1)));
|
||||
fRec1[0] = std::max<float>(fTemp0, ((fConst3 * fRec1[1]) + (fConst4 * fTemp0)));
|
||||
fRec0[0] = ((fConst1 * fRec0[1]) + (fConst2 * fRec1[0]));
|
||||
float output = fRec0[0];
|
||||
fRec1[1] = fRec1[0];
|
||||
fRec0[1] = fRec0[0];
|
||||
return output;
|
||||
}
|
||||
|
||||
float fConst0;
|
||||
float fConst1;
|
||||
float fConst2;
|
||||
float fConst3;
|
||||
float fConst4;
|
||||
float fRec1[2];
|
||||
float fRec0[2];
|
||||
};
|
||||
ReferenceFollower refFollower_;
|
||||
};
|
||||
|
||||
constexpr size_t PowerFollowerFixture::numFrames;
|
||||
|
||||
BENCHMARK_DEFINE_F(PowerFollowerFixture, ReferenceFollower) (benchmark::State& state)
|
||||
{
|
||||
sfz::AudioSpan<float> inputSignal(inputSignal_);
|
||||
auto input0 = inputSignal.getConstSpan(0);
|
||||
auto input1 = inputSignal.getConstSpan(1);
|
||||
|
||||
for (auto _ : state) {
|
||||
auto& follower = refFollower_;
|
||||
float output = 0;
|
||||
for (size_t i = 0, n = inputSignal.getNumFrames(); i < n; ++i)
|
||||
output = follower.process(input0[i], input1[i]);
|
||||
benchmark::DoNotOptimize(output);
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(PowerFollowerFixture, Follower) (benchmark::State& state)
|
||||
{
|
||||
sfz::AudioSpan<float> inputSignal(inputSignal_);
|
||||
for (auto _ : state) {
|
||||
auto& follower = follower_;
|
||||
auto blockSize = static_cast<size_t>(state.range(0));
|
||||
for (size_t i = 0; i < numFrames; i += blockSize)
|
||||
follower.process(inputSignal.subspan(i, blockSize));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_REGISTER_F(PowerFollowerFixture, ReferenceFollower)->Range(1, 1);
|
||||
BENCHMARK_REGISTER_F(PowerFollowerFixture, Follower)->RangeMultiplier(2)->Range(1 << 5, 1 << 12);
|
||||
|
|
@ -32,6 +32,7 @@ macro(sfizz_add_benchmark TARGET)
|
|||
target_link_libraries ("${TARGET}" PRIVATE atomic)
|
||||
endif()
|
||||
target_include_directories("${TARGET}" PRIVATE ../src/sfizz ../src/external)
|
||||
sfizz_enable_fast_math("${TARGET}")
|
||||
endmacro()
|
||||
|
||||
sfizz_add_benchmark(bm_opf_high_vs_low BM_OPF_high_vs_low.cpp)
|
||||
|
|
@ -48,6 +49,8 @@ target_link_libraries(bm_ADSR PRIVATE sfizz::sfizz)
|
|||
sfizz_add_benchmark(bm_add BM_add.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyAdd BM_multiplyAdd.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyAddFixedGain BM_multiplyAddFixedGain.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyMul BM_multiplyMul.cpp)
|
||||
sfizz_add_benchmark(bm_multiplyMulFixedGain BM_multiplyMulFixedGain.cpp)
|
||||
sfizz_add_benchmark(bm_subtract BM_subtract.cpp)
|
||||
sfizz_add_benchmark(bm_copy BM_copy.cpp)
|
||||
sfizz_add_benchmark(bm_mean BM_mean.cpp)
|
||||
|
|
@ -59,11 +62,15 @@ sfizz_add_benchmark(bm_maps BM_maps.cpp)
|
|||
target_link_libraries(bm_maps PRIVATE absl::flat_hash_map)
|
||||
sfizz_add_benchmark(bm_mapVsArray BM_mapVsArray.cpp)
|
||||
sfizz_add_benchmark(bm_random BM_random.cpp)
|
||||
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)
|
||||
sfizz_add_benchmark(bm_resample BM_resample.cpp ${BENCHMARK_SIMD_SOURCES})
|
||||
|
|
@ -78,6 +85,9 @@ target_link_libraries(bm_wavfile PRIVATE sfizz-sndfile)
|
|||
sfizz_add_benchmark(bm_flacfile BM_flacfile.cpp)
|
||||
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)
|
||||
|
||||
sfizz_add_benchmark(bm_readChunk BM_readChunk.cpp)
|
||||
target_link_libraries(bm_readChunk PRIVATE sfizz-sndfile)
|
||||
sfizz_add_benchmark(bm_readChunkFlac BM_readChunkFlac.cpp)
|
||||
|
|
@ -137,6 +147,12 @@ if (TARGET bm_resample)
|
|||
add_dependencies(sfizz_benchmarks bm_resample)
|
||||
endif()
|
||||
|
||||
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)
|
||||
endif()
|
||||
|
||||
configure_file("sample.wav" "${CMAKE_BINARY_DIR}/benchmarks/sample1.wav" COPYONLY)
|
||||
configure_file("sample.wav" "${CMAKE_BINARY_DIR}/benchmarks/sample2.wav" COPYONLY)
|
||||
configure_file("sample.wav" "${CMAKE_BINARY_DIR}/benchmarks/sample3.wav" COPYONLY)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ 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 jack absl::flags_parse ${JACK_LIBRARIES})
|
||||
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}
|
||||
COMPONENT "jack" OPTIONAL)
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "sfizz/Synth.h"
|
||||
#include "sfizz/Macros.h"
|
||||
#include "sfizz.hpp"
|
||||
#include "MidiHelpers.h"
|
||||
#include <absl/flags/parse.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
|
@ -47,9 +46,9 @@ static jack_client_t* client;
|
|||
|
||||
int process(jack_nframes_t numFrames, void* arg)
|
||||
{
|
||||
auto synth = reinterpret_cast<sfz::Synth*>(arg);
|
||||
auto* synth = reinterpret_cast<sfz::Sfizz*>(arg);
|
||||
|
||||
auto buffer = jack_port_get_buffer(midiInputPort, numFrames);
|
||||
auto* buffer = jack_port_get_buffer(midiInputPort, numFrames);
|
||||
assert(buffer);
|
||||
|
||||
auto numMidiEvents = jack_midi_get_event_count(buffer);
|
||||
|
|
@ -97,9 +96,11 @@ int process(jack_nframes_t numFrames, void* arg)
|
|||
}
|
||||
}
|
||||
|
||||
auto leftOutput = reinterpret_cast<float*>(jack_port_get_buffer(outputPort1, numFrames));
|
||||
auto rightOutput = reinterpret_cast<float*>(jack_port_get_buffer(outputPort2, numFrames));
|
||||
synth->renderBlock({ { leftOutput, rightOutput }, numFrames });
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -109,7 +110,7 @@ int sampleBlockChanged(jack_nframes_t nframes, void* arg)
|
|||
if (arg == nullptr)
|
||||
return 0;
|
||||
|
||||
auto synth = reinterpret_cast<sfz::Synth*>(arg);
|
||||
auto* synth = reinterpret_cast<sfz::Sfizz*>(arg);
|
||||
// DBG("Sample per block changed to " << nframes);
|
||||
synth->setSamplesPerBlock(nframes);
|
||||
return 0;
|
||||
|
|
@ -120,19 +121,19 @@ int sampleRateChanged(jack_nframes_t nframes, void* arg)
|
|||
if (arg == nullptr)
|
||||
return 0;
|
||||
|
||||
auto synth = reinterpret_cast<sfz::Synth*>(arg);
|
||||
auto* synth = reinterpret_cast<sfz::Sfizz*>(arg);
|
||||
// DBG("Sample rate changed to " << nframes);
|
||||
synth->setSampleRate(nframes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool shouldClose { false };
|
||||
static volatile sig_atomic_t shouldClose { false };
|
||||
|
||||
static void done(int sig)
|
||||
{
|
||||
std::cout << "Signal received" << '\n';
|
||||
shouldClose = true;
|
||||
UNUSED(sig);
|
||||
(void)sig;
|
||||
// if (client != nullptr)
|
||||
|
||||
// exit(0);
|
||||
|
|
@ -163,11 +164,11 @@ int main(int argc, char** argv)
|
|||
std::cout << "- Oversampling: " << oversampling << '\n';
|
||||
std::cout << "- Preloaded Size: " << preload_size << '\n';
|
||||
const auto factor = [&]() {
|
||||
if (oversampling == "x1") return sfz::Oversampling::x1;
|
||||
if (oversampling == "x2") return sfz::Oversampling::x2;
|
||||
if (oversampling == "x4") return sfz::Oversampling::x4;
|
||||
if (oversampling == "x8") return sfz::Oversampling::x8;
|
||||
return sfz::Oversampling::x1;
|
||||
if (oversampling == "x1") return 1;
|
||||
if (oversampling == "x2") return 2;
|
||||
if (oversampling == "x4") return 4;
|
||||
if (oversampling == "x8") return 8;
|
||||
return 1;
|
||||
}();
|
||||
|
||||
std::cout << "Positional arguments:";
|
||||
|
|
@ -175,7 +176,7 @@ int main(int argc, char** argv)
|
|||
std::cout << " " << file << ',';
|
||||
std::cout << '\n';
|
||||
|
||||
sfz::Synth synth;
|
||||
sfz::Sfizz synth;
|
||||
synth.setOversamplingFactor(factor);
|
||||
synth.setPreloadSize(preload_size);
|
||||
synth.loadSfzFile(filesToParse[0]);
|
||||
|
|
@ -186,6 +187,7 @@ int main(int argc, char** argv)
|
|||
std::cout << "\tRegions: " << synth.getNumRegions() << '\n';
|
||||
std::cout << "\tCurves: " << synth.getNumCurves() << '\n';
|
||||
std::cout << "\tPreloadedSamples: " << synth.getNumPreloadedSamples() << '\n';
|
||||
#if 0 // not currently in public API
|
||||
std::cout << "==========" << '\n';
|
||||
std::cout << "Included files:" << '\n';
|
||||
for (auto& file : synth.getParser().getIncludedFiles())
|
||||
|
|
@ -194,6 +196,7 @@ int main(int argc, char** argv)
|
|||
std::cout << "Defines:" << '\n';
|
||||
for (auto& define : synth.getParser().getDefines())
|
||||
std::cout << '\t' << define.first << '=' << define.second << '\n';
|
||||
#endif
|
||||
std::cout << "==========" << '\n';
|
||||
std::cout << "Unknown opcodes:";
|
||||
for (auto& opcode : synth.getUnknownOpcodes())
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ int main(int argc, char** argv)
|
|||
bool verbose { false };
|
||||
bool help { false };
|
||||
bool useEOT { false };
|
||||
int quality { 2 };
|
||||
int oversampling { 1 };
|
||||
|
||||
options.add_options()
|
||||
|
|
@ -74,6 +75,7 @@ int main(int argc, char** argv)
|
|||
("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>())
|
||||
("use-eot", "End the rendering at the last End of Track Midi message", cxxopts::value(useEOT))
|
||||
|
|
@ -118,6 +120,7 @@ int main(int argc, char** argv)
|
|||
sfz::Synth synth;
|
||||
synth.setSamplesPerBlock(blockSize);
|
||||
synth.setSampleRate(sampleRate);
|
||||
synth.setSampleQuality(sfz::Synth::ProcessMode::ProcessFreewheeling, quality);
|
||||
synth.enableFreeWheeling();
|
||||
|
||||
if (params.count("log") > 0)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,22 @@ else()
|
|||
set (LV2PLUGIN_SPDX_LICENSE_ID "ISC")
|
||||
endif()
|
||||
|
||||
if(SFIZZ_LV2_UI)
|
||||
set(LV2PLUGIN_IF_ENABLE_UI "")
|
||||
else()
|
||||
set(LV2PLUGIN_IF_ENABLE_UI "#")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(LV2_UI_TYPE "WindowsUI")
|
||||
elseif(APPLE)
|
||||
set(LV2_UI_TYPE "CocoaUI")
|
||||
elseif(HAIKU)
|
||||
set(LV2_UI_TYPE "BeUI")
|
||||
else()
|
||||
set(LV2_UI_TYPE "X11UI")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set (LV2PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lv2" CACHE STRING
|
||||
"Install destination for LV2 bundle [default: ${CMAKE_INSTALL_PREFIX}/lv2}]")
|
||||
|
|
|
|||
|
|
@ -17,6 +17,31 @@ if (WIN32)
|
|||
add_compile_definitions(_WIN32_WINNT=0x601)
|
||||
endif()
|
||||
|
||||
# Set macOS compatibility level
|
||||
if (APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")
|
||||
endif()
|
||||
|
||||
# Do not define macros `min` and `max`
|
||||
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
|
||||
|
||||
|
|
@ -32,10 +57,15 @@ endif()
|
|||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
add_compile_options(-Wall)
|
||||
add_compile_options(-Wextra)
|
||||
add_compile_options(-ffast-math)
|
||||
add_compile_options(-fno-omit-frame-pointer) # For debugging purposes
|
||||
add_compile_options(-Wno-multichar)
|
||||
add_compile_options(-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)
|
||||
add_compile_options(-mfloat-abi=hard)
|
||||
endif()
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
|
@ -43,22 +73,34 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
|||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
function(sfizz_enable_fast_math NAME)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
target_compile_options("${NAME}" PRIVATE "-ffast-math")
|
||||
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(LibSndFile REQUIRED)
|
||||
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-static)
|
||||
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_LIBSNDFILE)
|
||||
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()
|
||||
|
||||
|
||||
|
|
@ -107,12 +149,13 @@ Build using LTO: ${ENABLE_LTO}
|
|||
Build as shared library: ${SFIZZ_SHARED}
|
||||
Build JACK stand-alone client: ${SFIZZ_JACK}
|
||||
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}
|
||||
Use vcpkg: ${SFIZZ_USE_VCPKG}
|
||||
Statically link libsndfile: ${SFIZZ_STATIC_LIBSNDFILE}
|
||||
Statically link dependencies: ${SFIZZ_STATIC_DEPENDENCIES}
|
||||
Link libatomic: ${SFIZZ_LINK_LIBATOMIC}
|
||||
Use clang libc++: ${USE_LIBCPP}
|
||||
Release asserts: ${SFIZZ_RELEASE_ASSERTS}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ macro(sfizz_add_simd_sources SOURCES_VAR PREFIX)
|
|||
|
||||
list (APPEND ${SOURCES_VAR}
|
||||
${PREFIX}/sfizz/SIMDHelpers.cpp
|
||||
${PREFIX}/sfizz/simd/HelpersNEON.cpp
|
||||
${PREFIX}/sfizz/simd/HelpersSSE.cpp
|
||||
${PREFIX}/sfizz/simd/HelpersAVX.cpp)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ if(NOT VST3_PACKAGE_ARCHITECTURE)
|
|||
else()
|
||||
set(VST3_PACKAGE_ARCHITECTURE "i386")
|
||||
endif()
|
||||
elseif(VST3_SYSTEM_PROCESSOR MATCHES "^(armv7l)$")
|
||||
set(VST3_PACKAGE_ARCHITECTURE "armv7l")
|
||||
elseif(VST3_SYSTEM_PROCESSOR MATCHES "^(armv[3-8][a-z]*)$")
|
||||
set(VST3_PACKAGE_ARCHITECTURE "${VST3_SYSTEM_PROCESSOR}")
|
||||
elseif(VST3_SYSTEM_PROCESSOR MATCHES "^(aarch64)$")
|
||||
set(VST3_PACKAGE_ARCHITECTURE "aarch64")
|
||||
set(VST3_PACKAGE_ARCHITECTURE "aarch64")
|
||||
else()
|
||||
message(FATAL_ERROR "We don't know this architecture for VST3: ${VST3_SYSTEM_PROCESSOR}.")
|
||||
endif()
|
||||
|
|
|
|||
296
common.mk
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
# Common definitions for builds based on GNU Make
|
||||
|
||||
ifndef SFIZZ_DIR
|
||||
$(error sfizz: The source directory must be set before including)
|
||||
endif
|
||||
|
||||
###
|
||||
|
||||
SFIZZ_MACHINE := $(shell $(CC) -dumpmachine)
|
||||
SFIZZ_PROCESSOR := $(firstword $(subst -, ,$(SFIZZ_MACHINE)))
|
||||
|
||||
ifneq (,$(filter i%86,$(SFIZZ_PROCESSOR)))
|
||||
SFIZZ_CPU_I386 := 1
|
||||
SFIZZ_CPU_I386_OR_X86_64 := 1
|
||||
endif
|
||||
ifneq (,$(filter x86_64,$(SFIZZ_PROCESSOR)))
|
||||
SFIZZ_CPU_X86_64 := 1
|
||||
SFIZZ_CPU_I386_OR_X86_64 := 1
|
||||
endif
|
||||
ifneq (,$(filter arm%,$(SFIZZ_PROCESSOR)))
|
||||
SFIZZ_CPU_ARM := 1
|
||||
SFIZZ_CPU_ARM_OR_AARCH64 := 1
|
||||
endif
|
||||
ifneq (,$(filter aarch64%,$(SFIZZ_PROCESSOR)))
|
||||
SFIZZ_CPU_AARCH64 := 1
|
||||
SFIZZ_CPU_ARM_OR_AARCH64 := 1
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring linux,$(SFIZZ_MACHINE)))
|
||||
SFIZZ_OS_LINUX := 1
|
||||
endif
|
||||
ifneq (,$(findstring apple,$(SFIZZ_MACHINE)))
|
||||
SFIZZ_OS_APPLE := 1
|
||||
endif
|
||||
ifneq (,$(findstring mingw,$(SFIZZ_MACHINE)))
|
||||
SFIZZ_OS_WINDOWS := 1
|
||||
endif
|
||||
|
||||
###
|
||||
|
||||
SFIZZ_C_FLAGS = -I$(SFIZZ_DIR)/src
|
||||
SFIZZ_CXX_FLAGS = $(SFIZZ_C_FLAGS)
|
||||
|
||||
SFIZZ_SOURCES = \
|
||||
src/sfizz/ADSREnvelope.cpp \
|
||||
src/sfizz/AudioReader.cpp \
|
||||
src/sfizz/Curve.cpp \
|
||||
src/sfizz/effects/Apan.cpp \
|
||||
src/sfizz/Effects.cpp \
|
||||
src/sfizz/modulations/ModId.cpp \
|
||||
src/sfizz/modulations/ModKey.cpp \
|
||||
src/sfizz/modulations/ModKeyHash.cpp \
|
||||
src/sfizz/modulations/ModMatrix.cpp \
|
||||
src/sfizz/modulations/sources/ADSREnvelope.cpp \
|
||||
src/sfizz/modulations/sources/Controller.cpp \
|
||||
src/sfizz/modulations/sources/FlexEnvelope.cpp \
|
||||
src/sfizz/modulations/sources/LFO.cpp \
|
||||
src/sfizz/effects/Compressor.cpp \
|
||||
src/sfizz/effects/Disto.cpp \
|
||||
src/sfizz/effects/Eq.cpp \
|
||||
src/sfizz/effects/Filter.cpp \
|
||||
src/sfizz/effects/Fverb.cpp \
|
||||
src/sfizz/effects/Gain.cpp \
|
||||
src/sfizz/effects/Gate.cpp \
|
||||
src/sfizz/effects/impl/ResonantArrayAVX.cpp \
|
||||
src/sfizz/effects/impl/ResonantArray.cpp \
|
||||
src/sfizz/effects/impl/ResonantArraySSE.cpp \
|
||||
src/sfizz/effects/impl/ResonantStringAVX.cpp \
|
||||
src/sfizz/effects/impl/ResonantString.cpp \
|
||||
src/sfizz/effects/impl/ResonantStringSSE.cpp \
|
||||
src/sfizz/effects/Limiter.cpp \
|
||||
src/sfizz/effects/Lofi.cpp \
|
||||
src/sfizz/effects/Nothing.cpp \
|
||||
src/sfizz/effects/Rectify.cpp \
|
||||
src/sfizz/effects/Strings.cpp \
|
||||
src/sfizz/effects/Width.cpp \
|
||||
src/sfizz/EQPool.cpp \
|
||||
src/sfizz/FileId.cpp \
|
||||
src/sfizz/FileMetadata.cpp \
|
||||
src/sfizz/FilePool.cpp \
|
||||
src/sfizz/FilterPool.cpp \
|
||||
src/sfizz/FlexEGDescription.cpp \
|
||||
src/sfizz/FlexEnvelope.cpp \
|
||||
src/sfizz/FloatEnvelopes.cpp \
|
||||
src/sfizz/Logger.cpp \
|
||||
src/sfizz/LFO.cpp \
|
||||
src/sfizz/LFODescription.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 \
|
||||
src/sfizz/PowerFollower.cpp \
|
||||
src/sfizz/Region.cpp \
|
||||
src/sfizz/RegionSet.cpp \
|
||||
src/sfizz/RTSemaphore.cpp \
|
||||
src/sfizz/ScopedFTZ.cpp \
|
||||
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/Tuning.cpp \
|
||||
src/sfizz/utility/SpinMutex.cpp \
|
||||
src/sfizz/Voice.cpp \
|
||||
src/sfizz/VoiceStealing.cpp \
|
||||
src/sfizz/Wavetables.cpp
|
||||
|
||||
### Other internal
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/sfizz
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external
|
||||
|
||||
# Pkg-config dependency
|
||||
|
||||
SFIZZ_PKG_CONFIG ?= pkg-config
|
||||
|
||||
# Sndfile dependency
|
||||
|
||||
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_LINK_FLAGS += $(SFIZZ_SNDFILE_LINK_FLAGS)
|
||||
|
||||
### Abseil dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/external/abseil-cpp
|
||||
# absl::base
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/cycleclock.cc \
|
||||
external/abseil-cpp/absl/base/internal/spinlock.cc \
|
||||
external/abseil-cpp/absl/base/internal/sysinfo.cc \
|
||||
external/abseil-cpp/absl/base/internal/thread_identity.cc \
|
||||
external/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
|
||||
# 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
|
||||
# absl::raw_logging_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/raw_logging.cc
|
||||
# absl::spinlock_wait
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/spinlock_wait.cc
|
||||
# absl::throw_delegate
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/throw_delegate.cc
|
||||
# absl::strings
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/strings/ascii.cc \
|
||||
external/abseil-cpp/absl/strings/charconv.cc \
|
||||
external/abseil-cpp/absl/strings/escaping.cc \
|
||||
external/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
|
||||
external/abseil-cpp/absl/strings/internal/charconv_parse.cc \
|
||||
external/abseil-cpp/absl/strings/internal/memutil.cc \
|
||||
external/abseil-cpp/absl/strings/match.cc \
|
||||
external/abseil-cpp/absl/strings/numbers.cc \
|
||||
external/abseil-cpp/absl/strings/str_cat.cc \
|
||||
external/abseil-cpp/absl/strings/str_replace.cc \
|
||||
external/abseil-cpp/absl/strings/str_split.cc \
|
||||
external/abseil-cpp/absl/strings/string_view.cc \
|
||||
external/abseil-cpp/absl/strings/substitute.cc
|
||||
# absl::hashtablez_sampler
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/container/internal/hashtablez_sampler.cc \
|
||||
external/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
|
||||
# absl::raw_hash_set
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/container/internal/raw_hash_set.cc
|
||||
# absl::synchronization
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/synchronization/barrier.cc \
|
||||
external/abseil-cpp/absl/synchronization/blocking_counter.cc \
|
||||
external/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc \
|
||||
external/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc \
|
||||
external/abseil-cpp/absl/synchronization/internal/waiter.cc \
|
||||
external/abseil-cpp/absl/synchronization/notification.cc \
|
||||
external/abseil-cpp/absl/synchronization/mutex.cc
|
||||
# absl::graphcycles_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/synchronization/internal/graphcycles.cc
|
||||
# absl::time
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/time/civil_time.cc \
|
||||
external/abseil-cpp/absl/time/clock.cc \
|
||||
external/abseil-cpp/absl/time/duration.cc \
|
||||
external/abseil-cpp/absl/time/format.cc \
|
||||
external/abseil-cpp/absl/time/time.cc
|
||||
# absl::time_zone
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
|
||||
# absl::stacktrace
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/stacktrace.cc
|
||||
# absl::symbolize
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/symbolize.cc
|
||||
# absl::demangle_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/internal/demangle.cc
|
||||
# absl::debugging_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
|
||||
external/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
|
||||
external/abseil-cpp/absl/debugging/internal/vdso_support.cc
|
||||
# absl::hash
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/hash/internal/hash.cc
|
||||
# absl::city
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/hash/internal/city.cc
|
||||
# absl::int128
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/numeric/int128.cc
|
||||
|
||||
ifdef SFIZZ_OS_WINDOWS
|
||||
SFIZZ_LINK_FLAGS += -ldbghelp
|
||||
endif
|
||||
|
||||
### Spline dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/spline
|
||||
SFIZZ_SOURCES += src/external/spline/spline/spline.cpp
|
||||
|
||||
### Cpuid dependency
|
||||
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/src/external/cpuid/src \
|
||||
-I$(SFIZZ_DIR)/src/external/cpuid/platform/src
|
||||
SFIZZ_SOURCES += \
|
||||
src/external/cpuid/src/cpuid/cpuinfo.cpp \
|
||||
src/external/cpuid/src/cpuid/version.cpp
|
||||
|
||||
### Pugixml dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/pugixml/src
|
||||
SFIZZ_SOURCES += src/external/pugixml/src/pugixml.cpp
|
||||
|
||||
### Kissfft dependency
|
||||
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/src/external/kiss_fft \
|
||||
-I$(SFIZZ_DIR)/src/external/kiss_fft/tools
|
||||
SFIZZ_SOURCES += \
|
||||
src/external/kiss_fft/kiss_fft.c \
|
||||
src/external/kiss_fft/tools/kiss_fftr.c
|
||||
|
||||
### Surge tuning library dependency
|
||||
|
||||
SFIZZ_CXX_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/src/external/tunings/include
|
||||
SFIZZ_SOURCES += \
|
||||
src/external/tunings/src/Tunings.cpp
|
||||
|
||||
### jsl dependency
|
||||
|
||||
SFIZZ_CXX_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/external/jsl/include
|
||||
|
||||
### math dependency
|
||||
|
||||
ifdef SFIZZ_OS_LINUX
|
||||
SFIZZ_LINK_FLAGS += -lm
|
||||
endif
|
||||
|
||||
### pthread dependency
|
||||
|
||||
ifdef SFIZZ_OS_LINUX
|
||||
SFIZZ_C_FLAGS += -pthread
|
||||
SFIZZ_CXX_FLAGS += -pthread
|
||||
SFIZZ_LINK_FLAGS += -pthread
|
||||
endif
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
<doxygenlayout version="1.0">
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="no" title=""/>
|
||||
<tab type="pages" visible="yes" title="" intro=""/>
|
||||
<tab type="modules" visible="yes" title="Categories" intro=""/>
|
||||
<tab type="namespaces" visible="yes" title="">
|
||||
<tab type="namespacelist" visible="yes" title="" intro=""/>
|
||||
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="classes" visible="yes" title="">
|
||||
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||
<tab type="hierarchy" visible="yes" title="" intro=""/>
|
||||
<tab type="classmembers" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="files" visible="yes" title="">
|
||||
<tab type="filelist" visible="yes" title="" intro=""/>
|
||||
<tab type="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
<tab type="examples" visible="yes" title="" intro=""/>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="no"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
</memberdecl>
|
||||
<allmemberslink visible="yes"/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="no"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="no"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="no"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<membergroups visible="yes"/>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdecl>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<detaileddescription title=""/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
</directory>
|
||||
</doxygenlayout>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<hr>
|
||||
<footer>
|
||||
<p style="text-align:left">Copyright © 2019-2020 Paul Ferrand
|
||||
<span style="float:right">Generated for sfizz by
|
||||
<a href="http://www.doxygen.org/index.html"
|
||||
target="_new">Doxygen</a> $doxygenversion</span>
|
||||
</p>
|
||||
</footer>
|
||||
</div><!-- container -->
|
||||
<script src="/sfizz/assets/js/scripts.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Home - sfizz</title>
|
||||
|
||||
<meta name="author" content="Paul Ferrand">
|
||||
<meta name="web-author" content="Andrea Zanellato">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- Atom Feeds -->
|
||||
<link href="/sfizz/atom.xml" rel="alternate" title="News"
|
||||
type="application/atom+xml" />
|
||||
|
||||
<!-- Favicon Generator Icons -->
|
||||
<link rel="apple-touch-icon" sizes="180x180"
|
||||
href="/sfizz/assets/ico/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/sfizz/assets/ico/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/sfizz/assets/ico/favicon-16x16.png">
|
||||
<link rel="manifest" href="/sfizz/assets/ico/site.webmanifest">
|
||||
<link rel="mask-icon" href="/sfizz/assets/ico/safari-pinned-tab.svg"
|
||||
color="#5bbad5">
|
||||
<link rel="shortcut icon" href="/sfizz/assets/ico/favicon.ico">
|
||||
<meta name="msapplication-TileColor"
|
||||
content="#da532c">
|
||||
<meta name="msapplication-config" content="/sfizz/assets/ico/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<link href="$relpath$tabs.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="$relpath$jquery.js"></script>
|
||||
<script type="text/javascript" src="$relpath$dynsections.js"></script>
|
||||
$treeview
|
||||
$search
|
||||
$mathjax
|
||||
<link href="$relpath$$stylesheet" rel="stylesheet" type="text/css" />
|
||||
$extrastylesheet
|
||||
<!-- Stylesheets -->
|
||||
<link href="/sfizz/assets/css/style.min.css"
|
||||
rel="stylesheet" media="screen">
|
||||
|
||||
<!-- Font Awesome Icons -->
|
||||
<script src="https://kit.fontawesome.com/8d25d19870.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="topFunction()" id="scrollButton" title="Go to top">Top</button>
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark" style="background-color:#222">
|
||||
<a class="navbar-brand" href="/sfizz/">
|
||||
<img src="/sfizz/assets/img/logo.png"
|
||||
width="30" height="30" class="d-inline-block" alt="">
|
||||
sfizz</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
||||
data-target="#navbarContent" aria-controls="navbarContent"
|
||||
aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarContent">
|
||||
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">
|
||||
<i class="fas fa-home fa-fw" aria-hidden="true"></i>
|
||||
Home</a>
|
||||
</li>
|
||||
|
||||
<!-- FIXME: Dropdown buttons are shown but menus are broken for some reason
|
||||
(not the container div)
|
||||
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#"
|
||||
id="navbarProjects" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-hammer fa-fw" aria-hidden="true"></i>
|
||||
Projects</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarProjects">
|
||||
<a class="dropdown-item"
|
||||
href="/beatbox/">
|
||||
<i class="fas fa-drum fa-fw" aria-hidden="true"></i>
|
||||
BeatBox</a>
|
||||
<a class="dropdown-item disabled"
|
||||
href="/sfizz/">
|
||||
<i class="fas fa-play-circle fa-fw" aria-hidden="true"></i>
|
||||
sfizz</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfizz-render/">
|
||||
sfizz-render</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfz-flat/">
|
||||
sfz-flat</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfz-opcode-checker/">
|
||||
sfz-opcode-checker</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/emacs-sfz-mode/">
|
||||
Emacs Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-gedit/">
|
||||
gedit Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-geany/">
|
||||
Geany Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-sublime-text/">
|
||||
Sublime Text Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/sfz.vim">
|
||||
Vim Syntax Highlight</a>
|
||||
<a class="dropdown-item"
|
||||
href="https://github.com/sfztools/syntax-highlighting-vscode/">
|
||||
VSCode Syntax Highlight</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#"
|
||||
id="navbarDocumentation" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-book fa-fw" aria-hidden="true"></i>
|
||||
Documentation</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDocumentation">
|
||||
<a class="dropdown-item"
|
||||
href="/sfizz/api"><i class="fas fa-code fa-fw" aria-hidden="true"></i>
|
||||
API</a>
|
||||
<a class="dropdown-item"
|
||||
href="/sfizz/development/build">
|
||||
<i class="fas fa-code fa-fw" aria-hidden="true"></i>
|
||||
Build</a>
|
||||
<a class="dropdown-item"
|
||||
href="/sfizz/development/status">
|
||||
<i class="fas fa-tasks fa-fw" aria-hidden="true"></i>
|
||||
SFZ Opcodes</a>
|
||||
</div>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sfizz/downloads">
|
||||
<i class="fas fa-download fa-fw" aria-hidden="true"></i>
|
||||
Download</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sfizz/search/">
|
||||
<i class="fas fa-search fa-fw" aria-hidden="true"></i>
|
||||
Search</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--BEGIN DISABLE_INDEX-->
|
||||
<!--BEGIN SEARCHENGINE-->
|
||||
$searchbox
|
||||
<!--END SEARCHENGINE-->
|
||||
<!--END DISABLE_INDEX-->
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
|
|
@ -1,198 +0,0 @@
|
|||
#page_container {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: auto !important;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
div.contents, div.searchresults {
|
||||
margin-top: 10px;
|
||||
margin-right: 12px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
|
||||
#projectlogo {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#projectnumber {
|
||||
font-size: 120%;
|
||||
font-family: Tahoma, Arial, sans-serif;
|
||||
text-align: right;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
font-size: 14px;
|
||||
}
|
||||
.tabs2, .tabs3 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.navpath ul {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #002D88;
|
||||
font-weight: normal;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 150%;
|
||||
border-bottom: 1px solid #3276FF;
|
||||
}
|
||||
h2 {
|
||||
font-size: 135%;
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 120%;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 100%;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
div.headertitle h1 {
|
||||
margin: 10px 2px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
width: auto;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.toc h3 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
div.toc li {
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
img.logo {
|
||||
float: right;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
div.logo {
|
||||
float: right;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
table.directory {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.icon {
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
div.appearance {
|
||||
margin: 1em 0em;
|
||||
}
|
||||
div.appearance table {
|
||||
margin: 0.5em 0em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
div.appearance img {
|
||||
margin: 0.5em;
|
||||
}
|
||||
div.appearance .caption {
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.appearance_brief table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
div.appearance_brief table td:first-child {
|
||||
width: 20em;
|
||||
text-align: left;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
div.appearance_brief table td {
|
||||
border-style: none solid solid none;
|
||||
border-width: 1px;
|
||||
border-color: lightblue;
|
||||
}
|
||||
|
||||
|
||||
td.green { color: green; }
|
||||
td.orange { color: #ff8000; }
|
||||
td.red { color: red; }
|
||||
|
||||
span.literal {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
font-family: monospace, fixed;
|
||||
}
|
||||
|
||||
/* we make all the following <span> tags render the text just like
|
||||
the standard Doxygen @remarks, @see tags do, to obtain a uniform
|
||||
look and feel */
|
||||
span.itemdef, span.lib, span.category, span.stdobj, span.styles,
|
||||
span.events, span.flags, span.appearance, span.impl, span.avail {
|
||||
font-weight: bold;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
span.style, span.event, span.flag {
|
||||
font-weight: bold;
|
||||
color: #880000;
|
||||
}
|
||||
|
||||
div.styleDesc, div.eventDesc, div.flagDesc {
|
||||
margin-left: 3%;
|
||||
margin-bottom: 1ex;
|
||||
}
|
||||
|
||||
div.eventHandler {
|
||||
margin: 1em;
|
||||
text-indent: 3%;
|
||||
}
|
||||
|
||||
div.eventHandler span {
|
||||
padding: 5px;
|
||||
background-color: #eeeeee;
|
||||
font-family: monospace, fixed;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 110%;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
address.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid #0043CC;
|
||||
background-image: url('nav_h.png');
|
||||
background-repeat: repeat-x;
|
||||
background-color: #F4F8FF;
|
||||
}
|
||||
|
||||
address.footer small {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
# Global view of the engine
|
||||
|
||||
The sfizz engine is basically a "Synth" object that takes an SFZ file in, receives MIDI-type events
|
||||
and is able to render audio through successive calls to a callback function. This is in line with
|
||||
the way most audio applications and plugins are working. A high-level overview is presented in the
|
||||
following diagram.
|
||||
|
||||
```
|
||||
C and C++ API entry point
|
||||
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
+--------v-------+
|
||||
| |
|
||||
+-------------------------- Synth -----------------------------+
|
||||
| | | |
|
||||
| +----------------+ |
|
||||
| | |
|
||||
+--------v------+ | +---------v--------+
|
||||
| | +---------v---------+ | |
|
||||
| Region list | | Common resources | | Voice pool |
|
||||
| | | and state | | |
|
||||
+---------------+ | ----------------- | +------------------+
|
||||
Built from the SFZ file | File pool |
|
||||
| Envelope pool | The voices are the polyphony
|
||||
Each region is a semi-passive | LFO pool | of the synth. They are idle
|
||||
description object that can | Buffer pool | and they get activated by the
|
||||
decide whether it is "active" | Midi state | synth to play a region on a
|
||||
or not depending on the chain | ... | specific event. They are then
|
||||
of MIDI events it receives. +-------------------+ "linked" to the region while
|
||||
Once activated, a voice is There are a number of common it is played, and reset to
|
||||
chosen to play the region until resources that are needed for their idle state when they
|
||||
it ends naturally or through all the regions and in parti- are done playing the region.
|
||||
note-offs or off-groups. cular the voices. This includes
|
||||
all the (preloaded) files for
|
||||
the SFZ instrument, but will
|
||||
include in the future the EG
|
||||
and LFOs that are needed to
|
||||
achieve compliance with the
|
||||
SFZ v2 specification. This will
|
||||
also include a temporary buffer
|
||||
holder that voices may share.
|
||||
A common resource of importance
|
||||
is the MIDI state: note durations
|
||||
are needed for some opcodes --
|
||||
for example rt_decay -- and
|
||||
triggering velocities too.
|
||||
```
|
||||
|
||||
The Synth, Voices and Regions form the bulk of the code complexity. The rest of the engine is dedicated of
|
||||
mostly helper classes to enable easy management of floating-point buffers in which the audio data is held,
|
||||
signal processing and accelerated (SIMD) computations, and abstractions that are specific to the SFZ format
|
||||
such as envelope generators, curves or LFOs.
|
||||
|
||||
# Parsing the SFZ files
|
||||
|
||||
The sfz file logic is pretty simple and well defined. The sfzformat.com website contains an extensive documentation
|
||||
on it. At its core, an SFZ file describes a list of `region` objects on which a certain number of "opcodes" will
|
||||
apply. Opcodes can determine the sample played, the event conditions that will trigger the sample such as the range
|
||||
of notes, channels, velocities, the processing to apply on the sample while playing, and many more things. It is
|
||||
also possible to describe a `group` of regions, as well as exclusive groups that will shut off other regions that may
|
||||
already be playing. There are also `master` groups, and `global` opcodes and some other types.
|
||||
|
||||
All the opcodes are declared within a header, in a pseudo-xml markup language that looks like this
|
||||
```sfz
|
||||
<global> volume=6
|
||||
<control> set_cc4=5
|
||||
<region> key=36 sample=kick.wav
|
||||
```
|
||||
Here we have 3 headers (`global`, `control` and `region`) and each header holds some opcodes. All of these opcodes
|
||||
have a value---for example the volume is equal to 6 in the `global` header. Some opcodes also have parameters.
|
||||
The `control` header holds an opcode `set_cc` with the parameter `4` and value `5`. The parameter here is the CC to set,
|
||||
and the value at which to set it is 5.
|
||||
|
||||
The parsing logic of sfizz is handled through a base class called Parser---a very original choice. This parser has
|
||||
a virtual callback that gets called whenever a header description is "complete", along with a list of opcodes that
|
||||
apply to the header. Subclassing the Parser then allows to build different SFZ handlers, from full-blown synths as
|
||||
with sfizz to simpler things such as printers (see in particular https://github.com/sfztools/sfz-flat/). If we look
|
||||
at the core of the latter example, it will look something like the following
|
||||
|
||||
```cpp
|
||||
class PrintingParser: public sfz::Parser
|
||||
{
|
||||
protected:
|
||||
void callback(absl::string_view header, const std::vector<sfz::Opcode>& members) final
|
||||
{
|
||||
switch (hash(header)) // The hash(...) function transforms strings to large integers
|
||||
{
|
||||
case hash("global"): // It is also compile-time defined, which allows to do switch-case
|
||||
// statements on strings, something that is usually not possible
|
||||
globalMembers = members; // We save the global headers since they apply to the next
|
||||
// region (and groups and masters)
|
||||
masterMembers.clear();
|
||||
groupMembers.clear();
|
||||
break;
|
||||
case hash("master"):
|
||||
masterMembers = members; // So on
|
||||
groupMembers.clear();
|
||||
break;
|
||||
case hash("group"):
|
||||
groupMembers = members; // .. and so forth
|
||||
break;
|
||||
case hash("region"):
|
||||
std::cout << "<" << header << ">" << ' '; // Now we print the region along with all the opcodes
|
||||
// we memorized from earlier headers.
|
||||
printMembers(globalMembers);
|
||||
printMembers(masterMembers);
|
||||
printMembers(groupMembers);
|
||||
printMembers(members);
|
||||
std::cout << '\n';
|
||||
break;
|
||||
default:
|
||||
std::cout << "<" << header << ">" << ' ';
|
||||
printMembers(members);
|
||||
std::cout << '\n';
|
||||
break;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<sfz::Opcode> globalMembers;
|
||||
std::vector<sfz::Opcode> masterMembers;
|
||||
std::vector<sfz::Opcode> groupMembers;
|
||||
void printMembers(const std::vector<sfz::Opcode>& members)
|
||||
{
|
||||
for (auto& member: members)
|
||||
{
|
||||
std::cout << member.opcode;
|
||||
if (member.parameter)
|
||||
std::cout << +*member.parameter;
|
||||
std::cout << "=" << member.value;
|
||||
std::cout << ' ';
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The main function is then quite straightforward and we call a function from the Parser class that loads a file
|
||||
```cpp
|
||||
PrintingParser parser;
|
||||
parser.loadSfzFile("my_sfz_file.sfz");
|
||||
```
|
||||
If you circle back to the parser you will see that opcodes are stored in an `Opcode` class. This class does some parsing
|
||||
itself and separates the opcode name itself, parameters if any, and the value. Opcodes are very cheap to copy and pass
|
||||
around because they only refer to characters in the file that are stored inside the `Parser` class, so feel free to
|
||||
create vectors of them and move them around.
|
||||
|
||||
Note that you may also derive the loadSfzFile method if you have any processing you need to do before the actual parsing happens.
|
||||
|
||||
# Building the region list in sfizz
|
||||
|
||||
The callback method from sfizz is actually quite similar to the one shown above, except that instead of printing the region
|
||||
we actually fill a big structure from it.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# sfizz
|
||||
|
||||
SFZ file format library
|
||||
|
||||
- [public C API](sfizz_8h.html)
|
||||
- [public C++ API](classsfz_1_1_sfizz.html)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Must be called from the root directory
|
||||
if [[ -f api_index.md ]]; then rm api_index.md; fi
|
||||
cat >>api_index.md <<EOF
|
||||
---
|
||||
title: "API"
|
||||
---
|
||||
EOF
|
||||
tags=()
|
||||
for tag in $(git tag --list); do
|
||||
if [[ ${tag} != "list" && ${tag} != *"test"* ]]; then
|
||||
tag=$(echo "${tag}" | sed -r 's/v//g')
|
||||
tags+=("${tag}")
|
||||
fi
|
||||
done
|
||||
IFS=$'\n' tags=($(sort <<<"${tags[*]}")); unset IFS
|
||||
for tag in "${tags[@]}"; do
|
||||
echo "- [${tag}](${tag})" >> api_index.md
|
||||
done
|
||||
202
dpf.mk
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
#
|
||||
# A build file to help using sfizz with the DISTRHO Plugin Framework (DPF)
|
||||
# ------------------------------------------------------------------------
|
||||
|
|
@ -36,14 +37,9 @@
|
|||
|
||||
SFIZZ_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
SFIZZ_BUILD_DIR := $(SFIZZ_DIR)/dpf-build
|
||||
|
||||
SFIZZ_C_FLAGS = -I$(SFIZZ_DIR)/src
|
||||
SFIZZ_CXX_FLAGS = $(SFIZZ_C_FLAGS)
|
||||
SFIZZ_LINK_FLAGS = $(SFIZZ_BUILD_DIR)/libsfizz.a
|
||||
|
||||
ifeq ($(LINUX),true)
|
||||
SFIZZ_LINK_FLAGS += -pthread
|
||||
endif
|
||||
SFIZZ_PKG_CONFIG ?= $(PKG_CONFIG)
|
||||
include $(SFIZZ_DIR)/common.mk
|
||||
|
||||
sfizz-all: sfizz-lib
|
||||
|
||||
|
|
@ -54,198 +50,6 @@ sfizz-clean:
|
|||
|
||||
.PHONY: sfizz-all sfizz-lib sfizz-clean
|
||||
|
||||
SFIZZ_SOURCES = \
|
||||
src/sfizz/ADSREnvelope.cpp \
|
||||
src/sfizz/Curve.cpp \
|
||||
src/sfizz/effects/Apan.cpp \
|
||||
src/sfizz/Effects.cpp \
|
||||
src/sfizz/effects/Eq.cpp \
|
||||
src/sfizz/effects/Filter.cpp \
|
||||
src/sfizz/effects/Gain.cpp \
|
||||
src/sfizz/effects/impl/ResonantArrayAVX.cpp \
|
||||
src/sfizz/effects/impl/ResonantArray.cpp \
|
||||
src/sfizz/effects/impl/ResonantArraySSE.cpp \
|
||||
src/sfizz/effects/impl/ResonantStringAVX.cpp \
|
||||
src/sfizz/effects/impl/ResonantString.cpp \
|
||||
src/sfizz/effects/impl/ResonantStringSSE.cpp \
|
||||
src/sfizz/effects/Limiter.cpp \
|
||||
src/sfizz/effects/Lofi.cpp \
|
||||
src/sfizz/effects/Nothing.cpp \
|
||||
src/sfizz/effects/Rectify.cpp \
|
||||
src/sfizz/effects/Strings.cpp \
|
||||
src/sfizz/effects/Width.cpp \
|
||||
src/sfizz/EQPool.cpp \
|
||||
src/sfizz/FileId.cpp \
|
||||
src/sfizz/FileInstrument.cpp \
|
||||
src/sfizz/FilePool.cpp \
|
||||
src/sfizz/FilterPool.cpp \
|
||||
src/sfizz/FloatEnvelopes.cpp \
|
||||
src/sfizz/Logger.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/Region.cpp \
|
||||
src/sfizz/RTSemaphore.cpp \
|
||||
src/sfizz/ScopedFTZ.cpp \
|
||||
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/Synth.cpp \
|
||||
src/sfizz/Tuning.cpp \
|
||||
src/sfizz/Voice.cpp \
|
||||
src/sfizz/Wavetables.cpp
|
||||
|
||||
### Other internal
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/sfizz
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external
|
||||
|
||||
# Sndfile dependency
|
||||
|
||||
SFIZZ_C_FLAGS += $(shell $(PKG_CONFIG) --cflags sndfile)
|
||||
SFIZZ_LINK_FLAGS += $(shell $(PKG_CONFIG) --libs sndfile)
|
||||
|
||||
### Abseil dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/external/abseil-cpp
|
||||
# absl::base
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/cycleclock.cc \
|
||||
external/abseil-cpp/absl/base/internal/spinlock.cc \
|
||||
external/abseil-cpp/absl/base/internal/sysinfo.cc \
|
||||
external/abseil-cpp/absl/base/internal/thread_identity.cc \
|
||||
external/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
|
||||
# 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
|
||||
# absl::raw_logging_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/raw_logging.cc
|
||||
# absl::spinlock_wait
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/spinlock_wait.cc
|
||||
# absl::throw_delegate
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/base/internal/throw_delegate.cc
|
||||
# absl::strings
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/strings/ascii.cc \
|
||||
external/abseil-cpp/absl/strings/charconv.cc \
|
||||
external/abseil-cpp/absl/strings/escaping.cc \
|
||||
external/abseil-cpp/absl/strings/internal/charconv_bigint.cc \
|
||||
external/abseil-cpp/absl/strings/internal/charconv_parse.cc \
|
||||
external/abseil-cpp/absl/strings/internal/memutil.cc \
|
||||
external/abseil-cpp/absl/strings/match.cc \
|
||||
external/abseil-cpp/absl/strings/numbers.cc \
|
||||
external/abseil-cpp/absl/strings/str_cat.cc \
|
||||
external/abseil-cpp/absl/strings/str_replace.cc \
|
||||
external/abseil-cpp/absl/strings/str_split.cc \
|
||||
external/abseil-cpp/absl/strings/string_view.cc \
|
||||
external/abseil-cpp/absl/strings/substitute.cc
|
||||
# absl::hashtablez_sampler
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/container/internal/hashtablez_sampler.cc \
|
||||
external/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
|
||||
# absl::raw_hash_set
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/container/internal/raw_hash_set.cc
|
||||
# absl::synchronization
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/synchronization/barrier.cc \
|
||||
external/abseil-cpp/absl/synchronization/blocking_counter.cc \
|
||||
external/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc \
|
||||
external/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc \
|
||||
external/abseil-cpp/absl/synchronization/internal/waiter.cc \
|
||||
external/abseil-cpp/absl/synchronization/notification.cc \
|
||||
external/abseil-cpp/absl/synchronization/mutex.cc
|
||||
# absl::graphcycles_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/synchronization/internal/graphcycles.cc
|
||||
# absl::time
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/time/civil_time.cc \
|
||||
external/abseil-cpp/absl/time/clock.cc \
|
||||
external/abseil-cpp/absl/time/duration.cc \
|
||||
external/abseil-cpp/absl/time/format.cc \
|
||||
external/abseil-cpp/absl/time/time.cc
|
||||
# absl::time_zone
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc \
|
||||
external/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
|
||||
# absl::stacktrace
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/stacktrace.cc
|
||||
# absl::symbolize
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/symbolize.cc
|
||||
# absl::demangle_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/internal/demangle.cc
|
||||
# absl::debugging_internal
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/debugging/internal/address_is_readable.cc \
|
||||
external/abseil-cpp/absl/debugging/internal/elf_mem_image.cc \
|
||||
external/abseil-cpp/absl/debugging/internal/vdso_support.cc
|
||||
# absl::hash
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/hash/internal/hash.cc
|
||||
# absl::city
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/hash/internal/city.cc
|
||||
# absl::int128
|
||||
SFIZZ_SOURCES += \
|
||||
external/abseil-cpp/absl/numeric/int128.cc
|
||||
|
||||
### Spline dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/spline
|
||||
SFIZZ_SOURCES += src/external/spline/spline/spline.cpp
|
||||
|
||||
### Cpuid dependency
|
||||
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/src/external/cpuid/src \
|
||||
-I$(SFIZZ_DIR)/src/external/cpuid/platform/src
|
||||
SFIZZ_SOURCES += \
|
||||
src/external/cpuid/src/cpuid/cpuinfo.cpp \
|
||||
src/external/cpuid/src/cpuid/version.cpp
|
||||
|
||||
### Pugixml dependency
|
||||
|
||||
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/pugixml/src
|
||||
SFIZZ_SOURCES += src/external/pugixml/src/pugixml.cpp
|
||||
|
||||
### Kissfft dependency
|
||||
|
||||
SFIZZ_C_FLAGS += \
|
||||
-I$(SFIZZ_DIR)/src/external/kiss_fft \
|
||||
-I$(SFIZZ_DIR)/src/external/kiss_fft/tools
|
||||
SFIZZ_SOURCES += \
|
||||
src/external/kiss_fft/kiss_fft.c \
|
||||
src/external/kiss_fft/tools/kiss_fftr.c
|
||||
|
||||
###
|
||||
|
||||
SFIZZ_OBJECTS = $(SFIZZ_SOURCES:%=$(SFIZZ_BUILD_DIR)/%.o)
|
||||
|
|
|
|||
88
editor/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
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()
|
||||
224
editor/cmake/Vstgui.cmake
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
add_library(sfizz-vstgui STATIC EXCLUDE_FROM_ALL
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/animation/animations.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/animation/animator.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/animation/timingfunctions.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cbitmap.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cbitmapfilter.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/ccolor.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cdatabrowser.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cdrawcontext.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cdrawmethods.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cdropsource.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cfileselector.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cfont.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cframe.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cgradientview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cgraphicspath.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/clayeredviewcontainer.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/clinestyle.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/coffscreencontext.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cautoanimation.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cbuttons.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/ccolorchooser.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/ccontrol.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cfontchooser.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cknob.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/clistcontrol.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cmoviebitmap.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cmoviebutton.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/coptionmenu.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cparamdisplay.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cscrollbar.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/csearchtextedit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/csegmentbutton.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cslider.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cspecialdigit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/csplashscreen.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cstringlist.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cswitch.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/ctextedit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/ctextlabel.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cvumeter.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/controls/cxypad.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/copenglview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cpoint.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/crect.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/crowcolumnview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cscrollview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cshadowviewcontainer.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/csplitview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cstring.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/ctabview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/ctooltipsupport.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cviewcontainer.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/cvstguitimer.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/genericstringlistdatabrowsersource.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/genericoptionmenu.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/platformfactory.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/vstguidebug.cpp")
|
||||
|
||||
if(WIN32)
|
||||
target_sources(sfizz-vstgui PRIVATE
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/fileresourceinputstream.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/direct2d/d2dbitmap.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/direct2d/d2ddrawcontext.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/direct2d/d2dfont.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/direct2d/d2dgraphicspath.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32datapackage.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32dragging.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32frame.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32openglview.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32optionmenu.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32support.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32resourcestream.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32textedit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/win32factory.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/winfileselector.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/winstring.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/win32/wintimer.cpp")
|
||||
elseif(APPLE)
|
||||
target_sources(sfizz-vstgui PRIVATE
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/fileresourceinputstream.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/genericoptionmenu.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/generictextedit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/carbon/hiviewframe.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/carbon/hiviewoptionmenu.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/carbon/hiviewtextedit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/caviewlayer.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cfontmac.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cgbitmap.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cgdrawcontext.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/autoreleasepool.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/cocoahelpers.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/cocoaopenglview.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/cocoatextedit.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/nsviewdraggingsession.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/nsviewframe.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/cocoa/nsviewoptionmenu.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/macclipboard.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/macfactory.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/macfileselector.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/macglobals.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/macstring.mm"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/mactimer.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/mac/quartzgraphicspath.cpp")
|
||||
else()
|
||||
target_sources(sfizz-vstgui PRIVATE
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/fileresourceinputstream.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/common/generictextedit.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/cairobitmap.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/cairocontext.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/cairofont.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/cairogradient.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/cairopath.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/linuxfactory.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/linuxstring.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/x11dragging.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/x11fileselector.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/x11frame.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/x11platform.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/x11timer.cpp"
|
||||
"${VSTGUI_BASEDIR}/vstgui/lib/platform/linux/x11utils.cpp")
|
||||
endif()
|
||||
|
||||
target_include_directories(sfizz-vstgui PUBLIC "${VSTGUI_BASEDIR}")
|
||||
|
||||
if(WIN32)
|
||||
if (NOT MSVC)
|
||||
# autolinked on MSVC with pragmas
|
||||
target_link_libraries(sfizz-vstgui PRIVATE
|
||||
"opengl32"
|
||||
"d2d1"
|
||||
"dwrite"
|
||||
"dwmapi"
|
||||
"windowscodecs"
|
||||
"shlwapi")
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
target_link_libraries(sfizz-vstgui PRIVATE
|
||||
"${APPLE_COREFOUNDATION_LIBRARY}"
|
||||
"${APPLE_FOUNDATION_LIBRARY}"
|
||||
"${APPLE_COCOA_LIBRARY}"
|
||||
"${APPLE_OPENGL_LIBRARY}"
|
||||
"${APPLE_ACCELERATE_LIBRARY}"
|
||||
"${APPLE_QUARTZCORE_LIBRARY}"
|
||||
"${APPLE_CARBON_LIBRARY}"
|
||||
"${APPLE_AUDIOTOOLBOX_LIBRARY}"
|
||||
"${APPLE_COREAUDIO_LIBRARY}"
|
||||
"${APPLE_COREMIDI_LIBRARY}")
|
||||
else()
|
||||
find_package(X11 REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBXCB REQUIRED xcb)
|
||||
pkg_check_modules(LIBXCB_UTIL REQUIRED xcb-util)
|
||||
pkg_check_modules(LIBXCB_CURSOR REQUIRED xcb-cursor)
|
||||
pkg_check_modules(LIBXCB_KEYSYMS REQUIRED xcb-keysyms)
|
||||
pkg_check_modules(LIBXCB_XKB REQUIRED xcb-xkb)
|
||||
pkg_check_modules(LIBXKB_COMMON REQUIRED xkbcommon)
|
||||
pkg_check_modules(LIBXKB_COMMON_X11 REQUIRED xkbcommon-x11)
|
||||
pkg_check_modules(CAIRO REQUIRED cairo)
|
||||
pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
|
||||
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
||||
target_include_directories(sfizz-vstgui PRIVATE
|
||||
${X11_INCLUDE_DIRS}
|
||||
${FREETYPE_INCLUDE_DIRS}
|
||||
${LIBXCB_INCLUDE_DIRS}
|
||||
${LIBXCB_UTIL_INCLUDE_DIRS}
|
||||
${LIBXCB_CURSOR_INCLUDE_DIRS}
|
||||
${LIBXCB_KEYSYMS_INCLUDE_DIRS}
|
||||
${LIBXCB_XKB_INCLUDE_DIRS}
|
||||
${LIBXKB_COMMON_INCLUDE_DIRS}
|
||||
${LIBXKB_COMMON_X11_INCLUDE_DIRS}
|
||||
${CAIRO_INCLUDE_DIRS}
|
||||
${FONTCONFIG_INCLUDE_DIRS}
|
||||
${GLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(sfizz-vstgui PRIVATE
|
||||
${X11_LIBRARIES}
|
||||
${FREETYPE_LIBRARIES}
|
||||
${LIBXCB_LIBRARIES}
|
||||
${LIBXCB_UTIL_LIBRARIES}
|
||||
${LIBXCB_CURSOR_LIBRARIES}
|
||||
${LIBXCB_KEYSYMS_LIBRARIES}
|
||||
${LIBXCB_XKB_LIBRARIES}
|
||||
${LIBXKB_COMMON_LIBRARIES}
|
||||
${LIBXKB_COMMON_X11_LIBRARIES}
|
||||
${CAIRO_LIBRARIES}
|
||||
${FONTCONFIG_LIBRARIES}
|
||||
${GLIB_LIBRARIES})
|
||||
find_library(DL_LIBRARY "dl")
|
||||
if(DL_LIBRARY)
|
||||
target_link_libraries(sfizz-vstgui PRIVATE "${DL_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
target_compile_definitions(sfizz-vstgui PRIVATE "DEVELOPMENT")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
target_compile_definitions(sfizz-vstgui PRIVATE "RELEASE")
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
# higher C++ requirement on Windows
|
||||
set_property(TARGET sfizz-vstgui PROPERTY CXX_STANDARD 14)
|
||||
# Windows 10 RS2 DDI for custom fonts
|
||||
target_compile_definitions(sfizz-vstgui PRIVATE "NTDDI_VERSION=0x0A000003")
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
target_compile_options(sfizz-vstgui PRIVATE
|
||||
"-Wno-deprecated-copy"
|
||||
"-Wno-deprecated-declarations"
|
||||
"-Wno-extra"
|
||||
"-Wno-ignored-qualifiers"
|
||||
"-Wno-multichar"
|
||||
"-Wno-reorder"
|
||||
"-Wno-sign-compare"
|
||||
"-Wno-unknown-pragmas"
|
||||
"-Wno-unused-function"
|
||||
"-Wno-unused-parameter"
|
||||
"-Wno-unused-variable")
|
||||
endif()
|
||||
1
editor/external/vstgui4
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 055cbcc9ae858f0b07d5d86c205a1111e2fba7a4
|
||||
312
editor/layout/main.fl
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
# data file for the Fltk User Interface Designer (fluid)
|
||||
version 1.0305
|
||||
header_name {.h}
|
||||
code_name {.cxx}
|
||||
widget_class mainView {open
|
||||
xywh {576 416 800 475} type Double
|
||||
class LogicalGroup visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
image {../resources/background.png} xywh {190 110 600 280}
|
||||
class Background
|
||||
}
|
||||
Fl_Group {} {
|
||||
comment {theme=darkTheme} open
|
||||
xywh {0 0 800 110}
|
||||
class LogicalGroup
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {5 4 175 101} box ROUNDED_BOX align 0
|
||||
class RoundedGroup
|
||||
} {
|
||||
Fl_Box {} {
|
||||
comment {tag=kTagFirstChangePanel+kPanelGeneral}
|
||||
image {../resources/logo_text_white.png} xywh {35 9 120 60}
|
||||
class SfizzMainButton
|
||||
}
|
||||
Fl_Button {} {
|
||||
comment {tag=kTagFirstChangePanel+kPanelGeneral}
|
||||
xywh {49 73 25 25} labelsize 24
|
||||
class HomeButton
|
||||
}
|
||||
Fl_Button {} {
|
||||
comment {tag=kTagFirstChangePanel+kPanelControls}
|
||||
xywh {81 73 25 25} labelsize 24
|
||||
class CCButton
|
||||
}
|
||||
Fl_Button {} {
|
||||
comment {tag=kTagFirstChangePanel+kPanelSettings}
|
||||
xywh {112 73 25 25} labelsize 24
|
||||
class SettingsButton
|
||||
}
|
||||
}
|
||||
Fl_Group {} {open
|
||||
xywh {185 5 380 100} box ROUNDED_BOX
|
||||
class RoundedGroup
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {Separator 1}
|
||||
xywh {195 41 360 5} box BORDER_BOX labeltype NO_LABEL
|
||||
class HLine
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Separator 2}
|
||||
xywh {195 73 360 5} box BORDER_BOX labeltype NO_LABEL
|
||||
class HLine
|
||||
}
|
||||
Fl_Box sfzFileLabel_ {
|
||||
label {DefaultInstrument.sfz}
|
||||
comment {tag=kTagLoadSfzFile}
|
||||
xywh {195 11 250 31} labelsize 20 align 20
|
||||
class ClickableLabel
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Key switch:}
|
||||
xywh {195 44 250 30} labelsize 20 align 20
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Voices:}
|
||||
xywh {195 76 60 25} labelsize 12 align 24
|
||||
class Label
|
||||
}
|
||||
Fl_Button {} {
|
||||
comment {tag=kTagPreviousSfzFile}
|
||||
xywh {480 14 25 25} labelsize 24
|
||||
class PreviousFileButton
|
||||
}
|
||||
Fl_Button {} {
|
||||
comment {tag=kTagNextSfzFile}
|
||||
xywh {505 14 25 25} labelsize 24
|
||||
class NextFileButton
|
||||
}
|
||||
Fl_Button fileOperationsMenu_ {
|
||||
comment {tag=kTagFileOperations}
|
||||
xywh {530 14 25 25} labelsize 24
|
||||
class ChevronDropDown
|
||||
}
|
||||
Fl_Box infoVoicesLabel_ {
|
||||
xywh {260 76 50 25} labelsize 12 align 16
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Max:}
|
||||
xywh {315 76 60 25} labelsize 12 align 24
|
||||
class Label
|
||||
}
|
||||
Fl_Box numVoicesLabel_ {
|
||||
xywh {380 76 50 25} labelsize 12 align 16
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Memory:}
|
||||
xywh {435 76 60 25} labelsize 12 align 24
|
||||
class Label
|
||||
}
|
||||
Fl_Box memoryLabel_ {
|
||||
xywh {500 76 50 25} labelsize 12 align 16
|
||||
class Label
|
||||
}
|
||||
}
|
||||
Fl_Group {} {open
|
||||
xywh {570 5 225 100} box ROUNDED_BOX
|
||||
class RoundedGroup
|
||||
} {
|
||||
Fl_Dial {} {
|
||||
xywh {615 20 48 48} value 0.5 hide
|
||||
class Knob48
|
||||
}
|
||||
Fl_Box {} {
|
||||
label Center
|
||||
xywh {610 70 60 5} labelsize 12 hide
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Dial volumeSlider_ {
|
||||
comment {tag=kTagSetVolume}
|
||||
xywh {680 20 48 48} value 0.5
|
||||
class StyledKnob
|
||||
}
|
||||
Fl_Box volumeLabel_ {
|
||||
label {0.0 dB}
|
||||
xywh {675 70 60 22} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Box {} {
|
||||
xywh {745 20 35 55} box BORDER_BOX
|
||||
class VMeter
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group {subPanels_[kPanelGeneral]} {
|
||||
xywh {5 110 791 285}
|
||||
class LogicalGroup
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {5 110 175 280} box ROUNDED_BOX
|
||||
class RoundedGroup
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {Curves:}
|
||||
xywh {20 120 60 25} align 20
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Masters:}
|
||||
xywh {20 145 60 25} align 20
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Groups:}
|
||||
xywh {20 170 60 25} align 20
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Regions:}
|
||||
xywh {20 195 60 25} align 20
|
||||
class Label
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Samples:}
|
||||
xywh {20 220 60 25} align 20
|
||||
class Label
|
||||
}
|
||||
Fl_Box infoCurvesLabel_ {
|
||||
label 0
|
||||
xywh {120 120 40 25} align 16
|
||||
class Label
|
||||
}
|
||||
Fl_Box infoMastersLabel_ {
|
||||
label 0
|
||||
xywh {120 145 40 25} align 16
|
||||
class Label
|
||||
}
|
||||
Fl_Box infoGroupsLabel_ {
|
||||
label 0
|
||||
xywh {120 170 40 25} align 16
|
||||
class Label
|
||||
}
|
||||
Fl_Box infoRegionsLabel_ {
|
||||
label 0
|
||||
xywh {120 195 40 25} align 16
|
||||
class Label
|
||||
}
|
||||
Fl_Box infoSamplesLabel_ {
|
||||
label 0
|
||||
xywh {120 220 40 25} align 16
|
||||
class Label
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group {subPanels_[kPanelControls]} {
|
||||
xywh {5 110 790 285} hide
|
||||
class LogicalGroup
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {5 110 790 285} box ROUNDED_BOX
|
||||
class RoundedGroup
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {Controls not available}
|
||||
xywh {5 110 790 285} labelsize 40
|
||||
class Label
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group {subPanels_[kPanelSettings]} {open
|
||||
xywh {5 109 790 286} hide
|
||||
class LogicalGroup
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label Engine open
|
||||
xywh {260 135 280 100} box ROUNDED_BOX labelsize 12 align 17
|
||||
class TitleGroup
|
||||
} {
|
||||
Fl_Spinner numVoicesSlider_ {
|
||||
comment {tag=kTagSetNumVoices}
|
||||
xywh {285 195 60 25} labelsize 12 textsize 12
|
||||
class ValueMenu
|
||||
}
|
||||
Fl_Box {} {
|
||||
label Polyphony
|
||||
xywh {275 155 80 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Spinner oversamplingSlider_ {
|
||||
comment {tag=kTagSetOversampling}
|
||||
xywh {370 195 60 25} labelsize 12 textsize 12
|
||||
class ValueMenu
|
||||
}
|
||||
Fl_Box {} {
|
||||
label Oversampling
|
||||
xywh {360 155 80 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Preload size}
|
||||
xywh {445 155 80 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Spinner preloadSizeSlider_ {
|
||||
comment {tag=kTagSetPreloadSize}
|
||||
xywh {455 195 60 25} labelsize 12 textsize 12
|
||||
class ValueMenu
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label Tuning open
|
||||
xywh {205 270 390 100} box ROUNDED_BOX labelsize 12 align 17
|
||||
class TitleGroup
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {Root key}
|
||||
xywh {330 290 80 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Spinner tuningFrequencySlider_ {
|
||||
comment {tag=kTagSetTuningFrequency}
|
||||
xywh {425 330 60 25} labelsize 12 textsize 12
|
||||
class ValueMenu
|
||||
}
|
||||
Fl_Box {} {
|
||||
label Frequency
|
||||
xywh {415 290 80 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Dial stretchedTuningSlider_ {
|
||||
comment {tag=kTagSetStretchedTuning}
|
||||
xywh {515 315 48 48} value 0.5
|
||||
class StyledKnob
|
||||
}
|
||||
Fl_Box {} {
|
||||
label Stretch
|
||||
xywh {500 290 80 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {Scala file}
|
||||
xywh {225 290 100 25} labelsize 12
|
||||
class ValueLabel
|
||||
}
|
||||
Fl_Button scalaFileButton_ {
|
||||
label DefaultScale
|
||||
comment {tag=kTagLoadScalaFile}
|
||||
xywh {225 330 100 25} labelsize 12
|
||||
class ValueButton
|
||||
}
|
||||
Fl_Spinner scalaRootKeySlider_ {
|
||||
comment {tag=kTagSetScalaRootKey}
|
||||
xywh {340 330 35 25} labelsize 12 textsize 12
|
||||
class ValueMenu
|
||||
}
|
||||
Fl_Spinner scalaRootOctaveSlider_ {
|
||||
comment {tag=kTagSetScalaRootKey}
|
||||
xywh {375 330 30 25} labelsize 12 textsize 12
|
||||
class ValueMenu
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Box piano_ {selected
|
||||
xywh {5 400 790 70} labelsize 12
|
||||
class Piano
|
||||
}
|
||||
}
|
||||
BIN
editor/resources/Fonts/Roboto-Regular.ttf
Normal file
BIN
editor/resources/Fonts/sfizz-fluentui-system-r20.ttf
Normal file
BIN
editor/resources/background.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
editor/resources/background@2x.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
editor/resources/icon_white.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
253
editor/resources/icon_white.svg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
editor/resources/icon_white@2x.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
editor/resources/knob.knob
Normal file
BIN
editor/resources/knob48.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
editor/resources/knob48@2x.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
BIN
editor/resources/logo_text.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
252
editor/resources/logo_text.svg
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:export-ydpi="192"
|
||||
inkscape:export-xdpi="192"
|
||||
inkscape:export-filename="/home/jpc/documents/projects/sfizz/editor/resources/logo_text@2x.png"
|
||||
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||
sodipodi:docname="logo_text.svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 105.83333 66.145836"
|
||||
height="250"
|
||||
width="400">
|
||||
<title
|
||||
id="title1469">sfizz logo</title>
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="linearGradient1445"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop1441"
|
||||
offset="0"
|
||||
style="stop-color:#646464;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop1443"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect1150"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
|
||||
unit="mm"
|
||||
method="auto"
|
||||
mode="C"
|
||||
radius="1"
|
||||
chamfer_steps="2"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="2"
|
||||
radius="1"
|
||||
mode="C"
|
||||
method="auto"
|
||||
unit="mm"
|
||||
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect1136"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="2"
|
||||
radius="1"
|
||||
mode="C"
|
||||
method="auto"
|
||||
unit="mm"
|
||||
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect968"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect921"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
|
||||
unit="mm"
|
||||
method="auto"
|
||||
mode="C"
|
||||
radius="1"
|
||||
chamfer_steps="2"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
<inkscape:path-effect
|
||||
hide_knots="false"
|
||||
only_selected="false"
|
||||
apply_with_radius="true"
|
||||
apply_no_radius="true"
|
||||
use_knot_distance="true"
|
||||
flexible="false"
|
||||
chamfer_steps="2"
|
||||
radius="1"
|
||||
mode="C"
|
||||
method="auto"
|
||||
unit="mm"
|
||||
satellites_param="F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,1,0,2 @ F,0,0,1,0,0,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.47797039,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.51256137,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.33778335,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.27944107,0,2 | F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.25554572,0,2 @ F,0,0,1,0,0,0,2 @ F,0,0,1,0,0.29009315,0,2"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect1183"
|
||||
effect="fillet_chamfer" />
|
||||
<inkscape:path-effect
|
||||
end_linecap_type="zerowidth"
|
||||
scale_width="1"
|
||||
miter_limit="4"
|
||||
linejoin_type="round"
|
||||
start_linecap_type="zerowidth"
|
||||
interpolator_beta="0.2"
|
||||
interpolator_type="CubicBezierFit"
|
||||
sort_points="true"
|
||||
offset_points="0.19099662,0.36320029 | 0.41721681,0.40988822 | 0.9095762,0.070646707"
|
||||
lpeversion="1"
|
||||
is_visible="true"
|
||||
id="path-effect1172"
|
||||
effect="powerstroke" />
|
||||
<clipPath
|
||||
id="clipPath917"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<rect
|
||||
y="68.872978"
|
||||
x="24.792475"
|
||||
height="25.252825"
|
||||
width="39.659527"
|
||||
id="rect919"
|
||||
style="fill:#ffffff;stroke:none;stroke-width:2;stroke-linecap:round;paint-order:markers stroke fill" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="231.60674"
|
||||
x2="539.22601"
|
||||
y1="190.42654"
|
||||
x1="539.22601"
|
||||
id="linearGradient1447"
|
||||
xlink:href="#linearGradient1445"
|
||||
inkscape:collect="always"
|
||||
gradientTransform="translate(34.589224,10.333824)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
fit-margin-bottom="10"
|
||||
fit-margin-right="10"
|
||||
fit-margin-left="10"
|
||||
fit-margin-top="10"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-width="1920"
|
||||
showguides="false"
|
||||
inkscape:snap-global="false"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:cy="53.822531"
|
||||
inkscape:cx="17.632385"
|
||||
inkscape:zoom="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
units="px">
|
||||
<sodipodi:guide
|
||||
id="guide899"
|
||||
orientation="1,0"
|
||||
position="-452.4563,176.31198" />
|
||||
<sodipodi:guide
|
||||
id="guide901"
|
||||
orientation="0,-1"
|
||||
position="-351.71366,154.32488" />
|
||||
<sodipodi:guide
|
||||
id="guide1008"
|
||||
orientation="1,0"
|
||||
position="-536.98274,156.82863" />
|
||||
<sodipodi:guide
|
||||
id="guide1185"
|
||||
orientation="1,0"
|
||||
position="-351.75629,154.33106" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>sfizz logo</dc:title>
|
||||
<dc:date>2020-05-16</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Tobiasz 'unfa' Karoń</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>CC-0</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-495.92008,-191.91875)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
id="path1439"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:34.8154px;line-height:1.25;font-family:ABeeZee;-inkscape-font-specification:ABeeZee;letter-spacing:0px;word-spacing:0px;fill:url(#linearGradient1447);fill-opacity:1;stroke:none;stroke-width:0.264584"
|
||||
d="m 569.95053,215.93967 h 13.61282 v 2.40226 l -9.9572,12.91651 h 10.13128 v 2.78523 h -13.99579 v -2.47189 l 9.99202,-12.91651 h -9.78313 z m -16.4328,0 h 13.61282 v 2.40226 l -9.9572,12.91651 h 10.13128 v 2.78523 h -13.99579 v -2.47189 l 9.99202,-12.91651 h -9.78313 z m -6.38378,18.104 h -3.13338 l 3.1682,-18.104 h 3.13339 z m 2.33264,-21.20257 c -0.64989,0 -1.14891,-0.18568 -1.49707,-0.55705 -0.32494,-0.39457 -0.48741,-0.84717 -0.48741,-1.3578 0,-0.74273 0.2321,-1.33459 0.69631,-1.77559 0.4642,-0.46421 1.04446,-0.69631 1.74077,-0.69631 0.64989,0 1.1373,0.19729 1.46224,0.59187 0.34815,0.37136 0.52223,0.81235 0.52223,1.32298 0,0.74273 -0.2321,1.34619 -0.6963,1.8104 -0.46421,0.441 -1.04446,0.6615 -1.74077,0.6615 z m -12.24537,3.76006 h 5.36157 l -0.48741,2.7156 h -5.36157 l -3.06376,17.23362 c -0.18568,1.02125 -0.4526,1.88003 -0.80075,2.57634 -0.34815,0.71952 -0.76594,1.29978 -1.25336,1.74077 -0.48741,0.44099 -1.04446,0.75433 -1.67114,0.94002 -0.62667,0.20889 -1.29977,0.31334 -2.01929,0.31334 -0.76594,0 -1.46225,-0.10445 -2.08892,-0.31334 -0.64989,-0.20889 -1.21854,-0.49902 -1.70596,-0.87039 l 1.25336,-2.57634 c 0.32494,0.32495 0.70791,0.58026 1.1489,0.76594 0.41779,0.18568 0.8936,0.27852 1.42744,0.27852 0.62667,0 1.16051,-0.2205 1.6015,-0.66149 0.46421,-0.44099 0.78915,-1.14891 0.97484,-2.12374 l 3.06375,-17.30325 h -2.78523 l 0.48741,-2.7156 h 2.78524 l 0.52223,-2.78523 c 0.39457,-2.13535 1.14891,-3.65562 2.263,-4.56082 1.11409,-0.92841 2.54152,-1.39262 4.28229,-1.39262 0.95162,0 1.83361,0.12766 2.64597,0.38297 0.81236,0.23211 1.54348,0.52224 2.19337,0.87039 l -1.21854,2.64597 c -0.53383,-0.27853 -1.09088,-0.53384 -1.67114,-0.76594 -0.55704,-0.23211 -1.21853,-0.34816 -1.98447,-0.34816 -0.85878,0 -1.5899,0.25531 -2.19337,0.76594 -0.60347,0.48742 -0.99804,1.25336 -1.18373,2.29782 z m -21.96217,13.36911 c 0.60347,0.53384 1.3578,0.96323 2.263,1.28817 0.92841,0.32495 1.91485,0.48742 2.95931,0.48742 1.29977,0 2.2746,-0.20889 2.92449,-0.62668 0.6731,-0.44099 1.00965,-0.99804 1.00965,-1.67114 0,-0.34815 -0.0696,-0.6731 -0.20889,-0.97483 -0.11605,-0.30173 -0.34816,-0.59186 -0.69631,-0.87039 -0.32495,-0.27852 -0.77755,-0.54544 -1.3578,-0.80075 -0.58026,-0.27852 -1.33459,-0.58025 -2.263,-0.9052 -1.71756,-0.58026 -2.99413,-1.26496 -3.8297,-2.05411 -0.83557,-0.81236 -1.25335,-1.92645 -1.25335,-3.34228 0,-0.69631 0.15087,-1.34619 0.4526,-1.94966 0.32495,-0.60347 0.77755,-1.1257 1.3578,-1.56669 0.60347,-0.46421 1.32299,-0.82397 2.15856,-1.07928 0.85878,-0.25531 1.83361,-0.38297 2.92449,-0.38297 1.18372,0 2.21658,0.12766 3.09857,0.38297 0.9052,0.2321 1.71756,0.53383 2.43708,0.9052 l -0.87039,2.57634 c -0.62667,-0.37137 -1.34619,-0.6731 -2.15855,-0.9052 -0.78915,-0.2321 -1.67114,-0.34815 -2.64597,-0.34815 -1.20693,0 -2.12374,0.24371 -2.75042,0.73112 -0.62668,0.48741 -0.94002,1.02125 -0.94002,1.60151 0,0.27852 0.0464,0.53383 0.13927,0.76594 0.11605,0.2321 0.31333,0.4526 0.59186,0.66149 0.27852,0.20889 0.64988,0.41779 1.11409,0.62668 0.46421,0.20889 1.04446,0.42938 1.74077,0.66149 1.13731,0.39457 2.10053,0.80075 2.88968,1.21854 0.78915,0.39457 1.42743,0.83557 1.91485,1.32298 0.48741,0.48742 0.83557,1.02126 1.04446,1.60151 0.20889,0.55705 0.31334,1.18372 0.31334,1.88003 0,0.81236 -0.17408,1.54348 -0.52223,2.19337 -0.34816,0.64989 -0.83558,1.20693 -1.46225,1.67114 -0.62668,0.44099 -1.39262,0.77754 -2.29782,1.00965 -0.88199,0.25531 -1.86842,0.38297 -2.95931,0.38297 -1.39261,0 -2.63436,-0.17408 -3.72524,-0.52223 -1.09089,-0.34815 -1.99609,-0.80075 -2.71561,-1.3578 z"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccscscscscsccccccscsccccsccccccccsccccscccccscscccccscccsccccssscssccccssccsscc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
BIN
editor/resources/logo_text@2x.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
editor/resources/logo_text_white.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
editor/resources/logo_text_white@2x.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
32
editor/src/editor/EditIds.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// 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 "EditIds.h"
|
||||
|
||||
EditRange EditRange::get(EditId id)
|
||||
{
|
||||
switch (id) {
|
||||
default:
|
||||
assert(false);
|
||||
return {};
|
||||
case EditId::Volume:
|
||||
return { 0, -60, 6 };
|
||||
case EditId::Polyphony:
|
||||
return { 64, 1, 256 };
|
||||
case EditId::Oversampling:
|
||||
return { 0, 0, 3 };
|
||||
case EditId::PreloadSize:
|
||||
return { 8192, 1024, 65536 };
|
||||
case EditId::ScalaRootKey:
|
||||
return { 60, 0, 127 };
|
||||
case EditId::TuningFrequency:
|
||||
return { 440, 300, 500 };
|
||||
case EditId::StretchTuning:
|
||||
return { 0, 0, 1 };
|
||||
case EditId::UIActivePanel:
|
||||
return { 0, 0, 255 };
|
||||
}
|
||||
}
|
||||
37
editor/src/editor/EditIds.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// 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);
|
||||
};
|
||||
67
editor/src/editor/EditValue.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// 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 <string>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
|
||||
class EditValue {
|
||||
public:
|
||||
constexpr EditValue() : tag(Nil) {}
|
||||
EditValue(float value) { reset(value); }
|
||||
EditValue(std::string value) { reset(value); }
|
||||
~EditValue() { reset(); }
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if (tag == String)
|
||||
destruct(u.s);
|
||||
tag = Nil;
|
||||
}
|
||||
|
||||
void reset(float value) noexcept
|
||||
{
|
||||
reset();
|
||||
u.f = value;
|
||||
tag = Float;
|
||||
}
|
||||
|
||||
void reset(std::string value) noexcept
|
||||
{
|
||||
reset();
|
||||
new (&u.s) std::string(std::move(value));
|
||||
tag = String;
|
||||
}
|
||||
|
||||
float to_float() const
|
||||
{
|
||||
if (tag != Float)
|
||||
throw std::runtime_error("the tagged union does not contain `float`");
|
||||
return u.f;
|
||||
}
|
||||
|
||||
const std::string& to_string() const
|
||||
{
|
||||
if (tag != String)
|
||||
throw std::runtime_error("the tagged union does not contain `string`");
|
||||
return u.s;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class T> static void destruct(T& obj) { obj.~T(); }
|
||||
|
||||
private:
|
||||
enum TypeTag { Nil, Float, String };
|
||||
union Union {
|
||||
constexpr explicit Union(float f = 0.0f) noexcept : f(f) {}
|
||||
~Union() noexcept {}
|
||||
float f;
|
||||
std::string s;
|
||||
};
|
||||
TypeTag tag { Nil };
|
||||
Union u;
|
||||
};
|
||||
1175
editor/src/editor/Editor.cpp
Normal file
30
editor/src/editor/Editor.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// 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 <memory>
|
||||
class EditorController;
|
||||
|
||||
#include "utility/vstgui_before.h"
|
||||
#include "vstgui/lib/vstguifwd.h"
|
||||
#include "utility/vstgui_after.h"
|
||||
using VSTGUI::CFrame;
|
||||
|
||||
class Editor {
|
||||
public:
|
||||
static const int viewWidth;
|
||||
static const int viewHeight;
|
||||
|
||||
explicit Editor(EditorController& ctrl);
|
||||
~Editor();
|
||||
|
||||
void open(CFrame& frame);
|
||||
void close();
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
43
editor/src/editor/EditorController.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// 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 "EditValue.h"
|
||||
#include <absl/strings/string_view.h>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
enum class EditId : int;
|
||||
|
||||
class EditorController {
|
||||
public:
|
||||
virtual ~EditorController() {}
|
||||
|
||||
// called by Editor
|
||||
virtual void uiSendValue(EditId id, const EditValue& v) = 0;
|
||||
virtual void uiBeginSend(EditId id) = 0;
|
||||
virtual void uiEndSend(EditId id) = 0;
|
||||
virtual void uiSendMIDI(const uint8_t* msg, uint32_t len) = 0;
|
||||
class Receiver;
|
||||
void decorate(Receiver* r) { r_ = r; }
|
||||
|
||||
class Receiver {
|
||||
public:
|
||||
virtual ~Receiver() {}
|
||||
virtual void uiReceiveValue(EditId id, const EditValue& v) = 0;
|
||||
};
|
||||
|
||||
// called by DSP
|
||||
void uiReceiveValue(EditId id, const EditValue& v);
|
||||
|
||||
private:
|
||||
Receiver* r_ = nullptr;
|
||||
};
|
||||
|
||||
inline void EditorController::uiReceiveValue(EditId id, const EditValue& v)
|
||||
{
|
||||
if (r_)
|
||||
r_->uiReceiveValue(id, v);
|
||||
}
|
||||
495
editor/src/editor/GUIComponents.cpp
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
210
editor/src/editor/GUIComponents.h
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// 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 <bitset>
|
||||
|
||||
#include "utility/vstgui_before.h"
|
||||
#include "vstgui/lib/controls/cslider.h"
|
||||
#include "vstgui/lib/controls/cknob.h"
|
||||
#include "vstgui/lib/controls/ctextlabel.h"
|
||||
#include "vstgui/lib/controls/cbuttons.h"
|
||||
#include "vstgui/lib/controls/coptionmenu.h"
|
||||
#include "vstgui/lib/cviewcontainer.h"
|
||||
#include "vstgui/lib/ccolor.h"
|
||||
#include "vstgui/lib/dragging.h"
|
||||
#include "utility/vstgui_after.h"
|
||||
|
||||
using namespace VSTGUI;
|
||||
|
||||
///
|
||||
class SBoxContainer : public CViewContainer {
|
||||
public:
|
||||
explicit SBoxContainer(const CRect& size);
|
||||
virtual ~SBoxContainer() {}
|
||||
void setCornerRadius(CCoord radius);
|
||||
void setBackgroundColor(const CColor& color) override;
|
||||
CColor getBackgroundColor() const override;
|
||||
|
||||
protected:
|
||||
void drawRect(CDrawContext* dc, const CRect& updateRect) override;
|
||||
|
||||
protected:
|
||||
CCoord cornerRadius_ = 0.0;
|
||||
CColor backgroundColor_;
|
||||
};
|
||||
|
||||
///
|
||||
class STitleContainer : public SBoxContainer {
|
||||
public:
|
||||
explicit STitleContainer(const CRect& size, UTF8StringPtr text = nullptr);
|
||||
~STitleContainer() {}
|
||||
|
||||
void setTitleFont(CFontRef font);
|
||||
CFontRef getTitleFont() { return titleFont_; }
|
||||
|
||||
void setTitleFontColor(CColor color);
|
||||
CColor getTitleFontColor() const { return titleFontColor_; }
|
||||
void setTitleBackgroundColor(CColor color);
|
||||
CColor getTitleBackgroundColor() const { return titleBackgroundColor_; }
|
||||
|
||||
protected:
|
||||
void drawRect(CDrawContext* dc, const CRect& updateRect) override;
|
||||
|
||||
private:
|
||||
std::string text_;
|
||||
CColor titleFontColor_;
|
||||
CColor titleBackgroundColor_;
|
||||
SharedPointer<CFontDesc> titleFont_;
|
||||
};
|
||||
|
||||
///
|
||||
class SFileDropTarget : public IDropTarget,
|
||||
public NonAtomicReferenceCounted {
|
||||
public:
|
||||
typedef std::function<void(const std::string&)> FileDropFunction;
|
||||
void setFileDropFunction(FileDropFunction f);
|
||||
|
||||
protected:
|
||||
DragOperation onDragEnter(DragEventData data) override;
|
||||
DragOperation onDragMove(DragEventData data) override;
|
||||
void onDragLeave(DragEventData data) override;
|
||||
bool onDrop(DragEventData data) override;
|
||||
|
||||
private:
|
||||
static bool isFileDrop(IDataPackage* package);
|
||||
|
||||
private:
|
||||
DragOperation op_ = DragOperation::None;
|
||||
FileDropFunction dropFunction_;
|
||||
};
|
||||
|
||||
///
|
||||
class SValueMenu : public CParamDisplay {
|
||||
public:
|
||||
explicit SValueMenu(const CRect& bounds, IControlListener* listener, int32_t tag);
|
||||
CMenuItem* addEntry(CMenuItem* item, float value, int32_t index = -1);
|
||||
CMenuItem* addEntry(const UTF8String& title, float value, int32_t index = -1, int32_t itemFlags = CMenuItem::kNoFlags);
|
||||
CMenuItem* addSeparator(int32_t index = -1);
|
||||
int32_t getNbEntries() const;
|
||||
|
||||
protected:
|
||||
CMouseEventResult onMouseDown(CPoint& where, const CButtonState& buttons) override;
|
||||
|
||||
private:
|
||||
class MenuListener;
|
||||
|
||||
//
|
||||
void onItemClicked(int32_t index);
|
||||
|
||||
//
|
||||
CMenuItemList menuItems_;
|
||||
std::vector<float> menuItemValues_;
|
||||
SharedPointer<MenuListener> menuListener_;
|
||||
|
||||
//
|
||||
class MenuListener : public IControlListener, public NonAtomicReferenceCounted {
|
||||
public:
|
||||
explicit MenuListener(SValueMenu& menu) : menu_(menu) {}
|
||||
void valueChanged(CControl* control) override
|
||||
{
|
||||
menu_.onItemClicked(static_cast<int32_t>(control->getValue()));
|
||||
}
|
||||
private:
|
||||
SValueMenu& menu_;
|
||||
};
|
||||
};
|
||||
|
||||
///
|
||||
class SActionMenu : public CParamDisplay {
|
||||
public:
|
||||
explicit SActionMenu(const CRect& bounds, IControlListener* listener);
|
||||
std::string getTitle() const { return title_; }
|
||||
void setTitle(std::string title);
|
||||
CColor getHoverColor() const { return hoverColor_; }
|
||||
void setHoverColor(const CColor& color);
|
||||
CMenuItem* addEntry(CMenuItem* item, int32_t tag, int32_t index = -1);
|
||||
CMenuItem* addEntry(const UTF8String& title, int32_t tag, int32_t index = -1, int32_t itemFlags = CMenuItem::kNoFlags);
|
||||
CMenuItem* addSeparator(int32_t index = -1);
|
||||
int32_t getNbEntries() const;
|
||||
|
||||
protected:
|
||||
void draw(CDrawContext* dc) override;
|
||||
CMouseEventResult onMouseEntered(CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseExited(CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseDown(CPoint& where, const CButtonState& buttons) override;
|
||||
|
||||
private:
|
||||
std::string title_;
|
||||
CColor hoverColor_;
|
||||
bool hovered_ = false;
|
||||
|
||||
class MenuListener;
|
||||
|
||||
//
|
||||
void onItemClicked(int32_t index);
|
||||
|
||||
//
|
||||
CMenuItemList menuItems_;
|
||||
std::vector<int32_t> menuItemTags_;
|
||||
SharedPointer<MenuListener> menuListener_;
|
||||
|
||||
//
|
||||
class MenuListener : public IControlListener, public NonAtomicReferenceCounted {
|
||||
public:
|
||||
explicit MenuListener(SActionMenu& menu) : menu_(menu) {}
|
||||
void valueChanged(CControl* control) override
|
||||
{
|
||||
menu_.onItemClicked(static_cast<int32_t>(control->getValue()));
|
||||
}
|
||||
private:
|
||||
SActionMenu& menu_;
|
||||
};
|
||||
};
|
||||
|
||||
///
|
||||
class STextButton: public CTextButton {
|
||||
public:
|
||||
STextButton(const CRect& size, IControlListener* listener = nullptr, int32_t tag = -1, UTF8StringPtr title = nullptr)
|
||||
: CTextButton(size, listener, tag, title) {}
|
||||
|
||||
CColor getHoverColor() const { return hoverColor_; }
|
||||
void setHoverColor(const CColor& color);
|
||||
CColor getInactiveColor() const { return inactiveColor_; }
|
||||
void setInactiveColor(const CColor& color);
|
||||
bool isInactive() const { return inactive_; }
|
||||
void setInactive(bool b);
|
||||
CMouseEventResult onMouseEntered (CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseExited (CPoint& where, const CButtonState& buttons) override;
|
||||
void draw(CDrawContext* context) override;
|
||||
private:
|
||||
CColor hoverColor_;
|
||||
bool hovered_ { false };
|
||||
CColor inactiveColor_;
|
||||
bool inactive_ { false };
|
||||
};
|
||||
|
||||
///
|
||||
class SStyledKnob : public CKnobBase {
|
||||
public:
|
||||
SStyledKnob(const CRect& size, IControlListener* listener, int32_t tag);
|
||||
|
||||
const CColor& getActiveTrackColor() const { return activeTrackColor_; }
|
||||
void setActiveTrackColor(const CColor& color);
|
||||
const CColor& getInactiveTrackColor() const { return inactiveTrackColor_; }
|
||||
void setInactiveTrackColor(const CColor& color);
|
||||
const CColor& getLineIndicatorColor() const { return lineIndicatorColor_; }
|
||||
void setLineIndicatorColor(const CColor& color);
|
||||
|
||||
CLASS_METHODS(SStyledKnob, CKnobBase)
|
||||
protected:
|
||||
void draw(CDrawContext* dc) override;
|
||||
|
||||
private:
|
||||
CColor activeTrackColor_;
|
||||
CColor inactiveTrackColor_;
|
||||
CColor lineIndicatorColor_;
|
||||
};
|
||||
238
editor/src/editor/GUIPiano.cpp
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
// 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)));
|
||||
}
|
||||
72
editor/src/editor/GUIPiano.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// 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 "utility/vstgui_before.h"
|
||||
#include "vstgui/lib/cview.h"
|
||||
#include "vstgui/lib/ccolor.h"
|
||||
#include "utility/vstgui_after.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
using namespace VSTGUI;
|
||||
|
||||
class SPiano : public CView {
|
||||
public:
|
||||
explicit SPiano(CRect bounds);
|
||||
|
||||
CFontRef getFont() const { return font_; }
|
||||
void setFont(CFontRef font);
|
||||
|
||||
unsigned getNumOctaves() const { return octs_; }
|
||||
void setNumOctaves(unsigned octs);
|
||||
|
||||
std::function<void(unsigned, float)> onKeyPressed;
|
||||
std::function<void(unsigned, float)> onKeyReleased;
|
||||
|
||||
protected:
|
||||
void draw(CDrawContext* dc) override;
|
||||
CMouseEventResult onMouseDown(CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseUp(CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseMoved(CPoint& where, const CButtonState& buttons) override;
|
||||
|
||||
private:
|
||||
struct Dimensions {
|
||||
CRect bounds {};
|
||||
CRect paddedBounds {};
|
||||
CRect keyBounds {};
|
||||
unsigned keyWidth {};
|
||||
CRect labelBounds {};
|
||||
};
|
||||
const Dimensions& getDimensions(bool forceUpdate) const;
|
||||
|
||||
static CRect keyRect(const Dimensions& dim, unsigned key);
|
||||
CRect keyRect(unsigned key) const;
|
||||
unsigned keyAtPos(CPoint pos) const;
|
||||
|
||||
float mousePressVelocity(unsigned key, CCoord posY);
|
||||
|
||||
private:
|
||||
unsigned octs_ {};
|
||||
std::vector<unsigned> keyval_;
|
||||
unsigned mousePressedKey_ = ~0u;
|
||||
|
||||
CCoord innerPaddingX_ = 4.0;
|
||||
CCoord innerPaddingY_ = 4.0;
|
||||
CCoord spacingY_ = 4.0;
|
||||
|
||||
CColor backgroundFill_ { 0xca, 0xca, 0xca, 0xff };
|
||||
float backgroundRadius_ = 5.0;
|
||||
CColor whiteFill_ { 0xee, 0xee, 0xec, 0xff };
|
||||
CColor blackFill_ { 0x2e, 0x34, 0x36, 0xff };
|
||||
CColor pressedFill_ { 0xa0, 0xa0, 0xa0, 0xff };
|
||||
CColor outline_ { 0x00, 0x00, 0x00, 0xff };
|
||||
CColor shadeOutline_ { 0x80, 0x80, 0x80, 0xff };
|
||||
CColor labelStroke_ { 0x63, 0x63, 0x63, 0xff };
|
||||
|
||||
mutable Dimensions dim_;
|
||||
SharedPointer<CFontDesc> font_;
|
||||
};
|
||||
50
editor/src/editor/NativeHelpers.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// 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
|
||||
9
editor/src/editor/NativeHelpers.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// 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
|
||||
|
||||
bool openFileInExternalEditor(const char *filename);
|
||||
30
editor/src/editor/NativeHelpers.mm
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// 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
|
||||
155
editor/src/editor/layout/main.hpp
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/* 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);
|
||||
9
editor/src/editor/utility/vstgui_after.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// 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
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
14
editor/src/editor/utility/vstgui_before.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// 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
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-copy"
|
||||
#pragma GCC diagnostic ignored "-Wmultichar"
|
||||
#pragma GCC diagnostic ignored "-Wextra"
|
||||
#endif
|
||||
23
editor/tools/layout-maker/LICENSE
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
2
editor/tools/layout-maker/README
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
This purpose of this tool is to accept UI designs make with Fluid, the FLTK
|
||||
design editor, and convert these designs to music plugin interfaces.
|
||||
42
editor/tools/layout-maker/sources/layout.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
struct LayoutImage {
|
||||
std::string filepath;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
};
|
||||
|
||||
struct LayoutItem {
|
||||
std::string id;
|
||||
std::string classname;
|
||||
std::string label;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
std::string box;
|
||||
std::string down_box;
|
||||
int labelfont = 0;
|
||||
int labelsize = 14;
|
||||
std::string labeltype;
|
||||
int textsize = 14;
|
||||
int align = 0;
|
||||
double value = 0;
|
||||
double minimum = 0;
|
||||
double maximum = 0;
|
||||
double step = 0;
|
||||
std::string type;
|
||||
std::string callback;
|
||||
LayoutImage image;
|
||||
bool hidden = false;
|
||||
std::string comment;
|
||||
std::vector<LayoutItem> items;
|
||||
};
|
||||
|
||||
struct Layout {
|
||||
std::vector<LayoutItem> items;
|
||||
};
|
||||
136
editor/tools/layout-maker/sources/main.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
#include "layout.h"
|
||||
#include "reader.h"
|
||||
#include <absl/strings/ascii.h>
|
||||
#include <absl/strings/string_view.h>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
|
||||
///
|
||||
typedef std::unordered_map<std::string, std::string> Metadata;
|
||||
|
||||
static Metadata metadata_from_comment(absl::string_view comment)
|
||||
{
|
||||
Metadata md;
|
||||
|
||||
while (!comment.empty()) {
|
||||
absl::string_view line;
|
||||
|
||||
size_t pos = comment.find_first_of("\r\n");
|
||||
if (pos != comment.npos) {
|
||||
line = comment.substr(0, pos);
|
||||
comment.remove_prefix(pos + 1);
|
||||
}
|
||||
else {
|
||||
line = comment;
|
||||
comment = {};
|
||||
}
|
||||
|
||||
line = absl::StripAsciiWhitespace(line);
|
||||
if (line.empty() || line[0] == '#')
|
||||
continue;
|
||||
|
||||
std::string key, value;
|
||||
pos = line.find_first_of('=');
|
||||
if (pos != comment.npos) {
|
||||
key = std::string(line.substr(0, pos));
|
||||
value = std::string(line.substr(pos + 1));
|
||||
}
|
||||
else
|
||||
key = std::string(line);
|
||||
|
||||
md.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
///
|
||||
static void codegen_item(int& idCounter, int parentId, int parentX, int parentY, const LayoutItem& item, absl::string_view oldTheme)
|
||||
{
|
||||
const Metadata md = metadata_from_comment(item.comment);
|
||||
|
||||
absl::string_view tag = "-1";
|
||||
absl::string_view newTheme;
|
||||
|
||||
Metadata::const_iterator it;
|
||||
it = md.find("tag");
|
||||
if (it != md.end())
|
||||
tag = it->second;
|
||||
it = md.find("theme");
|
||||
if (it != md.end())
|
||||
newTheme = it->second;
|
||||
|
||||
absl::string_view currentTheme = newTheme.empty() ? oldTheme : newTheme;
|
||||
|
||||
int id = idCounter++;
|
||||
int myX = item.x;
|
||||
int myY = item.y;
|
||||
if (parentId == -1) {
|
||||
myX = 0;
|
||||
myY = 0;
|
||||
}
|
||||
int relX = myX - parentX;
|
||||
int relY = myY - parentY;
|
||||
|
||||
//std::cout << "// Begin " << id << " " << item.classname << " {" << item.label << "}" << "\n";
|
||||
|
||||
if (!newTheme.empty())
|
||||
std::cout << "enterTheme(" << newTheme << ");\n";
|
||||
|
||||
absl::string_view label;
|
||||
if (!item.label.empty() && item.labeltype != "NO_LABEL")
|
||||
label = item.label;
|
||||
|
||||
absl::string_view align = "kCenterText";
|
||||
if (item.align & 4)
|
||||
align = "kLeftText";
|
||||
else if (item.align & 8)
|
||||
align = "kRightText";
|
||||
|
||||
std::cout << item.classname << "* const view__" << id << " = create" << item.classname << "(CRect(" << relX << ", " << relY << ", " << (relX + item.w) << ", " << (relY + item.h) << "), " << tag << ", \"" << label << "\", " << align << ", " << item.labelsize << ");\n";
|
||||
|
||||
if (!item.id.empty())
|
||||
std::cout << item.id << " = view__" << id << ";\n";
|
||||
|
||||
if (parentId != -1)
|
||||
std::cout << "view__" << parentId << "->addView(view__" << id << ");\n";
|
||||
|
||||
if (item.hidden)
|
||||
std::cout << "view__" << id << "->setVisible(false);\n";
|
||||
|
||||
for (const LayoutItem& subItem : item.items)
|
||||
codegen_item(idCounter, id, myX, myY, subItem, currentTheme);
|
||||
|
||||
if (!newTheme.empty())
|
||||
std::cout << "enterTheme(" << oldTheme << ");\n";
|
||||
|
||||
//std::cout << "// End " << id << " " << item.classname << " {" << item.label << "}" << "\n";
|
||||
}
|
||||
|
||||
static void codegen_layout(const LayoutItem& item)
|
||||
{
|
||||
int idCounter = 0;
|
||||
codegen_item(idCounter, -1, 0, 0, item, "defaultTheme");
|
||||
}
|
||||
|
||||
///
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
std::cerr << "Please indicate a fluid design file.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Layout layout = read_file_layout(argv[1]);
|
||||
|
||||
if (layout.items.size() != 1) {
|
||||
std::cerr << "There must be exactly 1 top level component.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "/* This file is generated by the layout maker tool. */\n";
|
||||
|
||||
codegen_layout(layout.items[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
298
editor/tools/layout-maker/sources/reader.cpp
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
#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();
|
||||
}
|
||||
13
editor/tools/layout-maker/sources/reader.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
#include "layout.h"
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
Layout read_file_layout(const char *filename);
|
||||
|
||||
///
|
||||
struct file_format_error : public std::runtime_error {
|
||||
public:
|
||||
explicit file_format_error(const std::string &reason = "Format error")
|
||||
: runtime_error(reason) {}
|
||||
};
|
||||
23
external/jsl/LICENSE.md
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
73
external/jsl/include/jsl/allocator
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// -*- C++ -*-
|
||||
#pragma once
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
namespace jsl {
|
||||
|
||||
template <class T, class Traits>
|
||||
struct ordinary_allocator {
|
||||
typedef T value_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::true_type propagate_on_container_move_assignment;
|
||||
template <class U> struct rebind { typedef ordinary_allocator<U, Traits> other; };
|
||||
typedef std::true_type is_always_equal;
|
||||
|
||||
ordinary_allocator() noexcept {}
|
||||
ordinary_allocator(const ordinary_allocator &) noexcept {}
|
||||
template <class U> ordinary_allocator(const ordinary_allocator<U, Traits>&) noexcept {}
|
||||
|
||||
T *address(T &x) const noexcept;
|
||||
const T *address(const T &x) const noexcept;
|
||||
|
||||
T *allocate(std::size_t n, const void * = nullptr);
|
||||
void deallocate(T *p, std::size_t n) noexcept;
|
||||
std::size_t max_size() const noexcept;
|
||||
|
||||
template <class U, class... Args> void construct(U *p, Args &&...args);
|
||||
template <class U> void destroy(U *p);
|
||||
};
|
||||
|
||||
template <class T, class Traits>
|
||||
inline bool operator==(const ordinary_allocator<T, Traits> &, const ordinary_allocator<T, Traits> &) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
inline bool operator!=(const ordinary_allocator<T, Traits> &, const ordinary_allocator<T, Traits> &) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct stdc_allocator_traits {
|
||||
static void *allocate(std::size_t n);
|
||||
static void deallocate(void *p, std::size_t = 0);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using stdc_allocator = ordinary_allocator<T, stdc_allocator_traits>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <std::size_t Al>
|
||||
struct aligned_allocator_traits {
|
||||
static void *allocate(std::size_t n);
|
||||
static void deallocate(void *p, std::size_t = 0);
|
||||
};
|
||||
|
||||
template <class T, std::size_t Al>
|
||||
using aligned_allocator = ordinary_allocator<T, aligned_allocator_traits<Al>>;
|
||||
|
||||
} // namespace jsl
|
||||
|
||||
#include "bits/allocator/ordinary_allocator.tcc"
|
||||
#include "bits/allocator/stdc_allocator.tcc"
|
||||
#include "bits/allocator/aligned_allocator.tcc"
|
||||
41
external/jsl/include/jsl/bits/allocator/aligned_allocator.tcc
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#include "../../allocator"
|
||||
#include <new>
|
||||
#if defined(_WIN32)
|
||||
# include <malloc.h>
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
namespace jsl {
|
||||
|
||||
template <std::size_t Al>
|
||||
void *aligned_allocator_traits<Al>::allocate(std::size_t n)
|
||||
{
|
||||
static_assert(Al % sizeof(void *) == 0,
|
||||
"alignment must be a multiple of the pointer size");
|
||||
static_assert((Al & (~Al + 1)) == Al,
|
||||
"alignment must be a power of two");
|
||||
#if defined(_WIN32)
|
||||
void *p = ::_aligned_malloc(n, Al);
|
||||
if (!p)
|
||||
throw std::bad_alloc();
|
||||
return p;
|
||||
#else
|
||||
void *p;
|
||||
if (::posix_memalign(&p, Al, n) != 0)
|
||||
throw std::bad_alloc();
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <std::size_t Al>
|
||||
void aligned_allocator_traits<Al>::deallocate(void *p, std::size_t)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
::_aligned_free(p);
|
||||
#else
|
||||
::free(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace jsl
|
||||
53
external/jsl/include/jsl/bits/allocator/ordinary_allocator.tcc
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#include "../../allocator"
|
||||
#include <new>
|
||||
|
||||
namespace jsl {
|
||||
|
||||
template <class T, class Traits>
|
||||
inline T *ordinary_allocator<T, Traits>::address(T &x) const noexcept
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
inline const T *ordinary_allocator<T, Traits>::address(const T &x) const noexcept
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
T *ordinary_allocator<T, Traits>::allocate(std::size_t n, const void *)
|
||||
{
|
||||
T *ptr = (T *)Traits::allocate(n * sizeof(T));
|
||||
if (!ptr)
|
||||
throw std::bad_alloc();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
void ordinary_allocator<T, Traits>::deallocate(T *p, std::size_t n) noexcept
|
||||
{
|
||||
Traits::deallocate(p, n * sizeof(T));
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
std::size_t ordinary_allocator<T, Traits>::max_size() const noexcept
|
||||
{
|
||||
return std::numeric_limits<std::size_t>::max() / sizeof(T);
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
template <class U, class... Args>
|
||||
void ordinary_allocator<T, Traits>::construct(U *p, Args &&...args)
|
||||
{
|
||||
::new((void *)p) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T, class Traits>
|
||||
template <class U>
|
||||
void ordinary_allocator<T, Traits>::destroy(U *p)
|
||||
{
|
||||
p->~U();
|
||||
}
|
||||
|
||||
} // namespace jsl
|
||||
16
external/jsl/include/jsl/bits/allocator/stdc_allocator.tcc
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include "../../allocator"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace jsl {
|
||||
|
||||
inline void *stdc_allocator_traits::allocate(std::size_t n)
|
||||
{
|
||||
return ::malloc(n);
|
||||
}
|
||||
|
||||
inline void stdc_allocator_traits::deallocate(void *p, std::size_t)
|
||||
{
|
||||
::free(p);
|
||||
}
|
||||
|
||||
} // namespace jsl
|
||||
|
|
@ -11,6 +11,10 @@ set (LV2PLUGIN_TTL_SRC_FILES
|
|||
manifest.ttl.in
|
||||
${PROJECT_NAME}.ttl.in
|
||||
)
|
||||
if (SFIZZ_LV2_UI)
|
||||
list(APPEND LV2PLUGIN_TTL_SRC_FILES
|
||||
${PROJECT_NAME}_ui.ttl.in)
|
||||
endif()
|
||||
source_group("Turtle Files" FILES
|
||||
${LV2PLUGIN_TTL_SRC_FILES}
|
||||
)
|
||||
|
|
@ -19,33 +23,63 @@ add_library (${LV2PLUGIN_PRJ_NAME} MODULE
|
|||
atomic_compat.h
|
||||
${LV2PLUGIN_TTL_SRC_FILES})
|
||||
target_link_libraries (${LV2PLUGIN_PRJ_NAME} ${PROJECT_NAME}::${PROJECT_NAME})
|
||||
|
||||
if (SFIZZ_LV2_UI)
|
||||
add_library (${LV2PLUGIN_PRJ_NAME}_ui MODULE
|
||||
${PROJECT_NAME}_ui.cpp
|
||||
vstgui_helpers.h
|
||||
vstgui_helpers.cpp)
|
||||
target_link_libraries (${LV2PLUGIN_PRJ_NAME}_ui sfizz_editor sfizz-vstgui)
|
||||
endif()
|
||||
|
||||
# Explicitely strip all symbols on Linux but lv2_descriptor()
|
||||
# MacOS linker does not support this apparently https://bugs.webkit.org/show_bug.cgi?id=144555
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
file(COPY lv2.version DESTINATION ${CMAKE_BINARY_DIR}/lv2)
|
||||
target_link_libraries(${LV2PLUGIN_PRJ_NAME} "-Wl,--version-script=lv2.version")
|
||||
# target_link_libraries(${LV2PLUGIN_PRJ_NAME} "-Wl,-u,lv2_descriptor")
|
||||
if (SFIZZ_LV2_UI)
|
||||
file(COPY lv2ui.version DESTINATION ${CMAKE_BINARY_DIR}/lv2)
|
||||
target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui "-Wl,--version-script=lv2ui.version")
|
||||
# target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui "-Wl,-u,lv2ui_descriptor")
|
||||
endif()
|
||||
endif()
|
||||
target_include_directories(${LV2PLUGIN_PRJ_NAME} PRIVATE . external/ardour)
|
||||
sfizz_enable_lto_if_needed (${LV2PLUGIN_PRJ_NAME})
|
||||
if (MINGW)
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME} PROPERTIES LINK_FLAGS "-static")
|
||||
endif()
|
||||
if (SFIZZ_LV2_UI)
|
||||
target_include_directories(${LV2PLUGIN_PRJ_NAME}_ui PRIVATE . external/ardour)
|
||||
sfizz_enable_lto_if_needed (${LV2PLUGIN_PRJ_NAME}_ui)
|
||||
if (MINGW)
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME}_ui PROPERTIES LINK_FLAGS "-static")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Remove the "lib" prefix, rename the target name and build it in the .lv build dir
|
||||
# <build_dir>/lv2/<plugin_name>_lv2.<ext> to
|
||||
# <build_dir>/lv2/<plugin_name>.lv2/<plugin_name>.<ext>
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}")
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Contents/Binary/$<0:>")
|
||||
|
||||
if (SFIZZ_LV2_UI)
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME}_ui PROPERTIES PREFIX "")
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME}_ui PROPERTIES OUTPUT_NAME "${PROJECT_NAME}_ui")
|
||||
set_target_properties (${LV2PLUGIN_PRJ_NAME}_ui PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/Contents/Binary/$<0:>")
|
||||
endif()
|
||||
|
||||
# Generate *.ttl files from *.in sources,
|
||||
# create the destination directory if it doesn't exists and copy needed files
|
||||
file (MAKE_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
configure_file (manifest.ttl.in ${PROJECT_BINARY_DIR}/manifest.ttl)
|
||||
configure_file (${PROJECT_NAME}.ttl.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.ttl)
|
||||
if (SFIZZ_LV2_UI)
|
||||
configure_file (${PROJECT_NAME}_ui.ttl.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}_ui.ttl)
|
||||
endif()
|
||||
configure_file (LICENSE.md.in ${PROJECT_BINARY_DIR}/LICENSE.md)
|
||||
if (SFIZZ_USE_VCPKG OR SFIZZ_STATIC_LIBSNDFILE OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
if (SFIZZ_USE_VCPKG OR SFIZZ_STATIC_DEPENDENCIES OR CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
file(COPY "lgpl-3.0.txt" DESTINATION ${PROJECT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
|
|
@ -54,12 +88,21 @@ set(LV2_RESOURCES
|
|||
DefaultInstrument.sfz
|
||||
DefaultScale.scl)
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/Resources")
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/Contents/Resources")
|
||||
foreach(res ${LV2_RESOURCES})
|
||||
file (COPY "${CMAKE_CURRENT_SOURCE_DIR}/resources/${res}"
|
||||
DESTINATION "${PROJECT_BINARY_DIR}/Resources")
|
||||
DESTINATION "${PROJECT_BINARY_DIR}/Contents/Resources")
|
||||
endforeach()
|
||||
|
||||
# Copy editor resources
|
||||
if (SFIZZ_LV2_UI)
|
||||
execute_process (
|
||||
COMMAND "${CMAKE_COMMAND}" -E make_directory "${PROJECT_BINARY_DIR}/Contents/Resources")
|
||||
copy_editor_resources(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../editor/resources"
|
||||
"${PROJECT_BINARY_DIR}/Contents/Resources")
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
if (NOT MSVC)
|
||||
install (DIRECTORY ${PROJECT_BINARY_DIR} DESTINATION ${LV2PLUGIN_INSTALL_DIR}
|
||||
|
|
|
|||
|
|
@ -122,13 +122,13 @@ lv2_atom_sequence_next(const LV2_Atom_Event* i)
|
|||
@endcode
|
||||
*/
|
||||
#define LV2_ATOM_SEQUENCE_FOREACH(seq, iter) \
|
||||
for (LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(&(seq)->body); \
|
||||
for (LV2_Atom_Event* iter = lv2_atom_sequence_begin(&(seq)->body); \
|
||||
!lv2_atom_sequence_is_end(&(seq)->body, (seq)->atom.size, (iter)); \
|
||||
(iter) = lv2_atom_sequence_next(iter))
|
||||
|
||||
/** Like LV2_ATOM_SEQUENCE_FOREACH but for a headerless sequence body. */
|
||||
#define LV2_ATOM_SEQUENCE_BODY_FOREACH(body, size, iter) \
|
||||
for (LV2_Atom_Event* (iter) = lv2_atom_sequence_begin(body); \
|
||||
for (LV2_Atom_Event* iter = lv2_atom_sequence_begin(body); \
|
||||
!lv2_atom_sequence_is_end(body, size, (iter)); \
|
||||
(iter) = lv2_atom_sequence_next(iter))
|
||||
|
||||
|
|
@ -219,13 +219,13 @@ lv2_atom_tuple_next(const LV2_Atom* i)
|
|||
@endcode
|
||||
*/
|
||||
#define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \
|
||||
for (LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \
|
||||
for (LV2_Atom* iter = lv2_atom_tuple_begin(tuple); \
|
||||
!lv2_atom_tuple_is_end(LV2_ATOM_BODY(tuple), (tuple)->atom.size, (iter)); \
|
||||
(iter) = lv2_atom_tuple_next(iter))
|
||||
|
||||
/** Like LV2_ATOM_TUPLE_FOREACH but for a headerless tuple body. */
|
||||
#define LV2_ATOM_TUPLE_BODY_FOREACH(body, size, iter) \
|
||||
for (LV2_Atom* (iter) = (LV2_Atom*)(body); \
|
||||
for (LV2_Atom* iter = (LV2_Atom*)(body); \
|
||||
!lv2_atom_tuple_is_end(body, size, (iter)); \
|
||||
(iter) = lv2_atom_tuple_next(iter))
|
||||
|
||||
|
|
@ -275,13 +275,13 @@ lv2_atom_object_next(const LV2_Atom_Property_Body* i)
|
|||
@endcode
|
||||
*/
|
||||
#define LV2_ATOM_OBJECT_FOREACH(obj, iter) \
|
||||
for (LV2_Atom_Property_Body* (iter) = lv2_atom_object_begin(&(obj)->body); \
|
||||
for (LV2_Atom_Property_Body* iter = lv2_atom_object_begin(&(obj)->body); \
|
||||
!lv2_atom_object_is_end(&(obj)->body, (obj)->atom.size, (iter)); \
|
||||
(iter) = lv2_atom_object_next(iter))
|
||||
|
||||
/** Like LV2_ATOM_OBJECT_FOREACH but for a headerless object body. */
|
||||
#define LV2_ATOM_OBJECT_BODY_FOREACH(body, size, iter) \
|
||||
for (LV2_Atom_Property_Body* (iter) = lv2_atom_object_begin(body); \
|
||||
for (LV2_Atom_Property_Body* iter = lv2_atom_object_begin(body); \
|
||||
!lv2_atom_object_is_end(body, size, (iter)); \
|
||||
(iter) = lv2_atom_object_next(iter))
|
||||
|
||||
|
|
|
|||
4
lv2/lv2ui.version
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
LV2UIABI_1.0 {
|
||||
global: *lv2ui_descriptor*;
|
||||
local: *;
|
||||
};
|
||||
|
|
@ -1,7 +1,13 @@
|
|||
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
|
||||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
|
||||
|
||||
<@LV2PLUGIN_URI@>
|
||||
a lv2:Plugin ;
|
||||
lv2:binary <@PROJECT_NAME@@CMAKE_SHARED_MODULE_SUFFIX@> ;
|
||||
lv2:binary <Contents/Binary/@PROJECT_NAME@@CMAKE_SHARED_MODULE_SUFFIX@> ;
|
||||
rdfs:seeAlso <@PROJECT_NAME@.ttl> .
|
||||
|
||||
@LV2PLUGIN_IF_ENABLE_UI@<@LV2PLUGIN_URI@#ui>
|
||||
@LV2PLUGIN_IF_ENABLE_UI@ a ui:@LV2_UI_TYPE@ ;
|
||||
@LV2PLUGIN_IF_ENABLE_UI@ ui:binary <Contents/Binary/@PROJECT_NAME@_ui@CMAKE_SHARED_MODULE_SUFFIX@> ;
|
||||
@LV2PLUGIN_IF_ENABLE_UI@ rdfs:seeAlso <@PROJECT_NAME@_ui.ttl> .
|
||||
|
|
|
|||
232
lv2/sfizz.c
|
|
@ -32,6 +32,9 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sfizz_lv2.h"
|
||||
|
||||
#include <lv2/atom/atom.h>
|
||||
#include <lv2/atom/forge.h>
|
||||
#include <lv2/atom/util.h>
|
||||
#include <lv2/buf-size/buf-size.h>
|
||||
|
|
@ -58,23 +61,11 @@
|
|||
|
||||
#include "atomic_compat.h"
|
||||
|
||||
#define SFIZZ_URI "http://sfztools.github.io/sfizz"
|
||||
#define SFIZZ_PREFIX SFIZZ_URI "#"
|
||||
#define SFIZZ__sfzFile "http://sfztools.github.io/sfizz:sfzfile"
|
||||
#define SFIZZ__tuningfile "http://sfztools.github.io/sfizz:tuningfile"
|
||||
#define SFIZZ__numVoices "http://sfztools.github.io/sfizz:numvoices"
|
||||
#define SFIZZ__preloadSize "http://sfztools.github.io/sfizz:preload_size"
|
||||
#define SFIZZ__oversampling "http://sfztools.github.io/sfizz:oversampling"
|
||||
// These ones are just for the worker
|
||||
#define SFIZZ__logStatus "http://sfztools.github.io/sfizz:log_status"
|
||||
#define SFIZZ__checkModification "http://sfztools.github.io/sfizz:check_modification"
|
||||
|
||||
#define CHANNEL_MASK 0x0F
|
||||
#define MIDI_CHANNEL(byte) (byte & CHANNEL_MASK)
|
||||
#define MIDI_STATUS(byte) (byte & ~CHANNEL_MASK)
|
||||
#define PITCH_BUILD_AND_CENTER(first_byte, last_byte) (int)(((unsigned int)last_byte << 7) + (unsigned int)first_byte) - 8192
|
||||
#define MAX_BLOCK_SIZE 8192
|
||||
#define MAX_PATH_SIZE 1024
|
||||
#define MAX_VOICES 256
|
||||
#define DEFAULT_VOICES 64
|
||||
#define DEFAULT_OVERSAMPLING SFIZZ_OVERSAMPLING_X1
|
||||
|
|
@ -82,8 +73,8 @@
|
|||
#define LOG_SAMPLE_COUNT 48000
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#define DEFAULT_SCALA_FILE "Resources/DefaultScale.scl"
|
||||
#define DEFAULT_SFZ_FILE "Resources/DefaultInstrument.sfz"
|
||||
#define DEFAULT_SCALA_FILE "Contents/Resources/DefaultScale.scl"
|
||||
#define DEFAULT_SFZ_FILE "Contents/Resources/DefaultInstrument.sfz"
|
||||
// This assumes that the longest path is the default sfz file; if not, change it
|
||||
#define MAX_BUNDLE_PATH_SIZE (MAX_PATH_SIZE - sizeof(DEFAULT_SFZ_FILE))
|
||||
|
||||
|
|
@ -114,6 +105,12 @@ typedef struct
|
|||
const float *scala_root_key_port;
|
||||
const float *tuning_frequency_port;
|
||||
const float *stretch_tuning_port;
|
||||
float *active_voices_port;
|
||||
float *num_curves_port;
|
||||
float *num_masters_port;
|
||||
float *num_groups_port;
|
||||
float *num_regions_port;
|
||||
float *num_samples_port;
|
||||
|
||||
// Atom forge
|
||||
LV2_Atom_Forge forge; ///< Forge for writing atoms in run thread
|
||||
|
|
@ -129,8 +126,11 @@ typedef struct
|
|||
LV2_URID nominal_block_length_uri;
|
||||
LV2_URID sample_rate_uri;
|
||||
LV2_URID atom_object_uri;
|
||||
LV2_URID atom_blank_uri;
|
||||
LV2_URID atom_float_uri;
|
||||
LV2_URID atom_double_uri;
|
||||
LV2_URID atom_int_uri;
|
||||
LV2_URID atom_long_uri;
|
||||
LV2_URID atom_urid_uri;
|
||||
LV2_URID atom_path_uri;
|
||||
LV2_URID patch_set_uri;
|
||||
|
|
@ -147,7 +147,14 @@ typedef struct
|
|||
LV2_URID sfizz_oversampling_uri;
|
||||
LV2_URID sfizz_log_status_uri;
|
||||
LV2_URID sfizz_check_modification_uri;
|
||||
LV2_URID sfizz_active_voices_uri;
|
||||
LV2_URID time_position_uri;
|
||||
LV2_URID time_bar_uri;
|
||||
LV2_URID time_bar_beat_uri;
|
||||
LV2_URID time_beat_unit_uri;
|
||||
LV2_URID time_beats_per_bar_uri;
|
||||
LV2_URID time_beats_per_minute_uri;
|
||||
LV2_URID time_speed_uri;
|
||||
|
||||
// Sfizz related data
|
||||
sfizz_synth_t *synth;
|
||||
|
|
@ -164,24 +171,24 @@ typedef struct
|
|||
float sample_rate;
|
||||
atomic_int must_update_midnam;
|
||||
|
||||
// Timing data
|
||||
int bar;
|
||||
float bar_beat;
|
||||
int beats_per_bar;
|
||||
int beat_unit;
|
||||
float bpm_tempo;
|
||||
float speed;
|
||||
|
||||
// Paths
|
||||
char bundle_path[MAX_BUNDLE_PATH_SIZE];
|
||||
} sfizz_plugin_t;
|
||||
|
||||
enum
|
||||
{
|
||||
SFIZZ_CONTROL = 0,
|
||||
SFIZZ_NOTIFY = 1,
|
||||
SFIZZ_LEFT = 2,
|
||||
SFIZZ_RIGHT = 3,
|
||||
SFIZZ_VOLUME = 4,
|
||||
SFIZZ_POLYPHONY = 5,
|
||||
SFIZZ_OVERSAMPLING = 6,
|
||||
SFIZZ_PRELOAD = 7,
|
||||
SFIZZ_FREEWHEELING = 8,
|
||||
SFIZZ_SCALA_ROOT_KEY = 9,
|
||||
SFIZZ_TUNING_FREQUENCY = 10,
|
||||
SFIZZ_STRETCH_TUNING = 11,
|
||||
SFIZZ_TIMEINFO_POSITION = 1 << 0,
|
||||
SFIZZ_TIMEINFO_SIGNATURE = 1 << 1,
|
||||
SFIZZ_TIMEINFO_TEMPO = 1 << 2,
|
||||
SFIZZ_TIMEINFO_SPEED = 1 << 3,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -207,10 +214,13 @@ sfizz_lv2_map_required_uris(sfizz_plugin_t *self)
|
|||
self->nominal_block_length_uri = map->map(map->handle, LV2_BUF_SIZE__nominalBlockLength);
|
||||
self->sample_rate_uri = map->map(map->handle, LV2_PARAMETERS__sampleRate);
|
||||
self->atom_float_uri = map->map(map->handle, LV2_ATOM__Float);
|
||||
self->atom_double_uri = map->map(map->handle, LV2_ATOM__Double);
|
||||
self->atom_int_uri = map->map(map->handle, LV2_ATOM__Int);
|
||||
self->atom_long_uri = map->map(map->handle, LV2_ATOM__Long);
|
||||
self->atom_path_uri = map->map(map->handle, LV2_ATOM__Path);
|
||||
self->atom_urid_uri = map->map(map->handle, LV2_ATOM__URID);
|
||||
self->atom_object_uri = map->map(map->handle, LV2_ATOM__Object);
|
||||
self->atom_blank_uri = map->map(map->handle, LV2_ATOM__Blank);
|
||||
self->patch_set_uri = map->map(map->handle, LV2_PATCH__Set);
|
||||
self->patch_get_uri = map->map(map->handle, LV2_PATCH__Get);
|
||||
self->patch_put_uri = map->map(map->handle, LV2_PATCH__Put);
|
||||
|
|
@ -224,8 +234,71 @@ sfizz_lv2_map_required_uris(sfizz_plugin_t *self)
|
|||
self->sfizz_preload_size_uri = map->map(map->handle, SFIZZ__preloadSize);
|
||||
self->sfizz_oversampling_uri = map->map(map->handle, SFIZZ__oversampling);
|
||||
self->sfizz_log_status_uri = map->map(map->handle, SFIZZ__logStatus);
|
||||
self->sfizz_log_status_uri = map->map(map->handle, SFIZZ__logStatus);
|
||||
self->sfizz_check_modification_uri = map->map(map->handle, SFIZZ__checkModification);
|
||||
self->time_position_uri = map->map(map->handle, LV2_TIME__Position);
|
||||
self->time_bar_uri = map->map(map->handle, LV2_TIME__bar);
|
||||
self->time_bar_beat_uri = map->map(map->handle, LV2_TIME__barBeat);
|
||||
self->time_beat_unit_uri = map->map(map->handle, LV2_TIME__beatUnit);
|
||||
self->time_beats_per_bar_uri = map->map(map->handle, LV2_TIME__beatsPerBar);
|
||||
self->time_beats_per_minute_uri = map->map(map->handle, LV2_TIME__beatsPerMinute);
|
||||
self->time_speed_uri = map->map(map->handle, LV2_TIME__speed);
|
||||
}
|
||||
|
||||
static bool
|
||||
sfizz_atom_extract_real(sfizz_plugin_t *self, const LV2_Atom *atom, double *real)
|
||||
{
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
const LV2_URID type = atom->type;
|
||||
|
||||
if (type == self->atom_int_uri && atom->size >= sizeof(int32_t)) {
|
||||
*real = ((const LV2_Atom_Int *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
if (type == self->atom_long_uri && atom->size >= sizeof(int64_t)) {
|
||||
*real = ((const LV2_Atom_Long *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
if (type == self->atom_float_uri && atom->size >= sizeof(float)) {
|
||||
*real = ((const LV2_Atom_Float *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
if (type == self->atom_double_uri && atom->size >= sizeof(double)) {
|
||||
*real = ((const LV2_Atom_Double *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
sfizz_atom_extract_integer(sfizz_plugin_t *self, const LV2_Atom *atom, int64_t *integer)
|
||||
{
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
const LV2_URID type = atom->type;
|
||||
|
||||
if (type == self->atom_int_uri && atom->size >= sizeof(int32_t)) {
|
||||
*integer = ((const LV2_Atom_Int *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
if (type == self->atom_long_uri && atom->size >= sizeof(int64_t)) {
|
||||
*integer = ((const LV2_Atom_Long *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
if (type == self->atom_float_uri && atom->size >= sizeof(float)) {
|
||||
*integer = (int64_t)((const LV2_Atom_Float *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
if (type == self->atom_double_uri && atom->size >= sizeof(double)) {
|
||||
*integer = (int64_t)((const LV2_Atom_Double *)atom)->body;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -272,6 +345,24 @@ connect_port(LV2_Handle instance,
|
|||
case SFIZZ_STRETCH_TUNING:
|
||||
self->stretch_tuning_port = (const float *)data;
|
||||
break;
|
||||
case SFIZZ_ACTIVE_VOICES:
|
||||
self->active_voices_port = (float *)data;
|
||||
break;
|
||||
case SFIZZ_NUM_CURVES:
|
||||
self->num_curves_port = (float *)data;
|
||||
break;
|
||||
case SFIZZ_NUM_MASTERS:
|
||||
self->num_masters_port = (float *)data;
|
||||
break;
|
||||
case SFIZZ_NUM_GROUPS:
|
||||
self->num_groups_port = (float *)data;
|
||||
break;
|
||||
case SFIZZ_NUM_REGIONS:
|
||||
self->num_regions_port = (float *)data;
|
||||
break;
|
||||
case SFIZZ_NUM_SAMPLES:
|
||||
self->num_samples_port = (float *)data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -319,6 +410,19 @@ sfizz_lv2_get_default_scala_path(LV2_Handle instance, char *path, size_t size)
|
|||
snprintf(path, size, "%s/%s", self->bundle_path, DEFAULT_SCALA_FILE);
|
||||
}
|
||||
|
||||
static void
|
||||
sfizz_lv2_update_timeinfo(sfizz_plugin_t *self, int delay, int updates)
|
||||
{
|
||||
if (updates & SFIZZ_TIMEINFO_POSITION)
|
||||
sfizz_send_time_position(self->synth, delay, self->bar, self->bar_beat);
|
||||
if (updates & SFIZZ_TIMEINFO_SIGNATURE)
|
||||
sfizz_send_time_signature(self->synth, delay, self->beats_per_bar, self->beat_unit);
|
||||
if (updates & SFIZZ_TIMEINFO_TEMPO)
|
||||
sfizz_send_tempo(self->synth, delay, 60.0f / self->bpm_tempo);
|
||||
if (updates & SFIZZ_TIMEINFO_SPEED)
|
||||
sfizz_send_playback_state(self->synth, delay, self->speed > 0);
|
||||
}
|
||||
|
||||
static LV2_Handle
|
||||
instantiate(const LV2_Descriptor *descriptor,
|
||||
double rate,
|
||||
|
|
@ -354,6 +458,14 @@ instantiate(const LV2_Descriptor *descriptor,
|
|||
self->check_modification = false;
|
||||
self->sample_counter = 0;
|
||||
|
||||
// Initial timing
|
||||
self->bar = 0;
|
||||
self->bar_beat = 0;
|
||||
self->beats_per_bar = 4;
|
||||
self->beat_unit = 4;
|
||||
self->bpm_tempo = 120;
|
||||
self->speed = 1;
|
||||
|
||||
// Get the features from the host and populate the structure
|
||||
for (const LV2_Feature *const *f = features; *f; f++)
|
||||
{
|
||||
|
|
@ -465,6 +577,8 @@ instantiate(const LV2_Descriptor *descriptor,
|
|||
sfizz_load_file(self->synth, self->sfz_file_path);
|
||||
sfizz_load_scala_file(self->synth, self->scala_file_path);
|
||||
|
||||
sfizz_lv2_update_timeinfo(self, 0, ~0);
|
||||
|
||||
return (LV2_Handle)self;
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +623,6 @@ sfizz_lv2_send_file_path(sfizz_plugin_t *self, LV2_URID urid, const char *path)
|
|||
lv2_atom_forge_pop(&self->forge, &frame);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sfizz_lv2_handle_atom_object(sfizz_plugin_t *self, const LV2_Atom_Object *obj)
|
||||
{
|
||||
|
|
@ -745,8 +858,10 @@ run(LV2_Handle instance, uint32_t sample_count)
|
|||
|
||||
LV2_ATOM_SEQUENCE_FOREACH(self->control_port, ev)
|
||||
{
|
||||
const int delay = (int)ev->time.frames;
|
||||
|
||||
// If the received atom is an object/patch message
|
||||
if (ev->body.type == self->atom_object_uri)
|
||||
if (ev->body.type == self->atom_object_uri || ev->body.type == self->atom_blank_uri)
|
||||
{
|
||||
const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
|
||||
if (obj->body.otype == self->patch_set_uri)
|
||||
|
|
@ -773,7 +888,60 @@ run(LV2_Handle instance, uint32_t sample_count)
|
|||
}
|
||||
else if (obj->body.otype == self->time_position_uri)
|
||||
{
|
||||
// TODO: Handle time position atom
|
||||
const LV2_Atom *bar_atom = NULL;
|
||||
const LV2_Atom *bar_beat_atom = NULL;
|
||||
const LV2_Atom *beat_unit_atom = NULL;
|
||||
const LV2_Atom *beats_per_bar_atom = NULL;
|
||||
const LV2_Atom *beats_per_minute_atom = NULL;
|
||||
const LV2_Atom *speed_atom = NULL;
|
||||
|
||||
lv2_atom_object_get(
|
||||
obj,
|
||||
self->time_bar_uri, &bar_atom,
|
||||
self->time_bar_beat_uri, &bar_beat_atom,
|
||||
self->time_beats_per_bar_uri, &beats_per_bar_atom,
|
||||
self->time_beats_per_minute_uri, &beats_per_minute_atom,
|
||||
self->time_beat_unit_uri, &beat_unit_atom,
|
||||
self->time_speed_uri, &speed_atom,
|
||||
0);
|
||||
|
||||
int updates = 0;
|
||||
|
||||
int64_t bar;
|
||||
double bar_beat;
|
||||
if (sfizz_atom_extract_integer(self, bar_atom, &bar)) {
|
||||
self->bar = (int)bar;
|
||||
updates |= SFIZZ_TIMEINFO_POSITION;
|
||||
}
|
||||
if (sfizz_atom_extract_real(self, bar_beat_atom, &bar_beat)) {
|
||||
self->bar_beat = (float)bar_beat;
|
||||
updates |= SFIZZ_TIMEINFO_POSITION;
|
||||
}
|
||||
|
||||
double beats_per_bar;
|
||||
int64_t beat_unit;
|
||||
if (sfizz_atom_extract_real(self, beats_per_bar_atom, &beats_per_bar)) {
|
||||
self->beats_per_bar = (int)beats_per_bar;
|
||||
updates |= SFIZZ_TIMEINFO_SIGNATURE;
|
||||
}
|
||||
if (sfizz_atom_extract_integer(self, beat_unit_atom, &beat_unit)) {
|
||||
self->beat_unit = (int)beat_unit;
|
||||
updates |= SFIZZ_TIMEINFO_SIGNATURE;
|
||||
}
|
||||
|
||||
double tempo;
|
||||
if (sfizz_atom_extract_real(self, beats_per_minute_atom, &tempo)) {
|
||||
self->bpm_tempo = (float)tempo;
|
||||
updates |= SFIZZ_TIMEINFO_TEMPO;
|
||||
}
|
||||
|
||||
double speed;
|
||||
if (sfizz_atom_extract_real(self, speed_atom, &speed)) {
|
||||
self->speed = (float)speed;
|
||||
updates |= SFIZZ_TIMEINFO_SPEED;
|
||||
}
|
||||
|
||||
sfizz_lv2_update_timeinfo(self, delay, updates);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -802,6 +970,12 @@ run(LV2_Handle instance, uint32_t sample_count)
|
|||
sfizz_lv2_check_preload_size(self);
|
||||
sfizz_lv2_check_oversampling(self);
|
||||
sfizz_lv2_check_num_voices(self);
|
||||
*(self->active_voices_port) = sfizz_get_num_active_voices(self->synth);
|
||||
*(self->num_curves_port) = sfizz_get_num_curves(self->synth);
|
||||
*(self->num_masters_port) = sfizz_get_num_masters(self->synth);
|
||||
*(self->num_groups_port) = sfizz_get_num_groups(self->synth);
|
||||
*(self->num_regions_port) = sfizz_get_num_regions(self->synth);
|
||||
*(self->num_samples_port) = sfizz_get_num_preloaded_samples(self->synth);
|
||||
|
||||
// Log the buffer usage
|
||||
self->sample_counter += (int)sample_count;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
||||
@prefix state: <http://lv2plug.in/ns/ext/state#> .
|
||||
@prefix time: <http://lv2plug.in/ns/ext/time#> .
|
||||
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
|
||||
@prefix units: <http://lv2plug.in/ns/extensions/units#> .
|
||||
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
|
||||
@prefix work: <http://lv2plug.in/ns/ext/worker#> .
|
||||
|
|
@ -35,6 +36,12 @@ midnam:update a lv2:Feature .
|
|||
"Accordage"@fr ,
|
||||
"Accordatura"@it .
|
||||
|
||||
<@LV2PLUGIN_URI@#status>
|
||||
a pg:Group ;
|
||||
lv2:symbol "status" ;
|
||||
lv2:name "status",
|
||||
"Statut"@fr .
|
||||
|
||||
<@LV2PLUGIN_URI@:sfzfile>
|
||||
a lv2:Parameter ;
|
||||
rdfs:label "SFZ file",
|
||||
|
|
@ -77,8 +84,10 @@ midnam:update a lv2:Feature .
|
|||
opts:supportedOption param:sampleRate ;
|
||||
opts:supportedOption bufsize:maxBlockLength, bufsize:nominalBlockLength ;
|
||||
|
||||
patch:writable <@LV2PLUGIN_URI@:sfzfile> ;
|
||||
patch:writable <@LV2PLUGIN_URI@:tuningfile> ;
|
||||
@LV2PLUGIN_IF_ENABLE_UI@ui:ui <@LV2PLUGIN_URI@#ui> ;
|
||||
|
||||
patch:writable <@LV2PLUGIN_URI@:sfzfile> ,
|
||||
<@LV2PLUGIN_URI@:tuningfile> ;
|
||||
|
||||
lv2:port [
|
||||
a lv2:InputPort, atom:AtomPort ;
|
||||
|
|
@ -87,7 +96,8 @@ midnam:update a lv2:Feature .
|
|||
lv2:designation lv2:control ;
|
||||
lv2:index 0 ;
|
||||
lv2:symbol "control" ;
|
||||
lv2:name "Control"
|
||||
lv2:name "Control",
|
||||
"Contrôle"@fr ;
|
||||
] , [
|
||||
a lv2:OutputPort, atom:AtomPort ;
|
||||
atom:bufferType atom:Sequence ;
|
||||
|
|
@ -95,7 +105,8 @@ midnam:update a lv2:Feature .
|
|||
lv2:designation lv2:control ;
|
||||
lv2:index 1 ;
|
||||
lv2:symbol "notify" ;
|
||||
lv2:name "Notify" ;
|
||||
lv2:name "Notify",
|
||||
"Notification"@fr ;
|
||||
] , [
|
||||
a lv2:AudioPort, lv2:OutputPort ;
|
||||
lv2:index 2 ;
|
||||
|
|
@ -291,4 +302,70 @@ midnam:update a lv2:Feature .
|
|||
lv2:minimum 0.0 ;
|
||||
lv2:maximum 1.0 ;
|
||||
units:unit units:coef
|
||||
] , [
|
||||
a lv2:OutputPort, lv2:ControlPort ;
|
||||
lv2:index 12 ;
|
||||
lv2:symbol "active_voices" ;
|
||||
lv2:name "Active voices",
|
||||
"Voix utilisées"@fr ;
|
||||
pg:group <@LV2PLUGIN_URI@#status> ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 256 ;
|
||||
] , [
|
||||
a lv2:OutputPort, lv2:ControlPort ;
|
||||
lv2:index 13 ;
|
||||
lv2:symbol "num_curves" ;
|
||||
lv2:name "Number of curves",
|
||||
"Nombre de courbes"@fr ;
|
||||
pg:group <@LV2PLUGIN_URI@#status> ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 65535 ;
|
||||
] , [
|
||||
a lv2:OutputPort, lv2:ControlPort ;
|
||||
lv2:index 14 ;
|
||||
lv2:symbol "num_masters" ;
|
||||
lv2:name "Number of masters",
|
||||
"Nombre de maîtres"@fr ;
|
||||
pg:group <@LV2PLUGIN_URI@#status> ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 65535 ;
|
||||
] , [
|
||||
a lv2:OutputPort, lv2:ControlPort ;
|
||||
lv2:index 15 ;
|
||||
lv2:symbol "num_groups" ;
|
||||
lv2:name "Number of groups",
|
||||
"Nombre de groupes"@fr ;
|
||||
pg:group <@LV2PLUGIN_URI@#status> ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 65535 ;
|
||||
] , [
|
||||
a lv2:OutputPort, lv2:ControlPort ;
|
||||
lv2:index 16 ;
|
||||
lv2:symbol "num_regions" ;
|
||||
lv2:name "Number of regions",
|
||||
"Nombre de régions"@fr ;
|
||||
pg:group <@LV2PLUGIN_URI@#status> ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 65535 ;
|
||||
] , [
|
||||
a lv2:OutputPort, lv2:ControlPort ;
|
||||
lv2:index 17 ;
|
||||
lv2:symbol "num_samples" ;
|
||||
lv2:name "Number of samples",
|
||||
"Nombre d'échantillons"@fr ;
|
||||
pg:group <@LV2PLUGIN_URI@#status> ;
|
||||
lv2:portProperty lv2:integer ;
|
||||
lv2:default 0 ;
|
||||
lv2:minimum 0 ;
|
||||
lv2:maximum 65535 ;
|
||||
] .
|
||||
|
|
|
|||
43
lv2/sfizz_lv2.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// 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
|
||||
|
||||
#define MAX_PATH_SIZE 1024
|
||||
|
||||
#define SFIZZ_URI "http://sfztools.github.io/sfizz"
|
||||
#define SFIZZ_UI_URI "http://sfztools.github.io/sfizz#ui"
|
||||
#define SFIZZ_PREFIX SFIZZ_URI "#"
|
||||
#define SFIZZ__sfzFile SFIZZ_URI ":" "sfzfile"
|
||||
#define SFIZZ__tuningfile SFIZZ_URI ":" "tuningfile"
|
||||
#define SFIZZ__numVoices SFIZZ_URI ":" "numvoices"
|
||||
#define SFIZZ__preloadSize SFIZZ_URI ":" "preload_size"
|
||||
#define SFIZZ__oversampling SFIZZ_URI ":" "oversampling"
|
||||
// These ones are just for the worker
|
||||
#define SFIZZ__logStatus SFIZZ_URI ":" "log_status"
|
||||
#define SFIZZ__checkModification SFIZZ_URI ":" "check_modification"
|
||||
|
||||
enum
|
||||
{
|
||||
SFIZZ_CONTROL = 0,
|
||||
SFIZZ_NOTIFY = 1,
|
||||
SFIZZ_LEFT = 2,
|
||||
SFIZZ_RIGHT = 3,
|
||||
SFIZZ_VOLUME = 4,
|
||||
SFIZZ_POLYPHONY = 5,
|
||||
SFIZZ_OVERSAMPLING = 6,
|
||||
SFIZZ_PRELOAD = 7,
|
||||
SFIZZ_FREEWHEELING = 8,
|
||||
SFIZZ_SCALA_ROOT_KEY = 9,
|
||||
SFIZZ_TUNING_FREQUENCY = 10,
|
||||
SFIZZ_STRETCH_TUNING = 11,
|
||||
SFIZZ_ACTIVE_VOICES = 12,
|
||||
SFIZZ_NUM_CURVES = 13,
|
||||
SFIZZ_NUM_MASTERS = 14,
|
||||
SFIZZ_NUM_GROUPS = 15,
|
||||
SFIZZ_NUM_REGIONS = 16,
|
||||
SFIZZ_NUM_SAMPLES = 17,
|
||||
};
|
||||