diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ed2aabc..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Builds -NeuralSynth Installer.exe diff --git a/JuceLibraryCode/JuceHeader.h b/JuceLibraryCode/JuceHeader.h deleted file mode 100644 index 9eccfa7..0000000 --- a/JuceLibraryCode/JuceHeader.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - - This is the header file that your files should include in order to get all the - JUCE library headers. You should avoid including the JUCE headers directly in - your own source files, because that wouldn't pick up the correct configuration - options for your app. - -*/ - -#pragma once - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#if defined (JUCE_PROJUCER_VERSION) && JUCE_PROJUCER_VERSION < JUCE_VERSION - /** If you've hit this error then the version of the Projucer that was used to generate this project is - older than the version of the JUCE modules being included. To fix this error, re-save your project - using the latest version of the Projucer or, if you aren't using the Projucer to manage your project, - remove the JUCE_PROJUCER_VERSION define. - */ - #error "This project was last saved using an outdated version of the Projucer! Re-save this project with the latest version to fix this error." -#endif - - -#if ! JUCE_DONT_DECLARE_PROJECTINFO -namespace ProjectInfo -{ - const char* const projectName = "NeuralSynth"; - const char* const companyName = "Samedi Dimanche"; - const char* const versionString = "0.0.1"; - const int versionNumber = 0x1; -} -#endif diff --git a/JuceLibraryCode/JucePluginDefines.h b/JuceLibraryCode/JucePluginDefines.h deleted file mode 100644 index 6c0fa21..0000000 --- a/JuceLibraryCode/JucePluginDefines.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#pragma once - -//============================================================================== -// Audio plugin settings.. - -#ifndef JucePlugin_Build_VST - #define JucePlugin_Build_VST 0 -#endif -#ifndef JucePlugin_Build_VST3 - #define JucePlugin_Build_VST3 1 -#endif -#ifndef JucePlugin_Build_AU - #define JucePlugin_Build_AU 1 -#endif -#ifndef JucePlugin_Build_AUv3 - #define JucePlugin_Build_AUv3 0 -#endif -#ifndef JucePlugin_Build_AAX - #define JucePlugin_Build_AAX 0 -#endif -#ifndef JucePlugin_Build_Standalone - #define JucePlugin_Build_Standalone 1 -#endif -#ifndef JucePlugin_Build_Unity - #define JucePlugin_Build_Unity 0 -#endif -#ifndef JucePlugin_Build_LV2 - #define JucePlugin_Build_LV2 0 -#endif -#ifndef JucePlugin_Enable_IAA - #define JucePlugin_Enable_IAA 0 -#endif -#ifndef JucePlugin_Enable_ARA - #define JucePlugin_Enable_ARA 0 -#endif -#ifndef JucePlugin_Name - #define JucePlugin_Name "NeuralSynth" -#endif -#ifndef JucePlugin_Desc - #define JucePlugin_Desc "NeuralSynth" -#endif -#ifndef JucePlugin_Manufacturer - #define JucePlugin_Manufacturer "Samedi Dimanche" -#endif -#ifndef JucePlugin_ManufacturerWebsite - #define JucePlugin_ManufacturerWebsite "www.samedidimanche.com" -#endif -#ifndef JucePlugin_ManufacturerEmail - #define JucePlugin_ManufacturerEmail "" -#endif -#ifndef JucePlugin_ManufacturerCode - #define JucePlugin_ManufacturerCode 0x4d616e75 -#endif -#ifndef JucePlugin_PluginCode - #define JucePlugin_PluginCode 0x4d73347a -#endif -#ifndef JucePlugin_IsSynth - #define JucePlugin_IsSynth 1 -#endif -#ifndef JucePlugin_WantsMidiInput - #define JucePlugin_WantsMidiInput 1 -#endif -#ifndef JucePlugin_ProducesMidiOutput - #define JucePlugin_ProducesMidiOutput 0 -#endif -#ifndef JucePlugin_IsMidiEffect - #define JucePlugin_IsMidiEffect 0 -#endif -#ifndef JucePlugin_EditorRequiresKeyboardFocus - #define JucePlugin_EditorRequiresKeyboardFocus 0 -#endif -#ifndef JucePlugin_Version - #define JucePlugin_Version 0.0.1 -#endif -#ifndef JucePlugin_VersionCode - #define JucePlugin_VersionCode 0x1 -#endif -#ifndef JucePlugin_VersionString - #define JucePlugin_VersionString "0.0.1" -#endif -#ifndef JucePlugin_VSTUniqueID - #define JucePlugin_VSTUniqueID JucePlugin_PluginCode -#endif -#ifndef JucePlugin_VSTCategory - #define JucePlugin_VSTCategory kPlugCategSynth -#endif -#ifndef JucePlugin_Vst3Category - #define JucePlugin_Vst3Category "Instrument|Synth" -#endif -#ifndef JucePlugin_AUMainType - #define JucePlugin_AUMainType 'aumu' -#endif -#ifndef JucePlugin_AUSubType - #define JucePlugin_AUSubType JucePlugin_PluginCode -#endif -#ifndef JucePlugin_AUExportPrefix - #define JucePlugin_AUExportPrefix NeuralSynthAU -#endif -#ifndef JucePlugin_AUExportPrefixQuoted - #define JucePlugin_AUExportPrefixQuoted "NeuralSynthAU" -#endif -#ifndef JucePlugin_AUManufacturerCode - #define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode -#endif -#ifndef JucePlugin_CFBundleIdentifier - #define JucePlugin_CFBundleIdentifier com.samedidimanche.NeuralSynth -#endif -#ifndef JucePlugin_AAXIdentifier - #define JucePlugin_AAXIdentifier com.SamediDimanche.NeuralSynth -#endif -#ifndef JucePlugin_AAXManufacturerCode - #define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode -#endif -#ifndef JucePlugin_AAXProductId - #define JucePlugin_AAXProductId JucePlugin_PluginCode -#endif -#ifndef JucePlugin_AAXCategory - #define JucePlugin_AAXCategory 2048 -#endif -#ifndef JucePlugin_AAXDisableBypass - #define JucePlugin_AAXDisableBypass 0 -#endif -#ifndef JucePlugin_AAXDisableMultiMono - #define JucePlugin_AAXDisableMultiMono 0 -#endif -#ifndef JucePlugin_IAAType - #define JucePlugin_IAAType 0x61757269 -#endif -#ifndef JucePlugin_IAASubType - #define JucePlugin_IAASubType JucePlugin_PluginCode -#endif -#ifndef JucePlugin_IAAName - #define JucePlugin_IAAName "Samedi Dimanche: NeuralSynth" -#endif -#ifndef JucePlugin_VSTNumMidiInputs - #define JucePlugin_VSTNumMidiInputs 1 -#endif -#ifndef JucePlugin_VSTNumMidiOutputs - #define JucePlugin_VSTNumMidiOutputs 16 -#endif -#ifndef JucePlugin_ARAContentTypes - #define JucePlugin_ARAContentTypes 0 -#endif -#ifndef JucePlugin_ARATransformationFlags - #define JucePlugin_ARATransformationFlags 0 -#endif -#ifndef JucePlugin_ARAFactoryID - #define JucePlugin_ARAFactoryID "com.SamediDimanche.NeuralSynth.factory" -#endif -#ifndef JucePlugin_ARADocumentArchiveID - #define JucePlugin_ARADocumentArchiveID "com.SamediDimanche.NeuralSynth.aradocumentarchive.0.0.1" -#endif -#ifndef JucePlugin_ARACompatibleArchiveIDs - #define JucePlugin_ARACompatibleArchiveIDs "" -#endif -#ifndef JucePlugin_MaxNumInputChannels - #define JucePlugin_MaxNumInputChannels 0 -#endif -#ifndef JucePlugin_MaxNumOutputChannels - #define JucePlugin_MaxNumOutputChannels 2 -#endif -#ifndef JucePlugin_PreferredChannelConfigurations - #define JucePlugin_PreferredChannelConfigurations {0, 2} -#endif diff --git a/JuceLibraryCode/ReadMe.txt b/JuceLibraryCode/ReadMe.txt deleted file mode 100644 index 091a5aa..0000000 --- a/JuceLibraryCode/ReadMe.txt +++ /dev/null @@ -1,12 +0,0 @@ - - Important Note!! - ================ - -The purpose of this folder is to contain files that are auto-generated by the Projucer, -and ALL files in this folder will be mercilessly DELETED and completely re-written whenever -the Projucer saves your project. - -Therefore, it's a bad idea to make any manual changes to the files in here, or to -put any of your own files in here if you don't want to lose them. (Of course you may choose -to add the folder's contents to your version-control system so that you can re-merge your own -modifications after the Projucer has saved its changes). diff --git a/JuceLibraryCode/include_juce_audio_basics.cpp b/JuceLibraryCode/include_juce_audio_basics.cpp deleted file mode 100644 index e5c3ae9..0000000 --- a/JuceLibraryCode/include_juce_audio_basics.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_basics.mm b/JuceLibraryCode/include_juce_audio_basics.mm deleted file mode 100644 index c7f36c6..0000000 --- a/JuceLibraryCode/include_juce_audio_basics.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_devices.cpp b/JuceLibraryCode/include_juce_audio_devices.cpp deleted file mode 100644 index 29b774f..0000000 --- a/JuceLibraryCode/include_juce_audio_devices.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_devices.mm b/JuceLibraryCode/include_juce_audio_devices.mm deleted file mode 100644 index 287da26..0000000 --- a/JuceLibraryCode/include_juce_audio_devices.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_formats.cpp b/JuceLibraryCode/include_juce_audio_formats.cpp deleted file mode 100644 index 8dac332..0000000 --- a/JuceLibraryCode/include_juce_audio_formats.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_formats.mm b/JuceLibraryCode/include_juce_audio_formats.mm deleted file mode 100644 index 79e6a22..0000000 --- a/JuceLibraryCode/include_juce_audio_formats.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_AAX.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_AAX.cpp deleted file mode 100644 index 8ce6c02..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_AAX.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_AAX.mm b/JuceLibraryCode/include_juce_audio_plugin_client_AAX.mm deleted file mode 100644 index c813bc9..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_AAX.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_AAX_utils.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_AAX_utils.cpp deleted file mode 100644 index 1135bc7..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_AAX_utils.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_ARA.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_ARA.cpp deleted file mode 100644 index 69f205b..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_ARA.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_AU_1.mm b/JuceLibraryCode/include_juce_audio_plugin_client_AU_1.mm deleted file mode 100644 index 179c513..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_AU_1.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_AU_2.mm b/JuceLibraryCode/include_juce_audio_plugin_client_AU_2.mm deleted file mode 100644 index 3553cb9..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_AU_2.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_AUv3.mm b/JuceLibraryCode/include_juce_audio_plugin_client_AUv3.mm deleted file mode 100644 index a1fa5aa..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_AUv3.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_LV2.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_LV2.cpp deleted file mode 100644 index 7de5bef..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_LV2.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_LV2.mm b/JuceLibraryCode/include_juce_audio_plugin_client_LV2.mm deleted file mode 100644 index 89611a6..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_LV2.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_Standalone.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_Standalone.cpp deleted file mode 100644 index 02eb7db..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_Standalone.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_Unity.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_Unity.cpp deleted file mode 100644 index 5b42c8b..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_Unity.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_VST2.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_VST2.cpp deleted file mode 100644 index f3ab569..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_VST2.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_VST2.mm b/JuceLibraryCode/include_juce_audio_plugin_client_VST2.mm deleted file mode 100644 index c7ef970..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_VST2.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_VST3.cpp b/JuceLibraryCode/include_juce_audio_plugin_client_VST3.cpp deleted file mode 100644 index 546dd91..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_VST3.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_plugin_client_VST3.mm b/JuceLibraryCode/include_juce_audio_plugin_client_VST3.mm deleted file mode 100644 index d3eae05..0000000 --- a/JuceLibraryCode/include_juce_audio_plugin_client_VST3.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_processors.cpp b/JuceLibraryCode/include_juce_audio_processors.cpp deleted file mode 100644 index 217d330..0000000 --- a/JuceLibraryCode/include_juce_audio_processors.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_processors.mm b/JuceLibraryCode/include_juce_audio_processors.mm deleted file mode 100644 index 1f7cc41..0000000 --- a/JuceLibraryCode/include_juce_audio_processors.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_processors_ara.cpp b/JuceLibraryCode/include_juce_audio_processors_ara.cpp deleted file mode 100644 index e0c34d4..0000000 --- a/JuceLibraryCode/include_juce_audio_processors_ara.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_processors_lv2_libs.cpp b/JuceLibraryCode/include_juce_audio_processors_lv2_libs.cpp deleted file mode 100644 index 64b4d5f..0000000 --- a/JuceLibraryCode/include_juce_audio_processors_lv2_libs.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_utils.cpp b/JuceLibraryCode/include_juce_audio_utils.cpp deleted file mode 100644 index 046bf31..0000000 --- a/JuceLibraryCode/include_juce_audio_utils.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_audio_utils.mm b/JuceLibraryCode/include_juce_audio_utils.mm deleted file mode 100644 index a3f746d..0000000 --- a/JuceLibraryCode/include_juce_audio_utils.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_core.cpp b/JuceLibraryCode/include_juce_core.cpp deleted file mode 100644 index 84fe988..0000000 --- a/JuceLibraryCode/include_juce_core.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_core.mm b/JuceLibraryCode/include_juce_core.mm deleted file mode 100644 index 9ee67bf..0000000 --- a/JuceLibraryCode/include_juce_core.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_core_CompilationTime.cpp b/JuceLibraryCode/include_juce_core_CompilationTime.cpp deleted file mode 100644 index 63662e6..0000000 --- a/JuceLibraryCode/include_juce_core_CompilationTime.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_data_structures.cpp b/JuceLibraryCode/include_juce_data_structures.cpp deleted file mode 100644 index 152980a..0000000 --- a/JuceLibraryCode/include_juce_data_structures.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_data_structures.mm b/JuceLibraryCode/include_juce_data_structures.mm deleted file mode 100644 index 02b9711..0000000 --- a/JuceLibraryCode/include_juce_data_structures.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_dsp.cpp b/JuceLibraryCode/include_juce_dsp.cpp deleted file mode 100644 index 0f0af65..0000000 --- a/JuceLibraryCode/include_juce_dsp.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_dsp.mm b/JuceLibraryCode/include_juce_dsp.mm deleted file mode 100644 index a5cb956..0000000 --- a/JuceLibraryCode/include_juce_dsp.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_events.cpp b/JuceLibraryCode/include_juce_events.cpp deleted file mode 100644 index 39268e2..0000000 --- a/JuceLibraryCode/include_juce_events.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_events.mm b/JuceLibraryCode/include_juce_events.mm deleted file mode 100644 index 191a998..0000000 --- a/JuceLibraryCode/include_juce_events.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_graphics.cpp b/JuceLibraryCode/include_juce_graphics.cpp deleted file mode 100644 index 8ccabef..0000000 --- a/JuceLibraryCode/include_juce_graphics.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_graphics.mm b/JuceLibraryCode/include_juce_graphics.mm deleted file mode 100644 index 6bb7456..0000000 --- a/JuceLibraryCode/include_juce_graphics.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_graphics_Harfbuzz.cpp b/JuceLibraryCode/include_juce_graphics_Harfbuzz.cpp deleted file mode 100644 index 445d8c2..0000000 --- a/JuceLibraryCode/include_juce_graphics_Harfbuzz.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_graphics_Sheenbidi.c b/JuceLibraryCode/include_juce_graphics_Sheenbidi.c deleted file mode 100644 index 9b27ddd..0000000 --- a/JuceLibraryCode/include_juce_graphics_Sheenbidi.c +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_gui_basics.cpp b/JuceLibraryCode/include_juce_gui_basics.cpp deleted file mode 100644 index 71d04b2..0000000 --- a/JuceLibraryCode/include_juce_gui_basics.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_gui_basics.mm b/JuceLibraryCode/include_juce_gui_basics.mm deleted file mode 100644 index e449e0b..0000000 --- a/JuceLibraryCode/include_juce_gui_basics.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_gui_extra.cpp b/JuceLibraryCode/include_juce_gui_extra.cpp deleted file mode 100644 index a33ece0..0000000 --- a/JuceLibraryCode/include_juce_gui_extra.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/JuceLibraryCode/include_juce_gui_extra.mm b/JuceLibraryCode/include_juce_gui_extra.mm deleted file mode 100644 index 6dacee3..0000000 --- a/JuceLibraryCode/include_juce_gui_extra.mm +++ /dev/null @@ -1,8 +0,0 @@ -/* - - IMPORTANT! This file is auto-generated each time you save your - project - if you alter its contents, your changes may be overwritten! - -*/ - -#include diff --git a/NeuralSynth.iss b/NeuralSynth.iss deleted file mode 100644 index 8606a46..0000000 --- a/NeuralSynth.iss +++ /dev/null @@ -1,98 +0,0 @@ -[Setup] -AppName=NeuralSynth -AppVersion=1.0.0 -DefaultDirName={pf}\NeuralSynth -DefaultGroupName=NeuralSynth -Compression=lzma2 -SolidCompression=yes -OutputDir=.\ -ArchitecturesInstallIn64BitMode=x64 -OutputBaseFilename=NeuralSynth Installer -;LicenseFile=license.rtf -SetupLogging=yes - -[Types] -Name: "full"; Description: "Full installation" -Name: "custom"; Description: "Custom installation"; Flags: iscustom - -[Components] -Name: "app"; Description: "Standalone application (.exe)"; Types: full custom; -;Name: "vst2_32"; Description: "32-bit VST2 Plugin (.dll)"; Types: full custom; -;Name: "vst2_64"; Description: "64-bit VST2 Plugin (.dll)"; Types: full custom; Check: Is64BitInstallMode; -;Name: "vst3_32"; Description: "32-bit VST3 Plugin (.vst3)"; Types: full custom; -Name: "vst3_64"; Description: "64-bit VST3 Plugin (.vst3)"; Types: full custom; Check: Is64BitInstallMode; -;Name: "rtas_32"; Description: "32-bit RTAS Plugin (.dpm)"; Types: full custom; -;Name: "aax_32"; Description: "32-bit AAX Plugin (.aaxplugin)"; Types: full custom; -;Name: "aax_64"; Description: "64-bit AAX Plugin (.aaxplugin)"; Types: full custom; Check: Is64BitInstallMode; -;Name: "manual"; Description: "User guide"; Types: full custom; Flags: fixed - -[Files] -;Source: "..\build-win\app\Win32\bin\NeuralSynth.exe"; DestDir: "{app}"; Check: not Is64BitInstallMode; Components:app; Flags: ignoreversion; -Source: "Builds\VisualStudio2022\x64\Release\Standalone Plugin\NeuralSynth.exe"; DestDir: "{app}"; Check: Is64BitInstallMode; Components:app; Flags: ignoreversion; - -;Source: "..\build-win\vst2\Win32\bin\NeuralSynth.dll"; DestDir: {code:GetVST2Dir_32}; Check: not Is64BitInstallMode; Components:vst2_32; Flags: ignoreversion; -;Source: "..\build-win\vst2\Win32\bin\NeuralSynth.dll"; DestDir: {code:GetVST2Dir_32}; Check: Is64BitInstallMode; Components:vst2_32; Flags: ignoreversion; -;Source: "..\build-win\vst2\x64\bin\NeuralSynth.dll"; DestDir: {code:GetVST2Dir_64}; Check: Is64BitInstallMode; Components:vst2_64; Flags: ignoreversion; - -;Source: "..\build-win\vst3\Win32\bin\NeuralSynth.vst3"; DestDir: "{cf}\VST3\"; Check: not Is64BitInstallMode; Components:vst3_32; Flags: ignoreversion; -;Source: "..\build-win\vst3\Win32\bin\NeuralSynth.vst3"; DestDir: "{cf32}\VST3\"; Check: Is64BitInstallMode; Components:vst3_32; Flags: ignoreversion; -Source: "Builds\VisualStudio2022\x64\Release\VST3\NeuralSynth.vst3\Contents\x86_64-win\NeuralSynth.vst3"; DestDir: "{cf64}\VST3\"; Check: Is64BitInstallMode; Components:vst3_64; Flags: ignoreversion; - -;Source: "..\build-win\rtas\bin\NeuralSynth.dpm"; DestDir: "{cf32}\Digidesign\DAE\Plug-Ins\"; Components:rtas_32; Flags: ignoreversion; -;Source: "..\build-win\rtas\bin\NeuralSynth.dpm.rsr"; DestDir: "{cf32}\Digidesign\DAE\Plug-Ins\"; Components:rtas_32; Flags: ignoreversion; - -;Source: "..\build-win\aax\bin\NeuralSynth.aaxplugin\*.*"; DestDir: "{cf32}\Avid\Audio\Plug-Ins\NeuralSynth.aaxplugin\"; Components:aax_32; Flags: ignoreversion recursesubdirs; -;Source: "..\build-win\aax\bin\NeuralSynth.aaxplugin\*.*"; DestDir: "{cf}\Avid\Audio\Plug-Ins\NeuralSynth.aaxplugin\"; Components:aax_64; Flags: ignoreversion recursesubdirs; - -;Source: "..\manual\NeuralSynth_manual.pdf"; DestDir: "{app}" -;Source: "changelog.txt"; DestDir: "{app}" -;Source: "readmewin.rtf"; DestDir: "{app}"; DestName: "readme.rtf"; Flags: isreadme - -[Icons] -Name: "{group}\NeuralSynth"; Filename: "{app}\NeuralSynth.exe" -;Name: "{group}\User guide"; Filename: "{app}\NeuralSynth_manual.pdf" -;Name: "{group}\Changelog"; Filename: "{app}\changelog.txt" -;Name: "{group}\readme"; Filename: "{app}\readme.rtf" -Name: "{group}\Uninstall NeuralSynth"; Filename: "{app}\unins000.exe" - -;[Dirs] -;Name: {cf}\Digidesign\DAE\Plugins\ - -[Code] -var - OkToCopyLog : Boolean; - VST3DirPage_32: TInputDirWizardPage; - VST3DirPage_64: TInputDirWizardPage; - -procedure InitializeWizard; -begin - if IsWin64 then begin - VST3DirPage_64 := CreateInputDirPage(wpSelectDir, - 'Confirm 64-Bit VST3 Plugin Directory', '', - 'Select the folder in which setup should install the 64-bit VST3 Plugin, then click Next.', - False, ''); - VST3DirPage_64.Add(''); - VST3DirPage_64.Values[0] := ExpandConstant('{reg:HKLM\SOFTWARE\VST,VSTPluginsPath|{pf}\Common Files\VST3}\'); - end; -end; - -function GetVST3Dir_64(Param: String): String; -begin - Result := VST3DirPage_64.Values[0] -end; - -procedure CurStepChanged(CurStep: TSetupStep); -begin - if CurStep = ssDone then - OkToCopyLog := True; -end; - -procedure DeinitializeSetup(); -begin - if OkToCopyLog then - FileCopy (ExpandConstant ('{log}'), ExpandConstant ('{app}\InstallationLogFile.log'), FALSE); - RestartReplace (ExpandConstant ('{log}'), ''); -end; - -[UninstallDelete] -Type: files; Name: "{app}\InstallationLogFile.log" \ No newline at end of file diff --git a/NeuralSynth.jucer b/NeuralSynth.jucer deleted file mode 100644 index f43271b..0000000 --- a/NeuralSynth.jucer +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Source/AudioBufferQueue.h b/Source/AudioBufferQueue.h deleted file mode 100644 index db9efa0..0000000 --- a/Source/AudioBufferQueue.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -//============================================================================== -template -class AudioBufferQueue -{ -public: - //============================================================================== - static constexpr size_t order = 9; - static constexpr size_t bufferSize = 1U << order; - static constexpr size_t numBuffers = 5; - - //============================================================================== - void push(const SampleType* dataToPush, size_t numSamples) - { - jassert(numSamples <= bufferSize); - - int start1, size1, start2, size2; - abstractFifo.prepareToWrite(1, start1, size1, start2, size2); - - jassert(size1 <= 1); - jassert(size2 == 0); - - if (size1 > 0) - juce::FloatVectorOperations::copy(buffers[(size_t)start1].data(), dataToPush, (int)juce::jmin(bufferSize, numSamples)); - - abstractFifo.finishedWrite(size1); - } - - //============================================================================== - void pop(SampleType* outputBuffer) - { - int start1, size1, start2, size2; - abstractFifo.prepareToRead(1, start1, size1, start2, size2); - - jassert(size1 <= 1); - jassert(size2 == 0); - - if (size1 > 0) - juce::FloatVectorOperations::copy(outputBuffer, buffers[(size_t)start1].data(), (int)bufferSize); - - abstractFifo.finishedRead(size1); - } - -private: - //============================================================================== - juce::AbstractFifo abstractFifo{ numBuffers }; - std::array, numBuffers> buffers; -}; \ No newline at end of file diff --git a/Source/AudioEngine.h b/Source/AudioEngine.h deleted file mode 100644 index a6fd169..0000000 --- a/Source/AudioEngine.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "SynthVoice.h" -#include - -class NeuralAudioEngine : public juce::MPESynthesiser -{ -public: - static constexpr int maxNumVoices = 8; - - explicit NeuralAudioEngine(NeuralSharedParams& sp) - { - // Create MPE voices - for (int i = 0; i < maxNumVoices; ++i) - addVoice(new NeuralSynthVoice(sp)); // <-- takes MPESynthesiserVoice* - - // MPE synths do not use addSound(); note events are routed via MPE zones. - setVoiceStealingEnabled(true); - } - - void prepare(const juce::dsp::ProcessSpec& spec) noexcept - { - setCurrentPlaybackSampleRate(spec.sampleRate); - - for (auto* v : voices) - if (auto* nv = dynamic_cast(v)) - nv->prepare(spec); - } - - template - void applyToVoices(VoiceFunc&& fn) noexcept - { - for (auto* v : voices) - fn(dynamic_cast(v)); - } - -private: - // keep base render - using juce::MPESynthesiser::renderNextSubBlock; - - void renderNextSubBlock(juce::AudioBuffer& outputAudio, - int startSample, - int numSamples) override - { - juce::MPESynthesiser::renderNextSubBlock(outputAudio, startSample, numSamples); - } -}; diff --git a/Source/BlepOsc.h b/Source/BlepOsc.h deleted file mode 100644 index 46aa63f..0000000 --- a/Source/BlepOsc.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -#include - -enum class BlepWave : int { Sine = 0, Saw, Square, Triangle }; - -class BlepOsc -{ -public: - void prepare (double sampleRate) { sr = sampleRate; resetPhase(); } - void setWave (BlepWave w) { wave = w; } - void setFrequency (float f) { freq = juce::jmax (0.0f, f); inc = freq / (float) sr; } - void resetPhase (float p = 0.0f) { phase = juce::jlimit (0.0f, 1.0f, p); } - - inline float process() - { - // phase in [0..1) - float out = 0.0f; - float t = phase; - phase += inc; - if (phase >= 1.0f) phase -= 1.0f; - - switch (wave) - { - case BlepWave::Sine: out = std::sin (2.0f * juce::MathConstants::pi * t); break; - - case BlepWave::Saw: - { - // naive saw in [-1..1] - float s = 2.0f * t - 1.0f; - // apply BLEP at the discontinuity crossing t=0 - s -= polyBlep (t, inc); - out = s; - } break; - - case BlepWave::Square: - { - float s = (t < 0.5f ? 1.0f : -1.0f); - // rising edge at 0.0, falling at 0.5 - s += polyBlep (t, inc) - polyBlep (std::fmod (t + 0.5f, 1.0f), inc); - out = s; - } break; - - case BlepWave::Triangle: - { - // integrate the BLEP square for band-limited tri - float sq = (t < 0.5f ? 1.0f : -1.0f); - sq += polyBlep (t, inc) - polyBlep (std::fmod (t + 0.5f, 1.0f), inc); - // leaky integrator to keep DC under control - z1 = z1 + (sq - z1) * inc; - out = 2.0f * z1; // scale - } break; - } - - return out; - } - -private: - // PolyBLEP as in Valimäki/Huovilainen - static inline float polyBlep (float t, float dt) - { - // t in [0..1) - if (t < dt) - { - t /= dt; - return t + t - t * t - 1.0f; - } - else if (t > 1.0f - dt) - { - t = (t - 1.0f) / dt; - return t * t + t + t + 1.0f; - } - return 0.0f; - } - - double sr = 44100.0; - float freq = 440.0f, inc = 440.0f / 44100.0f; - float phase = 0.0f; - float z1 = 0.0f; - BlepWave wave = BlepWave::Sine; -}; diff --git a/Source/GraphComponent.h b/Source/GraphComponent.h deleted file mode 100644 index 1fa963e..0000000 --- a/Source/GraphComponent.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - ============================================================================== - - GraphComponent.h - Created: 4 Jul 2025 11:43:57pm - Author: timot - - ============================================================================== -*/ - -#pragma once - -#include // for std::minmax_element -#include "AudioBufferQueue.h" - -//============================================================================== -template -class GraphComponent : public juce::Component, - private juce::Timer -{ -public: - //============================================================================== - GraphComponent(SampleType minIn, SampleType maxIn, int numPointsIn) - : min(minIn), max(maxIn), numPoints(numPointsIn) - { - x.resize(numPoints); - y.resize(numPoints); - setFramesPerSecond(30); - // func will be set via setFunction before paint; provide a safe default - func = [](SampleType) noexcept { return SampleType(); }; - } - - //============================================================================== - void setFramesPerSecond(int framesPerSecond) - { - jassert(framesPerSecond > 0 && framesPerSecond < 1000); - startTimerHz(framesPerSecond); - } - - //============================================================================== - void setFunction(const std::function& f) { func = f; } - - //============================================================================== - void paint(juce::Graphics& g) override - { - g.fillAll(juce::Colours::black); - g.setColour(juce::Colours::white); - - auto area = getLocalBounds(); - - if (hasData && area.isFinite()) - { - auto h = (SampleType)area.getHeight(); - auto w = (SampleType)area.getWidth(); - - for (size_t i = 1; i < (size_t)numPoints; ++i) - { - auto px_prev = ((x[i - 1] - min) / (max - min)) * w; - auto py_prev = h - ((y[i - 1] - minY) / (maxY - minY)) * h; - - auto px_next = ((x[i] - min) / (max - min)) * w; - auto py_next = h - ((y[i] - minY) / (maxY - minY)) * h; - - g.drawLine({ px_prev, py_prev, px_next, py_next }); - } - } - } - - //============================================================================== - void resized() override {} - -private: - //============================================================================== - std::vector x, y; - SampleType minY{ SampleType() }, maxY{ SampleType(1) }; - SampleType min{}, max{}; - int numPoints{}; - std::function func; - bool hasData = false; - - //============================================================================== - void timerCallback() override - { - const SampleType step = (max - min) / (SampleType)(numPoints - 1); - - for (int i = 0; i < numPoints; i++) - { - x[(size_t)i] = min + step * (SampleType)i; - y[(size_t)i] = func(x[(size_t)i]); - } - - auto p = std::minmax_element(y.begin(), y.end()); - minY = *p.first; - maxY = *p.second; - - hasData = true; - repaint(); - } -}; diff --git a/Source/NeuralSharedParams.h b/Source/NeuralSharedParams.h deleted file mode 100644 index 270744c..0000000 --- a/Source/NeuralSharedParams.h +++ /dev/null @@ -1,145 +0,0 @@ -#pragma once - -#include -#include -#include - -struct SliderDetail { - std::string label; - float min, max, interval, defValue; -}; - -using ParamMap = std::unordered_map; - -// Each SliderDetail: { label, min, max, step, defaultValue } -const std::unordered_map PARAM_SETTINGS = { - { "chorus", { - { "rate", { "Rate", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "depth", { "Depth", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "centre", { "Centre", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "feedback", { "Feedback", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "mix", { "Mix", 0.0f, 1.0f, 0.1f, 0.1f } } - }}, - { "delay", { - { "delay", { "Delay", 0.0f, 1.0f, 0.1f, 0.1f } } - }}, - { "reverb", { - { "roomSize", { "Room Size", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "damping", { "Damping", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "wetLevel", { "Wet Level", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "dryLevel", { "Dry Level", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "width", { "Width", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "freezeMode", { "Freeze Mode", 0.0f, 1.0f, 0.1f, 0.1f } } - }}, - { "adsr", { - { "attack", { "Attack", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "decay", { "Decay", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "sustain", { "Sustain", 0.0f, 1.0f, 0.1f, 0.1f } }, - { "release", { "Release", 0.0f, 1.0f, 0.1f, 0.1f } } - }}, - // Filter envelope group (short key: "fenv") - { "fenv", { - { "attack", { "Attack", 0.0f, 2.0f, 0.001f, 0.01f } }, - { "decay", { "Decay", 0.0f, 2.0f, 0.001f, 0.10f } }, - { "sustain", { "Sustain", 0.0f, 1.0f, 0.001f, 0.80f } }, - { "release", { "Release", 0.0f, 4.0f, 0.001f, 0.40f } }, - { "amount", { "Amount", -1.0f, 1.0f, 0.001f, 0.50f } } - }}, - { "flanger", { - { "rate", { "Rate", 0.1f, 5.0f, 0.1f, 0.1f } }, - { "depth", { "Depth", 0.1f, 10.0f, 0.1f, 0.1f } }, // ms - { "feedback", { "Feedback", 0.0f, 0.95f, 0.01f, 0.1f } }, - { "dryMix", { "Dry/Wet", 0.0f, 1.0f, 0.01f, 0.0f } }, - { "phase", { "Phase", 0.0f, 1.0f, 0.1f, 0.0f } }, - { "delay", { "Delay", 0.0f, 3.0f, 0.1f, 0.25f } } // ms base - }}, - { "filter", { - { "cutoff", { "Cutoff", 20.0f, 20000.0f, 1.0f, 1000.0f } }, - { "resonance", { "Resonance", 0.1f, 10.0f, 0.1f, 0.7f } }, - { "type", { "L/H/B", 0.0f, 2.0f, 1.0f, 0.0f } }, - { "drive", { "Drive", 0.0f, 1.0f, 0.01f, 0.0f } }, - { "mod", { "Mod", -1.0f, 1.0f, 0.1f, 0.0f } }, - { "key", { "Key", 0.0f, 1.0f, 0.1f, 0.0f } } - }}, - { "distortion", { - { "drive", { "Drive", 0.0f, 30.0f, 0.1f, 10.0f } }, - { "mix", { "Mix", 0.0f, 1.0f, 0.01f, 0.0f } }, - { "bias", { "Bias", -1.0f, 1.0f, 0.01f, 0.0f } }, - { "tone", { "Tone", 100.0f, 8000.0f, 10.0f, 3000.0f } }, - { "shape", { "Shape", 0.0f, 2.0f, 1.0f, 0.0f } } - }} -}; - -struct NeuralSharedParams -{ - std::atomic waveform{ -1 }; - - // Amp ADSR - std::atomic* adsrAttack{}; - std::atomic* adsrDecay{}; - std::atomic* adsrSustain{}; - std::atomic* adsrRelease{}; - - // Delay - std::atomic* delayTime{}; - - // Chorus - std::atomic* chorusRate{}; - std::atomic* chorusDepth{}; - std::atomic* chorusCentre{}; - std::atomic* chorusFeedback{}; - std::atomic* chorusMix{}; - - // Reverb - std::atomic* reverbRoomSize{}; - std::atomic* reverbDamping{}; - std::atomic* reverbWetLevel{}; - std::atomic* reverbDryLevel{}; - std::atomic* reverbWidth{}; - std::atomic* reverbFreezeMode{}; - - // Flanger - std::atomic* flangerRate{}; - std::atomic* flangerDepth{}; - std::atomic* flangerFeedback{}; - std::atomic* flangerDryMix{}; - std::atomic* flangerPhase{}; - std::atomic* flangerDelay{}; - - // Filter (base) - std::atomic* filterCutoff{}; - std::atomic* filterResonance{}; - std::atomic* filterType{}; - std::atomic* filterDrive{}; - std::atomic* filterMod{}; - std::atomic* filterKey{}; - - // Filter Env (polyphonic) - std::atomic* fenvAttack{}; - std::atomic* fenvDecay{}; - std::atomic* fenvSustain{}; - std::atomic* fenvRelease{}; - std::atomic* fenvAmount{}; // +/- octaves - - // Distortion - std::atomic* distortionDrive{}; - std::atomic* distortionMix{}; - std::atomic* distortionBias{}; - std::atomic* distortionTone{}; - std::atomic* distortionShape{}; - - // Per-panel bypass (AudioParameterBool, exposed as float 0/1 via getRawParameterValue) - std::atomic* chorusOn{}; - std::atomic* delayOn{}; - std::atomic* reverbOn{}; - std::atomic* flangerOn{}; - std::atomic* distortionOn{}; - std::atomic* filterOn{}; - std::atomic* eqOn{}; - - // EQ + Master - std::atomic* lowGainDbls{}; - std::atomic* midGainDbls{}; - std::atomic* highGainDbls{}; - std::atomic* masterDbls{}; -}; diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp deleted file mode 100644 index a51d3f5..0000000 --- a/Source/PluginEditor.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include "PluginProcessor.h" -#include "PluginEditor.h" -#include "ScopeComponent.h" - -//============================================================================== -NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p) - : AudioProcessorEditor (&p), - audioProcessor (p), - mainScopeComponent(audioProcessor.getAudioBufferQueue()) -{ - auto& tree = audioProcessor.parameters; - - addAndMakeVisible(mainScopeComponent); - - waveformSelector.setModel(&waveformContents); - waveformContents.onSelect = [this](int row) - { - // write to the parameter so voices update safely - audioProcessor.parameters.getParameterAsValue("waveform") = (float)juce::jlimit(0, 3, row); - }; - addAndMakeVisible(waveformSelector); - - // --- Panels --- - adsrComponent.emplace(tree, "adsr", "Amp Env"); - adsrComponent->enableGraphScope([this](float x) { - auto& tree = this->audioProcessor.parameters; - - float A = tree.getParameter("adsr_attack")->getValue(); - float D = tree.getParameter("adsr_decay")->getValue(); - float S = tree.getParameter("adsr_sustain")->getValue(); - float R = tree.getParameter("adsr_release")->getValue(); - - const float sustainLen = 1.0f; - const float total = A + D + sustainLen + R; - A /= total; D /= total; R /= total; - - float m = 0.0f, c = 0.0f; - if (x < A) { m = 1.0f / A; c = 0.0f; } - else if (x < A + D) { m = (S - 1.0f) / D; c = 1.0f - m * A; } - else if (x < A + D + (sustainLen / total)) { m = 0.0f; c = S; } - else { m = (S / -R); c = -m; } - return m * x + c; - }); - addAndMakeVisible(*adsrComponent); - - chorusComponent.emplace(tree, "chorus", "Chorus"); - chorusComponent->enableSampleScope(audioProcessor.getChorusAudioBufferQueue()); - addAndMakeVisible(*chorusComponent); - - delayComponent.emplace(tree, "delay", "Delay"); - delayComponent->enableSampleScope(audioProcessor.getDelayAudioBufferQueue()); - addAndMakeVisible(*delayComponent); - - reverbComponent.emplace(tree, "reverb", "Reverb"); - reverbComponent->enableSampleScope(audioProcessor.getReverbAudioBufferQueue()); - addAndMakeVisible(*reverbComponent); - - eqComponent.emplace(tree, "EQ"); - addAndMakeVisible(*eqComponent); - - flangerComponent.emplace(tree, "flanger", "Flanger"); - flangerComponent->enableSampleScope(audioProcessor.getFlangerAudioBufferQueue()); - addAndMakeVisible(*flangerComponent); - - distortionComponent.emplace(tree, "distortion", "Distortion"); - distortionComponent->enableSampleScope(audioProcessor.getDistortionAudioBufferQueue()); - addAndMakeVisible(*distortionComponent); - - filterComponent.emplace(tree, "filter", "Filter"); - filterComponent->enableSampleScope(audioProcessor.getFilterAudioBufferQueue()); - addAndMakeVisible(*filterComponent); - - filterEnvComponent.emplace(tree, "fenv", "Filter Env"); - filterEnvComponent->enableGraphScope([this](float x) { - auto& tree = this->audioProcessor.parameters; - - float A = tree.getParameter("fenv_attack")->getValue(); - float D = tree.getParameter("fenv_decay")->getValue(); - float S = tree.getParameter("fenv_sustain")->getValue(); - float R = tree.getParameter("fenv_release")->getValue(); - - const float sustainLen = 1.0f; - const float total = A + D + sustainLen + R; - A /= total; D /= total; R /= total; - - float m = 0.0f, c = 0.0f; - if (x < A) { m = 1.0f / A; c = 0.0f; } - else if (x < A + D) { m = (S - 1.0f) / D; c = 1.0f - m * A; } - else if (x < A + D + (sustainLen / total)) { m = 0.0f; c = S; } - else { m = (S / -R); c = -m; } - return m * x + c; - }); - addAndMakeVisible(*filterEnvComponent); - - // Master fader + label - addAndMakeVisible(masterLevelSlider); - masterLevelLabel.setText("Master", juce::dontSendNotification); - { - juce::Font f; f.setHeight(12.0f); f.setBold(true); - masterLevelLabel.setFont(f); - } - masterLevelLabel.setJustificationType(juce::Justification::centred); - addAndMakeVisible(masterLevelLabel); - - // Blank placeholder - addAndMakeVisible(blankPanel); - - // Attach master parameter - gainAttachment = std::make_unique( - audioProcessor.parameters, "master", masterLevelSlider.slider); - - setSize(1400, 720); -} - -//============================================================================== -NeuralSynthAudioProcessorEditor::~NeuralSynthAudioProcessorEditor() = default; - -//============================================================================== -void NeuralSynthAudioProcessorEditor::paint (juce::Graphics& g) -{ - g.fillAll(getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId)); -} - -//============================================================================== -void NeuralSynthAudioProcessorEditor::resized() -{ - auto bounds = getLocalBounds().reduced(16); - - juce::Grid grid; - - grid.templateRows = { - juce::Grid::TrackInfo(juce::Grid::Fr(20)), // scope row - juce::Grid::TrackInfo(juce::Grid::Fr(40)), // row 1 - juce::Grid::TrackInfo(juce::Grid::Fr(40)) // row 2 - }; - - // 6 columns: 5 content + 1 sidebar (waveform+master) - grid.templateColumns = { - juce::Grid::TrackInfo(juce::Grid::Fr(18)), - juce::Grid::TrackInfo(juce::Grid::Fr(18)), - juce::Grid::TrackInfo(juce::Grid::Fr(18)), - juce::Grid::TrackInfo(juce::Grid::Fr(18)), - juce::Grid::TrackInfo(juce::Grid::Fr(18)), - juce::Grid::TrackInfo(juce::Grid::Fr(10)) - }; - - // Row 0 - grid.items.add(juce::GridItem(mainScopeComponent) - .withArea(juce::GridItem::Span(1), juce::GridItem::Span(5))); - grid.items.add(juce::GridItem(waveformSelector) - .withArea(juce::GridItem::Span(1), juce::GridItem::Span(1))); - - // Row 1 - grid.items.add(juce::GridItem(*adsrComponent)); - grid.items.add(juce::GridItem(*chorusComponent)); - grid.items.add(juce::GridItem(*delayComponent)); - grid.items.add(juce::GridItem(*reverbComponent)); - grid.items.add(juce::GridItem(*eqComponent)); - grid.items.add(juce::GridItem(masterLevelLabel)); - - // Row 2 - grid.items.add(juce::GridItem(*flangerComponent)); - grid.items.add(juce::GridItem(*distortionComponent)); - grid.items.add(juce::GridItem(*filterComponent)); - grid.items.add(juce::GridItem(*filterEnvComponent)); - grid.items.add(juce::GridItem(blankPanel)); - grid.items.add(juce::GridItem(masterLevelSlider)); - - grid.performLayout(bounds); -} diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h deleted file mode 100644 index 5a839ba..0000000 --- a/Source/PluginEditor.h +++ /dev/null @@ -1,341 +0,0 @@ -#pragma once - -#include -#include "PluginProcessor.h" -#include "GraphComponent.h" -#include "ScopeComponent.h" - -//============================== ScopeSliderComponent ========================== -// A generic panel: optional scope/graph + rotary sliders + labels. -// Adds a per-panel "On" toggle (bound to "_on"). -class ScopeSliderComponent : public juce::Component { - static const int fontSize = 11; - -public: - ScopeSliderComponent(juce::AudioProcessorValueTreeState& tree, - const std::string paramGroup, - const juce::String& titleText = {}) - : paramGroupId(paramGroup), treeRef(tree) - { - const auto& sliderDetails = PARAM_SETTINGS.at(paramGroup); - - for (const auto& [name, sliderDetail] : sliderDetails) { - sliders.push_back(std::make_unique()); - labels.push_back(std::make_unique()); - attachments.push_back(std::make_unique( - tree, paramGroup + "_" + name, *sliders.back())); - - labels.back()->setText(sliderDetail.label, juce::dontSendNotification); - sliders.back()->setRange(sliderDetail.min, sliderDetail.max); - } - - for (auto& slider : sliders) - { - slider->setSliderStyle(juce::Slider::Rotary); - slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, 50, 20); - addAndMakeVisible(*slider); - } - - for (auto& label : labels) - { - juce::Font f; f.setHeight((float)fontSize); f.setBold(true); - label->setFont(f); - label->setColour(juce::Label::textColourId, juce::Colours::lightgreen); - label->setJustificationType(juce::Justification::centred); - addAndMakeVisible(*label); - } - - if (titleText.isNotEmpty()) - { - titleLabel.setText(titleText, juce::dontSendNotification); - juce::Font tf; tf.setHeight(12.0f); tf.setBold(true); - titleLabel.setFont(tf); - titleLabel.setJustificationType(juce::Justification::centredLeft); - titleLabel.setColour(juce::Label::textColourId, juce::Colours::white); - addAndMakeVisible(titleLabel); - } - - // Bypass toggle (per panel), id "_on" - bypassButton.setButtonText("On"); - bypassButton.setClickingTogglesState(true); - addAndMakeVisible(bypassButton); - bypassAttachment = std::make_unique( - treeRef, paramGroupId + "_on", bypassButton); - } - - void enableSampleScope(AudioBufferQueue& audioBufferQueue) { - scope.emplace(audioBufferQueue); - useGraphScope = false; - addAndMakeVisible(*scope); - } - - void enableGraphScope(const std::function& func) { - graphScope.emplace(0.0f, 1.0f, 100); - graphScope->setFunction(func); - useGraphScope = true; - addAndMakeVisible(*graphScope); - } - -private: - void paint(juce::Graphics& g) override - { - g.fillAll(juce::Colours::darkgrey); - g.setColour(juce::Colours::white); - g.drawRect(getLocalBounds()); - } - - void resized() override - { - // --- Top bar (manual) ---------------------------------------------- - auto area = getLocalBounds().reduced(10); - auto top = area.removeFromTop(22); - auto btnW = 46; - bypassButton.setBounds(top.removeFromRight(btnW).reduced(2, 1)); - titleLabel.setBounds(top); - - // --- Rest (grid) ---------------------------------------------------- - juce::Grid grid; - grid.templateRows = { - juce::Grid::TrackInfo(juce::Grid::Fr(55)), // scope/graph - juce::Grid::TrackInfo(juce::Grid::Fr(30)), // sliders - juce::Grid::TrackInfo(juce::Grid::Fr(15)) // labels - }; - - const int n = (int)sliders.size(); - grid.templateColumns.resize(n); - for (int i = 0; i < n; ++i) - grid.templateColumns.getReference(i) = juce::Grid::TrackInfo(juce::Grid::Fr(1)); - - grid.items.clear(); - - // Row 1: scope/graph – only add if constructed - if (useGraphScope) - { - if (graphScope) - grid.items.add(juce::GridItem(*graphScope) - .withArea(juce::GridItem::Span(1), juce::GridItem::Span(n))); - else - grid.items.add(juce::GridItem() - .withArea(juce::GridItem::Span(1), juce::GridItem::Span(n))); - } - else - { - if (scope) - grid.items.add(juce::GridItem(*scope) - .withArea(juce::GridItem::Span(1), juce::GridItem::Span(n))); - else - grid.items.add(juce::GridItem() - .withArea(juce::GridItem::Span(1), juce::GridItem::Span(n))); - } - - // Row 2: sliders - for (int i = 0; i < n; ++i) - grid.items.add(juce::GridItem(*sliders[(size_t)i])); - - // Row 3: labels - for (int i = 0; i < n; ++i) - grid.items.add(juce::GridItem(*labels[(size_t)i])); - - grid.performLayout(area); - } - - bool useGraphScope{ false }; - std::optional> scope; - std::optional> graphScope; - - std::vector> sliders; - std::vector> labels; - std::vector> attachments; - - juce::ToggleButton bypassButton; - std::unique_ptr bypassAttachment; - - juce::Label titleLabel; - - std::string paramGroupId; - juce::AudioProcessorValueTreeState& treeRef; -}; - -//============================== EqualizerComponent ============================ -// Adds an On/Off toggle bound to "eq_on". -class EqualizerComponent : public juce::Component { - static const int fontSize = 11; - -public: - explicit EqualizerComponent(juce::AudioProcessorValueTreeState& tree, - const juce::String& titleText = {}) - { - setupSlider(lowGainSlider); - setupSlider(midGainSlider); - setupSlider(highGainSlider); - - setupLabel(lowGainLabel, "L"); - setupLabel(midGainLabel, "M"); - setupLabel(highGainLabel, "H"); - - if (titleText.isNotEmpty()) - { - titleLabel.setText(titleText, juce::dontSendNotification); - juce::Font tf; tf.setHeight(13.0f); tf.setBold(true); - titleLabel.setFont(tf); - titleLabel.setJustificationType(juce::Justification::centredLeft); - titleLabel.setColour(juce::Label::textColourId, juce::Colours::white); - addAndMakeVisible(titleLabel); - } - - // Attachments - lowGainAttachment = std::make_unique(tree, "lowEQ", lowGainSlider); - midGainAttachment = std::make_unique(tree, "midEQ", midGainSlider); - highGainAttachment = std::make_unique(tree, "highEQ", highGainSlider); - - // EQ bypass toggle - bypassButton.setButtonText("On"); - bypassButton.setClickingTogglesState(true); - addAndMakeVisible(bypassButton); - bypassAttachment = std::make_unique(tree, "eq_on", bypassButton); - } - -private: - void setupSlider(juce::Slider& slider) { - slider.setRange(-24.0f, 24.0f, 0.1f); - slider.setSliderStyle(juce::Slider::LinearBarVertical); - slider.setTextBoxStyle(juce::Slider::TextBoxBelow, false, 50, 20); - addAndMakeVisible(slider); - } - - void setupLabel(juce::Label& lbl, juce::String txt) { - juce::Font f; f.setHeight((float)fontSize); f.setBold(true); - lbl.setFont(f); - lbl.setColour(juce::Label::textColourId, juce::Colours::lightgreen); - lbl.setJustificationType(juce::Justification::centred); - lbl.setText(txt, juce::dontSendNotification); - addAndMakeVisible(lbl); - } - - void paint(juce::Graphics& g) override { - g.fillAll(juce::Colours::darkgrey); - g.setColour(juce::Colours::white); - g.drawRect(getLocalBounds()); - } - - void resized() override { - auto area = getLocalBounds().reduced(10); - auto top = area.removeFromTop(22); - auto btnW = 46; - bypassButton.setBounds(top.removeFromRight(btnW).reduced(2, 1)); - titleLabel.setBounds(top); - - juce::Grid grid; - grid.templateRows = { - juce::Grid::TrackInfo(juce::Grid::Fr(1)), - juce::Grid::TrackInfo(juce::Grid::Fr(1)) - }; - grid.templateColumns = { - juce::Grid::TrackInfo(juce::Grid::Fr(1)), - juce::Grid::TrackInfo(juce::Grid::Fr(1)), - juce::Grid::TrackInfo(juce::Grid::Fr(1)) - }; - - grid.items = { - lowGainSlider, midGainSlider, highGainSlider, - lowGainLabel, midGainLabel, highGainLabel - }; - - grid.performLayout(area); - } - - juce::Slider lowGainSlider, midGainSlider, highGainSlider; - juce::Label lowGainLabel, midGainLabel, highGainLabel; - std::unique_ptr lowGainAttachment, midGainAttachment, highGainAttachment; - - juce::ToggleButton bypassButton; - std::unique_ptr bypassAttachment; - - juce::Label titleLabel; -}; - -//============================== Waveform List Model =========================== -struct WaveformSelectorContents final : public juce::ListBoxModel -{ - int getNumRows() override { return 4; } - - void paintListBoxItem(int rowNumber, juce::Graphics& g, - int width, int height, bool rowIsSelected) override - { - if (rowIsSelected) g.fillAll(juce::Colours::lightblue); - g.setColour(juce::LookAndFeel::getDefaultLookAndFeel() - .findColour(juce::Label::textColourId)); - - juce::Font f; f.setHeight((float)height * 0.7f); - g.setFont(f); - g.drawText(waves[(size_t)rowNumber], 5, 0, width, height, - juce::Justification::centredLeft, true); - } - - void selectedRowsChanged (int lastRowSelected) override - { - if (onSelect) onSelect(lastRowSelected); - } - - std::function onSelect; - - std::vector waves { "Sine", "Saw", "Square", "Triangle" }; -}; - -//============================== MasterVolumeComponent ========================= -class MasterVolumeComponent : public juce::Component -{ -public: - MasterVolumeComponent() - { - slider.setSliderStyle(juce::Slider::LinearBarVertical); - slider.setTextBoxStyle(juce::Slider::NoTextBox, false, 20, 20); - addAndMakeVisible(slider); - } - - void resized() override - { - slider.setBounds(getLocalBounds().reduced(30)); - } - - juce::Slider slider; -}; - -//============================== Editor ======================================= -class NeuralSynthAudioProcessorEditor : public juce::AudioProcessorEditor -{ -public: - NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor&); - ~NeuralSynthAudioProcessorEditor() override; - - void paint (juce::Graphics&) override; - void resized() override; - -private: - NeuralSynthAudioProcessor& audioProcessor; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthAudioProcessorEditor) - - juce::ListBox waveformSelector; - WaveformSelectorContents waveformContents; - - std::optional adsrComponent; // Amp Env - std::optional chorusComponent; - std::optional delayComponent; - std::optional reverbComponent; - - std::optional flangerComponent; - std::optional distortionComponent; - std::optional filterComponent; - std::optional filterEnvComponent; // Filter Env panel - - MasterVolumeComponent masterLevelSlider; - juce::Label masterLevelLabel; - - std::optional eqComponent; - - std::unique_ptr gainAttachment; - - ScopeComponent mainScopeComponent; - - juce::Component blankPanel; -}; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp deleted file mode 100644 index ea1efbc..0000000 --- a/Source/PluginProcessor.cpp +++ /dev/null @@ -1,270 +0,0 @@ -#include "PluginProcessor.h" -#include "PluginEditor.h" - -//============================================================================== -NeuralSynthAudioProcessor::NeuralSynthAudioProcessor() - : parameters(*this, nullptr, "PARAMETERS", createParameterLayout()) - , AudioProcessor(BusesProperties().withOutput("Output", juce::AudioChannelSet::stereo(), true)) - , audioEngine(sp) -{ - parameters.addParameterListener("waveform", this); - - // === Per-panel bypass (default OFF) === - sp.chorusOn = parameters.getRawParameterValue("chorus_on"); - sp.delayOn = parameters.getRawParameterValue("delay_on"); - sp.reverbOn = parameters.getRawParameterValue("reverb_on"); - sp.flangerOn = parameters.getRawParameterValue("flanger_on"); - sp.distortionOn = parameters.getRawParameterValue("distortion_on"); - sp.filterOn = parameters.getRawParameterValue("filter_on"); - sp.eqOn = parameters.getRawParameterValue("eq_on"); - - // === Chorus === - parameters.addParameterListener("chorus_rate", this); - parameters.addParameterListener("chorus_depth", this); - parameters.addParameterListener("chorus_centre", this); - parameters.addParameterListener("chorus_feedback", this); - parameters.addParameterListener("chorus_mix", this); - - sp.chorusRate = parameters.getRawParameterValue("chorus_rate"); - sp.chorusDepth = parameters.getRawParameterValue("chorus_depth"); - sp.chorusCentre = parameters.getRawParameterValue("chorus_centre"); - sp.chorusFeedback = parameters.getRawParameterValue("chorus_feedback"); - sp.chorusMix = parameters.getRawParameterValue("chorus_mix"); - - // === Delay === - parameters.addParameterListener("delay_delay", this); - sp.delayTime = parameters.getRawParameterValue("delay_delay"); - - // === Reverb === - parameters.addParameterListener("reverb_roomSize", this); - parameters.addParameterListener("reverb_damping", this); - parameters.addParameterListener("reverb_wetLevel", this); - parameters.addParameterListener("reverb_dryLevel", this); - parameters.addParameterListener("reverb_width", this); - parameters.addParameterListener("reverb_freezeMode", this); - - sp.reverbRoomSize = parameters.getRawParameterValue("reverb_roomSize"); - sp.reverbDamping = parameters.getRawParameterValue("reverb_damping"); - sp.reverbWetLevel = parameters.getRawParameterValue("reverb_wetLevel"); - sp.reverbDryLevel = parameters.getRawParameterValue("reverb_dryLevel"); - sp.reverbWidth = parameters.getRawParameterValue("reverb_width"); - sp.reverbFreezeMode= parameters.getRawParameterValue("reverb_freezeMode"); - - // === Amp ADSR === - parameters.addParameterListener("adsr_attack", this); - parameters.addParameterListener("adsr_decay", this); - parameters.addParameterListener("adsr_sustain", this); - parameters.addParameterListener("adsr_release", this); - - sp.adsrAttack = parameters.getRawParameterValue("adsr_attack"); - sp.adsrDecay = parameters.getRawParameterValue("adsr_decay"); - sp.adsrSustain = parameters.getRawParameterValue("adsr_sustain"); - sp.adsrRelease = parameters.getRawParameterValue("adsr_release"); - - // === Filter Env === - parameters.addParameterListener("fenv_attack", this); - parameters.addParameterListener("fenv_decay", this); - parameters.addParameterListener("fenv_sustain", this); - parameters.addParameterListener("fenv_release", this); - parameters.addParameterListener("fenv_amount", this); - - sp.fenvAttack = parameters.getRawParameterValue("fenv_attack"); - sp.fenvDecay = parameters.getRawParameterValue("fenv_decay"); - sp.fenvSustain = parameters.getRawParameterValue("fenv_sustain"); - sp.fenvRelease = parameters.getRawParameterValue("fenv_release"); - sp.fenvAmount = parameters.getRawParameterValue("fenv_amount"); - - // === Filter base === - parameters.addParameterListener("filter_cutoff", this); - parameters.addParameterListener("filter_resonance", this); - parameters.addParameterListener("filter_type", this); - parameters.addParameterListener("filter_drive", this); - parameters.addParameterListener("filter_mod", this); - parameters.addParameterListener("filter_key", this); - - sp.filterCutoff = parameters.getRawParameterValue("filter_cutoff"); - sp.filterResonance = parameters.getRawParameterValue("filter_resonance"); - sp.filterType = parameters.getRawParameterValue("filter_type"); - sp.filterDrive = parameters.getRawParameterValue("filter_drive"); - sp.filterMod = parameters.getRawParameterValue("filter_mod"); - sp.filterKey = parameters.getRawParameterValue("filter_key"); - - // === Distortion === - parameters.addParameterListener("distortion_drive", this); - parameters.addParameterListener("distortion_mix", this); - parameters.addParameterListener("distortion_bias", this); - parameters.addParameterListener("distortion_tone", this); - parameters.addParameterListener("distortion_shape", this); - - sp.distortionDrive = parameters.getRawParameterValue("distortion_drive"); - sp.distortionMix = parameters.getRawParameterValue("distortion_mix"); - sp.distortionBias = parameters.getRawParameterValue("distortion_bias"); - sp.distortionTone = parameters.getRawParameterValue("distortion_tone"); - sp.distortionShape = parameters.getRawParameterValue("distortion_shape"); - - // === Master / EQ === - parameters.addParameterListener("master", this); - parameters.addParameterListener("lowEQ", this); - parameters.addParameterListener("midEQ", this); - parameters.addParameterListener("highEQ", this); - - sp.masterDbls = parameters.getRawParameterValue("master"); - sp.lowGainDbls = parameters.getRawParameterValue("lowEQ"); - sp.midGainDbls = parameters.getRawParameterValue("midEQ"); - sp.highGainDbls = parameters.getRawParameterValue("highEQ"); -} - -NeuralSynthAudioProcessor::~NeuralSynthAudioProcessor() = default; - -//============================================================================== -const juce::String NeuralSynthAudioProcessor::getName() const { return JucePlugin_Name; } - -bool NeuralSynthAudioProcessor::acceptsMidi() const -{ - #if JucePlugin_WantsMidiInput - return true; - #else - return false; - #endif -} - -bool NeuralSynthAudioProcessor::producesMidi() const -{ - #if JucePlugin_ProducesMidiOutput - return true; - #else - return false; - #endif -} - -bool NeuralSynthAudioProcessor::isMidiEffect() const -{ - #if JucePlugin_IsMidiEffect - return true; - #else - return false; - #endif -} - -double NeuralSynthAudioProcessor::getTailLengthSeconds() const { return 0.0; } - -int NeuralSynthAudioProcessor::getNumPrograms() { return 1; } -int NeuralSynthAudioProcessor::getCurrentProgram() { return 0; } -void NeuralSynthAudioProcessor::setCurrentProgram (int) {} -const juce::String NeuralSynthAudioProcessor::getProgramName (int) { return {}; } -void NeuralSynthAudioProcessor::changeProgramName (int, const juce::String&) {} - -//============================================================================== -void NeuralSynthAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) -{ - audioEngine.prepare({ sampleRate, (juce::uint32)samplesPerBlock, 2 }); - midiMessageCollector.reset(sampleRate); -} - -void NeuralSynthAudioProcessor::releaseResources() {} - -bool NeuralSynthAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const -{ - if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() - && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo()) - return false; - - return true; -} - -void NeuralSynthAudioProcessor::processBlock(juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiMessages) -{ - const int newWaveform = sp.waveform.exchange(-1); - - if (newWaveform != -1) { - audioEngine.applyToVoices([newWaveform](NeuralSynthVoice* v) - { - v->changeWaveform(newWaveform); - }); - } - - juce::ScopedNoDenormals noDenormals; - auto totalNumInputChannels = getTotalNumInputChannels(); - auto totalNumOutputChannels = getTotalNumOutputChannels(); - - midiMessageCollector.removeNextBlockOfMessages(midiMessages, buffer.getNumSamples()); - - for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i) - buffer.clear(i, 0, buffer.getNumSamples()); - - audioEngine.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples()); - scopeDataCollector.process(buffer.getReadPointer(0), (size_t)buffer.getNumSamples()); -} - -//============================================================================== -bool NeuralSynthAudioProcessor::hasEditor() const { return true; } - -juce::AudioProcessorEditor* NeuralSynthAudioProcessor::createEditor() -{ - return new NeuralSynthAudioProcessorEditor (*this); -} - -//============================================================================== -void NeuralSynthAudioProcessor::getStateInformation (juce::MemoryBlock& destData) { juce::ignoreUnused(destData); } -void NeuralSynthAudioProcessor::setStateInformation (const void* data, int sizeInBytes) { juce::ignoreUnused(data, sizeInBytes); } - -void NeuralSynthAudioProcessor::parameterChanged(const juce::String& id, float newValue) -{ - juce::ignoreUnused(newValue); - if (id == "waveform") - sp.waveform.store((int)newValue, std::memory_order_release); -} - -//============================================================================== -// This creates new instances of the plugin.. -juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new NeuralSynthAudioProcessor(); } - -void NeuralSynthAudioProcessor::buildParams(std::vector>& params, const std::string& paramGroup) { - const auto& paramGroupSettings = PARAM_SETTINGS.at(paramGroup); - - for (const auto& [name, s] : paramGroupSettings) { - params.push_back(std::make_unique( - paramGroup + "_" + name, s.label, - juce::NormalisableRange(s.min, s.max, s.interval), - s.defValue)); - } -} - -juce::AudioProcessorValueTreeState::ParameterLayout NeuralSynthAudioProcessor::createParameterLayout() -{ - std::vector> params; - - params.push_back(std::make_unique( - "waveform", "Waveform", - juce::StringArray{ "Sine", "Saw", "Square", "Triangle" }, 0)); - - // Per-panel bypass toggles (default OFF) - params.push_back(std::make_unique("chorus_on", "Chorus On", false)); - params.push_back(std::make_unique("delay_on", "Delay On", false)); - params.push_back(std::make_unique("reverb_on", "Reverb On", false)); - params.push_back(std::make_unique("flanger_on", "Flanger On", false)); - params.push_back(std::make_unique("distortion_on", "Distortion On", false)); - params.push_back(std::make_unique("filter_on", "Filter On", false)); - params.push_back(std::make_unique("eq_on", "EQ On", false)); - - buildParams(params, "adsr"); - buildParams(params, "fenv"); - buildParams(params, "chorus"); - buildParams(params, "delay"); - buildParams(params, "reverb"); - buildParams(params, "flanger"); - buildParams(params, "distortion"); - buildParams(params, "filter"); - - params.push_back(std::make_unique("master", "Master", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.1f)); - - params.push_back(std::make_unique("lowEQ", "Low Gain", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.5f)); - params.push_back(std::make_unique("midEQ", "Mid EQ", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.8f)); - params.push_back(std::make_unique("highEQ", "High EQ", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 1.0f)); - - return { params.begin(), params.end() }; -} diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h deleted file mode 100644 index c5eafb6..0000000 --- a/Source/PluginProcessor.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include -#include "AudioBufferQueue.h" -#include "AudioEngine.h" -#include "ScopeDataCollector.h" -#include "NeuralSharedParams.h" - -//============================================================================== -// Processor -class NeuralSynthAudioProcessor : public juce::AudioProcessor, - private juce::AudioProcessorValueTreeState::Listener -{ -public: - NeuralSynthAudioProcessor(); - ~NeuralSynthAudioProcessor() override; - - // AudioProcessor overrides - void prepareToPlay(double sampleRate, int samplesPerBlock) override; - void releaseResources() override; - -#ifndef JucePlugin_PreferredChannelConfigurations - bool isBusesLayoutSupported(const BusesLayout& layouts) const override; -#endif - - void processBlock(juce::AudioBuffer&, juce::MidiBuffer&) override; - - // Editor - juce::AudioProcessorEditor* createEditor() override; - bool hasEditor() const override; - - // Info - const juce::String getName() const override; - bool acceptsMidi() const override; - bool producesMidi() const override; - bool isMidiEffect() const override; - double getTailLengthSeconds() const override; - - // Programs - int getNumPrograms() override; - int getCurrentProgram() override; - void setCurrentProgram(int index) override; - const juce::String getProgramName(int index) override; - void changeProgramName(int index, const juce::String& newName) override; - - // State - void getStateInformation(juce::MemoryBlock& destData) override; - void setStateInformation(const void* data, int sizeInBytes) override; - - // Parameters - void parameterChanged(const juce::String& id, float newValue) override; - void buildParams(std::vector>& params, - const std::string& paramGroup); - juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout(); - - // Utilities - juce::MidiMessageCollector& getMidiMessageCollector() noexcept { return midiMessageCollector; } - AudioBufferQueue& getAudioBufferQueue() noexcept { return audioBufferQueue; } - - AudioBufferQueue& getChorusAudioBufferQueue() noexcept { return chorusBufferQueue; } - AudioBufferQueue& getDelayAudioBufferQueue() noexcept { return delayBufferQueue; } - AudioBufferQueue& getReverbAudioBufferQueue() noexcept { return reverbBufferQueue; } - AudioBufferQueue& getFlangerAudioBufferQueue() noexcept { return flangerBufferQueue; } - AudioBufferQueue& getDistortionAudioBufferQueue() noexcept { return distortionBufferQueue; } - AudioBufferQueue& getFilterAudioBufferQueue() noexcept { return filterBufferQueue; } - - // Public members (by JUCE convention) - juce::MidiMessageCollector midiMessageCollector; - juce::AudioProcessorValueTreeState parameters; - -private: - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthAudioProcessor) - - // ---- IMPORTANT ORDER FIX ---- - // Objects are constructed in THIS order. 'sp' must come BEFORE audioEngine. - NeuralSharedParams sp; // <— construct first - NeuralAudioEngine audioEngine; // needs a valid reference to 'sp' - - // Meter/scope queues - AudioBufferQueue audioBufferQueue; - AudioBufferQueue chorusBufferQueue; - AudioBufferQueue delayBufferQueue; - AudioBufferQueue reverbBufferQueue; - AudioBufferQueue flangerBufferQueue; - AudioBufferQueue distortionBufferQueue; - AudioBufferQueue filterBufferQueue; - - // Scope collector (uses audioBufferQueue, so declare after it) - ScopeDataCollector scopeDataCollector { audioBufferQueue }; -}; diff --git a/Source/ScopeComponent.h b/Source/ScopeComponent.h deleted file mode 100644 index da731de..0000000 --- a/Source/ScopeComponent.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include "AudioBufferQueue.h" - -//============================================================================== -template -class ScopeComponent : public juce::Component, - private juce::Timer -{ -public: - using Queue = AudioBufferQueue; - - //============================================================================== - ScopeComponent(Queue& queueToUse) - : audioBufferQueue(queueToUse) - { - sampleData.fill(SampleType(0)); - setFramesPerSecond(30); - } - - //============================================================================== - void setFramesPerSecond(int framesPerSecond) - { - jassert(framesPerSecond > 0 && framesPerSecond < 1000); - startTimerHz(framesPerSecond); - } - - //============================================================================== - void paint(juce::Graphics& g) override - { - g.fillAll(juce::Colours::black); - g.setColour(juce::Colours::white); - - auto area = getLocalBounds(); - auto h = (SampleType)area.getHeight(); - auto w = (SampleType)area.getWidth(); - - // Oscilloscope - auto scopeRect = juce::Rectangle{ SampleType(0), SampleType(0), w, h / 2 }; - plot(sampleData.data(), sampleData.size(), g, scopeRect, SampleType(1), h / 4); - - // Spectrum - auto spectrumRect = juce::Rectangle{ SampleType(0), h / 2, w, h / 2 }; - plot(spectrumData.data(), spectrumData.size() / 4, g, spectrumRect); - } - - //============================================================================== - void resized() override {} - -private: - //============================================================================== - Queue& audioBufferQueue; - std::array sampleData; - - juce::dsp::FFT fft{ Queue::order }; - using WindowFun = juce::dsp::WindowingFunction; - WindowFun windowFun{ (size_t)fft.getSize(), WindowFun::hann }; - std::array spectrumData; - - //============================================================================== - void timerCallback() override - { - audioBufferQueue.pop(sampleData.data()); - juce::FloatVectorOperations::copy(spectrumData.data(), sampleData.data(), (int)sampleData.size()); - - auto fftSize = (size_t)fft.getSize(); - - jassert(spectrumData.size() == 2 * fftSize); - windowFun.multiplyWithWindowingTable(spectrumData.data(), fftSize); - fft.performFrequencyOnlyForwardTransform(spectrumData.data()); - - static constexpr auto mindB = SampleType(-160); - static constexpr auto maxdB = SampleType(0); - - for (auto& s : spectrumData) - s = juce::jmap(juce::jlimit(mindB, maxdB, juce::Decibels::gainToDecibels(s) - juce::Decibels::gainToDecibels(SampleType(fftSize))), mindB, maxdB, SampleType(0), SampleType(1)); - - repaint(); - } - - //============================================================================== - static void plot(const SampleType* data, - size_t numSamples, - juce::Graphics& g, - juce::Rectangle rect, - SampleType scaler = SampleType(1), - SampleType offset = SampleType(0)) - { - auto w = rect.getWidth(); - auto h = rect.getHeight(); - auto right = rect.getRight(); - - auto center = rect.getBottom() - offset; - auto gain = h * scaler; - - for (size_t i = 1; i < numSamples; ++i) - g.drawLine({ juce::jmap(SampleType(i - 1), SampleType(0), SampleType(numSamples - 1), SampleType(right - w), SampleType(right)), - center - gain * data[i - 1], - juce::jmap(SampleType(i), SampleType(0), SampleType(numSamples - 1), SampleType(right - w), SampleType(right)), - center - gain * data[i] }); - } -}; \ No newline at end of file diff --git a/Source/ScopeDataCollector.h b/Source/ScopeDataCollector.h deleted file mode 100644 index a271ebb..0000000 --- a/Source/ScopeDataCollector.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -template -class ScopeDataCollector -{ -public: - //============================================================================== - ScopeDataCollector(AudioBufferQueue& queueToUse) - : audioBufferQueue(queueToUse) - { - } - - //============================================================================== - void process(const SampleType* data, size_t numSamples) - { - size_t index = 0; - - if (state == State::waitingForTrigger) - { - while (index++ < numSamples) - { - auto currentSample = *data++; - - if (currentSample >= triggerLevel && prevSample < triggerLevel) - { - numCollected = 0; - state = State::collecting; - break; - } - - prevSample = currentSample; - } - } - - if (state == State::collecting) - { - while (index++ < numSamples) - { - buffer[numCollected++] = *data++; - - if (numCollected == buffer.size()) - { - audioBufferQueue.push(buffer.data(), buffer.size()); - state = State::waitingForTrigger; - prevSample = SampleType(100); - break; - } - } - } - } - -private: - //============================================================================== - AudioBufferQueue& audioBufferQueue; - std::array::bufferSize> buffer; - size_t numCollected; - SampleType prevSample = SampleType(100); - - static constexpr auto triggerLevel = SampleType(0.05); - - enum class State { waitingForTrigger, collecting } state{ State::waitingForTrigger }; -}; \ No newline at end of file diff --git a/Source/SynthVoice.cpp b/Source/SynthVoice.cpp deleted file mode 100644 index c9467f5..0000000 --- a/Source/SynthVoice.cpp +++ /dev/null @@ -1,398 +0,0 @@ -#include "SynthVoice.h" -#include - -//============================================================================== - -NeuralSynthVoice::NeuralSynthVoice (NeuralSharedParams& sp) - : shared (sp) {} - -//============================================================================== - -void NeuralSynthVoice::prepare (const juce::dsp::ProcessSpec& newSpec) -{ - spec = newSpec; - - // --- Oscillator - osc.prepare (spec.sampleRate); - setWaveform (0); // default to sine - - // --- Scratch buffer (IMPORTANT: allocate real memory) - tempBuffer.setSize ((int) spec.numChannels, (int) spec.maximumBlockSize, - false, false, true); - tempBlock = juce::dsp::AudioBlock (tempBuffer); - - // --- Prepare chain elements - chain.prepare (spec); - - // Set maximum delay sizes BEFORE runtime changes - { - // Flanger: up to 20 ms - auto& flanger = chain.get(); - const size_t maxFlangerDelay = (size_t) juce::jmax( - 1, (size_t) std::ceil (0.020 * spec.sampleRate)); - flanger.setMaximumDelayInSamples (maxFlangerDelay); - flanger.reset(); - } - { - // Simple delay: up to 2 s - auto& delay = chain.get(); - const size_t maxDelay = (size_t) juce::jmax( - 1, (size_t) std::ceil (2.0 * spec.sampleRate)); - delay.setMaximumDelayInSamples (maxDelay); - delay.reset(); - } - - // Envelopes - adsr.setSampleRate (spec.sampleRate); - filterAdsr.setSampleRate (spec.sampleRate); - - // Filter - svf.reset(); - svf.prepare (spec); - - // Initial filter type - const int type = (int) std::lround (juce::jlimit (0.0f, 2.0f, - shared.filterType ? shared.filterType->load() : 0.0f)); - switch (type) - { - case 0: svf.setType (juce::dsp::StateVariableTPTFilterType::lowpass); break; - case 1: svf.setType (juce::dsp::StateVariableTPTFilterType::highpass); break; - case 2: svf.setType (juce::dsp::StateVariableTPTFilterType::bandpass); break; - default: break; - } -} - -//============================================================================== - -void NeuralSynthVoice::renderNextBlock (juce::AudioBuffer& outputBuffer, - int startSample, int numSamples) -{ - if (numSamples <= 0) - return; - - if (! adsr.isActive()) - clearCurrentNote(); - - // Apply pending waveform change (from GUI / processor thread) - const int wf = pendingWaveform.exchange (-1, std::memory_order_acq_rel); - if (wf != -1) - setWaveform (wf); - - // --- Generate oscillator into temp buffer - tempBuffer.clear(); - const int numCh = juce::jmin ((int) spec.numChannels, tempBuffer.getNumChannels()); - - for (int i = 0; i < numSamples; ++i) - { - const float s = osc.process(); - for (int ch = 0; ch < numCh; ++ch) - tempBuffer.getWritePointer (ch)[i] = s; - } - - auto block = tempBlock.getSubBlock (0, (size_t) numSamples); - - // ================================================================ - // Flanger (pre-filter) – manual per-sample to set varying delay - // ================================================================ - { - auto& flanger = chain.get(); - - const bool enabled = shared.flangerOn && shared.flangerOn->load() > 0.5f; - if (enabled) - { - const float rate = shared.flangerRate ? shared.flangerRate->load() : 0.0f; - float lfoPhase = shared.flangerPhase ? shared.flangerPhase->load() : 0.0f; - const float flangerDepth = shared.flangerDepth ? shared.flangerDepth->load() : 0.0f; // ms - const float mix = shared.flangerDryMix ? shared.flangerDryMix->load() : 0.0f; - const float feedback = shared.flangerFeedback ? shared.flangerFeedback->load() : 0.0f; - const float baseDelayMs = shared.flangerDelay ? shared.flangerDelay->load() : 0.25f; - - for (int i = 0; i < numSamples; ++i) - { - const float in = tempBuffer.getReadPointer (0)[i]; - - const float lfo = std::sin (lfoPhase); - const float delayMs = baseDelayMs + 0.5f * (1.0f + lfo) * flangerDepth; - const float delaySamples = juce::jmax (0.0f, delayMs * 0.001f * (float) spec.sampleRate); - - flanger.setDelay (delaySamples); - - const float delayed = flanger.popSample (0); - flanger.pushSample (0, in + delayed * feedback); - - const float out = in * (1.0f - mix) + delayed * mix; - for (int ch = 0; ch < numCh; ++ch) - tempBuffer.getWritePointer (ch)[i] = out; - - lfoPhase += juce::MathConstants::twoPi * rate / (float) spec.sampleRate; - if (lfoPhase > juce::MathConstants::twoPi) - lfoPhase -= juce::MathConstants::twoPi; - } - } - } - - // ================================================================ - // Filter with per-sample ADSR modulation (poly) - // ================================================================ - { - const bool enabled = shared.filterOn && shared.filterOn->load() > 0.5f; - - // Update filter type every block (cheap) - const int ftype = (int) std::lround (juce::jlimit (0.0f, 2.0f, - shared.filterType ? shared.filterType->load() : 0.0f)); - switch (ftype) - { - case 0: svf.setType (juce::dsp::StateVariableTPTFilterType::lowpass); break; - case 1: svf.setType (juce::dsp::StateVariableTPTFilterType::highpass); break; - case 2: svf.setType (juce::dsp::StateVariableTPTFilterType::bandpass); break; - default: break; - } - - const float qOrRes = juce::jlimit (0.1f, 10.0f, - shared.filterResonance ? shared.filterResonance->load() : 0.7f); - svf.setResonance (qOrRes); - - const float baseCutoff = juce::jlimit (20.0f, 20000.0f, - shared.filterCutoff ? shared.filterCutoff->load() : 1000.0f); - const float envAmt = shared.fenvAmount ? shared.fenvAmount->load() : 0.0f; - - for (int i = 0; i < numSamples; ++i) - { - const float envVal = filterAdsr.getNextSample(); - const float cutoff = juce::jlimit (20.0f, 20000.0f, - baseCutoff * std::pow (2.0f, envAmt * envVal)); - svf.setCutoffFrequency (cutoff); - - if (enabled) - { - for (int ch = 0; ch < numCh; ++ch) - { - float x = tempBuffer.getSample (ch, i); - x = svf.processSample (ch, x); - tempBuffer.setSample (ch, i, x); - } - } - } - } - - // ================================================================ - // Chorus - // ================================================================ - if (shared.chorusOn && shared.chorusOn->load() > 0.5f) - { - auto& chorus = chain.get(); - if (shared.chorusCentre) chorus.setCentreDelay (shared.chorusCentre->load()); - if (shared.chorusDepth) chorus.setDepth (shared.chorusDepth->load()); - if (shared.chorusFeedback) chorus.setFeedback (shared.chorusFeedback->load()); - if (shared.chorusMix) chorus.setMix (shared.chorusMix->load()); - if (shared.chorusRate) chorus.setRate (shared.chorusRate->load()); - - chain.get().process (juce::dsp::ProcessContextReplacing (block)); - } - - // ================================================================ - // Simple Delay (per-voice) - // ================================================================ - if (shared.delayOn && shared.delayOn->load() > 0.5f) - { - auto& delay = chain.get(); - const float time = shared.delayTime ? shared.delayTime->load() : 0.1f; - delay.setDelay (juce::jmax (0.0f, time * (float) spec.sampleRate)); - delay.process (juce::dsp::ProcessContextReplacing (block)); - } - - // ================================================================ - // Reverb - // ================================================================ - if (shared.reverbOn && shared.reverbOn->load() > 0.5f) - { - juce::Reverb::Parameters rp; - rp.damping = shared.reverbDamping ? shared.reverbDamping->load() : 0.0f; - rp.dryLevel = shared.reverbDryLevel ? shared.reverbDryLevel->load() : 0.0f; - rp.freezeMode = shared.reverbFreezeMode ? shared.reverbFreezeMode->load() : 0.0f; - rp.roomSize = shared.reverbRoomSize ? shared.reverbRoomSize->load() : 0.0f; - rp.wetLevel = shared.reverbWetLevel ? shared.reverbWetLevel->load() : 0.0f; - rp.width = shared.reverbWidth ? shared.reverbWidth->load() : 0.0f; - - chain.get().setParameters (rp); - chain.get().process (juce::dsp::ProcessContextReplacing (block)); - } - - // ================================================================ - // Distortion + tone (post LPF/Peak) - // ================================================================ - { - const float driveDb = shared.distortionDrive ? shared.distortionDrive->load() : 0.0f; - const float bias = juce::jlimit (-1.0f, 1.0f, shared.distortionBias ? shared.distortionBias->load() : 0.0f); - const float toneHz = juce::jlimit (100.0f, 8000.0f, shared.distortionTone ? shared.distortionTone->load() : 3000.0f); - const int shape = (int) std::lround (juce::jlimit (0.0f, 2.0f, - shared.distortionShape ? shared.distortionShape->load() : 0.0f)); - const float mix = shared.distortionMix ? shared.distortionMix->load() : 0.0f; - - auto& pre = chain.get(); - auto& sh = chain.get(); - auto& tone = chain.get(); - - pre.setGainDecibels (driveDb); - - // Explicit std::function target (works on MSVC) - if (shape == 0) sh.functionToUse = std::function{ [bias](float x) noexcept { return std::tanh (x + bias); } }; - else if (shape == 1) sh.functionToUse = std::function{ [bias](float x) noexcept { return juce::jlimit (-1.0f, 1.0f, x + bias); } }; - else sh.functionToUse = std::function{ [bias](float x) noexcept { return std::atan (x + bias) * (2.0f / juce::MathConstants::pi); } }; - - tone.coefficients = juce::dsp::IIR::Coefficients::makePeakFilter ( - spec.sampleRate, toneHz, 0.707f, - juce::Decibels::decibelsToGain (shared.highGainDbls ? shared.highGainDbls->load() : 0.0f)); - - if (shared.distortionOn && shared.distortionOn->load() > 0.5f) - { - // Wet/dry blend around the shaper - juce::AudioBuffer dryCopy (tempBuffer.getNumChannels(), numSamples); - for (int ch = 0; ch < numCh; ++ch) - dryCopy.copyFrom (ch, 0, tempBuffer, ch, 0, numSamples); - - // pre -> shaper -> tone - pre.process (juce::dsp::ProcessContextReplacing (block)); - sh.process (juce::dsp::ProcessContextReplacing (block)); - tone.process (juce::dsp::ProcessContextReplacing (block)); - - const float wet = mix, dry = 1.0f - mix; - for (int ch = 0; ch < numCh; ++ch) - { - auto* d = dryCopy.getReadPointer (ch); - auto* w = tempBuffer.getWritePointer (ch); - for (int i = 0; i < numSamples; ++i) - w[i] = dry * d[i] + wet * w[i]; - } - } - } - - // ================================================================ - // EQ + Master + Limiter (EQ guarded by eqOn) - // ================================================================ - { - const bool eqEnabled = shared.eqOn && shared.eqOn->load() > 0.5f; - - auto& eqL = chain.get(); - auto& eqM = chain.get(); - auto& eqH = chain.get(); - - if (eqEnabled) - { - eqL.coefficients = juce::dsp::IIR::Coefficients::makeLowShelf ( - spec.sampleRate, 100.0f, 0.707f, - juce::Decibels::decibelsToGain (shared.lowGainDbls ? shared.lowGainDbls->load() : 0.0f)); - - eqM.coefficients = juce::dsp::IIR::Coefficients::makePeakFilter ( - spec.sampleRate, 1000.0f, 1.0f, - juce::Decibels::decibelsToGain (shared.midGainDbls ? shared.midGainDbls->load() : 0.0f)); - - eqH.coefficients = juce::dsp::IIR::Coefficients::makePeakFilter ( - spec.sampleRate, 10000.0f, 0.707f, - juce::Decibels::decibelsToGain (shared.highGainDbls ? shared.highGainDbls->load() : 0.0f)); - - eqL.process (juce::dsp::ProcessContextReplacing (block)); - eqM.process (juce::dsp::ProcessContextReplacing (block)); - eqH.process (juce::dsp::ProcessContextReplacing (block)); - } - - chain.get().setGainDecibels (shared.masterDbls ? shared.masterDbls->load() : 0.0f); - chain.get().process (juce::dsp::ProcessContextReplacing (block)); - - chain.get().process (juce::dsp::ProcessContextReplacing (block)); - } - - // ================================================================ - // Apply AMP ADSR envelope - // ================================================================ - { - juce::AudioBuffer buf (tempBuffer.getArrayOfWritePointers(), numCh, numSamples); - adsr.applyEnvelopeToBuffer (buf, 0, numSamples); - } - - // Mix into output - juce::dsp::AudioBlock (outputBuffer) - .getSubBlock ((size_t) startSample, (size_t) numSamples) - .add (block); -} - -//============================================================================== - -void NeuralSynthVoice::noteStarted() -{ - const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz(); - - // Oscillator frequency and phase retrigger - osc.setFrequency (freqHz); - osc.resetPhase (0.0f); - - // Chorus snapshot - if (shared.chorusCentre) chain.get().setCentreDelay (shared.chorusCentre->load()); - if (shared.chorusDepth) chain.get().setDepth (shared.chorusDepth->load()); - if (shared.chorusFeedback) chain.get().setFeedback (shared.chorusFeedback->load()); - if (shared.chorusMix) chain.get().setMix (shared.chorusMix->load()); - if (shared.chorusRate) chain.get().setRate (shared.chorusRate->load()); - - // Delay time (in samples) - if (shared.delayTime) - chain.get().setDelay (juce::jmax (0.0f, shared.delayTime->load() * (float) spec.sampleRate)); - - // Reverb snapshot - juce::Reverb::Parameters rp; - rp.damping = shared.reverbDamping ? shared.reverbDamping->load() : 0.0f; - rp.dryLevel = shared.reverbDryLevel ? shared.reverbDryLevel->load() : 0.0f; - rp.freezeMode = shared.reverbFreezeMode ? shared.reverbFreezeMode->load() : 0.0f; - rp.roomSize = shared.reverbRoomSize ? shared.reverbRoomSize->load() : 0.0f; - rp.wetLevel = shared.reverbWetLevel ? shared.reverbWetLevel->load() : 0.0f; - rp.width = shared.reverbWidth ? shared.reverbWidth->load() : 0.0f; - chain.get().setParameters (rp); - - // Amp ADSR - juce::ADSR::Parameters ap; - ap.attack = shared.adsrAttack ? shared.adsrAttack->load() : 0.01f; - ap.decay = shared.adsrDecay ? shared.adsrDecay->load() : 0.10f; - ap.sustain = shared.adsrSustain ? shared.adsrSustain->load() : 0.80f; - ap.release = shared.adsrRelease ? shared.adsrRelease->load() : 0.40f; - adsr.setParameters (ap); - adsr.noteOn(); - - // Filter ADSR - juce::ADSR::Parameters fp; - fp.attack = shared.fenvAttack ? shared.fenvAttack->load() : 0.01f; - fp.decay = shared.fenvDecay ? shared.fenvDecay->load() : 0.10f; - fp.sustain = shared.fenvSustain ? shared.fenvSustain->load() : 0.80f; - fp.release = shared.fenvRelease ? shared.fenvRelease->load() : 0.40f; - filterAdsr.setParameters (fp); - filterAdsr.noteOn(); -} - -//============================================================================== - -void NeuralSynthVoice::notePitchbendChanged() -{ - const float freqHz = (float) getCurrentlyPlayingNote().getFrequencyInHertz(); - osc.setFrequency (freqHz); -} - -//============================================================================== - -void NeuralSynthVoice::noteStopped (bool allowTailOff) -{ - juce::ignoreUnused (allowTailOff); - adsr.noteOff(); - filterAdsr.noteOff(); -} - -//============================================================================== - -void NeuralSynthVoice::setWaveform (int waveformType) -{ - switch (juce::jlimit (0, 3, waveformType)) - { - case 0: osc.setWave (BlepWave::Sine); break; - case 1: osc.setWave (BlepWave::Saw); break; - case 2: osc.setWave (BlepWave::Square); break; - case 3: osc.setWave (BlepWave::Triangle); break; - default: osc.setWave (BlepWave::Sine); break; - } -} diff --git a/Source/SynthVoice.h b/Source/SynthVoice.h deleted file mode 100644 index e1e8856..0000000 --- a/Source/SynthVoice.h +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once -#include -#include // <-- for std::function used by WaveShaper -#include "NeuralSharedParams.h" -#include "BlepOsc.h" - -//============================================================================== -// A single polyBLEP oscillator voice with per-voice ADSR, filter ADSR, -// flanger (delayline), simple delay, chorus, reverb, distortion, EQ, master. -class NeuralSynthVoice : public juce::MPESynthesiserVoice -{ -public: - explicit NeuralSynthVoice (NeuralSharedParams& sharedParams); - - // JUCE voice API - void prepare (const juce::dsp::ProcessSpec& spec); - void renderNextBlock (juce::AudioBuffer& outputBuffer, - int startSample, int numSamples) override; - - void noteStarted() override; - void noteStopped (bool allowTailOff) override; - void notePitchbendChanged() override; - - void notePressureChanged() override {} - void noteTimbreChanged() override {} - void noteKeyStateChanged() override {} - - // Called from the processor when the GUI waveform param changes - void changeWaveform (int wf) { setWaveform (wf); } - -private: - void setWaveform (int waveformType); - - //=== Processing chain (without oscillator) =============================== - using DelayLine = juce::dsp::DelayLine; - using IIR = juce::dsp::IIR::Filter; - using Gain = juce::dsp::Gain; - using WaveShaper = juce::dsp::WaveShaper>; // <-- fix - using Chorus = juce::dsp::Chorus; - using Reverb = juce::dsp::Reverb; - using Limiter = juce::dsp::Limiter; - - enum ChainIndex - { - flangerIndex = 0, - delayIndex, - chorusIndex, - reverbIndex, - distortionPreGain, - distortionIndex, - distortionPostLPF, - eqLowIndex, - eqMidIndex, - eqHighIndex, - masterIndex, - limiterIndex - }; - - using Chain = juce::dsp::ProcessorChain< - DelayLine, // flanger - DelayLine, // simple delay - Chorus, // chorus - Reverb, // reverb - Gain, // distortion pre-gain (drive) - WaveShaper, // distortion waveshaper - IIR, // tone / post-EQ for distortion - IIR, // EQ low - IIR, // EQ mid - IIR, // EQ high - Gain, // master gain - Limiter // safety limiter - >; - -private: - NeuralSharedParams& shared; - - juce::dsp::ProcessSpec spec {}; - - // ==== Oscillator (polyBLEP) ============================================ - BlepOsc osc; - std::atomic pendingWaveform {-1}; // set by changeWaveform() - - // ==== Envelopes & Filter =============================================== - juce::ADSR adsr; - juce::ADSR filterAdsr; - juce::dsp::StateVariableTPTFilter svf; - - // ==== Chain (FX, EQ, master, limiter) ================================== - Chain chain; - - // ==== Scratch buffer (properly allocated) =============================== - juce::AudioBuffer tempBuffer; - juce::dsp::AudioBlock tempBlock; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthVoice) -}; diff --git a/Source/WavetableOsc.h b/Source/WavetableOsc.h deleted file mode 100644 index e65fa09..0000000 --- a/Source/WavetableOsc.h +++ /dev/null @@ -1,261 +0,0 @@ -#pragma once -#include -#include -#include - -// ============================== Design ======================================= -// - Bank with F frames, each frame is a single-cycle table of N samples. -// - For each frame, we create L mip-levels: level 0 = full bandwidth, -// level l halves the permitted harmonics (spectral truncation). -// - Runtime chooses level from note frequency and sampleRate, then morphs -// between adjacent frames and crossfades between the two nearest levels. -// - Table read uses linear interpolation (cheap and good enough with N>=2048). - -namespace WT -{ - // Utility: complex array wrapper for JUCE FFT (interleaved real/imag floats) - struct ComplexBuf - { - std::vector data; // size = 2 * N - explicit ComplexBuf(size_t N = 0) { resize(N); } - void resize(size_t N) { data.assign(2 * N, 0.0f); } - juce::dsp::Complex* asComplex() { return reinterpret_cast*>(data.data()); } - }; - - // ======================================================================= - // WavetableBank: holds raw frames + mipmapped versions - // ======================================================================= - class Bank - { - public: - // N = table length (must be power-of-two for FFT), frames = number of morph frames - // mipLevels = how many spectral levels (>=1). 5 ~ 6 is plenty for synth use. - Bank(size_t N = 2048, int frames = 16, int mipLevels = 6) - : tableSize(N), numFrames(frames), numLevels(mipLevels), - fft((int)std::log2((double)N)) - { - jassert(juce::isPowerOfTwo((int)N)); - tables.resize((size_t)numLevels); - for (int l = 0; l < numLevels; ++l) - tables[(size_t)l].resize((size_t)numFrames, std::vector(tableSize, 0.0f)); - } - - size_t getSize() const { return tableSize; } - int getFrames() const { return numFrames; } - int getLevels() const { return numLevels; } - - // Provide raw “design” frames (time-domain single-cycle) then call buildMipmaps(). - // framesRaw.size() must equal numFrames, each frame length must equal tableSize. - void setRawFrames(const std::vector>& framesRaw) - { - jassert((int)framesRaw.size() == numFrames); - for (const auto& f : framesRaw) jassert(f.size() == tableSize); - raw = framesRaw; - } - - // Convenience: generate 16-frame bank morphing Sine -> Saw -> Square -> Triangle - void generateDefaultMorph() - { - std::vector> frames; - frames.resize((size_t)numFrames, std::vector(tableSize, 0.0f)); - - auto fill = [&](int idx, auto func) - { - auto& t = frames[(size_t)idx]; - for (size_t n = 0; n < tableSize; ++n) - { - const float ph = (float) (juce::MathConstants::twoPi * (double)n / (double)tableSize); - t[n] = func(ph); - } - normalise(t); - }; - - // helper waves - auto sine = [](float ph) { return std::sin(ph); }; - auto saw = [](float ph) { return (float)(2.0 * (ph / juce::MathConstants::twoPi) - 1.0); }; - auto sq = [](float ph) { return ph < juce::MathConstants::pi ? 1.0f : -1.0f; }; - auto tri = [](float ph) { - float v = (float)(2.0 * std::abs(2.0 * (ph / juce::MathConstants::twoPi) - 1.0) - 1.0); - return v; - }; - - // 0..5: sine->saw, 6..10: saw->square, 11..15: square->triangle - const int F = numFrames; - for (int i = 0; i < F; ++i) - { - const float t = (float) i / (float) juce::jmax(1, F - 1); - std::function a, b; - float mix = 0.0f; - - if (i <= 5) { a = sine; b = saw; mix = (float)i / 5.0f; } - else if (i <=10) { a = saw; b = sq; mix = (float)(i - 6) / 4.0f; } - else { a = sq; b = tri; mix = (float)(i - 11) / 4.0f; } - - fill(i, [=](float ph){ return (1.0f - mix) * a(ph) + mix * b(ph); }); - } - - setRawFrames(frames); - } - - // Build mip-levels by FFT → spectral truncation → IFFT - void buildMipmaps() - { - jassert(!raw.empty()); - ComplexBuf freq(tableSize); - ComplexBuf time(tableSize); - - for (int f = 0; f < numFrames; ++f) - { - // Forward FFT of raw frame - std::fill(freq.data.begin(), freq.data.end(), 0.0f); - for (size_t n = 0; n < tableSize; ++n) - { - time.data[2 * n + 0] = raw[(size_t)f][n]; - time.data[2 * n + 1] = 0.0f; - } - fft.performRealOnlyForwardTransform(time.data.data()); - // After JUCE real FFT, bins are laid out as: Re[0], Re[N/2], Re[1], Im[1], Re[2], Im[2], ... - // We'll reconstruct complex bins for easy masking. - - // Helper to zero all harmonics above kMax (inclusive index in [0..N/2]) - auto maskAndIFFT = [&](int level, int kMax) - { - // Copy time.data into working complex bins - auto* bins = freq.asComplex(); - // DC & Nyquist are purely real in real-FFT - bins[0].real (time.data[0]); - bins[0].imag (0.0f); - bins[tableSize/2].real (time.data[1]); - bins[tableSize/2].imag (0.0f); - - // Rebuild the rest (Re[k], Im[k]) packed starting at index 2 - for (size_t k = 1; k < tableSize/2; ++k) - { - bins[k].real (time.data[2 * k + 0]); - bins[k].imag (time.data[2 * k + 1]); - } - - // Mask - for (size_t k = (size_t)kMax + 1; k < tableSize/2; ++k) - bins[k] = { 0.0f, 0.0f }; - - // Pack back into real-FFT layout for inverse - time.data[0] = bins[0].real(); // DC - time.data[1] = bins[tableSize/2].real(); // Nyquist - for (size_t k = 1; k < tableSize/2; ++k) - { - time.data[2 * k + 0] = bins[k].real(); - time.data[2 * k + 1] = bins[k].imag(); - } - - // IFFT - fft.performRealOnlyInverseTransform(time.data.data()); - - // Copy, normalise a little (scale JUCE inverse divides by N already) - auto& dst = tables[(size_t)level][(size_t)f]; - for (size_t n = 0; n < tableSize; ++n) - dst[n] = time.data[2 * n + 0]; - - normalise(dst); - }; - - // Level 0 → all harmonics available up to N/2 - 1 - for (int l = 0; l < numLevels; ++l) - { - const int maxH = (int)((tableSize / 2) >> l); // halve per level - const int kMax = juce::jmax(1, juce::jmin(maxH, (int)tableSize/2 - 1)); - maskAndIFFT(l, kMax); - } - } - } - - // sample at (frame, level, phase in [0,1)) - inline float lookup (float frameIdx, int level, float phase) const noexcept - { - const int f0 = juce::jlimit(0, numFrames - 1, (int)std::floor(frameIdx)); - const int f1 = juce::jlimit(0, numFrames - 1, f0 + 1); - const float t = juce::jlimit(0.0f, 1.0f, frameIdx - (float)f0); - - const auto& T0 = tables[(size_t)level][(size_t)f0]; - const auto& T1 = tables[(size_t)level][(size_t)f1]; - - const float pos = phase * (float)tableSize; - const int i0 = (int) std::floor(pos) & (int)(tableSize - 1); - const int i1 = (i0 + 1) & (int)(tableSize - 1); - const float a = pos - (float) std::floor(pos); - - const float s0 = juce::jmap(a, T0[(size_t)i0], T0[(size_t)i1]); - const float s1 = juce::jmap(a, T1[(size_t)i0], T1[(size_t)i1]); - return juce::jmap(t, s0, s1); - } - - // choose mip-level for given frequency (Hz) & sampleRate - inline int chooseLevel (float freq, double sampleRate) const noexcept - { - // permitted harmonics at this pitch: - const float maxH = (float) (0.5 * sampleRate / juce::jmax(1.0f, freq)); - // level so that harmonic budget of level >= maxH, i.e. l = ceil(log2((N/2)/maxH)) - const float base = (float)(tableSize * 0.5); - const float ratio = base / juce::jmax(1.0f, maxH); - int l = (int) std::ceil (std::log2 (ratio)); - return juce::jlimit (0, numLevels - 1, l); - } - - static void normalise (std::vector& t) - { - float mx = 0.0f; - for (float v : t) mx = juce::jmax(mx, std::abs(v)); - if (mx < 1.0e-6f) return; - for (float& v : t) v /= mx; - } - - private: - size_t tableSize; - int numFrames; - int numLevels; - - juce::dsp::FFT fft; - std::vector> raw; - // [level][frame][sample] - std::vector>> tables; - }; - - // ======================================================================= - // Wavetable Oscillator - // ======================================================================= - class Osc - { - public: - void prepare (double sr) { sampleRate = sr; } - void setBank (std::shared_ptr b) { bank = std::move(b); } - void setFrequency (float f) { freq = juce::jmax(0.0f, f); phaseInc = freq / (float)sampleRate; } - void setMorph (float m) { morph = m; } // 0..frames-1 (continuous) - void resetPhase (float p = 0.0f) { phase = juce::jlimit(0.0f, 1.0f, p); } - - float process() - { - if (!bank) return 0.0f; - - const int l0 = bank->chooseLevel(freq, sampleRate); - const int l1 = juce::jmin(l0 + 1, bank->getLevels() - 1); - const float preferL0 = 1.0f - juce::jlimit(0.0f, 1.0f, - (float)l0 - (float)bank->chooseLevel(freq * 0.99f, sampleRate)); - - const float s0 = bank->lookup(morph, l0, phase); - const float s1 = bank->lookup(morph, l1, phase); - const float out = juce::jmap(preferL0, s1, s0); // simple crossfade - - phase += phaseInc; - while (phase >= 1.0f) phase -= 1.0f; - return out; - } - - private: - std::shared_ptr bank; - double sampleRate { 44100.0 }; - float freq { 0.0f }; - float morph { 0.0f }; // 0..frames-1 - float phase { 0.0f }; - float phaseInc { 0.0f }; - }; -} // namespace WT