diff --git a/.github/workflows/all.yml b/.github/workflows/all.yml index 7aaaf02c..734c7d49 100644 --- a/.github/workflows/all.yml +++ b/.github/workflows/all.yml @@ -44,10 +44,10 @@ jobs: - name: Download libfaust run: | cd thirdparty/libfaust - sh download_libfaust.sh + python download_libfaust.py - name: Build wheels - uses: pypa/cibuildwheel@v2.16.2 + uses: pypa/cibuildwheel@v2.20.0 env: CIBW_PLATFORM: linux CIBW_BUILD: ${{ matrix.cibwbuild }} @@ -64,7 +64,7 @@ jobs: CIBW_ARCHS_LINUX: auto64 aarch64 # On an Linux Intel runner with qemu installed, build Intel and ARM wheels CIBW_TEST_SKIP: "*38* *39* *311* *312*" # Only care about 310 (current Google Colab version) - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: my-wheel-artifact path: ./wheelhouse/*.whl @@ -97,12 +97,12 @@ jobs: submodules: true - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.1 + uses: microsoft/setup-msbuild@v2 - name: Get CMake uses: lukka/get-cmake@latest @@ -115,7 +115,7 @@ jobs: shell: cmd run: | cd thirdparty/libfaust - call download_libfaust.bat + python download_libfaust.py - name: Build libsamplerate run: | @@ -143,7 +143,7 @@ jobs: CIBW_BUILD: ${{matrix.CIBW-BUILD}} CIBW_TEST_SKIP: "*312*" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: my-wheel-artifact path: ./wheelhouse/*.whl @@ -155,7 +155,7 @@ jobs: pip install -U sphinx cd docs && make.bat html - name: Deploy docs - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 # todo: make condition for being on main branch if: ${{ matrix.python-version == '3.9' && github.event_name == 'release' && github.event.action == 'published' }} with: @@ -199,10 +199,10 @@ jobs: - name: Download libfaust run: | cd thirdparty/libfaust - sh download_libfaust.sh + python download_libfaust.py - name: Build wheels ${{ matrix.python-version }} - uses: pypa/cibuildwheel@v2.16.2 + uses: pypa/cibuildwheel@v2.20.0 env: # note that the Projucer project refers to PYTHONMAJOR and pythonLocation, so they must be set here PYTHONMAJOR: ${{ matrix.python-version }} @@ -222,7 +222,7 @@ jobs: CIBW_ENVIRONMENT_MACOS: ARCHS="${{matrix.ARCHS}}" CIBW_TEST_SKIP: "*arm64* *312*" - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: my-wheel-artifact path: ./wheelhouse/*.whl @@ -233,7 +233,7 @@ jobs: name: "Upload wheels to PyPI" if: github.event_name == 'release' && github.event.action == 'published' steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: name: my-wheel-artifact path: dist diff --git a/Builds/LinuxMakefile/Makefile b/Builds/LinuxMakefile/Makefile index eed07add..00dd8b11 100644 --- a/Builds/LinuxMakefile/Makefile +++ b/Builds/LinuxMakefile/Makefile @@ -39,7 +39,7 @@ ifeq ($(CONFIG),Debug) TARGET_ARCH := endif - JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DJUCE_MODAL_LOOPS_PERMITTED" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.8.0" "-DJUCE_APP_VERSION_HEX=0x800" $(shell $(PKG_CONFIG) --cflags alsa freetype2 gl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I../../thirdparty -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/boxes -I../../thirdparty/faust/compiler/documentator -I../../thirdparty/faust/compiler/draw -I../../thirdparty/faust/compiler/draw/device -I../../thirdparty/faust/compiler/draw/schema -I../../thirdparty/faust/compiler/errors -I../../thirdparty/faust/compiler/evaluate -I../../thirdparty/faust/compiler/extended -I../../thirdparty/faust/compiler/generator -I../../thirdparty/faust/compiler/generator/interpreter -I../../thirdparty/faust/compiler/normalize -I../../thirdparty/faust/compiler/parallelize -I../../thirdparty/faust/compiler/parser -I../../thirdparty/faust/compiler/patternmatcher -I../../thirdparty/faust/compiler/propagate -I../../thirdparty/faust/compiler/signals -I../../thirdparty/faust/compiler/tlib -I../../thirdparty/faust/compiler/transform -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include $(CPPFLAGS) + JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DJUCE_MODAL_LOOPS_PERMITTED" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.8.1" "-DJUCE_APP_VERSION_HEX=0x801" $(shell $(PKG_CONFIG) --cflags alsa freetype2 gl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I../../thirdparty -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/boxes -I../../thirdparty/faust/compiler/documentator -I../../thirdparty/faust/compiler/draw -I../../thirdparty/faust/compiler/draw/device -I../../thirdparty/faust/compiler/draw/schema -I../../thirdparty/faust/compiler/errors -I../../thirdparty/faust/compiler/evaluate -I../../thirdparty/faust/compiler/extended -I../../thirdparty/faust/compiler/generator -I../../thirdparty/faust/compiler/generator/interpreter -I../../thirdparty/faust/compiler/normalize -I../../thirdparty/faust/compiler/parallelize -I../../thirdparty/faust/compiler/parser -I../../thirdparty/faust/compiler/patternmatcher -I../../thirdparty/faust/compiler/propagate -I../../thirdparty/faust/compiler/signals -I../../thirdparty/faust/compiler/tlib -I../../thirdparty/faust/compiler/transform -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include $(CPPFLAGS) JUCE_CPPFLAGS_DYNAMIC_LIBRARY := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0" JUCE_CFLAGS_DYNAMIC_LIBRARY := -fPIC -fvisibility=hidden JUCE_LDFLAGS_DYNAMIC_LIBRARY := -shared @@ -62,7 +62,7 @@ ifeq ($(CONFIG),Release) TARGET_ARCH := endif - JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DJUCE_MODAL_LOOPS_PERMITTED" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.8.0" "-DJUCE_APP_VERSION_HEX=0x800" $(shell $(PKG_CONFIG) --cflags alsa freetype2 gl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I../../thirdparty -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/boxes -I../../thirdparty/faust/compiler/documentator -I../../thirdparty/faust/compiler/draw -I../../thirdparty/faust/compiler/draw/device -I../../thirdparty/faust/compiler/draw/schema -I../../thirdparty/faust/compiler/errors -I../../thirdparty/faust/compiler/evaluate -I../../thirdparty/faust/compiler/extended -I../../thirdparty/faust/compiler/generator -I../../thirdparty/faust/compiler/generator/interpreter -I../../thirdparty/faust/compiler/normalize -I../../thirdparty/faust/compiler/parallelize -I../../thirdparty/faust/compiler/parser -I../../thirdparty/faust/compiler/patternmatcher -I../../thirdparty/faust/compiler/propagate -I../../thirdparty/faust/compiler/signals -I../../thirdparty/faust/compiler/tlib -I../../thirdparty/faust/compiler/transform -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include $(CPPFLAGS) + JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DPIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==" "-DSAMPLER_SKIP_UI" "-DJUCE_MODAL_LOOPS_PERMITTED" "-DHAVE_LIBSAMPLERATE" "-DUSE_BUILTIN_FFT" "-DUSE_PTHREADS" "-DBUILD_DAWDREAMER_FAUST" "-DBUILD_DAWDREAMER_RUBBERBAND" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=0.8.1" "-DJUCE_APP_VERSION_HEX=0x801" $(shell $(PKG_CONFIG) --cflags alsa freetype2 gl) -pthread -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/LV2_SDK -I../../JuceLibraryCode/modules/juce_audio_processors/format_types/VST3_SDK -I../../thirdparty/JUCE/modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../JuceLibraryCode/modules -I../../thirdparty -I../../thirdparty/pybind11/include -I../../thirdparty/faust/architecture -I../../thirdparty/faust/compiler -I../../thirdparty/faust/compiler/boxes -I../../thirdparty/faust/compiler/documentator -I../../thirdparty/faust/compiler/draw -I../../thirdparty/faust/compiler/draw/device -I../../thirdparty/faust/compiler/draw/schema -I../../thirdparty/faust/compiler/errors -I../../thirdparty/faust/compiler/evaluate -I../../thirdparty/faust/compiler/extended -I../../thirdparty/faust/compiler/generator -I../../thirdparty/faust/compiler/generator/interpreter -I../../thirdparty/faust/compiler/normalize -I../../thirdparty/faust/compiler/parallelize -I../../thirdparty/faust/compiler/parser -I../../thirdparty/faust/compiler/patternmatcher -I../../thirdparty/faust/compiler/propagate -I../../thirdparty/faust/compiler/signals -I../../thirdparty/faust/compiler/tlib -I../../thirdparty/faust/compiler/transform -I../../thirdparty/faust/compiler/utils -I../../thirdparty/libsamplerate/src -I../../thirdparty/libsamplerate/include $(CPPFLAGS) JUCE_CPPFLAGS_DYNAMIC_LIBRARY := "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0" JUCE_CFLAGS_DYNAMIC_LIBRARY := -fPIC -fvisibility=hidden JUCE_LDFLAGS_DYNAMIC_LIBRARY := -shared diff --git a/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj b/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj index e23a46e5..a9b642bc 100644 --- a/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/DawDreamer.xcodeproj/project.pbxproj @@ -636,8 +636,8 @@ "BUILD_DAWDREAMER_FAUST", "BUILD_DAWDREAMER_RUBBERBAND", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.8.0", - "JUCE_APP_VERSION_HEX=0x800", + "JUCE_APP_VERSION=0.8.1", + "JUCE_APP_VERSION_HEX=0x801", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -732,8 +732,8 @@ "BUILD_DAWDREAMER_FAUST", "BUILD_DAWDREAMER_RUBBERBAND", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.8.0", - "JUCE_APP_VERSION_HEX=0x800", + "JUCE_APP_VERSION=0.8.1", + "JUCE_APP_VERSION_HEX=0x801", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", @@ -829,8 +829,8 @@ "BUILD_DAWDREAMER_FAUST", "BUILD_DAWDREAMER_RUBBERBAND", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.8.0", - "JUCE_APP_VERSION_HEX=0x800", + "JUCE_APP_VERSION=0.8.1", + "JUCE_APP_VERSION_HEX=0x801", "JucePlugin_Build_VST=0", "JucePlugin_Build_VST3=0", "JucePlugin_Build_AU=0", diff --git a/Builds/VisualStudio2022/DawDreamer_DynamicLibrary.vcxproj b/Builds/VisualStudio2022/DawDreamer_DynamicLibrary.vcxproj index 171b8015..b30beb78 100644 --- a/Builds/VisualStudio2022/DawDreamer_DynamicLibrary.vcxproj +++ b/Builds/VisualStudio2022/DawDreamer_DynamicLibrary.vcxproj @@ -66,7 +66,7 @@ Disabled ProgramDatabase ..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\VST3_SDK;..\..\thirdparty\JUCE\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;$(pythonLocation)/include;../../thirdparty;../../thirdparty/pybind11/include;../../thirdparty/faust/architecture;../../thirdparty/faust/compiler;../../thirdparty/faust/compiler/boxes;../../thirdparty/faust/compiler/documentator;../../thirdparty/faust/compiler/draw;../../thirdparty/faust/compiler/draw/device;../../thirdparty/faust/compiler/draw/schema;../../thirdparty/faust/compiler/errors;../../thirdparty/faust/compiler/evaluate;../../thirdparty/faust/compiler/extended;../../thirdparty/faust/compiler/generator;../../thirdparty/faust/compiler/generator/interpreter;../../thirdparty/faust/compiler/normalize;../../thirdparty/faust/compiler/parallelize;../../thirdparty/faust/compiler/parser;../../thirdparty/faust/compiler/patternmatcher;../../thirdparty/faust/compiler/propagate;../../thirdparty/faust/compiler/signals;../../thirdparty/faust/compiler/tlib;../../thirdparty/faust/compiler/transform;../../thirdparty/faust/compiler/utils;../../thirdparty/libsamplerate/src;../../thirdparty/libsamplerate/include;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.0;JUCE_APP_VERSION_HEX=0x800;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.1;JUCE_APP_VERSION_HEX=0x801;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) MultiThreadedDebugDLL true NotUsing @@ -80,7 +80,7 @@ ..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\VST3_SDK;..\..\thirdparty\JUCE\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;$(pythonLocation)/include;../../thirdparty;../../thirdparty/pybind11/include;../../thirdparty/faust/architecture;../../thirdparty/faust/compiler;../../thirdparty/faust/compiler/boxes;../../thirdparty/faust/compiler/documentator;../../thirdparty/faust/compiler/draw;../../thirdparty/faust/compiler/draw/device;../../thirdparty/faust/compiler/draw/schema;../../thirdparty/faust/compiler/errors;../../thirdparty/faust/compiler/evaluate;../../thirdparty/faust/compiler/extended;../../thirdparty/faust/compiler/generator;../../thirdparty/faust/compiler/generator/interpreter;../../thirdparty/faust/compiler/normalize;../../thirdparty/faust/compiler/parallelize;../../thirdparty/faust/compiler/parser;../../thirdparty/faust/compiler/patternmatcher;../../thirdparty/faust/compiler/propagate;../../thirdparty/faust/compiler/signals;../../thirdparty/faust/compiler/tlib;../../thirdparty/faust/compiler/transform;../../thirdparty/faust/compiler/utils;../../thirdparty/libsamplerate/src;../../thirdparty/libsamplerate/include;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.0;JUCE_APP_VERSION_HEX=0x800;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.1;JUCE_APP_VERSION_HEX=0x801;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) $(OutDir)\dawdreamer.dll @@ -114,7 +114,7 @@ Full ..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\VST3_SDK;..\..\thirdparty\JUCE\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;$(pythonLocation)/include;../../thirdparty;../../thirdparty/pybind11/include;../../thirdparty/faust/architecture;../../thirdparty/faust/compiler;../../thirdparty/faust/compiler/boxes;../../thirdparty/faust/compiler/documentator;../../thirdparty/faust/compiler/draw;../../thirdparty/faust/compiler/draw/device;../../thirdparty/faust/compiler/draw/schema;../../thirdparty/faust/compiler/errors;../../thirdparty/faust/compiler/evaluate;../../thirdparty/faust/compiler/extended;../../thirdparty/faust/compiler/generator;../../thirdparty/faust/compiler/generator/interpreter;../../thirdparty/faust/compiler/normalize;../../thirdparty/faust/compiler/parallelize;../../thirdparty/faust/compiler/parser;../../thirdparty/faust/compiler/patternmatcher;../../thirdparty/faust/compiler/propagate;../../thirdparty/faust/compiler/signals;../../thirdparty/faust/compiler/tlib;../../thirdparty/faust/compiler/transform;../../thirdparty/faust/compiler/utils;../../thirdparty/libsamplerate/src;../../thirdparty/libsamplerate/include;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.0;JUCE_APP_VERSION_HEX=0x800;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.1;JUCE_APP_VERSION_HEX=0x801;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) MultiThreadedDLL true NotUsing @@ -128,7 +128,7 @@ ..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\LV2_SDK;..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\VST3_SDK;..\..\thirdparty\JUCE\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;$(pythonLocation)/include;../../thirdparty;../../thirdparty/pybind11/include;../../thirdparty/faust/architecture;../../thirdparty/faust/compiler;../../thirdparty/faust/compiler/boxes;../../thirdparty/faust/compiler/documentator;../../thirdparty/faust/compiler/draw;../../thirdparty/faust/compiler/draw/device;../../thirdparty/faust/compiler/draw/schema;../../thirdparty/faust/compiler/errors;../../thirdparty/faust/compiler/evaluate;../../thirdparty/faust/compiler/extended;../../thirdparty/faust/compiler/generator;../../thirdparty/faust/compiler/generator/interpreter;../../thirdparty/faust/compiler/normalize;../../thirdparty/faust/compiler/parallelize;../../thirdparty/faust/compiler/parser;../../thirdparty/faust/compiler/patternmatcher;../../thirdparty/faust/compiler/propagate;../../thirdparty/faust/compiler/signals;../../thirdparty/faust/compiler/tlib;../../thirdparty/faust/compiler/transform;../../thirdparty/faust/compiler/utils;../../thirdparty/libsamplerate/src;../../thirdparty/libsamplerate/include;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.0;JUCE_APP_VERSION_HEX=0x800;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;PIP_JUCE_EXAMPLES_DIRECTORY=QzpcdG9vbHNcSlVDRVxleGFtcGxlcw==;BUILD_DAWDREAMER_FAUST;BUILD_DAWDREAMER_RUBBERBAND;SAMPLER_SKIP_UI;JUCE_MODAL_LOOPS_PERMITTED;_WIN32;__SSE__;__SSE2__;NOMINMAX;HAVE_LIBSAMPLERATE;USE_BUILTIN_FFT;NO_THREADING;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=0.8.1;JUCE_APP_VERSION_HEX=0x801;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions) $(OutDir)\dawdreamer.dll diff --git a/Builds/VisualStudio2022/resources.rc b/Builds/VisualStudio2022/resources.rc index 7f83b37b..483f2773 100644 --- a/Builds/VisualStudio2022/resources.rc +++ b/Builds/VisualStudio2022/resources.rc @@ -9,16 +9,16 @@ #include VS_VERSION_INFO VERSIONINFO -FILEVERSION 0,8,0,0 +FILEVERSION 0,8,1,0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileDescription", "DawDreamer\0" - VALUE "FileVersion", "0.8.0\0" + VALUE "FileVersion", "0.8.1\0" VALUE "ProductName", "DawDreamer\0" - VALUE "ProductVersion", "0.8.0\0" + VALUE "ProductVersion", "0.8.1\0" END END diff --git a/DawDreamer.jucer b/DawDreamer.jucer index dbf97b63..8653f46a 100644 --- a/DawDreamer.jucer +++ b/DawDreamer.jucer @@ -1,6 +1,6 @@ - #include +#include #include #include #include // this lets std::vector be a default arg diff --git a/Source/FaustProcessor.cpp b/Source/FaustProcessor.cpp index 288c06f3..44a85686 100644 --- a/Source/FaustProcessor.cpp +++ b/Source/FaustProcessor.cpp @@ -105,7 +105,7 @@ void FaustProcessor::processBlock(juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiBuffer) { // todo: Faust should be able to use the incoming midiBuffer too. auto posInfo = getPlayHead()->getPosition(); - + const bool isPlaying = posInfo->getIsPlaying(); if (!isPlaying) { ProcessorBase::processBlock(buffer, midiBuffer); @@ -419,8 +419,6 @@ bool FaustProcessor::compile() { // clean up clear(); - // optimization level - const int optimize = -1; // arguments auto pathToFaustLibraries = getPathToFaustLibraries(); @@ -437,9 +435,13 @@ bool FaustProcessor::compile() { argv[argc++] = "-I"; argv[argc++] = pathToFaustLibraries.c_str(); - if (!m_faustLibrariesPath.empty()) { + for (const auto& p : m_faustLibrariesPaths) { argv[argc++] = "-I"; - argv[argc++] = m_faustLibrariesPath.c_str(); + argv[argc++] = p.c_str(); + } + + for (const auto& flag : m_compileFlags) { + argv[argc++] = flag.c_str(); } auto theCode = m_autoImport + "\n" + m_code; @@ -451,11 +453,13 @@ bool FaustProcessor::compile() { // create new factory bool is_polyphonic = m_nvoices > 0; if (is_polyphonic) { - m_poly_factory = createPolyDSPFactoryFromString( - "dawdreamer", theCode, argc, argv, target, m_errorString, optimize); + m_poly_factory = + createPolyDSPFactoryFromString("dawdreamer", theCode, argc, argv, + target, m_errorString, m_llvmOptLevel); } else { - m_factory = createDSPFactoryFromString("dawdreamer", theCode, argc, argv, - target, m_errorString, optimize); + m_factory = + createDSPFactoryFromString("dawdreamer", theCode, argc, argv, target, + m_errorString, m_llvmOptLevel); } for (int i = 0; i < argc; i++) { @@ -530,7 +534,7 @@ bool FaustProcessor::compile() { const int sr = (int)(mySampleRate + .5); - m_soundUI = new MySoundUI(&m_SoundfileMap, m_faustAssetsPath, sr); + m_soundUI = new MySoundUI(&m_SoundfileMap, m_faustAssetsPaths, sr); theDsp->buildUserInterface(m_soundUI); // init @@ -547,18 +551,22 @@ bool FaustProcessor::compileSignals( std::vector& wrappers, std::optional> in_argv) { clear(); - + auto pathToFaustLibraries = getPathToFaustLibraries(); int argc = 0; - const char* argv[64]; - + const char* argv[512]; + argv[argc++] = "-I"; argv[argc++] = pathToFaustLibraries.c_str(); - if (!m_faustLibrariesPath.empty()) { + for (const auto& p : m_faustLibrariesPaths) { argv[argc++] = "-I"; - argv[argc++] = m_faustLibrariesPath.c_str(); + argv[argc++] = p.c_str(); + } + + for (const auto& flag : m_compileFlags) { + argv[argc++] = flag.c_str(); } if (in_argv.has_value()) { @@ -576,7 +584,7 @@ bool FaustProcessor::compileSignals( std::string error_msg; m_factory = createDSPFactoryFromSignals("dawdreamer", signals, argc, argv, - target, error_msg); + target, error_msg, m_llvmOptLevel); if (!m_factory) { clear(); @@ -622,7 +630,7 @@ bool FaustProcessor::compileSignals( const int sr = (int)(mySampleRate + .5); - m_soundUI = new MySoundUI(&m_SoundfileMap, m_faustAssetsPath, sr); + m_soundUI = new MySoundUI(&m_SoundfileMap, m_faustAssetsPaths, sr); theDsp->buildUserInterface(m_soundUI); // init @@ -640,16 +648,20 @@ bool FaustProcessor::compileBox( clear(); auto pathToFaustLibraries = getPathToFaustLibraries(); - + int argc = 0; const char* argv[512]; - + argv[argc++] = "-I"; argv[argc++] = pathToFaustLibraries.c_str(); - if (!m_faustLibrariesPath.empty()) { + for (const auto& p : m_faustLibrariesPaths) { argv[argc++] = "-I"; - argv[argc++] = m_faustLibrariesPath.c_str(); + argv[argc++] = p.c_str(); + } + + for (const auto& flag : m_compileFlags) { + argv[argc++] = flag.c_str(); } if (in_argv.has_value()) { @@ -662,7 +674,7 @@ bool FaustProcessor::compileBox( std::string error_msg; m_factory = createDSPFactoryFromBoxes("dawdreamer", box, argc, argv, target, - error_msg); + error_msg, m_llvmOptLevel); if (!m_factory) { clear(); @@ -691,7 +703,7 @@ bool FaustProcessor::compileBox( m_numOutputChannels = outputs; setMainBusInputsAndOutputs(inputs, outputs); - + // make new UI if (is_polyphonic) { m_midi_handler = rt_midi("my_midi"); @@ -706,7 +718,7 @@ bool FaustProcessor::compileBox( const int sr = (int)(mySampleRate + .5); - m_soundUI = new MySoundUI(&m_SoundfileMap, m_faustAssetsPath, sr); + m_soundUI = new MySoundUI(&m_SoundfileMap, m_faustAssetsPaths, sr); theDsp->buildUserInterface(m_soundUI); // init diff --git a/Source/FaustProcessor.h b/Source/FaustProcessor.h index a122a64b..c8679196 100644 --- a/Source/FaustProcessor.h +++ b/Source/FaustProcessor.h @@ -32,9 +32,9 @@ class MySoundUI : public SoundUI { public: MySoundUI( std::map> *soundfileMap, - const std::string &sound_directory = "", int sample_rate = -1, + const std::vector &sound_directories, int sample_rate = -1, SoundfileReader *reader = nullptr, bool is_double = false) - : SoundUI(sound_directory, sample_rate, reader, is_double) { + : SoundUI(sound_directories, sample_rate, reader, is_double) { jassert(soundfileMap); m_SoundfileMap = soundfileMap; m_sampleRate = sample_rate; @@ -226,16 +226,59 @@ class FaustProcessor : public ProcessorBase { void setReleaseLength(double sec); void setFaustLibrariesPath(std::string faustLibrariesPath) { - m_faustLibrariesPath = faustLibrariesPath; + m_faustLibrariesPaths.clear(); + m_faustLibrariesPaths.push_back(faustLibrariesPath); } - std::string getFaustLibrariesPath() { return m_faustLibrariesPath; } + void setFaustLibrariesPaths(std::vector faustLibrariesPaths) { + m_faustLibrariesPaths.clear(); + m_faustLibrariesPaths = faustLibrariesPaths; + } + + std::string getFaustLibrariesPath() { + if (!m_faustLibrariesPaths.empty()) { + return m_faustLibrariesPaths.at(0); + } + return ""; + } + + std::vector getFaustLibrariesPaths() { + return m_faustLibrariesPaths; + } void setFaustAssetsPath(std::string faustAssetsPath) { - m_faustAssetsPath = faustAssetsPath; + m_faustAssetsPaths.clear(); + m_faustAssetsPaths.push_back(faustAssetsPath); + } + + void setFaustAssetsPaths(std::vector faustAssetsPath) { + m_faustAssetsPaths.clear(); + m_faustAssetsPaths = faustAssetsPath; + } + + std::string getFaustAssetsPath() { + if (!m_faustAssetsPaths.empty()) { + return m_faustAssetsPaths.at(0); + } + return ""; } - std::string getFaustAssetsPath() { return m_faustAssetsPath; } + std::vector getFaustAssetsPaths() { return m_faustAssetsPaths; } + + void setCompileFlags(std::vector compileFlags) { + m_compileFlags = compileFlags; + } + + std::vector getCompileFlags() { return m_compileFlags; } + + void setLLVMOpt(int optLevel) { + if (m_llvmOptLevel != optLevel) { + m_compileState = kNotCompiled; + } + m_llvmOptLevel = optLevel; + } + + int getLLVMOpt() { return m_llvmOptLevel; } std::map> m_SoundfileMap; @@ -267,12 +310,14 @@ class FaustProcessor : public ProcessorBase { std::string m_autoImport; std::string m_code; - std::string m_faustLibrariesPath = ""; - std::string m_faustAssetsPath = ""; + std::vector m_faustLibrariesPaths; + std::vector m_faustAssetsPaths; + std::vector m_compileFlags; int m_nvoices = 0; bool m_dynamicVoices = true; bool m_groupVoices = true; + int m_llvmOptLevel = -1; MidiBuffer myMidiBufferQN; MidiBuffer myMidiBufferSec; @@ -387,10 +432,28 @@ inline void create_bindings_for_faust_processor(py::module &m) { &FaustProcessor::setFaustLibrariesPath, "Absolute path to directory containing your custom " "\".lib\" files containing Faust code.") + .def_property( + "faust_libraries_paths", &FaustProcessor::getFaustLibrariesPaths, + &FaustProcessor::setFaustLibrariesPaths, + "List of absolute paths to directories containing your custom " + "\".lib\" files containing Faust code.") .def_property("faust_assets_path", &FaustProcessor::getFaustAssetsPath, &FaustProcessor::setFaustAssetsPath, "Absolute path to directory containing audio files to be " "used by Faust.") + .def_property( + "faust_assets_paths", &FaustProcessor::getFaustAssetsPaths, + &FaustProcessor::setFaustAssetsPaths, + "List of absolute paths to directories containing audio files to be " + "used by Faust.") + .def_property("compile_flags", &FaustProcessor::getCompileFlags, + &FaustProcessor::setCompileFlags, + "List of compilation flags.") + .def_property( + "opt_level", &FaustProcessor::getLLVMOpt, &FaustProcessor::setLLVMOpt, + "LLVM IR to IR optimization level (from -1 to 4, -1 means 'maximum " + "possible value' * since the maximum value may change with new LLVM " + "versions)") .def_property_readonly("n_midi_events", &FaustProcessor::getNumMidiEvents, "The number of MIDI events stored in the buffer. \ Note that note-ons and note-offs are counted separately.") diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 13cdc114..5fd08511 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -1,6 +1,7 @@ #include "PluginProcessor.h" #include +#include #include "StandalonePluginWindow.h" @@ -178,9 +179,9 @@ void PluginProcessor::processBlock(juce::AudioSampleBuffer& buffer, auto posInfo = getPlayHead()->getPosition(); myRenderMidiBuffer.clear(); - + const bool isPlaying = posInfo->getIsPlaying(); - + if (!isPlaying) { // send All Notes Off MIDI message to all channels and then process it. // todo: is it possible to send all notes midi off without doing a @@ -668,6 +669,186 @@ int PluginProcessorWrapper::wrapperGetPluginParameterSize() { return int(PluginProcessor::getPluginParameterSize()); } +// Function to convert various strings to floats +/* +"42.3" -> 42.3f +"75%" -> 0.75f +"75" -> 75f +"-4" -> -4f +"78% (-20.1 dB)" -> -20.1f +"-20.1 dB" -> -20.1f +"35% (30.1 kHz)" -> 30100f +"30.1 kHz" -> 30100f +"35% (30.1 khz)" -> 30100f +"1% (500 Hz)" -> 500f +"500 Hz" -> 500f +"0% (-oo dB)" -> -std::numeric_limits::infinity() +"100% (oo)" -> std::numeric_limits::infinity() +"35% (30.1 khz)" -> 30100f +"10% (-18 db)" -> -18f +"-4 Oct" -> -4f +"500 ms" -> 0.5f +"500 MS" -> 0.5f +"500 millisec" -> 0.5f +"500 milliseconds" -> 0.5f +"5 sec" -> 5 +*/ +float stringToFloat(const std::string& input) { + // Regex to match numbers in parentheses or the whole string + std::regex parenthesesRegex(R"(\(([^)]+)\))"); + std::smatch match; + + // Check for a number inside parentheses first + std::string extractedInput = input; + if (std::regex_search(input, match, parenthesesRegex)) { + extractedInput = match[1]; // Use the value inside parentheses + } + + // Handle percentage (before checking for other numbers) + std::regex percentRegex(R"((\d+)%$)"); + if (std::regex_search(input, match, percentRegex)) { + return std::stof(match[1]) / 100.0f; + } + + // Regex for different number formats, including infinity (oo) + std::regex numberRegex(R"(-?\d+(\.\d+)?(e[+-]?\d+)?|([+-]?\b(?:oo)\b))"); + if (std::regex_search(extractedInput, match, numberRegex)) { + std::string numberStr = match[0]; + + // Handle special cases of infinity + if (numberStr == "oo") { + return std::numeric_limits::infinity(); + } else if (numberStr == "-oo") { + return -std::numeric_limits::infinity(); + } + + // Convert the extracted number to float + try { + float result = std::stof(numberStr); + + // Check for frequency unit kHz or Hz, case insensitive + std::regex khzRegex( + R"((\d+(\.\d+)?)\s*[kK][hH][zZ])"); // Matches kHz or khz + std::regex hzRegex(R"((\d+(\.\d+)?)\s*[hH][zZ])"); // Matches Hz or hz + + if (std::regex_search(extractedInput, match, khzRegex)) { + return result * 1000.0f; // Convert kHz to Hz + } else if (std::regex_search(extractedInput, match, hzRegex)) { + return result; // Return Hz as is + } + + std::regex msRegex(R"((\d+(\.\d+)?)\s*(?:[mM][sS]|millisec.*))"); // Matches ms or MS + + // Check for unit ms or MS + if (std::regex_search(extractedInput, match, msRegex)) { + return result / 1000.0f; // Convert ms to seconds + } else { + return result; // Return the extracted number directly + } + } catch (...) { + // If something goes wrong in conversion, return 0 as a fallback + return 0.0f; + } + } + + // As a fallback, treat the input as a plain number + try { + return std::stof(extractedInput); + } catch (...) { + return 0.0f; // If no valid conversion was found, return 0 + } +} + +std::string getTextForRawValue(AudioProcessorParameter* parameter, + float rawValue) { + /* + Some plugins don't respond properly to parameter->getText but do respond when + a parameter's raw value is changed. This helper method works around this + issue. + */ + float originalValue = parameter->getValue(); + parameter->setValue(rawValue); + std::string text = parameter->getCurrentValueAsText().toStdString(); + parameter->setValue(originalValue); + + return text; +} + +// Function to attempt float extraction, fall back to string if exception occurs +ValueType extract_value(const std::string& s) { + try { + // Attempt to convert the string to a float + return std::stof(s); + } catch (const std::invalid_argument&) { + // If conversion fails, return the original string + return s; + } +} + +std::map, ValueType> getParameterRange( + AudioProcessorParameter* parameter, int searchSteps, bool convert) { + // Adapted from pedalboard (GPL-3.0) + // https://github.com/spotify/pedalboard/blob/ee16bb8805859fcd7e2fb7b00c8946666194774b/pedalboard/_pedalboard.py#L290-L318 + std::map, ValueType> ranges; + std::string text; + bool resultsLookIncorrect = false; + + float startOfRange = 0; + text.clear(); + ranges.clear(); + + for (int x = 0; x <= searchSteps; ++x) { + float rawValue = static_cast(x) / searchSteps; + std::string tmpTextValue = getTextForRawValue(parameter, rawValue); + + if (text.empty()) { + text = tmpTextValue; + } else if (tmpTextValue != text) { + // End current range and start a new one + ranges[{startOfRange, rawValue}] = text; + text = tmpTextValue; + startOfRange = rawValue; + } + } + + if (text.empty()) { + const std::string parameterName = + parameter->getName(DAW_PARAMETER_MAX_NAME_LENGTH).toStdString(); + throw std::runtime_error( + "Plugin parameter '" + parameterName + + "' failed to return a valid string for its value."); + } + + ranges[{ranges.rbegin()->first.second, 1.0f}] = text; // Final range + + if (!convert) { + return ranges; + } + + std::map, ValueType> rangeFloat; + for (auto& kv : ranges) { + try { + rangeFloat[kv.first] = stringToFloat(std::get(kv.second)); + } catch (const std::invalid_argument& e) { + return ranges; + } + } + + return rangeFloat; +} + +std::map, ValueType> +PluginProcessor::getParameterValueRange(const int parameterIndex, + int search_steps, bool convert) { + if (parameterIndex < 0 || parameterIndex >= getParameters().size()) { + throw std::runtime_error("Parameter not found for index: " + + std::to_string(parameterIndex)); + } + + auto pluginParameter = myPlugin->getParameters().getUnchecked(parameterIndex); + return getParameterRange(pluginParameter, search_steps, convert); +} + py::list PluginProcessorWrapper::getPluginParametersDescription() { THROW_ERROR_IF_NO_PLUGIN @@ -732,6 +913,8 @@ py::list PluginProcessorWrapper::getPluginParametersDescription() { myDictionary["category"] = category; myDictionary["text"] = currentText; + myDictionary["currentValText"] = + processorParams[i]->getCurrentValueAsText().toStdString(); myDictionary["isMetaParameter"] = processorParams[i]->isMetaParameter(); myDictionary["isAutomatable"] = processorParams[i]->isAutomatable(); myDictionary["defaultValue"] = processorParams[i]->getDefaultValue(); diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 4e4bbd87..96f00e68 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -5,6 +5,9 @@ typedef std::vector> PluginPatch; +// Alias for variant that can hold either float or string +using ValueType = std::variant; + class PluginProcessor : public ProcessorBase { public: PluginProcessor(std::string newUniqueName, double sampleRate, @@ -47,6 +50,8 @@ class PluginProcessor : public ProcessorBase { std::string getParameterAsText(const int parameter); const PluginPatch getPatch(); const size_t getPluginParameterSize(); + std::map, ValueType> getParameterValueRange( + const int parameterIndex, int search_steps, bool convert); const juce::String getName() const override { return "PluginProcessor"; } diff --git a/Source/source.cpp b/Source/source.cpp index 62defbee..ba910375 100644 --- a/Source/source.cpp +++ b/Source/source.cpp @@ -50,9 +50,6 @@ PYBIND11_MODULE(dawdreamer, m) { Returns ------- None - - """ - ---------- )pbdoc") .def("get_automation", &ProcessorBase::getAutomationNumpy, arg("parameter_name"), R"pbdoc( @@ -67,10 +64,6 @@ PYBIND11_MODULE(dawdreamer, m) { ------- np.array The parameter's automation. - - """ - ---------- - )pbdoc") .def("get_automation", &ProcessorBase::getAutomationAll, "After rendering, get all of a parameter's automation as a dict of " @@ -382,6 +375,29 @@ but the filter mode cannot under automation."; .def("get_parameters_description", &PluginProcessorWrapper::getPluginParametersDescription, "Get a list of dictionaries describing the plugin's parameters.") + .def("get_parameter_range", + &PluginProcessorWrapper::getParameterValueRange, arg("index"), + arg("search_steps") = 1000, arg("convert") = true, + R"pbdoc( + Return a dictionary with information about the parameter's range. The dictionary's keys are tuples of the form `(domain1, domain2)` + where `0<=domain1()) .def("__enter__", &DawDreamerFaustLibContext::enter) .def("__exit__", &DawDreamerFaustLibContext::exit); - + auto box_module = faust.def_submodule("box"); create_bindings_for_faust_box(faust, box_module); create_bindings_for_faust_signal(faust, box_module); diff --git a/dawdreamer/faustlibraries b/dawdreamer/faustlibraries index a456a776..3e74c39a 160000 --- a/dawdreamer/faustlibraries +++ b/dawdreamer/faustlibraries @@ -1 +1 @@ -Subproject commit a456a7765470968fb83de1686390eb434783f725 +Subproject commit 3e74c39a9fc7c00c1b4caceff2731af643706181 diff --git a/tests/faust_dsp/polyphonic_sampler.dsp b/tests/faust_dsp/polyphonic_sampler.dsp index 4d863457..283e8e9b 100644 --- a/tests/faust_dsp/polyphonic_sampler.dsp +++ b/tests/faust_dsp/polyphonic_sampler.dsp @@ -4,64 +4,59 @@ declare options "[nvoices:8]"; // FaustProcessor has a property which will overr import("stdfaust.lib"); // This example demonstrates a "sampler" in Faust, and it happens to use -// Lagrange interpolation. The interpolation probably only matters +// Lagrange interpolation. The interpolation mostly matters // when the sampler is played at a MIDI note other than the "center_note". // The following variable is excluded from this file because they come // from substitution with Python. // LAGRANGE_ORDER = 4; // lagrange order. [2-4] are good choices. -// variation of hs_phasor that doesn't loop. It's like a one-shot trigger. -my_phasor(tablesize,freq,c) = inc*on_memory : + ~ (_*(1-start_pulse)) : min(1.) *(tablesize) +// mathematical hard-syncing phasor (see `phasor_imp` in `faustlibraries/oscillators.lib`) +m_hsp_phasor(freq, reset, phase) = (select2(hard_reset, +(freq/ma.SR), phase) : ma.decimal) ~ _ with { - is_on = c>0; - - start_pulse = is_on & (1-is_on'); - on_memory = is_on : max ~ (_*(1-start_pulse)); - - inc = freq/float(ma.SR); + hard_reset = (1-1')|reset; // To correctly start at `phase` at the first sample +}; + +// NOTE: this is a modification of the original it.frdtable so that +// it works with a soundfile +// https://github.com/grame-cncm/faustlibraries/blob/master/interpolators.lib +// Inputs: +// * `sf`: a soundfile primitive such as `soundfile("foo.wav", 2)` +// * `N`: The Lagrange interpolation order (compile-time constant). See docs for `it.frdtable`. +// * `sound_number`: The sound number choice for the `soundfile` primitive. +// * `root_midi`: The MIDI note to consider as the root pitch. If the frequency of this note is played, then the soundfile will be played at its original pitch. +// * `freq`: A frequency in Hz which should probably come from an hslider for "freq" with polyphony. +// * `gain`: A gain in range [0-1] which serves as a note velocity. +// * `gate`: A gate which indicates the note's on/off state. +oneshot_sf(sf, N, sound_number, root_midi, freq, gain, gate) = par(i, N + 1, table(i_idx - int(N / 2) + i)) : ro.interleave(C, N+1) : par(i, C, it.lagrangeN(N, f_idx)) : volBus +with { + SFC = outputs(sf); + C = SFC-2; // num output channels. We subtract 2 to skip the outputs of sample rate and num samples + S = sound_number, 0 : sf : ba.selector(0, SFC); // table size + + noteOn = gate & (1-gate'); // impulse for a note on event + everPlayed = max(noteOn)~_; // whether noteOn has ever happened. + hold_timer = everPlayed : (+~ba.if(noteOn,0,_)); + phasor_freq = ba.hz2midikey(freq) - root_midi : ba.semi2ratio : _*everPlayed*ma.SR/S; + pct = m_hsp_phasor(phasor_freq, noteOn, 0); + + table(j) = int(ma.modulo(j, S)) : sf(sound_number) : !, !, si.bus(C); + idx = S*pct; + f_idx = ma.frac(idx) + int(N / 2); + i_idx = int(idx); + + volBus = par(i, C, ba.if((hold_timer>=S),0,_*gain)); }; gain = hslider("gain",0.1,0,1,0.01); // note velocity gate = button("gate"); // note on/off -key = hslider("freq", 60, 1, 127, 1) : ba.hz2midikey; +freq = hslider("freq", 20, 1, 20000, 1); root_midi = hslider("center_note", 60., 1., 128., 0.01); -semitones = key - root_midi; -ratio = semitones : ba.semi2ratio; - -soundfile_full = soundfile("mySample",2): _, !, _, _; -S = 0, 0 : soundfile_full : _, !, !; -soundfile_table_L = 0, _ : soundfile_full : !, _, !; -soundfile_table_R = 0, _ : soundfile_full : !, !, _; - -length_sec = S / ma.SR; -freq = ratio / length_sec; +envVol = 0.5*gain*en.adsr(.002, 0.1, 0.9, .1, gate); -envVol = en.adsr(.002, 0.1, 0.9, .1, gate); - -ridx = my_phasor(S, freq, gate); - -declare lagrangeCoeffs author "Dario Sanfilippo"; -declare lagrangeCoeffs copyright "Copyright (C) 2021 Dario Sanfilippo - "; -declare lagrangeCoeffs license "MIT license"; -// NOTE: this is a modification of the original it.frdtable so that -// it works with a soundfile -// https://github.com/grame-cncm/faustlibraries/blob/master/interpolators.lib -frdtable(N, S, init, idx) = - it.lagrangeN(N, f_idx, par(i, N + 1, table(i_idx - int(N / 2) + i))) - with { - table(j) = int(ma.modulo(j, S)) : init; - f_idx = ma.frac(idx) + int(N / 2); - i_idx = int(idx); - }; - -process = frdtable(LAGRANGE_ORDER, S, soundfile_table_L, ridx), - frdtable(LAGRANGE_ORDER, S, soundfile_table_R, ridx) <: _*finalGain, _*finalGain -with { - finalGain = gain*envVol*0.5; -}; +sound_number = 0; +process = oneshot_sf(soundfile("mySample",2), LAGRANGE_ORDER, sound_number, root_midi, freq, envVol, gate); // polyphonic DSP code must declare a stereo effect effect = _, _; \ No newline at end of file diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 65de36df..31c9d366 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -18,7 +18,8 @@ def test_stereo_plugin_effect(plugin_path): effect = engine.make_plugin_processor("effect", plugin_path) - # print(effect.get_parameters_description()) + desc = effect.get_parameters_description() + # print(desc) assert(effect.get_num_input_channels() == PLUGIN_INPUT_CHANNELS[plugin_basename]) assert(effect.get_num_output_channels() == PLUGIN_OUTPUT_CHANNELS[plugin_basename]) @@ -51,6 +52,9 @@ def test_plugin_instrument1(plugin_path): synth = engine.make_plugin_processor("synth", plugin_path) desc = synth.get_parameters_description() + for item in desc: + index = item['index'] + range = synth.get_parameter_range(index, 10) val = synth.get_parameter(0) synth.set_parameter(0, val) @@ -107,7 +111,8 @@ def test_plugin_instrument_add_midi_note_beats(plugin_path): synth = engine.make_plugin_processor("synth", plugin_path) - # print(synth.get_parameters_description()) + desc = synth.get_parameters_description() + # print(desc) for i in range(16): synth.add_midi_note(60, 60, i*4, 2, beats=True) @@ -133,7 +138,8 @@ def test_plugin_instrument_midi(plugin_path): synth = engine.make_plugin_processor("synth", plugin_path) - # print(synth.get_parameters_description()) + desc = synth.get_parameters_description() + # print(desc) synth.load_midi(abspath(ASSETS / 'MIDI-Unprocessed_SMF_02_R1_2004_01-05_ORIG_MID--AUDIO_02_R1_2004_05_Track05_wav.midi')) synth.clear_midi() diff --git a/thirdparty/faust b/thirdparty/faust index 5341a623..c4ad7d26 160000 --- a/thirdparty/faust +++ b/thirdparty/faust @@ -1 +1 @@ -Subproject commit 5341a623b04420089318e967153eaf7bef49aa5c +Subproject commit c4ad7d26481ee273e0cb3da3eb708300d58a0d74 diff --git a/thirdparty/libfaust/download_libfaust.bat b/thirdparty/libfaust/download_libfaust.bat deleted file mode 100644 index 504ad535..00000000 --- a/thirdparty/libfaust/download_libfaust.bat +++ /dev/null @@ -1,3 +0,0 @@ -set VERSION=2.69.3 -curl -L https://github.com/grame-cncm/faust/releases/download/%VERSION%/Faust-%VERSION%-win64.exe -o Faust-%VERSION%-win64.exe -call Faust-%VERSION%-win64.exe /S /D=%cd%\win64\Release \ No newline at end of file diff --git a/thirdparty/libfaust/download_libfaust.py b/thirdparty/libfaust/download_libfaust.py new file mode 100644 index 00000000..e75f1837 --- /dev/null +++ b/thirdparty/libfaust/download_libfaust.py @@ -0,0 +1,55 @@ +import argparse +import os +import platform +import subprocess +from pathlib import Path + + +def download_file(url: str, output: str) -> None: + if os.path.exists(output) and not args.force: + print(f"File already exists: {output}") + else: + subprocess.run(["curl", "-L", url, "-o", output], check=True) + +def install_windows(version: str) -> None: + exe_file = f"Faust-{version}-win64.exe" + download_file(f"https://github.com/grame-cncm/faust/releases/download/{version}/{exe_file}", exe_file) + cwd = str(Path(__file__).parent) + subprocess.run([exe_file, "/S", f"/D={cwd}\\win64\\Release"], check=True) + +def install_macos(version: str) -> None: + for arch in ["arm64", "x64"]: + dmg_file = f"Faust-{version}-{arch}.dmg" + download_file(f"https://github.com/grame-cncm/faust/releases/download/{version}/{dmg_file}", dmg_file) + subprocess.run(["hdiutil", "attach", dmg_file], check=True) + dir_path = f"darwin-{arch}/Release" + os.makedirs(dir_path, exist_ok=True) + subprocess.run(["cp", "-R", f"/Volumes/Faust-{version}/Faust-{version}/*", dir_path], check=True) + subprocess.run(["hdiutil", "detach", f"/Volumes/Faust-{version}/"], check=True) + +def install_linux(version: str) -> None: + zip_file = f"libfaust-ubuntu-x86_64.zip" + download_file(f"https://github.com/grame-cncm/faust/releases/download/{version}/{zip_file}", zip_file) + dir_path = "ubuntu-x86_64/Release" + os.makedirs(dir_path, exist_ok=True) + subprocess.run(["unzip", zip_file, "-d", dir_path], check=True) + +def main(version: str) -> None: + system = platform.system() + if system == "Windows": + install_windows(version) + elif system == "Darwin": + install_macos(version) + elif system == "Linux": + install_linux(version) + else: + raise RuntimeError(f"Unknown operating system: {system}.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Download and install Libfaust.") + parser.add_argument("-v", "--version", default="2.74.6", help="Specify the version of Faust to download.") + parser.add_argument("--force", action="store_true", help="Force download even if files already exist.") + args = parser.parse_args() + + main(args.version) diff --git a/thirdparty/libfaust/download_libfaust.sh b/thirdparty/libfaust/download_libfaust.sh deleted file mode 100644 index 2311d9df..00000000 --- a/thirdparty/libfaust/download_libfaust.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -VERSION=2.69.3 - -if [ "$(uname)" = "Darwin" ]; then - echo "You are running macOS" - curl -L https://github.com/grame-cncm/faust/releases/download/$VERSION/Faust-$VERSION-arm64.dmg -o Faust-$VERSION-arm64.dmg - hdiutil attach Faust-$VERSION-arm64.dmg - mkdir -p "darwin-arm64/Release" - cp -R /Volumes/Faust-$VERSION/Faust-$VERSION/* darwin-arm64/Release/ - hdiutil detach /Volumes/Faust-$VERSION/ - - curl -L https://github.com/grame-cncm/faust/releases/download/$VERSION/Faust-$VERSION-x64.dmg -o Faust-$VERSION-x64.dmg - hdiutil attach Faust-$VERSION-x64.dmg - mkdir -p "darwin-x64/Release" - cp -R /Volumes/Faust-$VERSION/Faust-$VERSION/* darwin-x64/Release/ - hdiutil detach /Volumes/Faust-$VERSION/ -elif [ "$(expr substr $(uname -s) 1 5)" = "Linux" ]; then - echo "You are running Linux" - curl -L https://github.com/grame-cncm/faust/releases/download/$VERSION/libfaust-ubuntu-x86_64.zip -o libfaust-ubuntu-x86_64.zip - mkdir -p "ubuntu-x86_64/Release" - unzip libfaust-ubuntu-x86_64.zip -d ubuntu-x86_64/Release -elif [ "$(expr substr $(uname -s) 1 10)" = "MINGW32_NT" ] || [ "$(expr substr $(uname -s) 1 10)" = "MINGW64_NT" ]; then - echo "You are running Windows. You should run download_libfaust.bat" - exit -else - echo "Unknown operating system" -fi \ No newline at end of file