diff --git a/.gitignore b/.gitignore index b3bacf5..cda1704 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ xcuserdata Builds JuceLibraryCode +ci/bin diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8f8e145 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,232 @@ +cmake_minimum_required (VERSION 3.24.0 FATAL_ERROR) + +# +# Set for each plugin +# +set (PLUGIN_NAME Wavetable) +set (PLUGIN_VERSION 1.0.0) +set (BUNDLE_ID com.socalabs.Wavetable) +set (AU_ID WavetableAU) +set (LV2_URI https://socalabs.com/wavetable/) +set (PLUGIN_CODE Wave) + +set (CMAKE_POLICY_DEFAULT_CMP0077 NEW) +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +set (CMAKE_SUPPRESS_REGENERATION true) +set (CMAKE_SKIP_INSTALL_RULES YES) +set_property (GLOBAL PROPERTY DEBUG_CONFIGURATIONS "Debug") + +set (CMAKE_C_FLAGS_DEVELOPMENT ${CMAKE_C_FLAGS_RELEASE}) +set (CMAKE_CXX_FLAGS_DEVELOPMENT ${CMAKE_CXX_FLAGS_RELEASE}) + +project (${PLUGIN_NAME} VERSION ${PLUGIN_VERSION} LANGUAGES CXX C HOMEPAGE_URL "https://socalabs.com/") + +include (CMakeDependentOption) + +set_property (DIRECTORY APPEND PROPERTY LABELS ${PLUGIN_NAME}) + +set_property (DIRECTORY APPEND PROPERTY LABELS SocaLabs) +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PLUGIN_NAME}_Standalone) + +set (CMAKE_OSX_DEPLOYMENT_TARGET 10.9) + +set (CMAKE_EXPORT_COMPILE_COMMANDS ON) +set (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION ON) +set (CMAKE_CXX_STANDARD 20) +set (CMAKE_CXX_STANDARD_REQUIRED ON) +set (CMAKE_CXX_EXTENSIONS OFF) +set (CMAKE_OBJCXX_STANDARD 20) +set (CMAKE_OBJCXX_STANDARD_REQUIRED ON) + set (CMAKE_CXX_VISIBILITY_PRESET hidden) + set (CMAKE_VISIBILITY_INLINES_HIDDEN ON) +set (CMAKE_MINSIZEREL_POSTFIX -rm) +set (CMAKE_RELWITHDEBINFO_POSTFIX -rd) +set (CMAKE_OPTIMIZE_DEPENDENCIES OFF) + +set (BUILD_SHARED_LIBS OFF) + +if(APPLE) + set (CMAKE_OSX_ARCHITECTURES arm64 x86_64) +endif() + +if (WIN32) + set (FORMATS Standalone VST VST3 LV2) +else() + set (FORMATS Standalone VST VST3 AU LV2) +endif() + +set_property (GLOBAL PROPERTY USE_FOLDERS YES) +set_property (GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER utility) +set_property (GLOBAL PROPERTY REPORT_UNDEFINED_PROPERTIES "${CMAKE_BINARY_DIR}/undefined_properties.log") +set_property (GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD YES) + +set_property (DIRECTORY APPEND PROPERTY LABELS External) + +# JUCE + +set (JUCE_MODULES_ONLY OFF) +set (JUCE_ENABLE_MODULE_SOURCE_GROUPS ON) +set (JUCE_BUILD_EXTRAS OFF) +set (JUCE_BUILD_EXAMPLES OFF) + +add_subdirectory (modules/juce) + +set_property (DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/modules/juce" APPEND PROPERTY LABELS JUCE) + +# + +# Gin modules + +foreach(module_name IN ITEMS gin gin_dsp gin_graphics gin_gui gin_metadata gin_network gin_plugin gin_webp) + juce_add_module ( + "${CMAKE_CURRENT_LIST_DIR}/modules/gin/modules/${module_name}" + ) + + set_property (TARGET "${module_name}" APPEND PROPERTY LABELS Gin) +endforeach() + +# Binary Data + +set_property (DIRECTORY APPEND PROPERTY LABELS Assets) + +juce_add_binary_data (${PLUGIN_NAME}_Assets SOURCES + "plugin/Resources/placeholder.txt" + ) + +set_target_properties(${PLUGIN_NAME}_Assets PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE BATCH UNITY_BUILD_BATCH_SIZE 50) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +juce_set_vst2_sdk_path (${CMAKE_SOURCE_DIR}/modules/plugin_sdk/vstsdk2.4) + +juce_add_plugin (${PLUGIN_NAME} + PRODUCT_NAME ${PLUGIN_NAME} + VERSION ${PLUGIN_VERSION} + COMPANY_NAME SocaLabs + COMPANY_WEBSITE "https://socalabs.com/" + BUNDLE_ID ${BUNDLE_ID} + FORMATS ${FORMATS} + PLUGIN_MANUFACTURER_CODE Soca + PLUGIN_CODE ${PLUGIN_CODE} + IS_SYNTH ON + NEEDS_MIDI_INPUT ON + EDITOR_WANTS_KEYBOARD_FOCUS ON + VST2_CATEGORY kPlugCategSynth + VST3_CATEGORIES Instrument + AU_MAIN_TYPE kAudioUnitType_MusicDevice + AU_EXPORT_PREFIX ${AU_ID} + AU_SANDBOX_SAFE FALSE + LV2URI LV2_URI) + +file (GLOB_RECURSE source_files CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.c + ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.cc + ${CMAKE_CURRENT_SOURCE_DIR}/plugin/*.h) + +target_sources (${PLUGIN_NAME} PRIVATE ${source_files}) +source_group (TREE ${CMAKE_CURRENT_SOURCE_DIR}/plugin PREFIX Source FILES ${source_files}) + +file (GLOB_RECURSE asset_files CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/Assets/*) + +target_sources (${PLUGIN_NAME} PRIVATE ${asset_files}) +source_group (TREE ${CMAKE_CURRENT_SOURCE_DIR}/Assets PREFIX Assets FILES ${asset_files}) + +target_link_libraries (${PLUGIN_NAME} PRIVATE + ${PLUGIN_NAME}_Assets + + gin + gin_dsp + gin_graphics + gin_gui + gin_plugin + + juce::juce_audio_basics + juce::juce_audio_devices + juce::juce_audio_formats + juce::juce_audio_plugin_client + juce::juce_audio_processors + juce::juce_audio_utils + juce::juce_core + juce::juce_cryptography + juce::juce_data_structures + juce::juce_events + juce::juce_graphics + juce::juce_gui_basics + juce::juce_gui_extra + + juce::juce_recommended_config_flags + ) + +target_include_directories (${PLUGIN_NAME} PRIVATE modules/fmt/include) +target_include_directories (${PLUGIN_NAME} PRIVATE modules/ASIO/common) +target_include_directories (${PLUGIN_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Source/Definitions) + +juce_generate_juce_header (${PLUGIN_NAME}) + +target_compile_definitions (${PLUGIN_NAME} PRIVATE + JUCE_DISPLAY_SPLASH_SCREEN=0 + JUCE_COREGRAPHICS_DRAW_ASYNC=1 + JUCE_MODAL_LOOPS_PERMITTED=1 + JUCE_WEB_BROWSER=0 + JUCE_USE_FLAC=0 + JUCE_USE_CURL=1 + JUCE_USE_MP3AUDIOFORMAT=0 + JUCE_USE_LAME_AUDIO_FORMAT=0 + JUCE_USE_WINDOWS_MEDIA_FORMAT=0 + JucePlugin_PreferredChannelConfigurations={0,2} + _CRT_SECURE_NO_WARNINGS + ) + +if (APPLE) + set_target_properties("juce_vst3_helper" PROPERTIES XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO) + + foreach(t ${FORMATS} "Assets" "All" "") + set(tgt ${CMAKE_PROJECT_NAME}) + if (NOT t STREQUAL "") + set(tgt ${tgt}_${t}) + endif() + if (TARGET ${tgt}) + set_target_properties(${tgt} PROPERTIES + XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO + #XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] YES + XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES" + ) + if (NOT t STREQUAL "All") + target_compile_options(${tgt} PRIVATE + -Wall -Wstrict-aliasing -Wunused-parameter -Wconditional-uninitialized -Woverloaded-virtual -Wreorder -Wconstant-conversion -Wbool-conversion -Wextra-semi + -Wunreachable-code -Winconsistent-missing-destructor-override -Wshift-sign-overflow -Wnullable-to-nonnull-conversion -Wuninitialized -Wno-missing-field-initializers + -Wno-ignored-qualifiers -Wno-missing-braces -Wno-char-subscripts -Wno-unused-private-field -fno-aligned-allocation -Wunused-private-field -Wunreachable-code + -Wenum-compare -Wshadow -Wfloat-conversion -Wshadow-uncaptured-local -Wshadow-field -Wsign-compare -Wdeprecated-this-capture -Wimplicit-float-conversion + -ffast-math -fno-finite-math-only) + endif() + endif() + endforeach() +endif() + +if (WIN32) + foreach(t ${FORMATS} "Assets" "All" "") + set(tgt ${CMAKE_PROJECT_NAME}) + if (NOT t STREQUAL "") + set(tgt ${tgt}_${t}) + endif() + if (TARGET ${tgt}) + set_property(TARGET ${tgt} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " /INCREMENTAL:NO") + set_target_properties(${tgt} PROPERTIES LINK_FLAGS "/ignore:4099") + endif() + endforeach() +endif() + +if(UNIX AND NOT APPLE) + target_link_libraries (${PLUGIN_NAME} PRIVATE curl) +endif() + + +if(WIN32) + set (dest "Program Files") +else() + set (dest "Applications") +endif() + +install (TARGETS ${PLUGIN_NAME} DESTINATION "${dest}") diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..edcdeae --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,13 @@ +{ + "cmakeMinimumRequired": { + "major": 3, + "minor": 24, + "patch": 0 + }, + "version": 5, + "include": [ + "modules/gin/ci/toolchains/xcode.json", + "modules/gin/ci/toolchains/vs.json", + "modules/gin/ci/toolchains/gcc.json" + ] +} diff --git a/ci/build.sh b/ci/build.sh index 77a3044..2f554b7 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -3,19 +3,13 @@ PLUGIN="Wavetable" # linux specific stiff -if [ $OS = "linux" ]; then - export GDK_BACKEND=x11 - +if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then sudo apt-get update - sudo apt-get install clang git ladspa-sdk freeglut3-dev g++ libasound2-dev libcurl4-openssl-dev libfreetype6-dev libjack-jackd2-dev libx11-dev libxcomposite-dev libxcursor-dev libxinerama-dev libxrandr-dev mesa-common-dev webkit2gtk-4.0 juce-tools xvfb - - Xvfb :99 & - export DISPLAY=:99 - sleep 5 + sudo apt-get install clang git ninja-build ladspa-sdk freeglut3-dev g++ libasound2-dev libcurl4-openssl-dev libfreetype6-dev libjack-jackd2-dev libx11-dev libxcomposite-dev libxcursor-dev libxinerama-dev libxrandr-dev mesa-common-dev webkit2gtk-4.0 juce-tools xvfb fi # mac specific stuff -if [ $OS = "mac" ]; then +if [ "$(uname)" == "Darwin" ]; then # Create a temp keychain if [ -n "$GITHUB_ACTIONS" ]; then echo "Create a keychain" @@ -41,109 +35,84 @@ ROOT=$(cd "$(dirname "$0")/.."; pwd) cd "$ROOT" echo "$ROOT" +BRANCH=${GITHUB_REF##*/} +echo "$BRANCH" + cd "$ROOT/ci" rm -Rf bin mkdir bin -# Get the hash -cd "$ROOT/modules/juce" -HASH=`git rev-parse HEAD` -echo "Hash: $HASH" - -# Get the Projucer -cd "$ROOT/ci/bin" -while true -do - PROJUCER_URL=$(curl -s -S "https://projucer.rabien.com/get_projucer.php?hash=$HASH&os=$OS&key=$APIKEY") - echo "Response: $PROJUCER_URL" - if [[ $PROJUCER_URL == http* ]]; then - curl -s -S $PROJUCER_URL -o "$ROOT/ci/bin/Projucer.zip" - unzip Projucer.zip - break - fi - sleep 15 -done - -# Resave jucer file -if [ "$OS" = "mac" ]; then - "$ROOT/ci/bin/Projucer.app/Contents/MacOS/Projucer" --resave "$ROOT/plugin/$PLUGIN.jucer" -elif [ "$OS" = "linux" ]; then - "$ROOT/ci/bin/Projucer" --resave "$ROOT/plugin/$PLUGIN.jucer" -else - "$ROOT/ci/bin/Projucer.exe" --resave "$ROOT/plugin/$PLUGIN.jucer" -fi - # Build mac version -if [ "$OS" = "mac" ]; then - cd "$ROOT/plugin/Builds/MacOSX" - xcodebuild -configuration Release || exit 1 +if [ "$(uname)" == "Darwin" ]; then + cd "$ROOT" + cmake --preset xcode + cmake --build --preset xcode --config Release - cp -R ~/Library/Audio/Plug-Ins/VST/$PLUGIN.vst "$ROOT/ci/bin" - cp -R ~/Library/Audio/Plug-Ins/Components/$PLUGIN.component "$ROOT/ci/bin" + cp -R "$ROOT/Builds/xcode/${PLUGIN}_artefacts/Release/AU/$PLUGIN.component" "$ROOT/ci/bin" + cp -R "$ROOT/Builds/xcode/${PLUGIN}_artefacts/Release/VST/$PLUGIN.vst" "$ROOT/ci/bin" + cp -R "$ROOT/Builds/xcode/${PLUGIN}_artefacts/Release/VST3/$PLUGIN.vst3" "$ROOT/ci/bin" cd "$ROOT/ci/bin" - for filename in ./*.vst; do - codesign -s "$DEV_APP_ID" -v "$filename" --options=runtime --timestamp - done - for filename in ./*.component; do - codesign -s "$DEV_APP_ID" -v "$filename" --options=runtime --timestamp - done - - # Build notarize tool - cd "$ROOT/modules/gin/tools/notarize" - "$ROOT/ci/bin/Projucer.app/Contents/MacOS/Projucer" --set-global-search-path osx defaultJuceModulePath "$ROOT/modules/juce/modules" - "$ROOT/ci/bin/Projucer.app/Contents/MacOS/Projucer" --resave "notarize.jucer" - cd Builds/MacOSX - xcodebuild -configuration Release || exit 1 - cd build/Release - cp notarize "$ROOT/ci/bin" + codesign -s "$DEV_APP_ID" -v $PLUGIN.vst --options=runtime --timestamp --force + codesign -s "$DEV_APP_ID" -v $PLUGIN.vst3 --options=runtime --timestamp --force + codesign -s "$DEV_APP_ID" -v $PLUGIN.component --options=runtime --timestamp --force # Notarize cd "$ROOT/ci/bin" - zip -r ${PLUGIN}_Mac.zip $PLUGIN.vst $PLUGIN.component + zip -r ${PLUGIN}_Mac.zip $PLUGIN.vst $PLUGIN.vst3 $PLUGIN.component - "$ROOT/ci/bin/notarize" -ns ${PLUGIN}_Mac.zip $APPLE_USER $APPLE_PASS com.figbug.$PLUGIN.vst + if [[ -n "$APPLE_USER" ]]; then + xcrun notarytool submit --verbose --apple-id "$APPLE_USER" --password "$APPLE_PASS" --team-id "3FS7DJDG38" --wait --timeout 30m ${PLUGIN}_Mac.zip + fi rm ${PLUGIN}_Mac.zip xcrun stapler staple $PLUGIN.vst + xcrun stapler staple $PLUGIN.vst3 xcrun stapler staple $PLUGIN.component - zip -r ${PLUGIN}_Mac.zip $PLUGIN.vst $PLUGIN.component - - curl -F "files=@${PLUGIN}_Mac.zip" "https://socalabs.com/files/set.php?key=$APIKEY" + zip -r ${PLUGIN}_Mac.zip $PLUGIN.vst $PLUGIN.vst3 $PLUGIN.component + + if [ "$BRANCH" = "release" ]; then + curl -F "files=@${PLUGIN}_Mac.zip" "https://socalabs.com/files/set.php?key=$APIKEY" + fi fi # Build linux version -if [ "$OS" = "linux" ]; then - cd "$ROOT/plugin/Builds/LinuxMakefile" - make CONFIG=Release +if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + cd "$ROOT" + + cmake --preset ninja-gcc + cmake --build --preset ninja-gcc --config Release - cd "$ROOT/plugin/Builds/LinuxMakefile" - cp ./build/$PLUGIN.so "$ROOT/ci/bin" + cp -R "$ROOT/Builds/ninja-gcc/${PLUGIN}_artefacts/Release/LV2/$PLUGIN.lv2" "$ROOT/ci/bin" + cp -R "$ROOT/Builds/ninja-gcc/${PLUGIN}_artefacts/Release/VST/lib$PLUGIN.so" "$ROOT/ci/bin/$PLUGIN.so" + cp -R "$ROOT/Builds/ninja-gcc/${PLUGIN}_artefacts/Release/VST3/$PLUGIN.vst3" "$ROOT/ci/bin" cd "$ROOT/ci/bin" - rm -Rf ${PLUGIN}_Linux.zip - zip -r ${PLUGIN}_Linux.zip $PLUGIN.so - curl -F "files=@${PLUGIN}_Linux.zip" "https://socalabs.com/files/set.php?key=$APIKEY" + # Upload + cd "$ROOT/ci/bin" + zip -r ${PLUGIN}_Linux.zip $PLUGIN.so $PLUGIN.vst3 $PLUGIN.lv2 + + if [ "$BRANCH" = "release" ]; then + curl -F "files=@${PLUGIN}_Linux.zip" "https://socalabs.com/files/set.php?key=$APIKEY" + fi fi # Build Win version -if [ "$OS" = "win" ]; then - VS_WHERE="C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe" - - MSBUILD_EXE=$("$VS_WHERE" -latest -requires Microsoft.Component.MSBuild -find "MSBuild\**\Bin\MSBuild.exe") - echo $MSBUILD_EXE +if [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then + cd "$ROOT" - cd "$ROOT/plugin/Builds/VisualStudio2019" - "$MSBUILD_EXE" "$PLUGIN.sln" "//p:VisualStudioVersion=16.0" "//m" "//t:Build" "//p:Configuration=Release64" "//p:Platform=x64" "//p:PreferredToolArchitecture=x64" - "$MSBUILD_EXE" "$PLUGIN.sln" "//p:VisualStudioVersion=16.0" "//m" "//t:Build" "//p:Configuration=Release" "//p:PlatformTarget=x86" "//p:PreferredToolArchitecture=x64" + cmake --preset vs + cmake --build --preset vs --config Release cd "$ROOT/ci/bin" - cp "$ROOT/plugin/Builds/VisualStudio2019/x64/Release64/VST/${PLUGIN}.dll" . - cp "$ROOT/plugin/Builds/VisualStudio2019/Win32/Release/VST/${PLUGIN}_32b.dll" . + cp -R "$ROOT/Builds/vs/${PLUGIN}_artefacts/Release/VST/$PLUGIN.dll" "$ROOT/ci/bin" + cp -R "$ROOT/Builds/vs/${PLUGIN}_artefacts/Release/VST3/$PLUGIN.vst3" "$ROOT/ci/bin" - 7z a ${PLUGIN}_Win.zip ${PLUGIN}.dll ${PLUGIN}_32b.dll + 7z a ${PLUGIN}_Win.zip $PLUGIN.dll $PLUGIN.vst3 - curl -F "files=@${PLUGIN}_Win.zip" "https://socalabs.com/files/set.php?key=$APIKEY" -fi \ No newline at end of file + if [ "$BRANCH" = "release" ]; then + curl -F "files=@${PLUGIN}_Win.zip" "https://socalabs.com/files/set.php?key=$APIKEY" + fi +fi diff --git a/ci/config_cmake.sh b/ci/config_cmake.sh new file mode 100755 index 0000000..233babd --- /dev/null +++ b/ci/config_cmake.sh @@ -0,0 +1,16 @@ +#!/bin/bash -e + +ROOT=$(cd "$(dirname "$0")/.."; pwd) +cd "$ROOT" + +export PATH=$PATH:"/c/Program Files/CMake/bin" + +if [ "$(uname)" == "Darwin" ]; then + TOOLCHAIN="xcode" +elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + TOOLCHAIN="ninja-gcc" +elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then + TOOLCHAIN="vs" +fi + +cmake --preset $TOOLCHAIN -D BUILD_EXTRAS=OFF -D JUCE_COPY_PLUGIN_AFTER_BUILD=ON diff --git a/modules/gin b/modules/gin index d8ead26..170e6fb 160000 --- a/modules/gin +++ b/modules/gin @@ -1 +1 @@ -Subproject commit d8ead26e5775c0b11bd5067399d3a38beb7602b2 +Subproject commit 170e6fb30e8581fe0f5370fa23c7cab522c7aeb2 diff --git a/modules/juce b/modules/juce index 83b1436..2a27ebc 160000 --- a/modules/juce +++ b/modules/juce @@ -1 +1 @@ -Subproject commit 83b1436c6a21f82ffdc4125592836f21dbd7b1e7 +Subproject commit 2a27ebcfae7ca7f6eb62b29d5f002ceefdaadbdb diff --git a/plugin/Resources/Wavetables/WINDOW_S.WAV b/plugin/Resources/Wavetables/WINDOW_S.WAV deleted file mode 100644 index e6f7134..0000000 Binary files a/plugin/Resources/Wavetables/WINDOW_S.WAV and /dev/null differ diff --git a/plugin/Resources/placeholder.txt b/plugin/Resources/placeholder.txt new file mode 100644 index 0000000..e69de29 diff --git a/plugin/Source/Boxes.h b/plugin/Source/Boxes.h deleted file mode 100644 index ec7bf19..0000000 --- a/plugin/Source/Boxes.h +++ /dev/null @@ -1,421 +0,0 @@ -#pragma once - -#include -#include "PluginProcessor.h" -#include "Cfg.h" - -//============================================================================== -class CommonBox : public gin::PagedControlBox -{ -public: - CommonBox (gin::ProcessorEditor& e, WavetableAudioProcessor& proc_) - : gin::PagedControlBox (e), proc (proc_) - { - auto& g = proc.globalParams; - - addPage ("Main", 3, 2); - - addControl (0, new gin::Knob (g.level), 0, 0); - addControl (0, new gin::Switch (g.mono), 1, 0); - addControl (0, new gin::Select (g.glideMode), 2, 0); - - addControl (0, v = new gin::Knob (g.voices), 0, 1); - addControl (0, l = new gin::Switch (g.legato), 1, 1); - addControl (0, s = new gin::Knob (g.glideRate), 2, 1); - - watchParam (g.mono); - watchParam (g.glideMode); - - addPage ("Control", 1, 2); - - addControl (1, new gin::Switch (g.mpe), 0, 0); - } - - void paramChanged() override - { - gin::PagedControlBox::paramChanged(); - - auto& g = proc.globalParams; - v->setEnabled (! g.mono->isOn()); - l->setEnabled (g.glideMode->getProcValue() != 0.0f); - s->setEnabled (g.glideMode->getProcValue() != 0.0f); - } - - WavetableAudioProcessor& proc; - ParamComponentPtr v, l, s; -}; - -//============================================================================== -class OscillatorBox : public gin::PagedControlBox -{ -public: - OscillatorBox (gin::ProcessorEditor& e, WavetableAudioProcessor& proc_) - : gin::PagedControlBox (e), proc (proc_) - { - for ( int i = 0; i < numElementsInArray (proc.wtParams); i++) - { - auto& wt = proc.wtParams[i]; - - addPage ("WT " + String (i + 1), 3, 4); - addPageEnable (i * 2, wt.enable); - - addControl (i * 2, new gin::Knob (wt.table), 0, 0); - addControl (i * 2, new gin::Knob (wt.tune, true), 1, 0); - addControl (i * 2, new gin::Knob (wt.finetune, true), 2, 0); - addControl (i * 2, new gin::Knob (wt.pan, true), 0, 1); - addControl (i * 2, new gin::Knob (wt.level), 1, 1); - - addPage ("Unison " + String (i + 1), 2, 4); - addControl (i * 2 + 1, new gin::Knob (wt.voices), 0, 0); - addControl (i * 2 + 1, trans[i] = new gin::Knob (wt.voicesTrns, true), 1, 0); - addControl (i * 2 + 1, detune[i] = new gin::Knob (wt.detune), 0, 1); - addControl (i * 2 + 1, spread[i] = new gin::Knob (wt.spread), 1, 1); - - watchParam (wt.voices); - } - - for ( int i = 0; i < numElementsInArray (proc.oscParams); i++) - { - auto& osc = proc.oscParams[i]; - - addPage ("OSC " + String (i + 1), 3, 4); - addPageEnable (Cfg::numWTs * 2 + i * 2, osc.enable); - - addControl (Cfg::numWTs * 2 + i * 2, new gin::Select (osc.wave), 0, 0); - addControl (Cfg::numWTs * 2 + i * 2, new gin::Knob (osc.tune, true), 1, 0); - addControl (Cfg::numWTs * 2 + i * 2, new gin::Knob (osc.finetune, true), 2, 0); - addControl (Cfg::numWTs * 2 + i * 2, new gin::Knob (osc.pan, true), 0, 1); - addControl (Cfg::numWTs * 2 + i * 2, new gin::Knob (osc.level), 1, 1); - addControl (Cfg::numWTs * 2 + i * 2, pw[Cfg::numWTs + i] = new gin::Knob (osc.pulsewidth), 2, 1); - - watchParam (osc.wave); - - addPage ("Unison " + String (i + 1), 2, 4); - addControl (Cfg::numWTs * 2 + i * 2 + 1, new gin::Knob (osc.voices), 0, 0); - addControl (Cfg::numWTs * 2 + i * 2 + 1, trans[Cfg::numWTs + i] = new gin::Knob (osc.voicesTrns, true), 1, 0); - addControl (Cfg::numWTs * 2 + i * 2 + 1, detune[Cfg::numWTs + i] = new gin::Knob (osc.detune), 0, 1); - addControl (Cfg::numWTs * 2 + i * 2 + 1, spread[Cfg::numWTs + i] = new gin::Knob (osc.spread), 1, 1); - - watchParam (osc.voices); - } - - setPageOpen (0, true); - setPageOpen (2, true); - setPageOpen (4, true); - } - - void paramChanged() override - { - gin::PagedControlBox::paramChanged(); - - for ( int i = 0; i < numElementsInArray (proc.wtParams); i++) - { - auto& wt = proc.oscParams[i]; - - trans[i]->setEnabled (wt.voices->getProcValue() > 1); - detune[i]->setEnabled (wt.voices->getProcValue() > 1); - spread[i]->setEnabled (wt.voices->getProcValue() > 1); - } - - for ( int i = 0; i < numElementsInArray (proc.oscParams); i++) - { - auto& osc = proc.oscParams[i]; - pw[Cfg::numWTs + i]->setEnabled ((gin::Wave) int (osc.wave->getProcValue()) == gin::Wave::pulse); - - trans[Cfg::numWTs + i]->setEnabled (osc.voices->getProcValue() > 1); - detune[Cfg::numWTs + i]->setEnabled (osc.voices->getProcValue() > 1); - spread[Cfg::numWTs + i]->setEnabled (osc.voices->getProcValue() > 1); - } - } - - WavetableAudioProcessor& proc; - ParamComponentPtr pw[Cfg::numOSCs + Cfg::numWTs], trans[Cfg::numOSCs + Cfg::numWTs], - detune[Cfg::numOSCs + Cfg::numWTs], spread[Cfg::numOSCs + Cfg::numWTs]; -}; - -//============================================================================== -class FilterAmpBox : public gin::PagedControlBox -{ -public: - FilterAmpBox (gin::ProcessorEditor& e, WavetableAudioProcessor& proc_) - : gin::PagedControlBox (e), proc (proc_) - { - for (int i = 0; i < numElementsInArray (proc.filterParams); i++) - { - auto& flt = proc.filterParams[i]; - - addPage ("Filter " + String (i + 1), 8, 2); - addBottomButton (i, new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcFilter[i], true)); - addPageEnable (i, flt.enable); - - addControl (i, new gin::Select (flt.type), 0, 0); - auto freq = new gin::Knob (flt.frequency); - addControl (i, freq, 1, 0); - addControl (i, new gin::Knob (flt.resonance), 2, 0); - - addControl (i, new gin::Knob (flt.keyTracking), 0, 1); - addControl (i, new gin::Knob (flt.amount, true), 1, 1); - addControl (i, v[i] = new gin::Knob (flt.velocityTracking), 2, 1); - - adsr[i] = new gin::ADSRComponent (); - adsr[i]->setParams (flt.attack, flt.decay, flt.sustain, flt.release); - addControl (i, adsr[i], 3, 0, 3, 2); - - addControl (i, a[i] = new gin::Knob (flt.attack), 6, 0); - addControl (i, d[i] = new gin::Knob (flt.decay), 7, 0); - addControl (i, s[i] = new gin::Knob (flt.sustain), 6, 1); - addControl (i, r[i] = new gin::Knob (flt.release), 7, 1); - - watchParam (flt.amount); - - freq->setLiveValuesCallback ([this, i] () - { - if (proc.filterParams[i].amount->getUserValue() != 0.0f || - proc.filterParams[i].keyTracking->getUserValue() != 0.0f || - proc.modMatrix.isModulated (gin::ModDstId (proc.filterParams[i].frequency->getModIndex()))) - return proc.getLiveFilterCutoff (i); - return Array(); - }); - - int n = numElementsInArray (proc.filterParams); - auto& env = proc.adsrParams; - - addPage ("ADSR", 8, 2); - addControl (n, new gin::Knob (env.attack), 0, 0); - addControl (n, new gin::Knob (env.decay), 1, 0); - addControl (n, new gin::Knob (env.sustain), 0, 1); - addControl (n, new gin::Knob (env.release), 1, 1); - addControl (n, new gin::Knob (env.velocityTracking), 2, 0); - - auto g = new gin::ADSRComponent (); - g->setParams (env.attack, env.decay, env.sustain, env.release); - addControl (n, g, 3, 0, 3, 2); - } - } - - void paramChanged () override - { - gin::PagedControlBox::paramChanged (); - - for ( int i = 0; i < numElementsInArray (proc.filterParams); i++) - { - auto& flt = proc.filterParams[i]; - v[i]->setEnabled (flt.amount->getUserValue() != 0.0f); - a[i]->setEnabled (flt.amount->getUserValue() != 0.0f); - d[i]->setEnabled (flt.amount->getUserValue() != 0.0f); - s[i]->setEnabled (flt.amount->getUserValue() != 0.0f); - r[i]->setEnabled (flt.amount->getUserValue() != 0.0f); - adsr[i]->setEnabled (flt.amount->getUserValue() != 0.0f); - } - } - - WavetableAudioProcessor& proc; - ParamComponentPtr v[Cfg::numFilters], a[Cfg::numFilters], d[Cfg::numFilters], s[Cfg::numFilters], r[Cfg::numFilters]; - gin::ADSRComponent* adsr[Cfg::numFilters]; -}; - -//============================================================================== -class ModulationBox : public gin::PagedControlBox -{ -public: - ModulationBox (gin::ProcessorEditor& e, WavetableAudioProcessor& proc_) - : gin::PagedControlBox (e), proc (proc_) - { - int cnt = 0; - for (int i = 0; i < numElementsInArray (proc.lfoParams); i++, cnt++) - { - auto& lfo = proc.lfoParams[i]; - - addPage ("LFO" + String (i + 1), 5, 2); - addPageEnable (cnt, lfo.enable); - addBottomButton (cnt, new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcLFO[i], true)); - addBottomButton (cnt, new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcMonoLFO[i], false)); - - addControl (cnt, new gin::Select (lfo.wave), 0, 0); - addControl (cnt, new gin::Switch (lfo.sync), 1, 0); - addControl (cnt, r[i] = new gin::Knob (lfo.rate), 2, 0); - addControl (cnt, b[i] = new gin::Select (lfo.beat), 2, 0); - - addControl (cnt, new gin::Knob (lfo.depth, true), 0, 1); - addControl (cnt, new gin::Knob (lfo.phase, true), 1, 1); - addControl (cnt, new gin::Knob (lfo.offset, true), 2, 1); - addControl (cnt, new gin::Knob (lfo.fade, true), 3, 1); - addControl (cnt, new gin::Knob (lfo.delay), 4, 1); - - auto l = new gin::LFOComponent(); - l->setParams (lfo.wave, lfo.sync, lfo.rate, lfo.beat, lfo.depth, lfo.offset, lfo.phase, lfo.enable); - addControl (cnt, l, 3, 0, 2, 1); - - watchParam (lfo.sync); - } - - for (int i = 0; i < numElementsInArray (proc.envParams); i++, cnt++) - { - auto& env = proc.envParams[i]; - - addPage ("ENV" + String (i + 1), 5, 2); - addPageEnable (cnt, env.enable); - addBottomButton (cnt, new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcEnv[i], true)); - - addControl (cnt, new gin::Knob (env.attack), 0, 0); - addControl (cnt, new gin::Knob (env.decay), 1, 0); - addControl (cnt, new gin::Knob (env.sustain), 0, 1); - addControl (cnt, new gin::Knob (env.release), 1, 1); - - auto adsr = new gin::ADSRComponent (); - adsr->setParams (env.attack, env.decay, env.sustain, env.release); - addControl (cnt, adsr, 2, 0, 3, 2); - } - - auto& stp = proc.stepLfoParams; - addPage ("Step", 6, 2); - addPageEnable (cnt, stp.enable); - addBottomButton (cnt, new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcStep, true)); - addBottomButton (cnt, new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcMonoStep, false)); - - addControl (cnt, new gin::Select (stp.beat), 0, 0); - addControl (cnt, new gin::Knob (stp.length), 0, 1); - - auto s = new gin::StepLFOComponent(); - s->setParams (stp.beat, stp.length, stp.level, stp.enable); - addControl (cnt, s, 1, 0, 5, 2); - cnt++; - - addPage ("All", 5, 2); - addControl (cnt, new gin::ModSrcListBox (proc.modMatrix), 0, 0, 5, 2); - cnt++; - - addPage ("Mod Matrix", 5, 2); - addControl (cnt, new gin::ModMatrixBox (proc, proc.modMatrix), 0, 0, 5, 2); - cnt++; - } - - void paramChanged () override - { - gin::PagedControlBox::paramChanged (); - - for (int i = 0; i < numElementsInArray (proc.lfoParams); i++) - { - auto& lfo = proc.lfoParams[i]; - r[i]->setVisible (! lfo.sync->isOn()); - b[i]->setVisible (lfo.sync->isOn()); - } - } - - WavetableAudioProcessor& proc; - ParamComponentPtr r[Cfg::numLFOs], b[Cfg::numLFOs]; -}; - -//============================================================================== -class EffectsBox : public gin::PagedControlBox -{ -public: - EffectsBox (gin::ProcessorEditor& e, WavetableAudioProcessor& proc_) - : gin::PagedControlBox (e), proc (proc_) - { - int idx = 0; - - addPage ("Gate", 8, 2); - addPageEnable (idx, proc.gateParams.enable); - addControl (idx, new gin::Select (proc.gateParams.beat), 0, 0); - addControl (idx, new gin::Knob (proc.gateParams.length), 1, 0); - addControl (idx, new gin::Knob (proc.gateParams.attack), 0, 1); - addControl (idx, new gin::Knob (proc.gateParams.release), 1, 1); - auto g = new gin::GateEffectComponent (); - g->setParams (proc.gateParams.length, proc.gateParams.l, proc.gateParams.r, proc.gateParams.enable); - addControl (idx, g, 2, 0, 6, 2); - idx++; - - addPage ("Chorus", 3, 2); - addPageEnable (idx, proc.chorusParams.enable); - addControl (idx, new gin::Knob (proc.chorusParams.delay), 0, 0); - addControl (idx, new gin::Knob (proc.chorusParams.rate), 1, 0); - addControl (idx, new gin::Knob (proc.chorusParams.depth), 2, 0); - addControl (idx, new gin::Knob (proc.chorusParams.width), 0, 1); - addControl (idx, new gin::Knob (proc.chorusParams.mix), 1, 1); - idx++; - - addPage ("Distortion", 2, 2); - addPageEnable (idx, proc.distortionParams.enable); - addControl (idx, new gin::Knob (proc.distortionParams.amount), 0, 0); - addControl (idx, new gin::Knob (proc.distortionParams.highpass), 1, 0); - addControl (idx, new gin::Knob (proc.distortionParams.output), 0, 1); - addControl (idx, new gin::Knob (proc.distortionParams.mix), 1, 1); - idx++; - - addPage ("EQ", 6, 2); - addPageEnable (idx, proc.eqParams.enable); - addControl (idx, new gin::Knob (proc.eqParams.loFreq), 0, 0); - addControl (idx, new gin::Knob (proc.eqParams.loGain), 1, 0); - addControl (idx, new gin::Knob (proc.eqParams.loQ), 2, 0); - addControl (idx, new gin::Knob (proc.eqParams.mid1Freq), 3, 0); - addControl (idx, new gin::Knob (proc.eqParams.mid1Gain), 4, 0); - addControl (idx, new gin::Knob (proc.eqParams.mid1Q), 5, 0); - addControl (idx, new gin::Knob (proc.eqParams.mid2Freq), 0, 1); - addControl (idx, new gin::Knob (proc.eqParams.mid2Gain), 1, 1); - addControl (idx, new gin::Knob (proc.eqParams.mid2Q), 2, 1); - addControl (idx, new gin::Knob (proc.eqParams.hiFreq), 3, 1); - addControl (idx, new gin::Knob (proc.eqParams.hiGain), 4, 1); - addControl (idx, new gin::Knob (proc.eqParams.hiQ), 5, 1); - idx++; - - addPage ("Comp", 3, 2); - addPageEnable (idx, proc.compressorParams.enable); - addControl (idx, new gin::Knob (proc.compressorParams.attack), 0, 0); - addControl (idx, new gin::Knob (proc.compressorParams.release), 1, 0); - addControl (idx, new gin::Knob (proc.compressorParams.ratio), 2, 0); - addControl (idx, new gin::Knob (proc.compressorParams.threshold), 0, 1); - addControl (idx, new gin::Knob (proc.compressorParams.gain), 1, 1); - idx++; - - addPage ("Delay", 3, 2); - addPageEnable (idx, proc.delayParams.enable); - addControl (idx, new gin::Switch (proc.delayParams.sync), 0, 0); - addControl (idx, t = new gin::Knob (proc.delayParams.time), 1, 0); - addControl (idx, b = new gin::Select (proc.delayParams.beat), 1, 0); - addControl (idx, new gin::Knob (proc.delayParams.fb), 2, 0); - addControl (idx, new gin::Knob (proc.delayParams.cf), 1, 1); - addControl (idx, new gin::Knob (proc.delayParams.mix), 2, 1); - idx++; - - watchParam (proc.delayParams.sync); - - addPage ("Reverb", 3, 2); - addPageEnable (idx, proc.reverbParams.enable); - addControl (idx, new gin::Knob (proc.reverbParams.damping), 0, 0); - addControl (idx, new gin::Knob (proc.reverbParams.freezeMode), 1, 0); - addControl (idx, new gin::Knob (proc.reverbParams.roomSize), 2, 0); - addControl (idx, new gin::Knob (proc.reverbParams.width), 0, 1); - addControl (idx, new gin::Knob (proc.reverbParams.mix), 1, 1); - idx++; - - addPage ("Limiter", 2, 2); - addPageEnable (idx, proc.limiterParams.enable); - addControl (idx, new gin::Knob (proc.limiterParams.attack), 0, 0); - addControl (idx, new gin::Knob (proc.limiterParams.release), 1, 0); - addControl (idx, new gin::Knob (proc.limiterParams.threshold), 0, 1); - addControl (idx, new gin::Knob (proc.limiterParams.gain), 1, 1); - idx++; - - addPage ("Scope", 8, 2); - auto scope = new gin::TriggeredScope (proc.fifo); - scope->setNumChannels (2); - scope->setTriggerMode (gin::TriggeredScope::TriggerMode::Up); - scope->setColour (gin::TriggeredScope::lineColourId, Colours::transparentBlack); - addControl (idx, scope, 0, 0, 8, 2); - idx++; - - setPageOpen (0, false); - } - - void paramChanged () override - { - gin::PagedControlBox::paramChanged (); - - t->setVisible (! proc.delayParams.sync->isOn()); - b->setVisible (proc.delayParams.sync->isOn()); - } - - WavetableAudioProcessor& proc; - ParamComponentPtr t, b; -}; diff --git a/plugin/Source/Cfg.h b/plugin/Source/Cfg.h index d4a413c..1343c51 100644 --- a/plugin/Source/Cfg.h +++ b/plugin/Source/Cfg.h @@ -2,9 +2,8 @@ namespace Cfg { - constexpr static int numWTs = 2; - constexpr static int numOSCs = 1; - constexpr static int numFilters = 1; + constexpr static int numOSCs = 4; + constexpr static int numFilters = 2; constexpr static int numENVs = 3; constexpr static int numLFOs = 3; } diff --git a/plugin/Source/Panels.h b/plugin/Source/Panels.h new file mode 100644 index 0000000..192b470 --- /dev/null +++ b/plugin/Source/Panels.h @@ -0,0 +1,435 @@ +#pragma once + +#include +#include "PluginProcessor.h" +#include "Cfg.h" + +//============================================================================== +class OscillatorBox : public gin::ParamBox +{ +public: + OscillatorBox (const juce::String& name, WavetableAudioProcessor& proc_, int idx_) + : gin::ParamBox (name), proc (proc_), idx (idx_) + { + auto& osc = proc.oscParams[idx]; + + addEnable (osc.enable); + + addControl (new gin::Select (osc.wave), 0, 0); + addControl (new gin::Knob (osc.tune, true), 1, 0); + addControl (new gin::Select (osc.voices), 2, 0); + addControl (detune = new gin::Knob (osc.detune), 3, 0); + + addControl (pw = new gin::Knob (osc.pulsewidth), 0, 1); + addControl (new gin::Knob (osc.finetune, true), 1, 1); + addControl (spread = new gin::Knob (osc.spread), 2, 1); + addControl (trans = new gin::Knob (osc.voicesTrns, true), 3, 1); + + watchParam (osc.wave); + watchParam (osc.voices); + } + + void paramChanged() override + { + gin::ParamBox::paramChanged(); + + auto& osc = proc.oscParams[idx]; + pw->setEnabled ((gin::Wave) int (osc.wave->getProcValue()) == gin::Wave::pulse); + + trans->setEnabled (osc.voices->getProcValue() > 1); + detune->setEnabled (osc.voices->getProcValue() > 1); + spread->setEnabled (osc.voices->getProcValue() > 1); + } + + WavetableAudioProcessor& proc; + int idx = 0; + gin::ParamComponent::Ptr pw, trans, detune, spread; +}; + +//============================================================================== +class FilterBox : public gin::ParamBox +{ +public: + FilterBox (const juce::String& name, WavetableAudioProcessor& proc_, int idx_) + : gin::ParamBox (name), proc (proc_), idx (idx_) + { + auto& flt = proc.filterParams[idx]; + + addEnable (flt.enable); + + auto freq = new gin::Knob (flt.frequency); + addControl (freq, 0, 0); + addControl (new gin::Knob (flt.resonance), 1, 0); + addControl (new gin::Knob (flt.amount, true), 2, 0); + + addControl (new gin::Knob (flt.keyTracking), 0, 1); + addControl (new gin::Select (flt.type), 1, 1); + addControl (v = new gin::Knob (flt.velocityTracking), 2, 1); + + freq->setLiveValuesCallback ([this] () + { + if (proc.filterParams[idx].amount->getUserValue() != 0.0f || + proc.filterParams[idx].keyTracking->getUserValue() != 0.0f || + proc.modMatrix.isModulated (gin::ModDstId (proc.filterParams[idx].frequency->getModIndex()))) + return proc.getLiveFilterCutoff (idx); + return juce::Array(); + }); + } + + void paramChanged () override + { + gin::ParamBox::paramChanged (); + + auto& flt = proc.filterParams[idx]; + v->setEnabled (flt.amount->getUserValue() != 0.0f); + } + + WavetableAudioProcessor& proc; + int idx = 0; + gin::ParamComponent::Ptr v; +}; + +//============================================================================== +class FilterADSRArea : public gin::ParamArea +{ +public: + FilterADSRArea (WavetableAudioProcessor& proc_, int idx_) + : proc (proc_), idx (idx_) + { + auto& flt = proc.filterParams[idx]; + + adsr = new gin::ADSRComponent (); + adsr->setParams (flt.attack, flt.decay, flt.sustain, flt.release); + addControl (adsr); + + addControl (a = new gin::Knob (flt.attack)); + addControl (d = new gin::Knob (flt.decay)); + addControl (s = new gin::Knob (flt.sustain)); + addControl (r = new gin::Knob (flt.release)); + + watchParam (flt.amount); + } + + void paramChanged() override + { + gin::ParamArea::paramChanged (); + + auto& flt = proc.filterParams[idx]; + a->setEnabled (flt.amount->getUserValue() != 0.0f); + d->setEnabled (flt.amount->getUserValue() != 0.0f); + s->setEnabled (flt.amount->getUserValue() != 0.0f); + r->setEnabled (flt.amount->getUserValue() != 0.0f); + adsr->setEnabled (flt.amount->getUserValue() != 0.0f); + } + + WavetableAudioProcessor& proc; + int idx; + gin::ParamComponent::Ptr a, d, s, r; + gin::ADSRComponent* adsr; +}; + +//============================================================================== +class MixBox : public gin::ParamBox +{ +public: + MixBox (const juce::String& name, WavetableAudioProcessor& proc_) + : gin::ParamBox (name), proc (proc_) + { + } + + void paramChanged () override + { + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class LFOBox : public gin::ParamBox +{ +public: + LFOBox (const juce::String& name, WavetableAudioProcessor& proc_, int idx_) + : gin::ParamBox (name), proc (proc_), idx (idx_) + { + auto& lfo = proc.lfoParams[idx]; + + addEnable (lfo.enable); + + addControl (r = new gin::Knob (lfo.rate), 0, 0); + addControl (b = new gin::Select (lfo.beat), 0, 0); + addControl (new gin::Knob (lfo.depth, true), 1, 0); + addControl (new gin::Knob (lfo.fade, true), 0, 1); + addControl (new gin::Knob (lfo.delay), 1, 1); + + watchParam (lfo.sync); + + setSize (112, 163); + } + + void paramChanged () override + { + gin::ParamBox::paramChanged (); + + auto& lfo = proc.lfoParams[idx]; + r->setVisible (! lfo.sync->isOn()); + b->setVisible (lfo.sync->isOn()); + } + + WavetableAudioProcessor& proc; + int idx; + gin::ParamComponent::Ptr r, b; +}; + +//============================================================================== +class LFOArea : public gin::ParamArea +{ +public: + LFOArea (WavetableAudioProcessor& proc_, int idx_) + : proc (proc_), idx (idx_) + { + auto& lfo = proc.lfoParams[idx]; + + addControl (new gin::Select (lfo.wave)); + addControl (new gin::Switch (lfo.sync)); + addControl (new gin::Knob (lfo.phase, true)); + addControl (new gin::Knob (lfo.offset, true)); + + auto l = new gin::LFOComponent(); + l->setParams (lfo.wave, lfo.sync, lfo.rate, lfo.beat, lfo.depth, lfo.offset, lfo.phase, lfo.enable); + addControl (l); + + setSize (186, 163); + } + + void paramChanged () override + { + gin::ParamArea::paramChanged (); + } + + WavetableAudioProcessor& proc; + int idx; +}; + +//============================================================================== +class GateBox : public gin::ParamBox +{ +public: + GateBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("Gate"), proc (proc_) + { + addControl (new gin::Select (proc.gateParams.beat), 0, 0); + addControl (new gin::Knob (proc.gateParams.length), 1, 0); + addControl (new gin::Knob (proc.gateParams.attack), 0, 1); + addControl (new gin::Knob (proc.gateParams.release), 1, 1); + + setSize (112, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class GateArea : public gin::ParamArea +{ +public: + GateArea (WavetableAudioProcessor& proc_) + : gin::ParamArea ("Pattern"), proc (proc_) + { + g = new gin::GateEffectComponent(); + g->setParams (proc.gateParams.length, proc.gateParams.l, proc.gateParams.r, proc.gateParams.enable); + addControl (g); + + setSize (272, 163); + } + + void paramChanged () override + { + gin::ParamArea::paramChanged (); + } + + void resized() override + { + g->setBounds (getLocalBounds().withSizeKeepingCentre (getWidth(), 128)); + } + + WavetableAudioProcessor& proc; + gin::GateEffectComponent* g; +}; + +//============================================================================== +class ChorusBox : public gin::ParamBox +{ +public: + ChorusBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("Chorus"), proc (proc_) + { + addControl (new gin::Knob (proc.chorusParams.delay), 0, 0); + addControl (new gin::Knob (proc.chorusParams.rate), 1, 0); + addControl (new gin::Knob (proc.chorusParams.mix), 2, 0); + + addControl (new gin::Knob (proc.chorusParams.depth), 0.5f, 1.0f); + addControl (new gin::Knob (proc.chorusParams.width), 1.5f, 1.0f); + + setSize (168, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class DistortBox : public gin::ParamBox +{ +public: + DistortBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("Distort"), proc (proc_) + { + addControl (new gin::Knob (proc.distortionParams.amount), 0, 0); + addControl (new gin::Knob (proc.distortionParams.highpass), 1, 0); + addControl (new gin::Knob (proc.distortionParams.output), 0, 1); + addControl (new gin::Knob (proc.distortionParams.mix), 1, 1); + + setSize (112, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class EQBox : public gin::ParamBox +{ +public: + EQBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("EQ"), proc (proc_) + { + addControl (new gin::Knob (proc.eqParams.loFreq), 0, 0); + addControl (new gin::Knob (proc.eqParams.loGain), 1, 0); + addControl (new gin::Knob (proc.eqParams.loQ), 2, 0); + addControl (new gin::Knob (proc.eqParams.mid1Freq), 3, 0); + addControl (new gin::Knob (proc.eqParams.mid1Gain), 4, 0); + addControl (new gin::Knob (proc.eqParams.mid1Q), 5, 0); + addControl (new gin::Knob (proc.eqParams.mid2Freq), 0, 1); + addControl (new gin::Knob (proc.eqParams.mid2Gain), 1, 1); + addControl (new gin::Knob (proc.eqParams.mid2Q), 2, 1); + addControl (new gin::Knob (proc.eqParams.hiFreq), 3, 1); + addControl (new gin::Knob (proc.eqParams.hiGain), 4, 1); + addControl (new gin::Knob (proc.eqParams.hiQ), 5, 1); + + setSize (308, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class CompressBox : public gin::ParamBox +{ +public: + CompressBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("Compress"), proc (proc_) + { + addControl (new gin::Knob (proc.compressorParams.ratio), 0, 0); + addControl (new gin::Knob (proc.compressorParams.threshold), 1, 0); + addControl (new gin::Knob (proc.compressorParams.gain), 2, 0); + + addControl (new gin::Knob (proc.compressorParams.attack), 0.5f, 1.0f); + addControl (new gin::Knob (proc.compressorParams.release), 1.5f, 1.0f); + + setSize (168, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class DelayBox : public gin::ParamBox +{ +public: + DelayBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("Delay"), proc (proc_) + { + addControl (t = new gin::Knob (proc.delayParams.time), 0, 0); + addControl (b = new gin::Select (proc.delayParams.beat), 0, 0); + addControl (new gin::Knob (proc.delayParams.fb), 1, 0); + addControl (new gin::Knob (proc.delayParams.cf), 2, 0); + + addControl (new gin::Switch (proc.delayParams.sync), 0, 1); + addControl (new gin::Knob (proc.delayParams.mix), 1.5f, 1.0f); + + watchParam (proc.delayParams.sync); + + setSize (168, 163); + } + + void paramChanged () override + { + gin::ParamBox::paramChanged(); + + t->setVisible (! proc.delayParams.sync->isOn()); + b->setVisible (proc.delayParams.sync->isOn()); + } + + WavetableAudioProcessor& proc; + gin::ParamComponent::Ptr t, b; +}; + +//============================================================================== +class ReverbBox : public gin::ParamBox +{ +public: + ReverbBox (WavetableAudioProcessor& proc_) + : gin::ParamBox ("Reverb"), proc (proc_) + { + addControl (new gin::Knob (proc.reverbParams.damping), 0, 0); + addControl (new gin::Knob (proc.reverbParams.freezeMode), 1, 0); + addControl (new gin::Knob (proc.reverbParams.roomSize), 2, 0); + addControl (new gin::Knob (proc.reverbParams.width), 0.5f, 1.0f); + addControl (new gin::Knob (proc.reverbParams.mix), 1.5f, 1.0f); + + setSize (168, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class LimitBox : public gin::ParamBox +{ +public: + LimitBox (WavetableAudioProcessor& proc_) + : gin::ParamBox (""), proc (proc_) + { + addControl (new gin::Knob (proc.limiterParams.attack), 0, 0); + addControl (new gin::Knob (proc.limiterParams.release), 1, 0); + addControl (new gin::Knob (proc.limiterParams.threshold), 0, 1); + addControl (new gin::Knob (proc.limiterParams.gain), 1, 1); + + setSize (112, 163); + } + + WavetableAudioProcessor& proc; +}; + +//============================================================================== +class ScopeArea : public gin::ParamArea +{ +public: + ScopeArea (WavetableAudioProcessor& proc_) + : gin::ParamArea ("Scope"), proc (proc_) + { + scope = new gin::TriggeredScope (proc.fifo); + scope->setNumChannels (2); + scope->setTriggerMode (gin::TriggeredScope::TriggerMode::Up); + scope->setColour (gin::TriggeredScope::lineColourId, juce::Colours::transparentBlack); + addControl (scope); + + setSize (272, 163); + } + + void resized() override + { + scope->setBounds (getLocalBounds().withSizeKeepingCentre (getWidth(), 140)); + } + + WavetableAudioProcessor& proc; + gin::TriggeredScope* scope; +}; diff --git a/plugin/Source/PluginEditor.cpp b/plugin/Source/PluginEditor.cpp index 33e4f03..0e37624 100644 --- a/plugin/Source/PluginEditor.cpp +++ b/plugin/Source/PluginEditor.cpp @@ -1,28 +1,13 @@ #include "PluginProcessor.h" #include "PluginEditor.h" -using namespace gin; - //============================================================================== WavetableAudioProcessorEditor::WavetableAudioProcessorEditor (WavetableAudioProcessor& p) - : ProcessorEditor (p, 50, 50 + 15), proc (p) + : ProcessorEditor (p), vaProc (p) { - oscHeaders.addChildComponent (modOverview); + addAndMakeVisible (editor); - gin::addAndMakeVisible (*this, { &commonHeader, &common, &unisonHeader }); - - gin::addAndMakeVisible (*this, { &oscHeaders }); - gin::addAndMakeVisible (*this, { &oscillators }); - - gin::addAndMakeVisible (*this, { &FiltersHeader }); - gin::addAndMakeVisible (*this, { &Filters }); - - gin::addAndMakeVisible (*this, { &modulationHeader, &modulation }); - gin::addAndMakeVisible (*this, { &effectsHeader, &effects }); - - oscHeaders.addAndMakeVisible ( usage ); - - setGridSize (14, 8, 0, 3 * 25); + setSize (901, 753); } WavetableAudioProcessorEditor::~WavetableAudioProcessorEditor() @@ -30,59 +15,21 @@ WavetableAudioProcessorEditor::~WavetableAudioProcessorEditor() } //============================================================================== -void WavetableAudioProcessorEditor::paint (Graphics& g) +void WavetableAudioProcessorEditor::paint (juce::Graphics& g) { ProcessorEditor::paint (g); - g.setColour (Colours::white.withAlpha (0.2f)); + titleBar.setShowBrowser (true); - auto rc = getFullGridArea(); - g.drawRect (rc.expanded (1)); + g.fillAll (findColour (gin::PluginLookAndFeel::blackColourId)); } void WavetableAudioProcessorEditor::resized() { ProcessorEditor::resized (); - auto rc = getFullGridArea(); + auto rc = getLocalBounds().reduced (1); + rc.removeFromTop (40); - int hh = 25; - - int gx = getGridWidth(); - int gy = getGridHeight(); - - // Oscillators - { - auto rHeaders = rc.removeFromTop (hh); - oscHeaders.setBounds (rHeaders.removeFromLeft (gx * 14)); - - auto rOscs = rc.removeFromTop (gy * 4); - oscillators.setBounds (rOscs.removeFromLeft (gx * 14)); - - modOverview.setBounds (4, 4, 200, hh - 8); - - usage.setBounds ( oscHeaders.getLocalBounds().removeFromRight (14 * 5 + 2).withSizeKeepingCentre (14 * 5 + 2, 16)); - } - - // ADSR and mod - { - auto rHeaders = rc.removeFromTop (hh); - ampFiltersHeader.setBounds (rHeaders.removeFromLeft (gx * 6)); - modulationHeader.setBounds (rHeaders.removeFromLeft (gx * 8)); - - auto rFilters = rc.removeFromTop (gy * 2); - ampFilters.setBounds (rFilters.removeFromLeft (gx * 6)); - modulation.setBounds (rFilters.removeFromLeft (gx * 8)); - } - - // Effects & Common - { - auto rHeaders = rc.removeFromTop (hh); - effectsHeader.setBounds (rHeaders.removeFromLeft (gx * 10)); - commonHeader.setBounds (rHeaders.removeFromLeft (gx * 4)); - - auto rControls = rc.removeFromTop (gy * 2); - effects.setBounds (rControls.removeFromLeft (gx * 10)); - common.setBounds (rControls.removeFromLeft (gx * 4)); - } + editor.setBounds (rc); } diff --git a/plugin/Source/PluginEditor.h b/plugin/Source/PluginEditor.h index 4546bbb..da47090 100644 --- a/plugin/Source/PluginEditor.h +++ b/plugin/Source/PluginEditor.h @@ -2,7 +2,153 @@ #include #include "PluginProcessor.h" -#include "Boxes.h" +#include "Panels.h" + +//============================================================================== +class Editor : public juce::Component +{ +public: + Editor (WavetableAudioProcessor& proc_) + : proc ( proc_ ) + { + for (auto& o : oscillators) addAndMakeVisible (o); + for (auto& f : filters) addAndMakeVisible (f); + for (auto& a : fltADSR) addAndMakeVisible (a); + for (auto& l : lfos) addAndMakeVisible (l); + for (auto& l : lfoGraphs) addAndMakeVisible (l); + + addAndMakeVisible (mix); + + for (auto& i : modItems) + modHeader.addItem (i); + + addAndMakeVisible (modHeader); + + for (int i = 0; i < Cfg::numLFOs; i++) + { + lfoBox.addBox (i, &lfos[i]); + lfoBox.addBox (i, &lfoGraphs[i]); + } + addAndMakeVisible (lfoBox); + lfoBox.setPage (0); + + for (auto& i : fxItems) + fxHeader.addItem (i); + + addAndMakeVisible (fxHeader); + + effects.addBox (&gate); + effects.addBox (&pattern); + effects.addBox (&chorus); + effects.addBox (&distort); + effects.addBox (&eq); + effects.addBox (&compress); + effects.addBox (&delay); + effects.addBox (&reverb); + effects.addBox (&limit); + effects.addBox (&scope); + + addAndMakeVisible (effects); + + setupCallbacks(); + } + + void setupCallbacks() + { + // LFO mod items + for (int i = 0; i < Cfg::numLFOs; i++) + { + modItems[i].onClick = [this, i] + { + modItems[0].setSelected (i == 0); + modItems[1].setSelected (i == 1); + modItems[2].setSelected (i == 2); + + lfoBox.setPage (i); + }; + } + modItems[0].onClick(); + } + + void resized() override + { + auto rc = getLocalBounds(); + + auto rcOsc = rc.removeFromTop (163); + for (auto& o : oscillators) { o.setBounds (rcOsc.removeFromLeft (224)); rcOsc.removeFromLeft (1); }; + + rc.removeFromTop (1); + + auto rcFlt = rc.removeFromTop (163); + filters[0].setBounds (rcFlt.removeFromLeft (168)); rcFlt.removeFromLeft (1); + fltADSR[0].setBounds (rcFlt.removeFromLeft (186)); rcFlt.removeFromLeft (1); + mix.setBounds (rcFlt.removeFromLeft (187)); rcFlt.removeFromLeft (1); + fltADSR[1].setBounds (rcFlt.removeFromLeft (186)); rcFlt.removeFromLeft (1); + filters[1].setBounds (rcFlt.removeFromLeft (168)); rcFlt.removeFromLeft (1); + + auto rcB1 = rc.removeFromTop (26); + modHeader.setBounds (rcB1); + + auto rcMod = rc.removeFromTop (163); + lfoBox.setBounds (rcMod); + + auto rcB2 = rc.removeFromTop (26); + fxHeader.setBounds (rcB2); + + auto rcFX = rc.removeFromTop (163); + effects.setBounds (rcFX); + } + + WavetableAudioProcessor& proc; + + OscillatorBox oscillators[Cfg::numOSCs] { { "oscillator 1", proc, 0 }, { "oscillator 2", proc, 1 }, + { "oscillator 3", proc, 2 }, { "oscillator 4", proc, 3 } }; + + FilterBox filters[Cfg::numFilters] { { "filter 1", proc, 0 }, { "filter 2", proc, 1 } }; + + FilterADSRArea fltADSR[Cfg::numFilters] { { proc, 0 }, { proc, 1 } }; + + MixBox mix { "osc mix", proc }; + + LFOBox lfos[Cfg::numLFOs] { { "LFO 1", proc, 0 }, { "LFO 2", proc, 1 }, { "LFO 3", proc, 2 } }; + LFOArea lfoGraphs[Cfg::numLFOs] { { proc, 0 }, { proc, 1 }, { proc, 2 } }; + + gin::HeaderItem modItems[8] { { "LFO 1", proc.lfoParams[0].enable, proc.modMatrix, proc.modSrcMonoLFO[0], proc.modSrcLFO[0] }, + { "LFO 2", proc.lfoParams[1].enable, proc.modMatrix, proc.modSrcMonoLFO[1], proc.modSrcLFO[1] }, + { "LFO 3", proc.lfoParams[2].enable, proc.modMatrix, proc.modSrcMonoLFO[2], proc.modSrcLFO[2] }, + { "ENV 1", proc.envParams[0].enable, proc.modMatrix, {}, proc.modSrcEnv[0] }, + { "ENV 2", proc.envParams[1].enable, proc.modMatrix, {}, proc.modSrcEnv[1] }, + { "ENV 3", proc.envParams[2].enable, proc.modMatrix, {}, proc.modSrcEnv[2] }, + { "STEP", proc.stepLfoParams.enable, proc.modMatrix, proc.modSrcMonoStep, proc.modSrcStep }, + { "MIDI", nullptr } }; + gin::HeaderRow modHeader; + + gin::HeaderItem fxItems[8] { { "GATE", proc.gateParams.enable }, + { "CHORUS", proc.chorusParams.enable }, + { "DISTORT", proc.distortionParams.enable }, + { "EQ", proc.eqParams.enable }, + { "COMPRESS", proc.compressorParams.enable }, + { "DELAY", proc.delayParams.enable }, + { "REVERB", proc.reverbParams.enable }, + { "LIMIT", proc.limiterParams.enable } }; + + gin::HeaderRow fxHeader; + + + GateBox gate { proc }; + GateArea pattern { proc }; + ChorusBox chorus { proc }; + DistortBox distort { proc }; + EQBox eq { proc }; + CompressBox compress { proc }; + DelayBox delay { proc }; + ReverbBox reverb { proc }; + LimitBox limit { proc }; + ScopeArea scope { proc }; + + gin::BoxArea lfoBox; + gin::BoxArea effects; +}; //============================================================================== class WavetableAudioProcessorEditor : public gin::ProcessorEditor @@ -12,32 +158,13 @@ public: ~WavetableAudioProcessorEditor() override; //============================================================================== - void paint (Graphics&) override; + void paint (juce::Graphics&) override; void resized() override; private: - WavetableAudioProcessor& proc; + WavetableAudioProcessor& vaProc; - gin::ModulationOverview modOverview { proc.modMatrix }; - - gin::ControlHeader commonHeader { "Common" }; - gin::ControlHeader unisonHeader { "Unison" }; - - CommonBox common { *this, proc }; - - gin::ControlHeader oscHeaders = { "Oscillators" }; - OscillatorBox oscillators = { *this, proc }; - - gin::ControlHeader ampFiltersHeader { "Filter / ADSR" }; - FilterAmpBox ampFilters { *this, proc }; - - gin::ControlHeader modulationHeader { "Modulation" }; - ModulationBox modulation { *this, proc }; - - gin::ControlHeader effectsHeader { "Effects" }; - EffectsBox effects { *this, proc }; - - gin::SynthesiserUsage usage { proc }; + Editor editor { vaProc }; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavetableAudioProcessorEditor) }; diff --git a/plugin/Source/PluginProcessor.cpp b/plugin/Source/PluginProcessor.cpp index fc01145..7f53906 100644 --- a/plugin/Source/PluginProcessor.cpp +++ b/plugin/Source/PluginProcessor.cpp @@ -2,69 +2,69 @@ #include "PluginEditor.h" #include "WavetableVoice.h" -using namespace gin; - -static String waveTextFunction (const Parameter&, float v) +static juce::String waveTextFunction (const gin::Parameter&, float v) { - switch ((Wave)int (v)) + switch ((gin::Wave)int (v)) { - case Wave::sine: return "Sine"; - case Wave::triangle: return "Triangle"; - case Wave::sawUp: return "Saw (Up)"; - case Wave::sawDown: return "Saw (Down)"; - case Wave::pulse: return "Pulse"; - case Wave::square: return "Square"; - case Wave::noise: return "Noise"; + case gin::Wave::silence: return "Off"; + case gin::Wave::sine: return "Sine"; + case gin::Wave::triangle: return "Triangle"; + case gin::Wave::sawUp: return "Saw (Up)"; + case gin::Wave::sawDown: return "Saw (Down)"; + case gin::Wave::pulse: return "Pulse"; + case gin::Wave::square: return "Square"; + case gin::Wave::noise: return "Noise"; + case gin::Wave::wavetable: default: jassertfalse; return {}; } } -static String lfoTextFunction (const Parameter&, float v) +static juce::String lfoTextFunction (const gin::Parameter&, float v) { - switch ((LFO::WaveShape)int (v)) + switch ((gin::LFO::WaveShape)int (v)) { - case LFO::WaveShape::none: return "None"; - case LFO::WaveShape::sine: return "Sine"; - case LFO::WaveShape::triangle: return "Triangle"; - case LFO::WaveShape::sawUp: return "Saw Up"; - case LFO::WaveShape::sawDown: return "Saw Down"; - case LFO::WaveShape::square: return "Square"; - case LFO::WaveShape::squarePos: return "Square+"; - case LFO::WaveShape::sampleAndHold: return "S&H"; - case LFO::WaveShape::noise: return "Noise"; - case LFO::WaveShape::stepUp3: return "Step Up 3"; - case LFO::WaveShape::stepUp4: return "Step Up 4"; - case LFO::WaveShape::stepup8: return "Step Up 8"; - case LFO::WaveShape::stepDown3: return "Step Down 3"; - case LFO::WaveShape::stepDown4: return "Step Down 4"; - case LFO::WaveShape::stepDown8: return "Step Down 8"; - case LFO::WaveShape::pyramid3: return "Pyramid 3"; - case LFO::WaveShape::pyramid5: return "Pyramid 5"; - case LFO::WaveShape::pyramid9: return "Pyramid 9"; + case gin::LFO::WaveShape::none: return "None"; + case gin::LFO::WaveShape::sine: return "Sine"; + case gin::LFO::WaveShape::triangle: return "Triangle"; + case gin::LFO::WaveShape::sawUp: return "Saw Up"; + case gin::LFO::WaveShape::sawDown: return "Saw Down"; + case gin::LFO::WaveShape::square: return "Square"; + case gin::LFO::WaveShape::squarePos: return "Square+"; + case gin::LFO::WaveShape::sampleAndHold: return "S&H"; + case gin::LFO::WaveShape::noise: return "Noise"; + case gin::LFO::WaveShape::stepUp3: return "Step Up 3"; + case gin::LFO::WaveShape::stepUp4: return "Step Up 4"; + case gin::LFO::WaveShape::stepup8: return "Step Up 8"; + case gin::LFO::WaveShape::stepDown3: return "Step Down 3"; + case gin::LFO::WaveShape::stepDown4: return "Step Down 4"; + case gin::LFO::WaveShape::stepDown8: return "Step Down 8"; + case gin::LFO::WaveShape::pyramid3: return "Pyramid 3"; + case gin::LFO::WaveShape::pyramid5: return "Pyramid 5"; + case gin::LFO::WaveShape::pyramid9: return "Pyramid 9"; default: jassertfalse; return {}; } } -static String enableTextFunction (const Parameter&, float v) +static juce::String enableTextFunction (const gin::Parameter&, float v) { return v > 0.0f ? "On" : "Off"; } -static String durationTextFunction (const Parameter&, float v) +static juce::String durationTextFunction (const gin::Parameter&, float v) { - return NoteDuration::getNoteDurations()[size_t (v)].getName(); + return gin::NoteDuration::getNoteDurations()[size_t (v)].getName(); } -static String distortionAmountTextFunction (const Parameter&, float v) +static juce::String distortionAmountTextFunction (const gin::Parameter&, float v) { - return String (v * 5.0f - 1.0f, 1); + return juce::String (v * 5.0f - 1.0f, 1); } -static String filterTextFunction (const Parameter&, float v) +static juce::String filterTextFunction (const gin::Parameter&, float v) { switch (int (v)) { @@ -82,12 +82,12 @@ static String filterTextFunction (const Parameter&, float v) } } -static String freqTextFunction (const Parameter&, float v) +static juce::String freqTextFunction (const gin::Parameter&, float v) { - return String (int (getMidiNoteInHertz (v))); + return juce::String (int (gin::getMidiNoteInHertz (v))); } -static String glideModeTextFunction (const Parameter&, float v) +static juce::String glideModeTextFunction (const gin::Parameter&, float v) { switch (int (v)) { @@ -100,33 +100,13 @@ static String glideModeTextFunction (const Parameter&, float v) } } -//============================================================================== -void WavetableAudioProcessor::WTParams::setup (WavetableAudioProcessor& p, int idx) -{ - String id = "wt" + String (idx + 1); - String nm = "WT" + String (idx + 1) + " "; - - enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, idx == 0 ? 1.0f : 0.0f, 0.0f); - table = p.addExtParam (id + "table", nm + "Table", "Table", "", { 0.0, 1.0, 0.0, 1.0 }, 0.0f, 0.0f); - voices = p.addIntParam (id + "unison", nm + "Unison", "Unison", "", { 1.0, 8.0, 1.0, 1.0 }, 1.0, 0.0f); - voicesTrns = p.addExtParam (id + "unisontrns", nm + "Unison Trns", "LTrans", "st", { -36.0, 36.0, 1.0, 1.0 }, 0.0, 0.0f); - tune = p.addExtParam (id + "tune", nm + "Tune", "Tune", "st", { -36.0, 36.0, 1.0, 1.0 }, 0.0, 0.0f); - finetune = p.addExtParam (id + "finetune", nm + "Fine Tune", "Fine", "ct", { -100.0, 100.0, 0.0, 1.0 }, 0.0, 0.0f); - level = p.addExtParam (id + "level", nm + "Level", "Level", "db", { -100.0, 0.0, 1.0, 4.0 }, 0.0, 0.0f); - detune = p.addExtParam (id + "detune", nm + "Detune", "Detune", "", { 0.0, 0.5, 0.0, 1.0 }, 0.0, 0.0f); - spread = p.addExtParam (id + "spread", nm + "Spread", "Spread", "%", { -100.0, 100.0, 0.0, 1.0 }, 0.0, 0.0f); - pan = p.addExtParam (id + "pan", nm + "Pan", "Pan", "", { -1.0, 1.0, 0.0, 1.0 }, 0.0, 0.0f); - - level->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; -} - //============================================================================== void WavetableAudioProcessor::OSCParams::setup (WavetableAudioProcessor& p, int idx) { - String id = "osc" + String (idx + 1); - String nm = "OSC" + String (idx + 1) + " "; + juce::String id = "osc" + juce::String (idx + 1); + juce::String nm = "OSC" + juce::String (idx + 1) + " "; - enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f); + enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, idx == 0 ? 1.0f : 0.0f, 0.0f); wave = p.addIntParam (id + "wave", nm + "Wave", "Wave", "", { 1.0, 7.0, 1.0, 1.0 }, 1.0, 0.0f, waveTextFunction); voices = p.addIntParam (id + "unison", nm + "Unison", "Unison", "", { 1.0, 8.0, 1.0, 1.0 }, 1.0, 0.0f); voicesTrns = p.addExtParam (id + "unisontrns", nm + "Unison Trns", "LTrans", "st", { -36.0, 36.0, 1.0, 1.0 }, 0.0, 0.0f); @@ -138,16 +118,16 @@ void WavetableAudioProcessor::OSCParams::setup (WavetableAudioProcessor& p, int spread = p.addExtParam (id + "spread", nm + "Spread", "Spread", "%", { -100.0, 100.0, 0.0, 1.0 }, 0.0, 0.0f); pan = p.addExtParam (id + "pan", nm + "Pan", "Pan", "", { -1.0, 1.0, 0.0, 1.0 }, 0.0, 0.0f); - level->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; + level->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; } //============================================================================== void WavetableAudioProcessor::FilterParams::setup (WavetableAudioProcessor& p, int idx) { - String id = "flt" + String (idx + 1); - String nm = "FLT" + String (idx + 1) + " "; + juce::String id = "flt" + juce::String (idx + 1); + juce::String nm = "FLT" + juce::String (idx + 1) + " "; - float maxFreq = float (getMidiNoteFromHertz (20000.0)); + float maxFreq = float (gin::getMidiNoteFromHertz (20000.0)); enable = p.addIntParam (id + "enable", nm + "Enable", "", "", { 0.0, 1.0, 1.0, 1.0 }, idx == 0 ? 1.0f : 0.0f, 0.0f); type = p.addIntParam (id + "type", nm + "Type", "Type", "", { 0.0, 7.0, 1.0, 1.0 }, 0.0, 0.0f, filterTextFunction); @@ -169,8 +149,8 @@ void WavetableAudioProcessor::FilterParams::setup (WavetableAudioProcessor& p, i //============================================================================== void WavetableAudioProcessor::EnvParams::setup (WavetableAudioProcessor& p, int idx) { - String id = "env" + String (idx + 1); - String nm = "ENV" + String (idx + 1) + " "; + juce::String id = "env" + juce::String (idx + 1); + juce::String nm = "ENV" + juce::String (idx + 1) + " "; enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0, 0.0f, enableTextFunction); attack = p.addExtParam (id + "attack", nm + "Attack", "A", "s", { 0.0, 60.0, 0.0, 0.2f }, 0.1f, 0.0f); @@ -184,10 +164,10 @@ void WavetableAudioProcessor::EnvParams::setup (WavetableAudioProcessor& p, int //============================================================================== void WavetableAudioProcessor::LFOParams::setup (WavetableAudioProcessor& p, int idx) { - String id = "lfo" + String (idx + 1); - String nm = "LFO" + String (idx + 1) + " "; + juce::String id = "lfo" + juce::String (idx + 1); + juce::String nm = "LFO" + juce::String (idx + 1) + " "; - auto notes = NoteDuration::getNoteDurations(); + auto notes = gin::NoteDuration::getNoteDurations(); enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f, enableTextFunction); sync = p.addIntParam (id + "sync", nm + "Sync", "Sync", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0, 0.0f, enableTextFunction); @@ -204,10 +184,10 @@ void WavetableAudioProcessor::LFOParams::setup (WavetableAudioProcessor& p, int //============================================================================== void WavetableAudioProcessor::StepLFOParams::setup (WavetableAudioProcessor& p) { - String id = "slfo"; - String nm = "Step LFO"; + juce::String id = "slfo"; + juce::String nm = "Step LFO"; - auto notes = NoteDuration::getNoteDurations(); + auto notes = gin::NoteDuration::getNoteDurations(); enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f, enableTextFunction); beat = p.addIntParam (id + "beat", nm + "Beat", "Beat", "", { 0.0, float (notes.size() - 1), 1.0, 1.0 }, 13.0, 0.0f, durationTextFunction); @@ -215,7 +195,7 @@ void WavetableAudioProcessor::StepLFOParams::setup (WavetableAudioProcessor& p) for (int i = 0; i < 32; i++) { - auto num = String (i + 1); + auto num = juce::String (i + 1); level[i] = p.addIntParam (id + "step" + num, nm + "Step " + num, "", "", { -1.0, 1.0, 0.0, 1.0f }, 0.0f, 0.0f); } } @@ -223,20 +203,20 @@ void WavetableAudioProcessor::StepLFOParams::setup (WavetableAudioProcessor& p) //============================================================================== void WavetableAudioProcessor::GateParams::setup (WavetableAudioProcessor& p) { - String id = "gate"; - String nm = "Gate"; + juce::String id = "gate"; + juce::String nm = "Gate"; - auto notes = NoteDuration::getNoteDurations(); + auto notes = gin::NoteDuration::getNoteDurations(); enable = p.addIntParam (id + "enable", nm + "Enable", "Enable", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f, enableTextFunction); beat = p.addIntParam (id + "beat", nm + "Beat", "Beat", "", { 0.0, float (notes.size() - 1), 1.0, 1.0 }, 7.0, 0.0f, durationTextFunction); length = p.addIntParam (id + "length", nm + "Length", "Length", "", { 2.0, 32.0, 1.0, 1.0f }, 8.0f, 0.0f); - attack = p.addExtParam (id + "attack", nm + "Attack", "A", "s", { 0.0, 60.0, 0.0, 0.2f }, 0.1f, 0.0f); - release = p.addExtParam (id + "release", nm + "Release", "R", "s", { 0.0, 60.0, 0.0, 0.2f }, 0.1f, 0.0f); + attack = p.addExtParam (id + "attack", nm + "Attack", "A", "s", { 0.0, 1.0, 0.0, 0.2f }, 0.1f, 0.0f); + release = p.addExtParam (id + "release", nm + "Release", "R", "s", { 0.0, 1.0, 0.0, 0.2f }, 0.1f, 0.0f); for (int i = 0; i < 32; i++) { - auto num = String (i + 1); + auto num = juce::String (i + 1); l[i] = p.addIntParam (id + "l" + num, nm + "L " + num, "", "", { 0.0, 1.0, 1.0, 1.0f }, (i % 2 == 0 || i % 5 == 0) ? 1.0f : 0.0f, 0.0f); r[i] = p.addIntParam (id + "r" + num, nm + "R " + num, "", "", { 0.0, 1.0, 1.0, 1.0f }, (i % 2 == 0 || i % 5 == 0) ? 1.0f : 0.0f, 0.0f); } @@ -266,7 +246,7 @@ void WavetableAudioProcessor::GlobalParams::setup (WavetableAudioProcessor& p) voices = p.addIntParam ("voices", "Voices", "", "", { 2.0, 40.0, 1.0, 1.0 }, 40.0f, 0.0f); mpe = p.addIntParam ("mpe", "MPE", "", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f, enableTextFunction); - level->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; + level->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; } //============================================================================== @@ -296,11 +276,11 @@ void WavetableAudioProcessor::DistortionParams::setup (WavetableAudioProcessor& //============================================================================== void WavetableAudioProcessor::EQParams::setup (WavetableAudioProcessor& p) { - float maxFreq = float (getMidiNoteFromHertz (20000.0)); - float d1 = float (getMidiNoteFromHertz (80.0)); - float d2 = float (getMidiNoteFromHertz (3000.0)); - float d3 = float (getMidiNoteFromHertz (5000.0)); - float d4 = float (getMidiNoteFromHertz (17000.0)); + float maxFreq = float (gin::getMidiNoteFromHertz (20000.0)); + float d1 = float (gin::getMidiNoteFromHertz (80.0)); + float d2 = float (gin::getMidiNoteFromHertz (3000.0)); + float d3 = float (gin::getMidiNoteFromHertz (5000.0)); + float d4 = float (gin::getMidiNoteFromHertz (17000.0)); enable = p.addIntParam ("eqEnable", "Enable", "", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f, enableTextFunction); @@ -320,15 +300,15 @@ void WavetableAudioProcessor::EQParams::setup (WavetableAudioProcessor& p) hiQ = p.addExtParam ("eqHiQ", "Hi Q", "Q", "", { 0.025f, 40.0f, 0.0, 0.2f }, 1.0f, 0.0f); hiGain = p.addExtParam ("eqHiGain", "Hi Gain", "Gain", "dB", { -20.0f, 20.0f, 0.0, 1.0 }, 0.0f, 0.0f); - loFreq->conversionFunction = [] (float in) { return getMidiNoteInHertz (in); }; - mid1Freq->conversionFunction = [] (float in) { return getMidiNoteInHertz (in); }; - mid2Freq->conversionFunction = [] (float in) { return getMidiNoteInHertz (in); }; - hiFreq->conversionFunction = [] (float in) { return getMidiNoteInHertz (in); }; + loFreq->conversionFunction = [] (float in) { return gin::getMidiNoteInHertz (in); }; + mid1Freq->conversionFunction = [] (float in) { return gin::getMidiNoteInHertz (in); }; + mid2Freq->conversionFunction = [] (float in) { return gin::getMidiNoteInHertz (in); }; + hiFreq->conversionFunction = [] (float in) { return gin::getMidiNoteInHertz (in); }; - loGain->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; - mid1Gain->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; - mid2Gain->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; - hiGain->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; + loGain->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; + mid1Gain->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; + mid2Gain->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; + hiGain->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; } //============================================================================== @@ -344,7 +324,7 @@ void WavetableAudioProcessor::CompressorParams::setup (WavetableAudioProcessor& attack->conversionFunction = [] (float in) { return in / 1000.0f; }; release->conversionFunction = [] (float in) { return in / 1000.0f; }; - gain->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; + gain->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; } //============================================================================== @@ -352,7 +332,7 @@ void WavetableAudioProcessor::DelayParams::setup (WavetableAudioProcessor& p) { enable = p.addIntParam ("dlEnable", "Enable", "", "", { 0.0, 1.0, 1.0, 1.0 }, 0.0f, 0.0f, enableTextFunction); - float mxd = float (NoteDuration::getNoteDurations().size()) - 1.0f; + float mxd = float (gin::NoteDuration::getNoteDurations().size()) - 1.0f; sync = p.addExtParam ("dlSync", "Sync", "", "", { 0.0f, 1.0f, 1.0f, 1.0f}, 0.0f, 0.0f, enableTextFunction); time = p.addExtParam ("dlTime", "Delay", "", "", { 0.0f, 120.0f, 0.0f, 0.3f}, 1.0f, 0.0f); @@ -361,10 +341,10 @@ void WavetableAudioProcessor::DelayParams::setup (WavetableAudioProcessor& p) cf = p.addExtParam ("dlCf", "CF", "", "dB", {-100.0f, 0.0f, 0.0f, 5.0f}, -100.0f, 0.1f); mix = p.addExtParam ("dlMix", "Mix", "", "%", { 0.0f, 100.0f, 0.0f, 1.0f}, 0.5f, 0.1f); - delay = p.addIntParam ("dlDelay", "Delay", "", "", { 0.0f, 120.0f, 0.0f, 1.0f}, 1.0f, {0.2f, SmoothingType::eased}); + delay = p.addIntParam ("dlDelay", "Delay", "", "", { 0.0f, 120.0f, 0.0f, 1.0f}, 1.0f, {0.2f, gin::SmoothingType::eased}); - fb->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; - cf->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; + fb->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; + cf->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; mix->conversionFunction = [] (float in) { return in / 100.0f; }; } @@ -392,30 +372,27 @@ void WavetableAudioProcessor::LimiterParams::setup (WavetableAudioProcessor& p) attack->conversionFunction = [] (float in) { return in / 1000.0f; }; release->conversionFunction = [] (float in) { return in / 1000.0f; }; - gain->conversionFunction = [] (float in) { return Decibels::decibelsToGain (in); }; + gain->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; } //============================================================================== WavetableAudioProcessor::WavetableAudioProcessor() { - formatManager->registerBasicFormats(); + lf = std::make_unique(); enableLegacyMode(); setVoiceStealingEnabled (true); - for (int i = 0; i < numElementsInArray (wtParams); i++) - wtParams[i].setup (*this, i); - - for (int i = 0; i < numElementsInArray (oscParams); i++) + for (int i = 0; i < juce::numElementsInArray (oscParams); i++) oscParams[i].setup (*this, i); - for (int i = 0; i < numElementsInArray (filterParams); i++) + for (int i = 0; i < juce::numElementsInArray (filterParams); i++) filterParams[i].setup (*this, i); - for (int i = 0; i < numElementsInArray (envParams); i++) + for (int i = 0; i < juce::numElementsInArray (envParams); i++) envParams[i].setup (*this, i); - for (int i = 0; i < numElementsInArray (lfoParams); i++) + for (int i = 0; i < juce::numElementsInArray (lfoParams); i++) lfoParams[i].setup (*this, i); stepLfoParams.setup (*this); @@ -443,9 +420,6 @@ WavetableAudioProcessor::WavetableAudioProcessor() } setupModMatrix(); - - MemoryBlock mb (BinaryData::WINDOW_S_WAV, BinaryData::WINDOW_S_WAVSize); - updateWavetable (0, mb, 256); } WavetableAudioProcessor::~WavetableAudioProcessor() @@ -476,27 +450,27 @@ void WavetableAudioProcessor::setupModMatrix() for (int i = 0; i <= 119; i++) { - String name = MidiMessage::getControllerName (i); + juce::String name = juce::MidiMessage::getControllerName (i); if (name.isEmpty()) - modSrcCC.add (modMatrix.addMonoModSource (String::formatted ("cc%d", i), String::formatted ("CC %d", i), false)); + modSrcCC.add (modMatrix.addMonoModSource (juce::String::formatted ("cc%d", i), juce::String::formatted ("CC %d", i), false)); else - modSrcCC.add (modMatrix.addMonoModSource (String::formatted ("cc%d", i), String::formatted ("CC %d ", i) + name, false)); + modSrcCC.add (modMatrix.addMonoModSource (juce::String::formatted ("cc%d", i), juce::String::formatted ("CC %d ", i) + name, false)); } for (int i = 0; i < Cfg::numLFOs; i++) - modSrcMonoLFO.add (modMatrix.addMonoModSource (String::formatted ("mlfo%d", i + 1), String::formatted ("LFO %d (Mono)", i + 1), true)); + modSrcMonoLFO.add (modMatrix.addMonoModSource (juce::String::formatted ("mlfo%d", i + 1), juce::String::formatted ("LFO %d (Mono)", i + 1), true)); for (int i = 0; i < Cfg::numLFOs; i++) - modSrcLFO.add (modMatrix.addPolyModSource (String::formatted ("lfo%d", i + 1), String::formatted ("LFO %d", i + 1), true)); + modSrcLFO.add (modMatrix.addPolyModSource (juce::String::formatted ("lfo%d", i + 1), juce::String::formatted ("LFO %d", i + 1), true)); modSrcMonoStep = modMatrix.addMonoModSource ("mstep", "Step LFO (Mono)", true); modSrcStep = modMatrix.addPolyModSource ("step", "Step LFO", true); for (int i = 0; i < Cfg::numFilters; i++) - modSrcFilter.add (modMatrix.addPolyModSource (String::formatted ("fenv%d", i + 1), String::formatted ("Filter Envelope %d", i + 1), false)); + modSrcFilter.add (modMatrix.addPolyModSource (juce::String::formatted ("fenv%d", i + 1), juce::String::formatted ("Filter Envelope %d", i + 1), false)); for (int i = 0; i < Cfg::numENVs; i++) - modSrcEnv.add (modMatrix.addPolyModSource (String::formatted ("env%d", i + 1), String::formatted ("Envelope %d", i + 1), false)); + modSrcEnv.add (modMatrix.addPolyModSource (juce::String::formatted ("env%d", i + 1), juce::String::formatted ("Envelope %d", i + 1), false)); auto firstMonoParam = globalParams.mono; bool polyParam = true; @@ -565,9 +539,9 @@ void WavetableAudioProcessor::releaseResources() { } -void WavetableAudioProcessor::processBlock (AudioBuffer& buffer, MidiBuffer& midi) +void WavetableAudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midi) { - ScopedNoDenormals noDenormals; + juce::ScopedNoDenormals noDenormals; startBlock(); setMPE (globalParams.mpe->isOn()); @@ -594,8 +568,8 @@ void WavetableAudioProcessor::processBlock (AudioBuffer& buffer, MidiBuff renderNextBlock (buffer, midi, pos, thisBlock); - auto slice = sliceBuffer (buffer, pos, thisBlock); - applyEffects (slice); + auto bufferSlice = gin::sliceBuffer (buffer, pos, thisBlock); + applyEffects (bufferSlice); modMatrix.finishBlock (thisBlock); @@ -609,9 +583,9 @@ void WavetableAudioProcessor::processBlock (AudioBuffer& buffer, MidiBuff endBlock (buffer.getNumSamples()); } -Array WavetableAudioProcessor::getLiveFilterCutoff (int i) +juce::Array WavetableAudioProcessor::getLiveFilterCutoff (int i) { - Array values; + juce::Array values; for (auto v : voices) { @@ -624,7 +598,7 @@ Array WavetableAudioProcessor::getLiveFilterCutoff (int i) return values; } -void WavetableAudioProcessor::applyEffects (AudioSampleBuffer& buffer) +void WavetableAudioProcessor::applyEffects (juce::AudioSampleBuffer& buffer) { // Apply gate if (gateParams.enable->isOn()) @@ -669,15 +643,15 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) { if (lfoParams[i].enable->isOn()) { - LFO::Parameters params; + gin::LFO::Parameters params; float freq = 0; if (lfoParams[i].sync->getProcValue() > 0.0f) - freq = 1.0f / NoteDuration::getNoteDurations()[size_t (lfoParams[i].beat->getProcValue())].toSeconds (playhead); + freq = 1.0f / gin::NoteDuration::getNoteDurations()[size_t (lfoParams[i].beat->getProcValue())].toSeconds (playhead); else freq = modMatrix.getValue (lfoParams[i].rate); - params.waveShape = (LFO::WaveShape) int (lfoParams[i].wave->getProcValue()); + params.waveShape = (gin::LFO::WaveShape) int (lfoParams[i].wave->getProcValue()); params.frequency = freq; params.phase = modMatrix.getValue (lfoParams[i].phase); params.offset = modMatrix.getValue (lfoParams[i].offset); @@ -699,7 +673,7 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) // Update Mono Step LFO if (stepLfoParams.enable->isOn()) { - float freq = 1.0f / NoteDuration::getNoteDurations()[size_t (stepLfoParams.beat->getProcValue())].toSeconds (playhead); + float freq = 1.0f / gin::NoteDuration::getNoteDurations()[size_t (stepLfoParams.beat->getProcValue())].toSeconds (playhead); modStepLFO.setFreq (freq); @@ -720,7 +694,7 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) // Update Gate if (gateParams.enable->isOn()) { - float freq = 1.0f / NoteDuration::getNoteDurations()[size_t (gateParams.beat->getProcValue())].toSeconds (playhead); + float freq = 1.0f / gin::NoteDuration::getNoteDurations()[size_t (gateParams.beat->getProcValue())].toSeconds (playhead); int n = int (gateParams.length->getProcValue()); @@ -757,22 +731,22 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) // Update EQ if (eqParams.enable->isOn()) { - eq.setParams (0, EQ::lowshelf, + eq.setParams (0, gin::EQ::lowshelf, modMatrix.getValue (eqParams.loFreq), modMatrix.getValue (eqParams.loQ), modMatrix.getValue (eqParams.loGain)); - eq.setParams (1, EQ::peak, + eq.setParams (1, gin::EQ::peak, modMatrix.getValue (eqParams.mid1Freq), modMatrix.getValue (eqParams.mid1Q), modMatrix.getValue (eqParams.mid1Gain)); - eq.setParams (2, EQ::peak, + eq.setParams (2, gin::EQ::peak, modMatrix.getValue (eqParams.mid2Freq), modMatrix.getValue (eqParams.mid2Q), modMatrix.getValue (eqParams.mid2Gain)); - eq.setParams (3, EQ::highshelf, + eq.setParams (3, gin::EQ::highshelf, modMatrix.getValue (eqParams.hiFreq), modMatrix.getValue (eqParams.hiQ), modMatrix.getValue (eqParams.hiGain)); @@ -784,6 +758,7 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) compressor.setInputGain (1.0f); compressor.setOutputGain (modMatrix.getValue (compressorParams.gain)); compressor.setParams (modMatrix.getValue (compressorParams.attack), + 0, modMatrix.getValue (compressorParams.release), modMatrix.getValue (compressorParams.threshold), modMatrix.getValue (compressorParams.ratio), @@ -795,7 +770,7 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) { if (delayParams.sync->isOn()) { - auto& duration = NoteDuration::getNoteDurations()[(size_t)delayParams.beat->getUserValueInt()]; + auto& duration = gin::NoteDuration::getNoteDurations()[(size_t)delayParams.beat->getUserValueInt()]; delayParams.delay->setUserValue (duration.toSeconds (getPlayHead())); } else @@ -813,10 +788,10 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) // Update Reverb if (reverbParams.enable->isOn()) { - Reverb::Parameters p; + juce::Reverb::Parameters p; auto mix = modMatrix.getValue (reverbParams.mix); - WetDryMix wetDry (mix); + gin::WetDryMix wetDry (mix); p.damping = modMatrix.getValue (reverbParams.damping); p.freezeMode = modMatrix.getValue (reverbParams.freezeMode); @@ -834,6 +809,7 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) limiter.setInputGain (1.0f); limiter.setOutputGain (modMatrix.getValue (limiterParams.gain)); limiter.setParams (modMatrix.getValue (limiterParams.attack), + 0, modMatrix.getValue (limiterParams.release), modMatrix.getValue (limiterParams.threshold), 100, 6); @@ -843,7 +819,7 @@ void WavetableAudioProcessor::updateParams (int newBlockSize) outputGain.setGain (modMatrix.getValue (globalParams.level)); } -void WavetableAudioProcessor::handleMidiEvent (const MidiMessage& m) +void WavetableAudioProcessor::handleMidiEvent (const juce::MidiMessage& m) { MPESynthesiser::handleMidiEvent (m); @@ -856,36 +832,20 @@ void WavetableAudioProcessor::handleController ([[maybe_unused]] int ch, int num modMatrix.setMonoValue (modSrcCC[num], val / 127.0f); } -void WavetableAudioProcessor::updateWavetable (int idx, MemoryBlock& src, int tableSize) -{ - if (auto reader = std::unique_ptr (formatManager->createReaderFor (std::make_unique (src, false)))) - { - AudioSampleBuffer buffer; - buffer.setSize (1, int (reader->lengthInSamples)); - reader->read (&buffer, 0, int (reader->lengthInSamples), 0, true, false); - - loadWavetables (waveTables[idx], buffer, reader->sampleRate, tableSize); - - for (auto v : voices) - if (auto wtv = dynamic_cast(v)) - wtv->setWavetable (idx, waveTables[idx]); - } -} - //============================================================================== bool WavetableAudioProcessor::hasEditor() const { return true; } -AudioProcessorEditor* WavetableAudioProcessor::createEditor() +juce::AudioProcessorEditor* WavetableAudioProcessor::createEditor() { return new WavetableAudioProcessorEditor (*this); } //============================================================================== // This creates new instances of the plugin.. -AudioProcessor* JUCE_CALLTYPE createPluginFilter() +juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new WavetableAudioProcessor(); } diff --git a/plugin/Source/PluginProcessor.h b/plugin/Source/PluginProcessor.h index c2b5778..5161c85 100644 --- a/plugin/Source/PluginProcessor.h +++ b/plugin/Source/PluginProcessor.h @@ -6,7 +6,7 @@ //============================================================================== class WavetableAudioProcessor : public gin::Processor, - public gin::Synthesiser + public gin::Synthesiser { public: //============================================================================== @@ -21,10 +21,10 @@ public: void prepareToPlay (double sampleRate, int samplesPerBlock) override; void releaseResources() override; - void processBlock (AudioBuffer&, MidiBuffer&) override; + void processBlock (juce::AudioBuffer&, juce::MidiBuffer&) override; //============================================================================== - AudioProcessorEditor* createEditor() override; + juce::AudioProcessorEditor* createEditor() override; bool hasEditor() const override; void updateParams (int blockSize); @@ -33,25 +33,12 @@ public: gin::BandLimitedLookupTables bandLimitedLookupTables; //============================================================================== - void handleMidiEvent (const MidiMessage& m) override; + void handleMidiEvent (const juce::MidiMessage& m) override; void handleController (int ch, int num, int val) override; //============================================================================== - Array getLiveFilterCutoff (int idx); + juce::Array getLiveFilterCutoff (int idx); - void applyEffects (AudioSampleBuffer& buffer); - - // WT Params - struct WTParams - { - WTParams() = default; - - gin::Parameter::Ptr enable, table, voices, voicesTrns, tune, finetune, - level, detune, spread, pan; - - void setup (WavetableAudioProcessor& p, int idx); - - JUCE_DECLARE_NON_COPYABLE (WTParams) - }; + void applyEffects (juce::AudioSampleBuffer& buffer); // Voice Params struct OSCParams @@ -230,19 +217,14 @@ public: JUCE_DECLARE_NON_COPYABLE (LimiterParams) }; - //============================================================================== - void updateWavetable (int idx, MemoryBlock& src, int tableSize); - //============================================================================== gin::ModSrcId modSrcPressure, modSrcTimbre, modScrPitchBend, modSrcNote, modSrcVelocity, modSrcStep, modSrcMonoStep; - Array modSrcCC, modSrcMonoLFO, modSrcLFO, modSrcFilter, modSrcEnv; + juce::Array modSrcCC, modSrcMonoLFO, modSrcLFO, modSrcFilter, modSrcEnv; //============================================================================== - SharedResourcePointer formatManager; - WTParams wtParams[Cfg::numWTs]; OSCParams oscParams[Cfg::numOSCs]; FilterParams filterParams[Cfg::numFilters]; EnvParams envParams[Cfg::numENVs]; @@ -269,7 +251,7 @@ public: gin::Dynamics compressor; gin::Dynamics limiter; gin::EQ eq {4}; - Reverb reverb; + juce::Reverb reverb; gin::GainProcessor outputGain; gin::AudioFifo fifo { 2, 44100 }; @@ -279,9 +261,7 @@ public: gin::LFO modLFOs[Cfg::numLFOs]; gin::StepLFO modStepLFO; - AudioPlayHead* playhead = nullptr; - - OwnedArray waveTables[Cfg::numWTs]; + juce::AudioPlayHead* playhead = nullptr; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavetableAudioProcessor) diff --git a/plugin/Source/WavetableVoice.cpp b/plugin/Source/WavetableVoice.cpp index 4509358..99fd7a7 100644 --- a/plugin/Source/WavetableVoice.cpp +++ b/plugin/Source/WavetableVoice.cpp @@ -1,10 +1,8 @@ #include "WavetableVoice.h" #include "PluginProcessor.h" -using namespace gin; - //============================================================================== -WavetableVoice::WavetableVoice (WavetableAudioProcessor& p, BandLimitedLookupTables& bllt) +WavetableVoice::WavetableVoice (WavetableAudioProcessor& p, gin::BandLimitedLookupTables& bllt) : proc (p) , bandLimitedLookupTables (bllt) { @@ -12,11 +10,6 @@ WavetableVoice::WavetableVoice (WavetableAudioProcessor& p, BandLimitedLookupTab f.setNumChannels (2); } -void WavetableVoice::setWavetable (int idx, OwnedArray& table) -{ - wtOscillators[idx].setWavetable (table); -} - void WavetableVoice::noteStarted() { fastKill = false; @@ -38,7 +31,7 @@ void WavetableVoice::noteStarted() proc.modMatrix.setPolyValue (*this, proc.modSrcTimbre, note.initialTimbre.asUnsignedFloat()); proc.modMatrix.setPolyValue (*this, proc.modSrcPressure, note.pressure.asUnsignedFloat()); - ScopedValueSetter svs (disableSmoothing, true); + juce::ScopedValueSetter svs (disableSmoothing, true); for (auto& f : filters) f.reset(); @@ -56,10 +49,7 @@ void WavetableVoice::noteStarted() snapParams(); updateParams (0); snapParams(); - - for (auto& osc : wtOscillators) - osc.noteOn(); - + for (auto& osc : oscillators) osc.noteOn(); @@ -99,9 +89,6 @@ void WavetableVoice::noteRetriggered() updateParams (0); - for (auto& osc : wtOscillators) - osc.noteOn(); - for (auto& osc : oscillators) osc.noteOn(); @@ -148,9 +135,6 @@ void WavetableVoice::setCurrentSampleRate (double newRate) { MPESynthesiserVoice::setCurrentSampleRate (newRate); - for (auto& osc : wtOscillators) - osc.setSampleRate (newRate); - for (auto& osc : oscillators) osc.setSampleRate (newRate); @@ -168,34 +152,30 @@ void WavetableVoice::setCurrentSampleRate (double newRate) adsr.setSampleRate (newRate); } -void WavetableVoice::renderNextBlock (AudioBuffer& outputBuffer, int startSample, int numSamples) +void WavetableVoice::renderNextBlock (juce::AudioBuffer& outputBuffer, int startSample, int numSamples) { updateParams (numSamples); // Run OSC - ScratchBuffer buffer (2, numSamples); - - for (int i = 0; i < Cfg::numWTs; i++) - if (proc.wtParams[i].enable->isOn()) - wtOscillators[i].processAdding (currentMidiNotes[i], wtParams[i], buffer); + gin::ScratchBuffer buffer (2, numSamples); for (int i = 0; i < Cfg::numOSCs; i++) if (proc.oscParams[i].enable->isOn()) - oscillators[i].processAdding (currentMidiNotes[Cfg::numWTs + i], oscParams[i], buffer); + oscillators[i].processAdding (currentMidiNotes[i], oscParams[i], buffer); // Apply velocity float velocity = currentlyPlayingNote.noteOnVelocity.asUnsignedFloat(); - buffer.applyGain (velocityToGain (velocity, ampKeyTrack)); + buffer.applyGain (gin::velocityToGain (velocity, ampKeyTrack)); // Apply filters - for (int i = 0; i < numElementsInArray (filters); i++) + for (int i = 0; i < juce::numElementsInArray (filters); i++) if (proc.filterParams[i].enable->isOn()) filters[i].process (buffer); // Run ADSR adsr.processMultiplying (buffer); - if (adsr.getState() == AnalogADSR::State::idle) + if (adsr.getState() == gin::AnalogADSR::State::idle) { clearCurrentNote(); stopVoice(); @@ -214,34 +194,16 @@ void WavetableVoice::updateParams (int blockSize) proc.modMatrix.setPolyValue (*this, proc.modSrcNote, note.initialNote / 127.0f); - for (int i = 0; i < Cfg::numWTs; i++) - { - if (! proc.wtParams[i].enable->isOn()) continue; - - currentMidiNotes[i] = noteSmoother.getCurrentValue() * 127.0f; - if (glideInfo.glissando) currentMidiNotes[i] = roundToInt (currentMidiNotes[i]); - currentMidiNotes[i] += float (note.totalPitchbendInSemitones); - currentMidiNotes[i] += getValue (proc.wtParams[i].tune) + getValue (proc.wtParams[i].finetune) / 100.0f; - - wtParams[i].voices = int (proc.wtParams[i].voices->getProcValue()); - wtParams[i].vcTrns = int (proc.wtParams[i].voicesTrns->getProcValue()); - wtParams[i].pw = getValue (proc.wtParams[i].table); - wtParams[i].pan = getValue (proc.wtParams[i].pan); - wtParams[i].spread = getValue (proc.wtParams[i].spread) / 100.0f; - wtParams[i].detune = getValue (proc.wtParams[i].detune); - wtParams[i].gain = getValue (proc.wtParams[i].level); - } - for (int i = 0; i < Cfg::numOSCs; i++) { if (! proc.oscParams[i].enable->isOn()) continue; - currentMidiNotes[Cfg::numWTs + i] = noteSmoother.getCurrentValue() * 127.0f; - if (glideInfo.glissando) currentMidiNotes[Cfg::numWTs + i] = roundToInt (currentMidiNotes[Cfg::numWTs + i]); - currentMidiNotes[Cfg::numWTs + i] += float (note.totalPitchbendInSemitones); - currentMidiNotes[Cfg::numWTs + i] += getValue (proc.oscParams[i].tune) + getValue (proc.oscParams[i].finetune) / 100.0f; + currentMidiNotes[i] = noteSmoother.getCurrentValue() * 127.0f; + if (glideInfo.glissando) currentMidiNotes[i] = (float) juce::roundToInt (currentMidiNotes[i]); + currentMidiNotes[i] += float (note.totalPitchbendInSemitones); + currentMidiNotes[i] += getValue (proc.oscParams[i].tune) + getValue (proc.oscParams[i].finetune) / 100.0f; - oscParams[i].wave = (Wave) int (proc.oscParams[i].wave->getProcValue()); + oscParams[i].wave = (gin::Wave) int (proc.oscParams[i].wave->getProcValue()); oscParams[i].voices = int (proc.oscParams[i].voices->getProcValue()); oscParams[i].vcTrns = int (proc.oscParams[i].voicesTrns->getProcValue()); oscParams[i].pw = getValue (proc.oscParams[i].pulsewidth) / 100.0f; @@ -268,7 +230,7 @@ void WavetableVoice::updateParams (int blockSize) filterADSRs[i].process (blockSize); - float filterWidth = float (getMidiNoteFromHertz (20000.0)); + float filterWidth = float (gin::getMidiNoteFromHertz (20000.0)); float filterEnv = filterADSRs[i].getOutput(); float filterSens = getValue (proc.filterParams[i].velocityTracking); filterSens = currentlyPlayingNote.noteOnVelocity.asUnsignedFloat() * filterSens + 1.0f - filterSens; @@ -277,45 +239,45 @@ void WavetableVoice::updateParams (int blockSize) n += (currentlyPlayingNote.initialNote - 60) * getValue (proc.filterParams[i].keyTracking); n += filterEnv * filterSens * getValue (proc.filterParams[i].amount) * filterWidth; - float f = getMidiNoteInHertz (n); + float f = gin::getMidiNoteInHertz (n); float maxFreq = std::min (20000.0f, float (getSampleRate() / 2)); - f = jlimit (4.0f, maxFreq, f); + f = juce::jlimit (4.0f, maxFreq, f); - float q = Q / (1.0f - (getValue (proc.filterParams[i].resonance) / 100.0f) * 0.99f); + float q = gin::Q / (1.0f - (getValue (proc.filterParams[i].resonance) / 100.0f) * 0.99f); switch (int (proc.filterParams[i].type->getProcValue())) { case 0: - filters[i].setType (Filter::lowpass); - filters[i].setSlope (Filter::db12); + filters[i].setType (gin::Filter::lowpass); + filters[i].setSlope (gin::Filter::db12); break; case 1: - filters[i].setType (Filter::lowpass); - filters[i].setSlope (Filter::db24); + filters[i].setType (gin::Filter::lowpass); + filters[i].setSlope (gin::Filter::db24); break; case 2: - filters[i].setType (Filter::highpass); - filters[i].setSlope (Filter::db12); + filters[i].setType (gin::Filter::highpass); + filters[i].setSlope (gin::Filter::db12); break; case 3: - filters[i].setType (Filter::highpass); - filters[i].setSlope (Filter::db24); + filters[i].setType (gin::Filter::highpass); + filters[i].setSlope (gin::Filter::db24); break; case 4: - filters[i].setType (Filter::bandpass); - filters[i].setSlope (Filter::db12); + filters[i].setType (gin::Filter::bandpass); + filters[i].setSlope (gin::Filter::db12); break; case 5: - filters[i].setType (Filter::bandpass); - filters[i].setSlope (Filter::db24); + filters[i].setType (gin::Filter::bandpass); + filters[i].setSlope (gin::Filter::db24); break; case 6: - filters[i].setType (Filter::notch); - filters[i].setSlope (Filter::db12); + filters[i].setType (gin::Filter::notch); + filters[i].setSlope (gin::Filter::db12); break; case 7: - filters[i].setType (Filter::notch); - filters[i].setSlope (Filter::db24); + filters[i].setType (gin::Filter::notch); + filters[i].setSlope (gin::Filter::db24); break; } @@ -347,15 +309,15 @@ void WavetableVoice::updateParams (int blockSize) { if (proc.lfoParams[i].enable->isOn()) { - LFO::Parameters params; + gin::LFO::Parameters params; float freq = 0; if (proc.lfoParams[i].sync->getProcValue() > 0.0f) - freq = 1.0f / NoteDuration::getNoteDurations()[size_t (proc.lfoParams[i].beat->getProcValue())].toSeconds (proc.playhead); + freq = 1.0f / gin::NoteDuration::getNoteDurations()[size_t (proc.lfoParams[i].beat->getProcValue())].toSeconds (proc.playhead); else freq = getValue (proc.lfoParams[i].rate); - params.waveShape = (LFO::WaveShape) int (proc.lfoParams[i].wave->getProcValue()); + params.waveShape = (gin::LFO::WaveShape) int (proc.lfoParams[i].wave->getProcValue()); params.frequency = freq; params.phase = getValue (proc.lfoParams[i].phase); params.offset = getValue (proc.lfoParams[i].offset); @@ -377,7 +339,7 @@ void WavetableVoice::updateParams (int blockSize) // Update Step LFO if (proc.stepLfoParams.enable->isOn()) { - float freq = 1.0f / NoteDuration::getNoteDurations()[size_t (proc.stepLfoParams.beat->getProcValue())].toSeconds (proc.playhead); + float freq = 1.0f / gin::NoteDuration::getNoteDurations()[size_t (proc.stepLfoParams.beat->getProcValue())].toSeconds (proc.playhead); modStepLFO.setFreq (freq); @@ -411,5 +373,5 @@ bool WavetableVoice::isVoiceActive() float WavetableVoice::getFilterCutoffNormalized (int idx) { float freq = filters[idx].getFrequency(); - return proc.filterParams[idx].frequency->getUserRange().convertTo0to1 (getMidiNoteFromHertz (freq)); + return proc.filterParams[idx].frequency->getUserRange().convertTo0to1 (gin::getMidiNoteFromHertz (freq)); } diff --git a/plugin/Source/WavetableVoice.h b/plugin/Source/WavetableVoice.h index ae73949..6101193 100644 --- a/plugin/Source/WavetableVoice.h +++ b/plugin/Source/WavetableVoice.h @@ -7,13 +7,11 @@ class WavetableAudioProcessor; //============================================================================== class WavetableVoice : public gin::SynthesiserVoice, - public gin::ModVoice + public gin::ModVoice { public: WavetableVoice (WavetableAudioProcessor& p, gin::BandLimitedLookupTables& bandLimitedLookupTables); - - void setWavetable (int idx, OwnedArray& table); - + void noteStarted() override; void noteRetriggered() override; void noteStopped (bool allowTailOff) override; @@ -25,7 +23,7 @@ public: void setCurrentSampleRate (double newRate) override; - void renderNextBlock (AudioBuffer& outputBuffer, int startSample, int numSamples) override; + void renderNextBlock (juce::AudioBuffer& outputBuffer, int startSample, int numSamples) override; bool isVoiceActive() override; @@ -37,10 +35,12 @@ private: WavetableAudioProcessor& proc; gin::BandLimitedLookupTables& bandLimitedLookupTables; - gin::WTVoicedStereoOscillator wtOscillators[Cfg::numWTs]; gin::BLLTVoicedStereoOscillator oscillators[Cfg::numOSCs] = { bandLimitedLookupTables, + bandLimitedLookupTables, + bandLimitedLookupTables, + bandLimitedLookupTables, }; gin::Filter filters[Cfg::numFilters]; @@ -52,9 +52,7 @@ private: gin::AnalogADSR adsr; - float currentMidiNotes[Cfg::numWTs + Cfg::numOSCs]; - - gin::WTVoicedStereoOscillator::Params wtParams[Cfg::numWTs]; + float currentMidiNotes[Cfg::numOSCs]; gin::BLLTVoicedStereoOscillator::Params oscParams[Cfg::numOSCs]; gin::EasedValueSmoother noteSmoother; diff --git a/plugin/Wavetable.jucer b/plugin/Wavetable.jucer deleted file mode 100644 index 7e2b7c7..0000000 --- a/plugin/Wavetable.jucer +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -