closes #7
Processor editor and processor in seperate files. slider paramters now can be added by simply adding them in the processor, everything else is dynamic
This commit is contained in:
@ -48,10 +48,10 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Container>
|
<Container>
|
||||||
<JuceSlider identifier="formantSlider" title="Formant" />
|
<JuceSlider identifier="formantPreserve" title="Formant" />
|
||||||
<JuceSlider identifier="autoTuneSpeedSlider" title="Auto Tune Speed" />
|
<JuceSlider identifier="autoTuneSpeed" title="Auto Tune Speed" />
|
||||||
<JuceSlider identifier="autoTuneDepthSlider" title="Auto Tune Depth" />
|
<JuceSlider identifier="autoTuneDepth" title="Auto Tune Depth" />
|
||||||
<JuceSlider identifier="portTimeSlider" title="Portamento Speed" />
|
<JuceSlider identifier="portTime" title="Portamento Speed" />
|
||||||
</Container>
|
</Container>
|
||||||
<MidiNoteInfo />
|
<MidiNoteInfo />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Harmonizer\Assets">
|
<Filter Include="Harmonizer\Assets">
|
||||||
@ -685,6 +684,12 @@
|
|||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\Source\PluginEditor.cpp">
|
||||||
|
<Filter>Harmonizer\Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\Source\PluginProcessor.cpp">
|
||||||
|
<Filter>Harmonizer\Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\Source\shifter_voice.cpp">
|
<ClCompile Include="..\..\Source\shifter_voice.cpp">
|
||||||
<Filter>Harmonizer\Source</Filter>
|
<Filter>Harmonizer\Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -838,9 +843,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_basics\juce_audio_basics.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_basics\juce_audio_basics.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_basics</Filter>
|
<Filter>JUCE Modules\juce_audio_basics</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_basics\juce_audio_basics.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_basics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\audio_io\juce_AudioDeviceManager.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\audio_io\juce_AudioDeviceManager.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_devices\audio_io</Filter>
|
<Filter>JUCE Modules\juce_audio_devices\audio_io</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1066,9 +1068,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\native\juce_CoreAudio_mac.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\native\juce_CoreAudio_mac.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_devices\native</Filter>
|
<Filter>JUCE Modules\juce_audio_devices\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\native\juce_CoreMidi_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_devices\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\native\juce_DirectSound_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\native\juce_DirectSound_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_devices\native</Filter>
|
<Filter>JUCE Modules\juce_audio_devices\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1102,9 +1101,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\juce_audio_devices.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\juce_audio_devices.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_devices</Filter>
|
<Filter>JUCE Modules\juce_audio_devices</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_devices\juce_audio_devices.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_devices</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_formats\codecs\flac\libFLAC\deduplication\bitreader_read_rice_signed_block.c">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_formats\codecs\flac\libFLAC\deduplication\bitreader_read_rice_signed_block.c">
|
||||||
<Filter>JUCE Modules\juce_audio_formats\codecs\flac\libFLAC\deduplication</Filter>
|
<Filter>JUCE Modules\juce_audio_formats\codecs\flac\libFLAC\deduplication</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1291,9 +1287,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_formats\juce_audio_formats.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_formats\juce_audio_formats.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_formats</Filter>
|
<Filter>JUCE Modules\juce_audio_formats</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_formats\juce_audio_formats.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_formats</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_plugin_client\juce_audio_plugin_client_ARA.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_plugin_client\juce_audio_plugin_client_ARA.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_plugin_client</Filter>
|
<Filter>JUCE Modules\juce_audio_plugin_client</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1477,9 +1470,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting\module_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting\module_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting</Filter>
|
<Filter>JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting\module_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting\module_win32.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting\module_win32.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting</Filter>
|
<Filter>JUCE Modules\juce_audio_processors\format_types\VST3_SDK\public.sdk\source\vst\hosting</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1525,9 +1515,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\juce_ARAHosting.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\juce_ARAHosting.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_processors\format_types</Filter>
|
<Filter>JUCE Modules\juce_audio_processors\format_types</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_processors\format_types</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat_test.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat_test.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_processors\format_types</Filter>
|
<Filter>JUCE Modules\juce_audio_processors\format_types</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1648,9 +1635,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\juce_audio_processors.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\juce_audio_processors.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_processors</Filter>
|
<Filter>JUCE Modules\juce_audio_processors</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\juce_audio_processors.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_processors</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\juce_audio_processors_ara.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_processors\juce_audio_processors_ara.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_processors</Filter>
|
<Filter>JUCE Modules\juce_audio_processors</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1684,33 +1668,21 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\gui\juce_MPEKeyboardComponent.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\gui\juce_MPEKeyboardComponent.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\gui</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\gui</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDBurner_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDBurner_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDBurner_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDReader_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDReader_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDReader_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDReader_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_AudioCDReader_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\native\juce_BluetoothMidiDevicePairingDialogue_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
<Filter>JUCE Modules\juce_audio_utils\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1723,9 +1695,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\juce_audio_utils.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\juce_audio_utils.cpp">
|
||||||
<Filter>JUCE Modules\juce_audio_utils</Filter>
|
<Filter>JUCE Modules\juce_audio_utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_audio_utils\juce_audio_utils.mm">
|
|
||||||
<Filter>JUCE Modules\juce_audio_utils</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\containers\juce_AbstractFifo.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\containers\juce_AbstractFifo.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\containers</Filter>
|
<Filter>JUCE Modules\juce_core\containers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1864,9 +1833,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Files_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Files_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Files_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Files_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Files_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1888,42 +1854,27 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Network_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Network_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Network_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Network_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Network_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_ObjCHelpers_mac_test.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_PlatformTimer_generic.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_PlatformTimer_generic.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_PlatformTimer_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_PlatformTimer_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Process_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Registry_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Registry_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_RuntimePermissions_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_RuntimePermissions_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Strings_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_wasm.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_SystemStats_wasm.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1936,9 +1887,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Threads_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Threads_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Threads_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Threads_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\native\juce_Threads_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_core\native</Filter>
|
<Filter>JUCE Modules\juce_core\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2107,9 +2055,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\juce_core.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\juce_core.cpp">
|
||||||
<Filter>JUCE Modules\juce_core</Filter>
|
<Filter>JUCE Modules\juce_core</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\juce_core.mm">
|
|
||||||
<Filter>JUCE Modules\juce_core</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\juce_core_CompilationTime.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_core\juce_core_CompilationTime.cpp">
|
||||||
<Filter>JUCE Modules\juce_core</Filter>
|
<Filter>JUCE Modules\juce_core</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2143,9 +2088,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_data_structures\juce_data_structures.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_data_structures\juce_data_structures.cpp">
|
||||||
<Filter>JUCE Modules\juce_data_structures</Filter>
|
<Filter>JUCE Modules\juce_data_structures</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_data_structures\juce_data_structures.mm">
|
|
||||||
<Filter>JUCE Modules\juce_data_structures</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_dsp\containers\juce_AudioBlock_test.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_dsp\containers\juce_AudioBlock_test.cpp">
|
||||||
<Filter>JUCE Modules\juce_dsp\containers</Filter>
|
<Filter>JUCE Modules\juce_dsp\containers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2251,9 +2193,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_dsp\juce_dsp.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_dsp\juce_dsp.cpp">
|
||||||
<Filter>JUCE Modules\juce_dsp</Filter>
|
<Filter>JUCE Modules\juce_dsp</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_dsp\juce_dsp.mm">
|
|
||||||
<Filter>JUCE Modules\juce_dsp</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\broadcasters\juce_ActionBroadcaster.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\broadcasters\juce_ActionBroadcaster.cpp">
|
||||||
<Filter>JUCE Modules\juce_events\broadcasters</Filter>
|
<Filter>JUCE Modules\juce_events\broadcasters</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2293,12 +2232,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\messages\juce_MessageManager.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\messages\juce_MessageManager.cpp">
|
||||||
<Filter>JUCE Modules\juce_events\messages</Filter>
|
<Filter>JUCE Modules\juce_events\messages</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\native\juce_MessageManager_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_events\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\native\juce_MessageManager_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_events\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\native\juce_Messaging_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\native\juce_Messaging_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_events\native</Filter>
|
<Filter>JUCE Modules\juce_events\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2323,9 +2256,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\juce_events.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\juce_events.cpp">
|
||||||
<Filter>JUCE Modules\juce_events</Filter>
|
<Filter>JUCE Modules\juce_events</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_events\juce_events.mm">
|
|
||||||
<Filter>JUCE Modules\juce_events</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\colour\juce_Colour.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\colour\juce_Colour.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics\colour</Filter>
|
<Filter>JUCE Modules\juce_graphics\colour</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2848,9 +2778,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\images\juce_ImageFileFormat.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\images\juce_ImageFileFormat.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics\images</Filter>
|
<Filter>JUCE Modules\juce_graphics\images</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_CoreGraphicsContext_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_Direct2DGraphicsContext_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_Direct2DGraphicsContext_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2881,9 +2808,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_Fonts_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_Fonts_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_Fonts_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_GraphicsContext_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\native\juce_GraphicsContext_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
<Filter>JUCE Modules\juce_graphics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -2983,9 +2907,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\juce_graphics.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\juce_graphics.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics</Filter>
|
<Filter>JUCE Modules\juce_graphics</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\juce_graphics.mm">
|
|
||||||
<Filter>JUCE Modules\juce_graphics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\juce_graphics_Harfbuzz.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\juce_graphics_Harfbuzz.cpp">
|
||||||
<Filter>JUCE Modules\juce_graphics</Filter>
|
<Filter>JUCE Modules\juce_graphics</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3262,21 +3183,12 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_Accessibility_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_Accessibility_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_Accessibility_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_Accessibility_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_Accessibility_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_Accessibility_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_AccessibilityElement_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_AccessibilityElement_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_AccessibilitySharedCode_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_AccessibilityTextHelpers_test.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\accessibility\juce_AccessibilityTextHelpers_test.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3298,63 +3210,33 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_FileChooser_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_MainMenu_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_MouseCursor_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NativeMessageBox_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_NSViewComponentPeer_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_UIViewComponentPeer_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_VBlank_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_VBlank_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_Windowing_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3364,15 +3246,9 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\native\juce_WindowUtils_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
<Filter>JUCE Modules\juce_gui_basics\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3514,9 +3390,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\juce_gui_basics.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\juce_gui_basics.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_basics</Filter>
|
<Filter>JUCE Modules\juce_gui_basics</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\JUCE\modules\juce_gui_basics\juce_gui_basics.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_basics</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\code_editor\juce_CodeDocument.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\code_editor\juce_CodeDocument.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\code_editor</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\code_editor</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3577,15 +3450,9 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_AndroidViewComponent.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_AndroidViewComponent.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_AppleRemote_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_HWNDComponent_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_HWNDComponent_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_NSViewComponent_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_PushNotifications_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_PushNotifications_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3604,18 +3471,12 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_SystemTrayIcon_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_SystemTrayIcon_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_UIViewComponent_ios.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_android.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_android.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_linux.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_linux.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_mac.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_windows.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\native\juce_WebBrowserComponent_windows.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
<Filter>JUCE Modules\juce_gui_extra\native</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3625,9 +3486,6 @@
|
|||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\juce_gui_extra.cpp">
|
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\juce_gui_extra.cpp">
|
||||||
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\..\..\Downloads\juce-8.0.4-windows\JUCE\modules\juce_gui_extra\juce_gui_extra.mm">
|
|
||||||
<Filter>JUCE Modules\juce_gui_extra</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\JuceLibraryCode\BinaryData.cpp">
|
<ClCompile Include="..\..\JuceLibraryCode\BinaryData.cpp">
|
||||||
<Filter>JUCE Library Code</Filter>
|
<Filter>JUCE Library Code</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -3690,6 +3548,15 @@
|
|||||||
<ClInclude Include="..\..\Source\DemoUtilities.h">
|
<ClInclude Include="..\..\Source\DemoUtilities.h">
|
||||||
<Filter>Harmonizer\Assets</Filter>
|
<Filter>Harmonizer\Assets</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\Source\PluginEditor.h">
|
||||||
|
<Filter>Harmonizer\Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\Source\PluginProcessor.h">
|
||||||
|
<Filter>Harmonizer\Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\Source\CircularBuffer.h">
|
||||||
|
<Filter>Harmonizer\Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\Source\shifter_voice.h">
|
<ClInclude Include="..\..\Source\shifter_voice.h">
|
||||||
<Filter>Harmonizer\Source</Filter>
|
<Filter>Harmonizer\Source</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -7847,6 +7714,6 @@
|
|||||||
<None Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\unicode\sheenbidi\JUCE_CHANGES.txt">
|
<None Include="..\..\..\..\..\Downloads\JUCE\modules\juce_graphics\unicode\sheenbidi\JUCE_CHANGES.txt">
|
||||||
<Filter>JUCE Modules\juce_graphics\unicode\sheenbidi</Filter>
|
<Filter>JUCE Modules\juce_graphics\unicode\sheenbidi</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="packages.config"/>
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
714
Builds/VisualStudio2022/olddemo.h
Normal file
714
Builds/VisualStudio2022/olddemo.h
Normal file
@ -0,0 +1,714 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file is part of the JUCE framework examples.
|
||||||
|
Copyright (c) Raw Material Software Limited
|
||||||
|
|
||||||
|
The code included in this file is provided under the terms of the ISC license
|
||||||
|
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
|
||||||
|
to use, copy, modify, and/or distribute this software for any purpose with or
|
||||||
|
without fee is hereby granted provided that the above copyright notice and
|
||||||
|
this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
The block below describes the properties of this PIP. A PIP is a short snippet
|
||||||
|
of code that can be read by the Projucer and used to generate a JUCE project.
|
||||||
|
|
||||||
|
BEGIN_JUCE_PIP_METADATA
|
||||||
|
|
||||||
|
name: WebViewPluginDemo
|
||||||
|
version: 1.0.0
|
||||||
|
vendor: JUCE
|
||||||
|
website: http://juce.com
|
||||||
|
description: Filtering audio plugin using an HTML/JS user interface
|
||||||
|
|
||||||
|
dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats,
|
||||||
|
juce_audio_plugin_client, juce_audio_processors, juce_dsp,
|
||||||
|
juce_audio_utils, juce_core, juce_data_structures,
|
||||||
|
juce_events, juce_graphics, juce_gui_basics, juce_gui_extra
|
||||||
|
exporters: xcode_mac, vs2022, linux_make, androidstudio, xcode_iphone
|
||||||
|
|
||||||
|
moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1, JUCE_USE_WIN_WEBVIEW2_WITH_STATIC_LINKING=1
|
||||||
|
|
||||||
|
type: AudioProcessor
|
||||||
|
mainClass: WebViewPluginAudioProcessorWrapper
|
||||||
|
|
||||||
|
useLocalCopy: 1
|
||||||
|
|
||||||
|
END_JUCE_PIP_METADATA
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DemoUtilities.h"
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "Shifter.h"
|
||||||
|
|
||||||
|
//using namespace juce::dsp;
|
||||||
|
|
||||||
|
namespace ID
|
||||||
|
{
|
||||||
|
#define PARAMETER_ID(str) static const ParameterID str { #str, 1 };
|
||||||
|
|
||||||
|
PARAMETER_ID(formantPreserve)
|
||||||
|
PARAMETER_ID(autoTuneSpeed)
|
||||||
|
PARAMETER_ID(autoTuneDepth)
|
||||||
|
PARAMETER_ID(portTime)
|
||||||
|
PARAMETER_ID(mute)
|
||||||
|
PARAMETER_ID(filterType)
|
||||||
|
|
||||||
|
#undef PARAMETER_ID
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircularBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CircularBuffer(int numChannels, int numSamples)
|
||||||
|
: buffer(data, (size_t)numChannels, (size_t)numSamples)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void push(dsp::AudioBlock<T> b)
|
||||||
|
{
|
||||||
|
jassert(b.getNumChannels() == buffer.getNumChannels());
|
||||||
|
|
||||||
|
const auto trimmed = b.getSubBlock(b.getNumSamples()
|
||||||
|
- std::min(b.getNumSamples(), buffer.getNumSamples()));
|
||||||
|
|
||||||
|
const auto bufferLength = (int64)buffer.getNumSamples();
|
||||||
|
|
||||||
|
for (auto samplesRemaining = (int64)trimmed.getNumSamples(); samplesRemaining > 0;)
|
||||||
|
{
|
||||||
|
const auto writeOffset = writeIx % bufferLength;
|
||||||
|
const auto numSamplesToWrite = std::min(samplesRemaining, bufferLength - writeOffset);
|
||||||
|
|
||||||
|
auto destSubBlock = buffer.getSubBlock((size_t)writeOffset, (size_t)numSamplesToWrite);
|
||||||
|
const auto sourceSubBlock = trimmed.getSubBlock(trimmed.getNumSamples() - (size_t)samplesRemaining,
|
||||||
|
(size_t)numSamplesToWrite);
|
||||||
|
|
||||||
|
destSubBlock.copyFrom(sourceSubBlock);
|
||||||
|
|
||||||
|
samplesRemaining -= numSamplesToWrite;
|
||||||
|
writeIx += numSamplesToWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void push(Span<T> s)
|
||||||
|
{
|
||||||
|
auto* ptr = s.begin();
|
||||||
|
dsp::AudioBlock<T> b(&ptr, 1, s.size());
|
||||||
|
push(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(int64 readIx, dsp::AudioBlock<float> output) const
|
||||||
|
{
|
||||||
|
const auto numChannelsToUse = std::min(buffer.getNumChannels(), output.getNumChannels());
|
||||||
|
|
||||||
|
jassert(output.getNumChannels() == buffer.getNumChannels());
|
||||||
|
|
||||||
|
const auto bufferLength = (int64)buffer.getNumSamples();
|
||||||
|
|
||||||
|
for (auto outputOffset = (size_t)0; outputOffset < output.getNumSamples();)
|
||||||
|
{
|
||||||
|
const auto inputOffset = (size_t)((readIx + (int64)outputOffset) % bufferLength);
|
||||||
|
const auto numSamplesToRead = std::min(output.getNumSamples() - outputOffset,
|
||||||
|
(size_t)bufferLength - inputOffset);
|
||||||
|
|
||||||
|
auto destSubBlock = output.getSubBlock(outputOffset, numSamplesToRead)
|
||||||
|
.getSubsetChannelBlock(0, numChannelsToUse);
|
||||||
|
|
||||||
|
destSubBlock.copyFrom(buffer.getSubBlock(inputOffset, numSamplesToRead)
|
||||||
|
.getSubsetChannelBlock(0, numChannelsToUse));
|
||||||
|
|
||||||
|
outputOffset += numSamplesToRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 getWriteIndex() const noexcept { return writeIx; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
HeapBlock<char> data;
|
||||||
|
dsp::AudioBlock<float> buffer;
|
||||||
|
int64 writeIx = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//class SpectralBars
|
||||||
|
//{
|
||||||
|
//public:
|
||||||
|
// //template <typename T>
|
||||||
|
// void push(int data)
|
||||||
|
// {
|
||||||
|
// testQueue.push(data);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void compute(Span<int> output) {
|
||||||
|
// int index = 0;
|
||||||
|
// for (auto it = output.begin(); it != output.end(); ++it) {
|
||||||
|
// *it = testQueue.get(index++);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//private:
|
||||||
|
// circ_queue<int, 256> testQueue;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
class WebViewPluginAudioProcessor : public AudioProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
|
||||||
|
void releaseResources() override {}
|
||||||
|
|
||||||
|
bool isBusesLayoutSupported(const BusesLayout& layouts) const override;
|
||||||
|
|
||||||
|
void processBlock(AudioBuffer<float>&, MidiBuffer&) override;
|
||||||
|
using AudioProcessor::processBlock;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
const String getName() const override { return JucePlugin_Name; }
|
||||||
|
|
||||||
|
bool acceptsMidi() const override { return false; }
|
||||||
|
bool producesMidi() const override { return false; }
|
||||||
|
bool isMidiEffect() const override { return false; }
|
||||||
|
double getTailLengthSeconds() const override { return 0.0; }
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
int getNumPrograms() override { return 1; }
|
||||||
|
int getCurrentProgram() override { return 0; }
|
||||||
|
void setCurrentProgram(int) override {}
|
||||||
|
const String getProgramName(int) override { return {}; }
|
||||||
|
void changeProgramName(int, const String&) override {}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void getStateInformation(MemoryBlock& destData) override;
|
||||||
|
void setStateInformation(const void* data, int sizeInBytes) override;
|
||||||
|
bool new_midi = false;
|
||||||
|
|
||||||
|
struct Parameters
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Parameters(AudioProcessorValueTreeState::ParameterLayout& layout)
|
||||||
|
: formantPreserve(addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ID::formantPreserve,
|
||||||
|
"Formant Preserve",
|
||||||
|
NormalisableRange<float> {0.0f, 1.0f, .01f},
|
||||||
|
.5f)),
|
||||||
|
|
||||||
|
autoTuneSpeed(addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ID::autoTuneSpeed,
|
||||||
|
"AutoTune Speed",
|
||||||
|
NormalisableRange<float> {0.001f, 0.1f, .001f},
|
||||||
|
.5f)),
|
||||||
|
autoTuneDepth(addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ID::autoTuneDepth,
|
||||||
|
"AutoTune Depth",
|
||||||
|
NormalisableRange<float> {0.0f, 1.1f, .01f},
|
||||||
|
.5f)),
|
||||||
|
portTime(addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ID::portTime,
|
||||||
|
"Portamento Speed",
|
||||||
|
NormalisableRange<float> {0.001f, 0.2f, .001f},
|
||||||
|
.01f)),
|
||||||
|
mute(addToLayout<AudioParameterBool>(layout, ID::mute, "Mute", false)),
|
||||||
|
filterType(addToLayout<AudioParameterChoice>(layout,
|
||||||
|
ID::filterType,
|
||||||
|
"Filter type",
|
||||||
|
StringArray{ "Low-pass", "High-pass", "Band-pass" },
|
||||||
|
0))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioParameterFloat& formantPreserve;
|
||||||
|
AudioParameterFloat& autoTuneSpeed;
|
||||||
|
AudioParameterFloat& autoTuneDepth;
|
||||||
|
AudioParameterFloat& portTime;
|
||||||
|
AudioParameterBool& mute;
|
||||||
|
AudioParameterChoice& filterType;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Param>
|
||||||
|
static void add(AudioProcessorParameterGroup& group, std::unique_ptr<Param> param)
|
||||||
|
{
|
||||||
|
group.addChild(std::move(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Param>
|
||||||
|
static void add(AudioProcessorValueTreeState::ParameterLayout& group, std::unique_ptr<Param> param)
|
||||||
|
{
|
||||||
|
group.add(std::move(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Param, typename Group, typename... Ts>
|
||||||
|
static Param& addToLayout(Group& layout, Ts&&... ts)
|
||||||
|
{
|
||||||
|
auto param = std::make_unique<Param>(std::forward<Ts>(ts)...);
|
||||||
|
auto& ref = *param;
|
||||||
|
add(layout, std::move(param));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parameters parameters;
|
||||||
|
AudioProcessorValueTreeState state;
|
||||||
|
SpinLock midiLock;
|
||||||
|
|
||||||
|
/*std::vector<int> spectrumData = [] { return std::vector<int>(256, 0.0f); }();
|
||||||
|
SpinLock spectrumDataLock;
|
||||||
|
|
||||||
|
SpectralBars spectralBars;*/
|
||||||
|
|
||||||
|
dsp::LadderFilter<float> filter;
|
||||||
|
Shifter shifter;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessor)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
WebViewPluginAudioProcessor::WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout)
|
||||||
|
: AudioProcessor(BusesProperties()
|
||||||
|
#if ! JucePlugin_IsMidiEffect
|
||||||
|
#if ! JucePlugin_IsSynth
|
||||||
|
.withInput("Input", juce::AudioChannelSet::stereo(), true)
|
||||||
|
#endif
|
||||||
|
.withOutput("Output", juce::AudioChannelSet::stereo(), true)
|
||||||
|
#endif
|
||||||
|
),
|
||||||
|
parameters(layout),
|
||||||
|
state(*this, nullptr, "STATE", std::move(layout))
|
||||||
|
{
|
||||||
|
shifter.Init(48000.0f, 48);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void WebViewPluginAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
|
||||||
|
{
|
||||||
|
const auto channels = std::max(getTotalNumInputChannels(), getTotalNumOutputChannels());
|
||||||
|
shifter.Init((float)sampleRate, samplesPerBlock);
|
||||||
|
if (channels == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
filter.prepare({ sampleRate, (uint32_t)samplesPerBlock, (uint32_t)channels });
|
||||||
|
filter.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebViewPluginAudioProcessor::isBusesLayoutSupported(const BusesLayout& layouts) const
|
||||||
|
{
|
||||||
|
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
|
||||||
|
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer,
|
||||||
|
juce::MidiBuffer& midi)
|
||||||
|
{
|
||||||
|
juce::ScopedNoDenormals noDenormals;
|
||||||
|
|
||||||
|
const auto totalNumInputChannels = getTotalNumInputChannels();
|
||||||
|
const auto totalNumOutputChannels = getTotalNumOutputChannels();
|
||||||
|
|
||||||
|
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
|
||||||
|
buffer.clear(i, 0, buffer.getNumSamples());
|
||||||
|
shifter.SetFormantPreserve(parameters.formantPreserve.get());
|
||||||
|
shifter.SetAutoTuneSpeed(parameters.autoTuneSpeed.get());
|
||||||
|
shifter.SetAutoTuneDepth(parameters.autoTuneDepth.get());
|
||||||
|
shifter.SetPortamentoTime(parameters.portTime.get());
|
||||||
|
juce::AudioBuffer<float> const_buff;
|
||||||
|
const_buff.makeCopyOf(buffer);
|
||||||
|
shifter.Process(const_buff.getArrayOfReadPointers(), (float**)buffer.getArrayOfWritePointers(), buffer.getNumSamples());
|
||||||
|
|
||||||
|
for (const auto metadata : midi)
|
||||||
|
{
|
||||||
|
const auto msg = metadata.getMessage();
|
||||||
|
if (msg.isNoteOn()) {
|
||||||
|
shifter.AddMidiNote(msg.getNoteNumber());
|
||||||
|
new_midi = true;
|
||||||
|
//editor.webComponent.emitEventIfBrowserIsVisible("midNoteData", var{});
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (msg.isNoteOff()) {
|
||||||
|
shifter.RemoveMidiNote(msg.getNoteNumber());
|
||||||
|
new_midi = true;
|
||||||
|
//editor.webComponent.emitEventIfBrowserIsVisible("midNoteData", var{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
//DBG(shifter.out_midi[MAX_VOICES]);
|
||||||
|
//push midi note
|
||||||
|
//spectralBars.push(shifter.out_midi[MAX_VOICES]);
|
||||||
|
const SpinLock::ScopedTryLockType lock(midiLock);
|
||||||
|
|
||||||
|
if (!lock.isLocked())
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*for(auto i = 0; i < buffer.getNumSamples(); ++i)
|
||||||
|
{
|
||||||
|
bool process = (i % 256) == 0 && i != 0;
|
||||||
|
|
||||||
|
for(auto j = 0; j < totalNumInputChannels; ++j)
|
||||||
|
{
|
||||||
|
input[j][i] = buffer.getReadPointer(j)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.setCutoffFrequencyHz (parameters.cutoffFreqHz.get());
|
||||||
|
|
||||||
|
const auto filterMode = [this]
|
||||||
|
{
|
||||||
|
switch (parameters.filterType.getIndex())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return dsp::LadderFilter<float>::Mode::LPF12;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return dsp::LadderFilter<float>::Mode::HPF12;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return dsp::LadderFilter<float>::Mode::BPF12;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
filter.setMode (filterMode);
|
||||||
|
|
||||||
|
auto outBlock = dsp::AudioBlock<float> { buffer }.getSubsetChannelBlock (0, (size_t) getTotalNumOutputChannels());
|
||||||
|
|
||||||
|
if (parameters.mute.get())
|
||||||
|
outBlock.clear();
|
||||||
|
|
||||||
|
filter.process (dsp::ProcessContextReplacing<float> (outBlock));
|
||||||
|
|
||||||
|
spectralBars.push (Span { buffer.getReadPointer (0), (size_t) buffer.getNumSamples() });
|
||||||
|
|
||||||
|
{
|
||||||
|
const SpinLock::ScopedTryLockType lock (spectrumDataLock);
|
||||||
|
|
||||||
|
if (! lock.isLocked())
|
||||||
|
return;
|
||||||
|
|
||||||
|
spectralBars.compute ({ spectrumData.data(), spectrumData.size() });
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void WebViewPluginAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
||||||
|
{
|
||||||
|
juce::ignoreUnused(destData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
||||||
|
{
|
||||||
|
juce::ignoreUnused(data, sizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const String localDevServerAddress;
|
||||||
|
|
||||||
|
std::optional<WebBrowserComponent::Resource> getResource(const String& url);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
struct SinglePageBrowser : WebBrowserComponent
|
||||||
|
{
|
||||||
|
using WebBrowserComponent::WebBrowserComponent;
|
||||||
|
|
||||||
|
// Prevent page loads from navigating away from our single page web app
|
||||||
|
bool pageAboutToLoad(const String& newURL) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
class WebViewPluginAudioProcessorEditor : public AudioProcessorEditor, private Timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit WebViewPluginAudioProcessorEditor(WebViewPluginAudioProcessor&);
|
||||||
|
|
||||||
|
std::optional<WebBrowserComponent::Resource> getResource(const String& url);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void paint(Graphics&) override;
|
||||||
|
void resized() override;
|
||||||
|
|
||||||
|
int getControlParameterIndex(Component&) override
|
||||||
|
{
|
||||||
|
return controlParameterIndexReceiver.getControlParameterIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerCallback() override
|
||||||
|
{
|
||||||
|
static constexpr size_t numFramesBuffered = 5;
|
||||||
|
|
||||||
|
SpinLock::ScopedLockType lock{ processorRef.midiLock };
|
||||||
|
|
||||||
|
static int64 callbackCounter = 0;
|
||||||
|
processorRef.new_midi = false;
|
||||||
|
juce::Array<var> notes;
|
||||||
|
int voice_num = 0;
|
||||||
|
for (auto& voice : processorRef.shifter.voices) {
|
||||||
|
if (voice.onoff_) {
|
||||||
|
auto obj = new DynamicObject();
|
||||||
|
obj->setProperty("voice", voice_num);
|
||||||
|
obj->setProperty("midi", voice.GetMidiNote());
|
||||||
|
notes.add(var(obj));
|
||||||
|
}
|
||||||
|
voice_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicObject::Ptr d(new DynamicObject());
|
||||||
|
d->setProperty("notes", notes);
|
||||||
|
d->setProperty("input_pitch", processorRef.shifter.getInputPitch());
|
||||||
|
d->setProperty("output_pitch", processorRef.shifter.getOutputPitch());
|
||||||
|
webComponent.emitEventIfBrowserIsVisible("midNoteData", d.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebViewPluginAudioProcessor& processorRef;
|
||||||
|
|
||||||
|
WebSliderRelay formantSliderRelay{ "formantSlider" };
|
||||||
|
WebSliderRelay autoTuneSpeedSliderRelay{ "autoTuneSpeedSlider" };
|
||||||
|
WebSliderRelay autoTuneDepthSliderRelay{ "autoTuneDepthSlider" };
|
||||||
|
WebSliderRelay portTimeSliderRelay{ "portTimeSlider" };
|
||||||
|
WebToggleButtonRelay muteToggleRelay{ "muteToggle" };
|
||||||
|
WebComboBoxRelay filterTypeComboRelay{ "filterTypeCombo" };
|
||||||
|
|
||||||
|
WebControlParameterIndexReceiver controlParameterIndexReceiver;
|
||||||
|
|
||||||
|
SinglePageBrowser webComponent{ WebBrowserComponent::Options{}
|
||||||
|
.withBackend(WebBrowserComponent::Options::Backend::webview2)
|
||||||
|
.withWinWebView2Options(WebBrowserComponent::Options::WinWebView2{}
|
||||||
|
.withUserDataFolder(File::getSpecialLocation(File::SpecialLocationType::tempDirectory)))
|
||||||
|
.withNativeIntegrationEnabled()
|
||||||
|
.withOptionsFrom(formantSliderRelay)
|
||||||
|
.withOptionsFrom(autoTuneSpeedSliderRelay)
|
||||||
|
.withOptionsFrom(autoTuneDepthSliderRelay)
|
||||||
|
.withOptionsFrom(portTimeSliderRelay)
|
||||||
|
.withOptionsFrom(muteToggleRelay)
|
||||||
|
.withOptionsFrom(filterTypeComboRelay)
|
||||||
|
.withOptionsFrom(controlParameterIndexReceiver)
|
||||||
|
.withNativeFunction("sayHello", [](auto& var, auto complete)
|
||||||
|
{
|
||||||
|
complete("Hello " + var[0].toString());
|
||||||
|
})
|
||||||
|
.withResourceProvider([this](const auto& url)
|
||||||
|
{
|
||||||
|
return getResource(url);
|
||||||
|
},
|
||||||
|
URL { localDevServerAddress }.getOrigin()) };
|
||||||
|
|
||||||
|
WebSliderParameterAttachment formantAttachment;
|
||||||
|
WebSliderParameterAttachment autoTuneSpeedAttachment;
|
||||||
|
WebSliderParameterAttachment autoTuneDepthAttachment;
|
||||||
|
WebSliderParameterAttachment portTimeAttachment;
|
||||||
|
WebToggleButtonParameterAttachment muteAttachment;
|
||||||
|
WebComboBoxParameterAttachment filterTypeAttachment;
|
||||||
|
|
||||||
|
std::deque<Array<var>> spectrumDataFrames;
|
||||||
|
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessorEditor)
|
||||||
|
};
|
||||||
|
|
||||||
|
static ZipFile* getZipFile()
|
||||||
|
{
|
||||||
|
static auto stream = createAssetInputStream("webviewplugin-gui_1.0.0.zip", AssertAssetExists::no);
|
||||||
|
|
||||||
|
if (stream == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
static ZipFile f{ stream.get(), false };
|
||||||
|
return &f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* getMimeForExtension(const String& extension)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<String, const char*> mimeMap =
|
||||||
|
{
|
||||||
|
{ { "htm" }, "text/html" },
|
||||||
|
{ { "html" }, "text/html" },
|
||||||
|
{ { "txt" }, "text/plain" },
|
||||||
|
{ { "jpg" }, "image/jpeg" },
|
||||||
|
{ { "jpeg" }, "image/jpeg" },
|
||||||
|
{ { "svg" }, "image/svg+xml" },
|
||||||
|
{ { "ico" }, "image/vnd.microsoft.icon" },
|
||||||
|
{ { "json" }, "application/json" },
|
||||||
|
{ { "png" }, "image/png" },
|
||||||
|
{ { "css" }, "text/css" },
|
||||||
|
{ { "map" }, "application/json" },
|
||||||
|
{ { "js" }, "text/javascript" },
|
||||||
|
{ { "woff2" }, "font/woff2" }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (const auto it = mimeMap.find(extension.toLowerCase()); it != mimeMap.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
jassertfalse;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getExtension(String filename)
|
||||||
|
{
|
||||||
|
return filename.fromLastOccurrenceOf(".", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto streamToVector(InputStream& stream)
|
||||||
|
{
|
||||||
|
std::vector<std::byte> result((size_t)stream.getTotalLength());
|
||||||
|
stream.setPosition(0);
|
||||||
|
[[maybe_unused]] const auto bytesRead = stream.read(result.data(), result.size());
|
||||||
|
jassert(bytesRead == (ssize_t)result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<WebBrowserComponent::Resource> WebViewPluginAudioProcessorEditor::getResource(const String& url)
|
||||||
|
{
|
||||||
|
const auto urlToRetrive = url == "/" ? String{ "index.html" }
|
||||||
|
: url.fromFirstOccurrenceOf("/", false, false);
|
||||||
|
|
||||||
|
if (auto* archive = getZipFile())
|
||||||
|
{
|
||||||
|
if (auto* entry = archive->getEntry(urlToRetrive))
|
||||||
|
{
|
||||||
|
auto stream = rawToUniquePtr(archive->createStreamForEntry(*entry));
|
||||||
|
auto v = streamToVector(*stream);
|
||||||
|
auto mime = getMimeForExtension(getExtension(entry->filename).toLowerCase());
|
||||||
|
return WebBrowserComponent::Resource{ std::move(v),
|
||||||
|
std::move(mime) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlToRetrive == "index.html")
|
||||||
|
{
|
||||||
|
auto fallbackIndexHtml = createAssetInputStream("webviewplugin-gui-fallback.html");
|
||||||
|
return WebBrowserComponent::Resource{ streamToVector(*fallbackIndexHtml),
|
||||||
|
String { "text/html" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlToRetrive == "data.txt")
|
||||||
|
{
|
||||||
|
WebBrowserComponent::Resource resource;
|
||||||
|
static constexpr char testData[] = "testdata";
|
||||||
|
MemoryInputStream stream{ testData, numElementsInArray(testData) - 1, false };
|
||||||
|
return WebBrowserComponent::Resource{ streamToVector(stream), String { "text/html" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlToRetrive == "midNoteData.json")
|
||||||
|
{
|
||||||
|
|
||||||
|
juce::Array<var> notes;
|
||||||
|
int voice_num = 0;
|
||||||
|
for (auto& voice : processorRef.shifter.voices) {
|
||||||
|
if (voice.onoff_) {
|
||||||
|
auto obj = new DynamicObject();
|
||||||
|
obj->setProperty("voice", voice_num);
|
||||||
|
obj->setProperty("midi", voice.GetMidiNote());
|
||||||
|
notes.add(var(obj));
|
||||||
|
}
|
||||||
|
voice_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicObject::Ptr d(new DynamicObject());
|
||||||
|
d->setProperty("notes", notes);
|
||||||
|
|
||||||
|
const auto s = JSON::toString(d.get());
|
||||||
|
MemoryInputStream stream{ s.getCharPointer(), s.getNumBytesAsUTF8(), false };
|
||||||
|
return WebBrowserComponent::Resource{ streamToVector(stream), String { "application/json" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if JUCE_ANDROID
|
||||||
|
// The localhost is available on this address to the emulator
|
||||||
|
const String localDevServerAddress = "http://10.0.2.2:3000/";
|
||||||
|
#else
|
||||||
|
const String localDevServerAddress = "http://localhost:3000/";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool SinglePageBrowser::pageAboutToLoad(const String& newURL)
|
||||||
|
{
|
||||||
|
return newURL == localDevServerAddress || newURL == getResourceProviderRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
WebViewPluginAudioProcessorEditor::WebViewPluginAudioProcessorEditor(WebViewPluginAudioProcessor& p)
|
||||||
|
: AudioProcessorEditor(&p), processorRef(p),
|
||||||
|
formantAttachment(*processorRef.state.getParameter(ID::formantPreserve.getParamID()),
|
||||||
|
formantSliderRelay,
|
||||||
|
processorRef.state.undoManager),
|
||||||
|
autoTuneSpeedAttachment(*processorRef.state.getParameter(ID::autoTuneSpeed.getParamID()),
|
||||||
|
autoTuneSpeedSliderRelay,
|
||||||
|
processorRef.state.undoManager),
|
||||||
|
autoTuneDepthAttachment(*processorRef.state.getParameter(ID::autoTuneDepth.getParamID()),
|
||||||
|
autoTuneDepthSliderRelay,
|
||||||
|
processorRef.state.undoManager),
|
||||||
|
portTimeAttachment(*processorRef.state.getParameter(ID::portTime.getParamID()),
|
||||||
|
portTimeSliderRelay,
|
||||||
|
processorRef.state.undoManager),
|
||||||
|
muteAttachment(*processorRef.state.getParameter(ID::mute.getParamID()),
|
||||||
|
muteToggleRelay,
|
||||||
|
processorRef.state.undoManager),
|
||||||
|
filterTypeAttachment(*processorRef.state.getParameter(ID::filterType.getParamID()),
|
||||||
|
filterTypeComboRelay,
|
||||||
|
processorRef.state.undoManager)
|
||||||
|
{
|
||||||
|
addAndMakeVisible(webComponent);
|
||||||
|
|
||||||
|
webComponent.goToURL(localDevServerAddress);
|
||||||
|
//webComponent.goToURL (WebBrowserComponent::getResourceProviderRoot());
|
||||||
|
|
||||||
|
setSize(500, 500);
|
||||||
|
|
||||||
|
startTimerHz(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void WebViewPluginAudioProcessorEditor::paint(Graphics& g)
|
||||||
|
{
|
||||||
|
// (Our component is opaque, so we must completely fill the background with a solid colour)
|
||||||
|
g.fillAll(getLookAndFeel().findColour(ResizableWindow::backgroundColourId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessorEditor::resized()
|
||||||
|
{
|
||||||
|
webComponent.setBounds(getLocalBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebViewPluginAudioProcessorWrapper : public WebViewPluginAudioProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebViewPluginAudioProcessorWrapper() : WebViewPluginAudioProcessor({})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasEditor() const override { return true; }
|
||||||
|
AudioProcessorEditor* createEditor() override {
|
||||||
|
return new WebViewPluginAudioProcessorEditor(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -10,6 +10,15 @@
|
|||||||
resource="1" file="Assets/webviewplugin-gui-fallback.html"/>
|
resource="1" file="Assets/webviewplugin-gui-fallback.html"/>
|
||||||
</GROUP>
|
</GROUP>
|
||||||
<GROUP id="{BA45FF6A-23B2-0FFB-BB29-84A581170899}" name="Source">
|
<GROUP id="{BA45FF6A-23B2-0FFB-BB29-84A581170899}" name="Source">
|
||||||
|
<FILE id="eO13ze" name="PluginEditor.cpp" compile="1" resource="0"
|
||||||
|
file="Source/PluginEditor.cpp"/>
|
||||||
|
<FILE id="izJGih" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
|
||||||
|
<FILE id="m8Uj9j" name="PluginProcessor.cpp" compile="1" resource="0"
|
||||||
|
file="Source/PluginProcessor.cpp"/>
|
||||||
|
<FILE id="UtuXpw" name="PluginProcessor.h" compile="0" resource="0"
|
||||||
|
file="Source/PluginProcessor.h"/>
|
||||||
|
<FILE id="N1TngJ" name="CircularBuffer.h" compile="0" resource="0"
|
||||||
|
file="Source/CircularBuffer.h"/>
|
||||||
<FILE id="dgTaja" name="shifter_voice.cpp" compile="1" resource="0"
|
<FILE id="dgTaja" name="shifter_voice.cpp" compile="1" resource="0"
|
||||||
file="Source/shifter_voice.cpp"/>
|
file="Source/shifter_voice.cpp"/>
|
||||||
<FILE id="clLeAX" name="shifter_voice.h" compile="0" resource="0" file="Source/shifter_voice.h"/>
|
<FILE id="clLeAX" name="shifter_voice.h" compile="0" resource="0" file="Source/shifter_voice.h"/>
|
||||||
|
|||||||
86
Source/CircularBuffer.h
Normal file
86
Source/CircularBuffer.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
CircularBuffer.h
|
||||||
|
Created: 4 Nov 2025 6:20:15pm
|
||||||
|
Author: mickl
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
|
||||||
|
class CircularBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CircularBuffer(int numChannels, int numSamples)
|
||||||
|
: buffer(data, (size_t)numChannels, (size_t)numSamples)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void push(dsp::AudioBlock<T> b)
|
||||||
|
{
|
||||||
|
jassert(b.getNumChannels() == buffer.getNumChannels());
|
||||||
|
|
||||||
|
const auto trimmed = b.getSubBlock(b.getNumSamples()
|
||||||
|
- std::min(b.getNumSamples(), buffer.getNumSamples()));
|
||||||
|
|
||||||
|
const auto bufferLength = (int64)buffer.getNumSamples();
|
||||||
|
|
||||||
|
for (auto samplesRemaining = (int64)trimmed.getNumSamples(); samplesRemaining > 0;)
|
||||||
|
{
|
||||||
|
const auto writeOffset = writeIx % bufferLength;
|
||||||
|
const auto numSamplesToWrite = std::min(samplesRemaining, bufferLength - writeOffset);
|
||||||
|
|
||||||
|
auto destSubBlock = buffer.getSubBlock((size_t)writeOffset, (size_t)numSamplesToWrite);
|
||||||
|
const auto sourceSubBlock = trimmed.getSubBlock(trimmed.getNumSamples() - (size_t)samplesRemaining,
|
||||||
|
(size_t)numSamplesToWrite);
|
||||||
|
|
||||||
|
destSubBlock.copyFrom(sourceSubBlock);
|
||||||
|
|
||||||
|
samplesRemaining -= numSamplesToWrite;
|
||||||
|
writeIx += numSamplesToWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void push(Span<T> s)
|
||||||
|
{
|
||||||
|
auto* ptr = s.begin();
|
||||||
|
dsp::AudioBlock<T> b(&ptr, 1, s.size());
|
||||||
|
push(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(int64 readIx, dsp::AudioBlock<float> output) const
|
||||||
|
{
|
||||||
|
const auto numChannelsToUse = std::min(buffer.getNumChannels(), output.getNumChannels());
|
||||||
|
|
||||||
|
jassert(output.getNumChannels() == buffer.getNumChannels());
|
||||||
|
|
||||||
|
const auto bufferLength = (int64)buffer.getNumSamples();
|
||||||
|
|
||||||
|
for (auto outputOffset = (size_t)0; outputOffset < output.getNumSamples();)
|
||||||
|
{
|
||||||
|
const auto inputOffset = (size_t)((readIx + (int64)outputOffset) % bufferLength);
|
||||||
|
const auto numSamplesToRead = std::min(output.getNumSamples() - outputOffset,
|
||||||
|
(size_t)bufferLength - inputOffset);
|
||||||
|
|
||||||
|
auto destSubBlock = output.getSubBlock(outputOffset, numSamplesToRead)
|
||||||
|
.getSubsetChannelBlock(0, numChannelsToUse);
|
||||||
|
|
||||||
|
destSubBlock.copyFrom(buffer.getSubBlock(inputOffset, numSamplesToRead)
|
||||||
|
.getSubsetChannelBlock(0, numChannelsToUse));
|
||||||
|
|
||||||
|
outputOffset += numSamplesToRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 getWriteIndex() const noexcept { return writeIx; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
HeapBlock<char> data;
|
||||||
|
dsp::AudioBlock<float> buffer;
|
||||||
|
int64 writeIx = 0;
|
||||||
|
};
|
||||||
185
Source/PluginEditor.cpp
Normal file
185
Source/PluginEditor.cpp
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
PluginEditor.cpp
|
||||||
|
Created: 4 Nov 2025 6:20:46pm
|
||||||
|
Author: mickl
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PluginEditor.h"
|
||||||
|
#include "DemoUtilities.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static ZipFile* getZipFile()
|
||||||
|
{
|
||||||
|
static auto stream = createAssetInputStream("webviewplugin-gui_1.0.0.zip", AssertAssetExists::no);
|
||||||
|
|
||||||
|
if (stream == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
static ZipFile f{ stream.get(), false };
|
||||||
|
return &f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* getMimeForExtension(const String& extension)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<String, const char*> mimeMap =
|
||||||
|
{
|
||||||
|
{ { "htm" }, "text/html" },
|
||||||
|
{ { "html" }, "text/html" },
|
||||||
|
{ { "txt" }, "text/plain" },
|
||||||
|
{ { "jpg" }, "image/jpeg" },
|
||||||
|
{ { "jpeg" }, "image/jpeg" },
|
||||||
|
{ { "svg" }, "image/svg+xml" },
|
||||||
|
{ { "ico" }, "image/vnd.microsoft.icon" },
|
||||||
|
{ { "json" }, "application/json" },
|
||||||
|
{ { "png" }, "image/png" },
|
||||||
|
{ { "css" }, "text/css" },
|
||||||
|
{ { "map" }, "application/json" },
|
||||||
|
{ { "js" }, "text/javascript" },
|
||||||
|
{ { "woff2" }, "font/woff2" }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (const auto it = mimeMap.find(extension.toLowerCase()); it != mimeMap.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
jassertfalse;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getExtension(String filename)
|
||||||
|
{
|
||||||
|
return filename.fromLastOccurrenceOf(".", false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto streamToVector(InputStream& stream)
|
||||||
|
{
|
||||||
|
std::vector<std::byte> result((size_t)stream.getTotalLength());
|
||||||
|
stream.setPosition(0);
|
||||||
|
[[maybe_unused]] const auto bytesRead = stream.read(result.data(), result.size());
|
||||||
|
jassert(bytesRead == (ssize_t)result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<WebBrowserComponent::Resource> WebViewPluginAudioProcessorEditor::getResource(const String& url)
|
||||||
|
{
|
||||||
|
const auto urlToRetrive = url == "/" ? String{ "index.html" }
|
||||||
|
: url.fromFirstOccurrenceOf("/", false, false);
|
||||||
|
|
||||||
|
if (auto* archive = getZipFile())
|
||||||
|
{
|
||||||
|
if (auto* entry = archive->getEntry(urlToRetrive))
|
||||||
|
{
|
||||||
|
auto stream = rawToUniquePtr(archive->createStreamForEntry(*entry));
|
||||||
|
auto v = streamToVector(*stream);
|
||||||
|
auto mime = getMimeForExtension(getExtension(entry->filename).toLowerCase());
|
||||||
|
return WebBrowserComponent::Resource{ std::move(v),
|
||||||
|
std::move(mime) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlToRetrive == "index.html")
|
||||||
|
{
|
||||||
|
auto fallbackIndexHtml = createAssetInputStream("webviewplugin-gui-fallback.html");
|
||||||
|
return WebBrowserComponent::Resource{ streamToVector(*fallbackIndexHtml),
|
||||||
|
String { "text/html" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlToRetrive == "data.txt")
|
||||||
|
{
|
||||||
|
WebBrowserComponent::Resource resource;
|
||||||
|
static constexpr char testData[] = "testdata";
|
||||||
|
MemoryInputStream stream{ testData, numElementsInArray(testData) - 1, false };
|
||||||
|
return WebBrowserComponent::Resource{ streamToVector(stream), String { "text/html" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlToRetrive == "midNoteData.json")
|
||||||
|
{
|
||||||
|
|
||||||
|
juce::Array<var> notes;
|
||||||
|
int voice_num = 0;
|
||||||
|
for (auto& voice : processorRef.shifter.voices) {
|
||||||
|
if (voice.onoff_) {
|
||||||
|
auto obj = new DynamicObject();
|
||||||
|
obj->setProperty("voice", voice_num);
|
||||||
|
obj->setProperty("midi", voice.GetMidiNote());
|
||||||
|
notes.add(var(obj));
|
||||||
|
}
|
||||||
|
voice_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicObject::Ptr d(new DynamicObject());
|
||||||
|
d->setProperty("notes", notes);
|
||||||
|
|
||||||
|
const auto s = JSON::toString(d.get());
|
||||||
|
MemoryInputStream stream{ s.getCharPointer(), s.getNumBytesAsUTF8(), false };
|
||||||
|
return WebBrowserComponent::Resource{ streamToVector(stream), String { "application/json" } };
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if JUCE_ANDROID
|
||||||
|
// The localhost is available on this address to the emulator
|
||||||
|
const String localDevServerAddress = "http://10.0.2.2:3000/";
|
||||||
|
#else
|
||||||
|
const String localDevServerAddress = "http://localhost:3000/";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool SinglePageBrowser::pageAboutToLoad(const String& newURL)
|
||||||
|
{
|
||||||
|
return newURL == localDevServerAddress || newURL == getResourceProviderRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WebViewPluginAudioProcessorEditor::WebViewPluginAudioProcessorEditor(WebViewPluginAudioProcessor& p)
|
||||||
|
: AudioProcessorEditor(&p), processorRef(p)
|
||||||
|
{
|
||||||
|
auto options = WebBrowserComponent::Options{}
|
||||||
|
.withBackend(WebBrowserComponent::Options::Backend::webview2)
|
||||||
|
.withWinWebView2Options(WebBrowserComponent::Options::WinWebView2{}
|
||||||
|
.withUserDataFolder(File::getSpecialLocation(File::SpecialLocationType::tempDirectory)))
|
||||||
|
.withNativeIntegrationEnabled()
|
||||||
|
.withOptionsFrom(controlParameterIndexReceiver)
|
||||||
|
.withResourceProvider([this](const auto& url)
|
||||||
|
{
|
||||||
|
return getResource(url);
|
||||||
|
},
|
||||||
|
URL{ localDevServerAddress }.getOrigin());
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& sliderId : p.parameters.sliderIds) {
|
||||||
|
slider_relays.push_back(new WebSliderRelay{ sliderId });
|
||||||
|
slider_attatchments.push_back(new
|
||||||
|
WebSliderParameterAttachment(
|
||||||
|
*processorRef.state.getParameter(sliderId),
|
||||||
|
*slider_relays.back(),
|
||||||
|
processorRef.state.undoManager));
|
||||||
|
options = options.withOptionsFrom(*slider_relays.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
webComponent = new SinglePageBrowser(options);
|
||||||
|
addAndMakeVisible(*webComponent);
|
||||||
|
|
||||||
|
webComponent->goToURL(localDevServerAddress);
|
||||||
|
//webComponent.goToURL (WebBrowserComponent::getResourceProviderRoot());
|
||||||
|
|
||||||
|
setSize(500, 500);
|
||||||
|
|
||||||
|
startTimerHz(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessorEditor::paint(Graphics& g)
|
||||||
|
{
|
||||||
|
// (Our component is opaque, so we must completely fill the background with a solid colour)
|
||||||
|
g.fillAll(getLookAndFeel().findColour(ResizableWindow::backgroundColourId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessorEditor::resized()
|
||||||
|
{
|
||||||
|
if (webComponent == nullptr) return;
|
||||||
|
webComponent->setBounds(getLocalBounds());
|
||||||
|
}
|
||||||
93
Source/PluginEditor.h
Normal file
93
Source/PluginEditor.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
PluginEditor.h
|
||||||
|
Created: 4 Nov 2025 6:20:46pm
|
||||||
|
Author: mickl
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
extern const String localDevServerAddress;
|
||||||
|
|
||||||
|
std::optional<WebBrowserComponent::Resource> getResource(const String& url);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
class SinglePageBrowser : public WebBrowserComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using WebBrowserComponent::WebBrowserComponent;
|
||||||
|
|
||||||
|
// Prevent page loads from navigating away from our single page web app
|
||||||
|
bool pageAboutToLoad(const String& newURL) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
class WebViewPluginAudioProcessorEditor : public AudioProcessorEditor, private Timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit WebViewPluginAudioProcessorEditor(WebViewPluginAudioProcessor&);
|
||||||
|
~WebViewPluginAudioProcessorEditor() {
|
||||||
|
delete webComponent;
|
||||||
|
for (auto& attatchments : slider_attatchments) {
|
||||||
|
delete attatchments;
|
||||||
|
}
|
||||||
|
for (auto& relays : slider_relays) {
|
||||||
|
delete relays;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<WebBrowserComponent::Resource> getResource(const String& url);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void paint(Graphics&) override;
|
||||||
|
void resized() override;
|
||||||
|
|
||||||
|
int getControlParameterIndex(Component&) override
|
||||||
|
{
|
||||||
|
return controlParameterIndexReceiver.getControlParameterIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerCallback() override
|
||||||
|
{
|
||||||
|
static constexpr size_t numFramesBuffered = 5;
|
||||||
|
|
||||||
|
SpinLock::ScopedLockType lock{ processorRef.midiLock };
|
||||||
|
|
||||||
|
static int64 callbackCounter = 0;
|
||||||
|
processorRef.new_midi = false;
|
||||||
|
juce::Array<var> notes;
|
||||||
|
int voice_num = 0;
|
||||||
|
for (auto& voice : processorRef.shifter.voices) {
|
||||||
|
if (voice.onoff_) {
|
||||||
|
auto obj = new DynamicObject();
|
||||||
|
obj->setProperty("voice", voice_num);
|
||||||
|
obj->setProperty("midi", voice.GetMidiNote());
|
||||||
|
notes.add(var(obj));
|
||||||
|
}
|
||||||
|
voice_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicObject::Ptr d(new DynamicObject());
|
||||||
|
d->setProperty("notes", notes);
|
||||||
|
d->setProperty("input_pitch", processorRef.shifter.getInputPitch());
|
||||||
|
d->setProperty("output_pitch", processorRef.shifter.getOutputPitch());
|
||||||
|
webComponent->emitEventIfBrowserIsVisible("midNoteData", d.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebViewPluginAudioProcessor& processorRef;
|
||||||
|
std::vector<WebSliderRelay*> slider_relays;
|
||||||
|
std::vector< WebSliderParameterAttachment*> slider_attatchments;
|
||||||
|
|
||||||
|
WebControlParameterIndexReceiver controlParameterIndexReceiver;
|
||||||
|
|
||||||
|
SinglePageBrowser* webComponent = nullptr;
|
||||||
|
|
||||||
|
std::deque<Array<var>> spectrumDataFrames;
|
||||||
|
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessorEditor)
|
||||||
|
};
|
||||||
96
Source/PluginProcessor.cpp
Normal file
96
Source/PluginProcessor.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
PluginProcessor.cpp
|
||||||
|
Created: 4 Nov 2025 6:20:37pm
|
||||||
|
Author: mickl
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
WebViewPluginAudioProcessor::WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout)
|
||||||
|
: AudioProcessor(BusesProperties()
|
||||||
|
.withInput("Input", juce::AudioChannelSet::stereo(), true)
|
||||||
|
.withOutput("Output", juce::AudioChannelSet::stereo(), true)
|
||||||
|
),
|
||||||
|
parameters(layout),
|
||||||
|
state(*this, nullptr, "STATE", std::move(layout))
|
||||||
|
{
|
||||||
|
shifter.Init(48000.0f, 48);
|
||||||
|
shifter.SetFormantPreserve(state.getParameterAsValue("formantPreserve").getValue());
|
||||||
|
shifter.SetAutoTuneSpeed(state.getParameterAsValue("autoTuneSpeed").getValue());
|
||||||
|
shifter.SetAutoTuneDepth(state.getParameterAsValue("autoTuneDepth").getValue());
|
||||||
|
shifter.SetPortamentoTime(state.getParameterAsValue("portTime").getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void WebViewPluginAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
|
||||||
|
{
|
||||||
|
const auto channels = std::max(getTotalNumInputChannels(), getTotalNumOutputChannels());
|
||||||
|
shifter.Init((float)sampleRate, samplesPerBlock);
|
||||||
|
if (channels == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
filter.prepare({ sampleRate, (uint32_t)samplesPerBlock, (uint32_t)channels });
|
||||||
|
filter.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebViewPluginAudioProcessor::isBusesLayoutSupported(const BusesLayout& layouts) const
|
||||||
|
{
|
||||||
|
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
|
||||||
|
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer,
|
||||||
|
juce::MidiBuffer& midi)
|
||||||
|
{
|
||||||
|
juce::ScopedNoDenormals noDenormals;
|
||||||
|
|
||||||
|
const auto totalNumInputChannels = getTotalNumInputChannels();
|
||||||
|
const auto totalNumOutputChannels = getTotalNumOutputChannels();
|
||||||
|
|
||||||
|
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
|
||||||
|
buffer.clear(i, 0, buffer.getNumSamples());
|
||||||
|
shifter.SetFormantPreserve(state.getParameterAsValue("formantPreserve").getValue());
|
||||||
|
shifter.SetAutoTuneSpeed(state.getParameterAsValue("autoTuneSpeed").getValue());
|
||||||
|
shifter.SetAutoTuneDepth(state.getParameterAsValue("autoTuneDepth").getValue());
|
||||||
|
shifter.SetPortamentoTime(state.getParameterAsValue("portTime").getValue());
|
||||||
|
juce::AudioBuffer<float> const_buff;
|
||||||
|
const_buff.makeCopyOf(buffer);
|
||||||
|
shifter.Process(const_buff.getArrayOfReadPointers(), (float**)buffer.getArrayOfWritePointers(), buffer.getNumSamples());
|
||||||
|
|
||||||
|
for (const auto metadata : midi)
|
||||||
|
{
|
||||||
|
const auto msg = metadata.getMessage();
|
||||||
|
if (msg.isNoteOn()) {
|
||||||
|
shifter.AddMidiNote(msg.getNoteNumber());
|
||||||
|
new_midi = true;
|
||||||
|
}
|
||||||
|
else if (msg.isNoteOff()) {
|
||||||
|
shifter.RemoveMidiNote(msg.getNoteNumber());
|
||||||
|
new_midi = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void WebViewPluginAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
||||||
|
{
|
||||||
|
juce::ignoreUnused(destData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPluginAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
||||||
|
{
|
||||||
|
juce::ignoreUnused(data, sizeInBytes);
|
||||||
|
}
|
||||||
131
Source/PluginProcessor.h
Normal file
131
Source/PluginProcessor.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
PluginProcessor.h
|
||||||
|
Created: 4 Nov 2025 6:20:37pm
|
||||||
|
Author: mickl
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
#include "Shifter.h"
|
||||||
|
|
||||||
|
class WebViewPluginAudioProcessor : public AudioProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
|
||||||
|
void releaseResources() override {}
|
||||||
|
|
||||||
|
bool isBusesLayoutSupported(const BusesLayout& layouts) const override;
|
||||||
|
|
||||||
|
void processBlock(AudioBuffer<float>&, MidiBuffer&) override;
|
||||||
|
using AudioProcessor::processBlock;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
const String getName() const override { return JucePlugin_Name; }
|
||||||
|
|
||||||
|
bool acceptsMidi() const override { return false; }
|
||||||
|
bool producesMidi() const override { return false; }
|
||||||
|
bool isMidiEffect() const override { return false; }
|
||||||
|
double getTailLengthSeconds() const override { return 0.0; }
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
int getNumPrograms() override { return 1; }
|
||||||
|
int getCurrentProgram() override { return 0; }
|
||||||
|
void setCurrentProgram(int) override {}
|
||||||
|
const String getProgramName(int) override { return {}; }
|
||||||
|
void changeProgramName(int, const String&) override {}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void getStateInformation(MemoryBlock& destData) override;
|
||||||
|
void setStateInformation(const void* data, int sizeInBytes) override;
|
||||||
|
bool new_midi = false;
|
||||||
|
|
||||||
|
struct Parameters
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Parameters(AudioProcessorValueTreeState::ParameterLayout& layout)
|
||||||
|
{
|
||||||
|
sliderIds.push_back("formantPreserve");
|
||||||
|
addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ParameterID{ "formantPreserve" },
|
||||||
|
"Formant Preserve",
|
||||||
|
NormalisableRange<float> {0.0f, 1.0f, .01f},
|
||||||
|
.5f);
|
||||||
|
|
||||||
|
sliderIds.push_back("autoTuneDepth");
|
||||||
|
addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ParameterID("autoTuneDepth"),
|
||||||
|
"AutoTune Depth",
|
||||||
|
NormalisableRange<float> {0.0f, 1.1f, .01f},
|
||||||
|
.5f);
|
||||||
|
|
||||||
|
sliderIds.push_back("autoTuneSpeed");
|
||||||
|
addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ParameterID("autoTuneSpeed"),
|
||||||
|
"AutoTune Speed",
|
||||||
|
NormalisableRange<float> {0.001f, 0.1f, .001f},
|
||||||
|
.5f);
|
||||||
|
sliderIds.push_back("portTime");
|
||||||
|
addToLayout<AudioParameterFloat>(layout,
|
||||||
|
ParameterID("portTime"),
|
||||||
|
"Portamento Speed",
|
||||||
|
NormalisableRange<float> {0.001f, 0.2f, .001f},
|
||||||
|
.01f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*AudioParameterFloat& formantPreserve;
|
||||||
|
AudioParameterFloat& autoTuneSpeed;
|
||||||
|
AudioParameterFloat& autoTuneDepth;
|
||||||
|
AudioParameterFloat& portTime;*/
|
||||||
|
std::vector<juce::String> sliderIds;
|
||||||
|
/*AudioParameterBool& mute;
|
||||||
|
AudioParameterChoice& filterType;*/
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Param>
|
||||||
|
static void add(AudioProcessorParameterGroup& group, std::unique_ptr<Param> param)
|
||||||
|
{
|
||||||
|
group.addChild(std::move(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Param>
|
||||||
|
static void add(AudioProcessorValueTreeState::ParameterLayout& group, std::unique_ptr<Param> param)
|
||||||
|
{
|
||||||
|
group.add(std::move(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Param, typename Group, typename... Ts>
|
||||||
|
static Param& addToLayout(Group& layout, Ts&&... ts)
|
||||||
|
{
|
||||||
|
auto param = std::make_unique<Param>(std::forward<Ts>(ts)...);
|
||||||
|
auto& ref = *param;
|
||||||
|
add(layout, std::move(param));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Parameters parameters;
|
||||||
|
AudioProcessorValueTreeState state;
|
||||||
|
SpinLock midiLock;
|
||||||
|
|
||||||
|
/*std::vector<int> spectrumData = [] { return std::vector<int>(256, 0.0f); }();
|
||||||
|
SpinLock spectrumDataLock;
|
||||||
|
|
||||||
|
SpectralBars spectralBars;*/
|
||||||
|
|
||||||
|
dsp::LadderFilter<float> filter;
|
||||||
|
Shifter shifter;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessor)
|
||||||
|
|
||||||
|
};
|
||||||
@ -52,652 +52,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "DemoUtilities.h"
|
|
||||||
#include <JuceHeader.h>
|
#include <JuceHeader.h>
|
||||||
#include "Shifter.h"
|
#include "PluginEditor.h"
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
|
||||||
//using namespace juce::dsp;
|
|
||||||
|
|
||||||
namespace ID
|
|
||||||
{
|
|
||||||
#define PARAMETER_ID(str) static const ParameterID str { #str, 1 };
|
|
||||||
|
|
||||||
PARAMETER_ID(formantPreserve)
|
|
||||||
PARAMETER_ID(autoTuneSpeed)
|
|
||||||
PARAMETER_ID(autoTuneDepth)
|
|
||||||
PARAMETER_ID(portTime)
|
|
||||||
PARAMETER_ID(mute)
|
|
||||||
PARAMETER_ID(filterType)
|
|
||||||
|
|
||||||
#undef PARAMETER_ID
|
|
||||||
}
|
|
||||||
|
|
||||||
class CircularBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CircularBuffer(int numChannels, int numSamples)
|
|
||||||
: buffer(data, (size_t)numChannels, (size_t)numSamples)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void push(dsp::AudioBlock<T> b)
|
|
||||||
{
|
|
||||||
jassert(b.getNumChannels() == buffer.getNumChannels());
|
|
||||||
|
|
||||||
const auto trimmed = b.getSubBlock(b.getNumSamples()
|
|
||||||
- std::min(b.getNumSamples(), buffer.getNumSamples()));
|
|
||||||
|
|
||||||
const auto bufferLength = (int64)buffer.getNumSamples();
|
|
||||||
|
|
||||||
for (auto samplesRemaining = (int64)trimmed.getNumSamples(); samplesRemaining > 0;)
|
|
||||||
{
|
|
||||||
const auto writeOffset = writeIx % bufferLength;
|
|
||||||
const auto numSamplesToWrite = std::min(samplesRemaining, bufferLength - writeOffset);
|
|
||||||
|
|
||||||
auto destSubBlock = buffer.getSubBlock((size_t)writeOffset, (size_t)numSamplesToWrite);
|
|
||||||
const auto sourceSubBlock = trimmed.getSubBlock(trimmed.getNumSamples() - (size_t)samplesRemaining,
|
|
||||||
(size_t)numSamplesToWrite);
|
|
||||||
|
|
||||||
destSubBlock.copyFrom(sourceSubBlock);
|
|
||||||
|
|
||||||
samplesRemaining -= numSamplesToWrite;
|
|
||||||
writeIx += numSamplesToWrite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void push(Span<T> s)
|
|
||||||
{
|
|
||||||
auto* ptr = s.begin();
|
|
||||||
dsp::AudioBlock<T> b(&ptr, 1, s.size());
|
|
||||||
push(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(int64 readIx, dsp::AudioBlock<float> output) const
|
|
||||||
{
|
|
||||||
const auto numChannelsToUse = std::min(buffer.getNumChannels(), output.getNumChannels());
|
|
||||||
|
|
||||||
jassert(output.getNumChannels() == buffer.getNumChannels());
|
|
||||||
|
|
||||||
const auto bufferLength = (int64)buffer.getNumSamples();
|
|
||||||
|
|
||||||
for (auto outputOffset = (size_t)0; outputOffset < output.getNumSamples();)
|
|
||||||
{
|
|
||||||
const auto inputOffset = (size_t)((readIx + (int64)outputOffset) % bufferLength);
|
|
||||||
const auto numSamplesToRead = std::min(output.getNumSamples() - outputOffset,
|
|
||||||
(size_t)bufferLength - inputOffset);
|
|
||||||
|
|
||||||
auto destSubBlock = output.getSubBlock(outputOffset, numSamplesToRead)
|
|
||||||
.getSubsetChannelBlock(0, numChannelsToUse);
|
|
||||||
|
|
||||||
destSubBlock.copyFrom(buffer.getSubBlock(inputOffset, numSamplesToRead)
|
|
||||||
.getSubsetChannelBlock(0, numChannelsToUse));
|
|
||||||
|
|
||||||
outputOffset += numSamplesToRead;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 getWriteIndex() const noexcept { return writeIx; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
HeapBlock<char> data;
|
|
||||||
dsp::AudioBlock<float> buffer;
|
|
||||||
int64 writeIx = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//class SpectralBars
|
|
||||||
//{
|
|
||||||
//public:
|
|
||||||
// //template <typename T>
|
|
||||||
// void push(int data)
|
|
||||||
// {
|
|
||||||
// testQueue.push(data);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void compute(Span<int> output) {
|
|
||||||
// int index = 0;
|
|
||||||
// for (auto it = output.begin(); it != output.end(); ++it) {
|
|
||||||
// *it = testQueue.get(index++);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//private:
|
|
||||||
// circ_queue<int, 256> testQueue;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
class WebViewPluginAudioProcessor : public AudioProcessor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
|
|
||||||
void releaseResources() override {}
|
|
||||||
|
|
||||||
bool isBusesLayoutSupported(const BusesLayout& layouts) const override;
|
|
||||||
|
|
||||||
void processBlock(AudioBuffer<float>&, MidiBuffer&) override;
|
|
||||||
using AudioProcessor::processBlock;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
const String getName() const override { return JucePlugin_Name; }
|
|
||||||
|
|
||||||
bool acceptsMidi() const override { return false; }
|
|
||||||
bool producesMidi() const override { return false; }
|
|
||||||
bool isMidiEffect() const override { return false; }
|
|
||||||
double getTailLengthSeconds() const override { return 0.0; }
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
int getNumPrograms() override { return 1; }
|
|
||||||
int getCurrentProgram() override { return 0; }
|
|
||||||
void setCurrentProgram(int) override {}
|
|
||||||
const String getProgramName(int) override { return {}; }
|
|
||||||
void changeProgramName(int, const String&) override {}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void getStateInformation(MemoryBlock& destData) override;
|
|
||||||
void setStateInformation(const void* data, int sizeInBytes) override;
|
|
||||||
bool new_midi = false;
|
|
||||||
|
|
||||||
struct Parameters
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Parameters(AudioProcessorValueTreeState::ParameterLayout& layout)
|
|
||||||
: formantPreserve(addToLayout<AudioParameterFloat>(layout,
|
|
||||||
ID::formantPreserve,
|
|
||||||
"Formant Preserve",
|
|
||||||
NormalisableRange<float> {0.0f, 1.0f, .01f},
|
|
||||||
.5f)),
|
|
||||||
|
|
||||||
autoTuneSpeed(addToLayout<AudioParameterFloat>(layout,
|
|
||||||
ID::autoTuneSpeed,
|
|
||||||
"AutoTune Speed",
|
|
||||||
NormalisableRange<float> {0.001f, 0.1f, .001f},
|
|
||||||
.5f)),
|
|
||||||
autoTuneDepth(addToLayout<AudioParameterFloat>(layout,
|
|
||||||
ID::autoTuneDepth,
|
|
||||||
"AutoTune Depth",
|
|
||||||
NormalisableRange<float> {0.0f, 1.1f, .01f},
|
|
||||||
.5f)),
|
|
||||||
portTime(addToLayout<AudioParameterFloat>(layout,
|
|
||||||
ID::portTime,
|
|
||||||
"Portamento Speed",
|
|
||||||
NormalisableRange<float> {0.001f, 0.2f, .001f},
|
|
||||||
.01f)),
|
|
||||||
mute(addToLayout<AudioParameterBool>(layout, ID::mute, "Mute", false)),
|
|
||||||
filterType(addToLayout<AudioParameterChoice>(layout,
|
|
||||||
ID::filterType,
|
|
||||||
"Filter type",
|
|
||||||
StringArray{ "Low-pass", "High-pass", "Band-pass" },
|
|
||||||
0))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioParameterFloat& formantPreserve;
|
|
||||||
AudioParameterFloat& autoTuneSpeed;
|
|
||||||
AudioParameterFloat& autoTuneDepth;
|
|
||||||
AudioParameterFloat& portTime;
|
|
||||||
AudioParameterBool& mute;
|
|
||||||
AudioParameterChoice& filterType;
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename Param>
|
|
||||||
static void add(AudioProcessorParameterGroup& group, std::unique_ptr<Param> param)
|
|
||||||
{
|
|
||||||
group.addChild(std::move(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Param>
|
|
||||||
static void add(AudioProcessorValueTreeState::ParameterLayout& group, std::unique_ptr<Param> param)
|
|
||||||
{
|
|
||||||
group.add(std::move(param));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Param, typename Group, typename... Ts>
|
|
||||||
static Param& addToLayout(Group& layout, Ts&&... ts)
|
|
||||||
{
|
|
||||||
auto param = std::make_unique<Param>(std::forward<Ts>(ts)...);
|
|
||||||
auto& ref = *param;
|
|
||||||
add(layout, std::move(param));
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Parameters parameters;
|
|
||||||
AudioProcessorValueTreeState state;
|
|
||||||
SpinLock midiLock;
|
|
||||||
|
|
||||||
/*std::vector<int> spectrumData = [] { return std::vector<int>(256, 0.0f); }();
|
|
||||||
SpinLock spectrumDataLock;
|
|
||||||
|
|
||||||
SpectralBars spectralBars;*/
|
|
||||||
|
|
||||||
dsp::LadderFilter<float> filter;
|
|
||||||
Shifter shifter;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessor)
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
WebViewPluginAudioProcessor::WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout)
|
|
||||||
: AudioProcessor(BusesProperties()
|
|
||||||
#if ! JucePlugin_IsMidiEffect
|
|
||||||
#if ! JucePlugin_IsSynth
|
|
||||||
.withInput("Input", juce::AudioChannelSet::stereo(), true)
|
|
||||||
#endif
|
|
||||||
.withOutput("Output", juce::AudioChannelSet::stereo(), true)
|
|
||||||
#endif
|
|
||||||
),
|
|
||||||
parameters(layout),
|
|
||||||
state(*this, nullptr, "STATE", std::move(layout))
|
|
||||||
{
|
|
||||||
shifter.Init(48000.0f, 48);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void WebViewPluginAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
|
|
||||||
{
|
|
||||||
const auto channels = std::max(getTotalNumInputChannels(), getTotalNumOutputChannels());
|
|
||||||
shifter.Init((float)sampleRate, samplesPerBlock);
|
|
||||||
if (channels == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
filter.prepare({ sampleRate, (uint32_t)samplesPerBlock, (uint32_t)channels });
|
|
||||||
filter.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebViewPluginAudioProcessor::isBusesLayoutSupported(const BusesLayout& layouts) const
|
|
||||||
{
|
|
||||||
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
|
|
||||||
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewPluginAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer,
|
|
||||||
juce::MidiBuffer& midi)
|
|
||||||
{
|
|
||||||
juce::ScopedNoDenormals noDenormals;
|
|
||||||
|
|
||||||
const auto totalNumInputChannels = getTotalNumInputChannels();
|
|
||||||
const auto totalNumOutputChannels = getTotalNumOutputChannels();
|
|
||||||
|
|
||||||
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
|
|
||||||
buffer.clear(i, 0, buffer.getNumSamples());
|
|
||||||
shifter.SetFormantPreserve(parameters.formantPreserve.get());
|
|
||||||
shifter.SetAutoTuneSpeed(parameters.autoTuneSpeed.get());
|
|
||||||
shifter.SetAutoTuneDepth(parameters.autoTuneDepth.get());
|
|
||||||
shifter.SetPortamentoTime(parameters.portTime.get());
|
|
||||||
juce::AudioBuffer<float> const_buff;
|
|
||||||
const_buff.makeCopyOf(buffer);
|
|
||||||
shifter.Process(const_buff.getArrayOfReadPointers(), (float**)buffer.getArrayOfWritePointers(), buffer.getNumSamples());
|
|
||||||
|
|
||||||
for (const auto metadata : midi)
|
|
||||||
{
|
|
||||||
const auto msg = metadata.getMessage();
|
|
||||||
if (msg.isNoteOn()) {
|
|
||||||
shifter.AddMidiNote(msg.getNoteNumber());
|
|
||||||
new_midi = true;
|
|
||||||
//editor.webComponent.emitEventIfBrowserIsVisible("midNoteData", var{});
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (msg.isNoteOff()) {
|
|
||||||
shifter.RemoveMidiNote(msg.getNoteNumber());
|
|
||||||
new_midi = true;
|
|
||||||
//editor.webComponent.emitEventIfBrowserIsVisible("midNoteData", var{});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
//DBG(shifter.out_midi[MAX_VOICES]);
|
|
||||||
//push midi note
|
|
||||||
//spectralBars.push(shifter.out_midi[MAX_VOICES]);
|
|
||||||
const SpinLock::ScopedTryLockType lock(midiLock);
|
|
||||||
|
|
||||||
if (!lock.isLocked())
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*for(auto i = 0; i < buffer.getNumSamples(); ++i)
|
|
||||||
{
|
|
||||||
bool process = (i % 256) == 0 && i != 0;
|
|
||||||
|
|
||||||
for(auto j = 0; j < totalNumInputChannels; ++j)
|
|
||||||
{
|
|
||||||
input[j][i] = buffer.getReadPointer(j)[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.setCutoffFrequencyHz (parameters.cutoffFreqHz.get());
|
|
||||||
|
|
||||||
const auto filterMode = [this]
|
|
||||||
{
|
|
||||||
switch (parameters.filterType.getIndex())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return dsp::LadderFilter<float>::Mode::LPF12;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
return dsp::LadderFilter<float>::Mode::HPF12;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return dsp::LadderFilter<float>::Mode::BPF12;
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
filter.setMode (filterMode);
|
|
||||||
|
|
||||||
auto outBlock = dsp::AudioBlock<float> { buffer }.getSubsetChannelBlock (0, (size_t) getTotalNumOutputChannels());
|
|
||||||
|
|
||||||
if (parameters.mute.get())
|
|
||||||
outBlock.clear();
|
|
||||||
|
|
||||||
filter.process (dsp::ProcessContextReplacing<float> (outBlock));
|
|
||||||
|
|
||||||
spectralBars.push (Span { buffer.getReadPointer (0), (size_t) buffer.getNumSamples() });
|
|
||||||
|
|
||||||
{
|
|
||||||
const SpinLock::ScopedTryLockType lock (spectrumDataLock);
|
|
||||||
|
|
||||||
if (! lock.isLocked())
|
|
||||||
return;
|
|
||||||
|
|
||||||
spectralBars.compute ({ spectrumData.data(), spectrumData.size() });
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void WebViewPluginAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
|
||||||
{
|
|
||||||
juce::ignoreUnused(destData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewPluginAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
|
|
||||||
{
|
|
||||||
juce::ignoreUnused(data, sizeInBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const String localDevServerAddress;
|
|
||||||
|
|
||||||
std::optional<WebBrowserComponent::Resource> getResource(const String& url);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
struct SinglePageBrowser : WebBrowserComponent
|
|
||||||
{
|
|
||||||
using WebBrowserComponent::WebBrowserComponent;
|
|
||||||
|
|
||||||
// Prevent page loads from navigating away from our single page web app
|
|
||||||
bool pageAboutToLoad(const String& newURL) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
class WebViewPluginAudioProcessorEditor : public AudioProcessorEditor, private Timer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit WebViewPluginAudioProcessorEditor(WebViewPluginAudioProcessor&);
|
|
||||||
|
|
||||||
std::optional<WebBrowserComponent::Resource> getResource(const String& url);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void paint(Graphics&) override;
|
|
||||||
void resized() override;
|
|
||||||
|
|
||||||
int getControlParameterIndex(Component&) override
|
|
||||||
{
|
|
||||||
return controlParameterIndexReceiver.getControlParameterIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
void timerCallback() override
|
|
||||||
{
|
|
||||||
static constexpr size_t numFramesBuffered = 5;
|
|
||||||
|
|
||||||
SpinLock::ScopedLockType lock{ processorRef.midiLock };
|
|
||||||
|
|
||||||
static int64 callbackCounter = 0;
|
|
||||||
processorRef.new_midi = false;
|
|
||||||
juce::Array<var> notes;
|
|
||||||
int voice_num = 0;
|
|
||||||
for (auto& voice : processorRef.shifter.voices) {
|
|
||||||
if (voice.onoff_) {
|
|
||||||
auto obj = new DynamicObject();
|
|
||||||
obj->setProperty("voice", voice_num);
|
|
||||||
obj->setProperty("midi", voice.GetMidiNote());
|
|
||||||
notes.add(var(obj));
|
|
||||||
}
|
|
||||||
voice_num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicObject::Ptr d(new DynamicObject());
|
|
||||||
d->setProperty("notes", notes);
|
|
||||||
d->setProperty("input_pitch", processorRef.shifter.getInputPitch());
|
|
||||||
d->setProperty("output_pitch", processorRef.shifter.getOutputPitch());
|
|
||||||
webComponent.emitEventIfBrowserIsVisible("midNoteData", d.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
WebViewPluginAudioProcessor& processorRef;
|
|
||||||
|
|
||||||
WebSliderRelay formantSliderRelay{ "formantSlider" };
|
|
||||||
WebSliderRelay autoTuneSpeedSliderRelay{ "autoTuneSpeedSlider" };
|
|
||||||
WebSliderRelay autoTuneDepthSliderRelay{ "autoTuneDepthSlider" };
|
|
||||||
WebSliderRelay portTimeSliderRelay{ "portTimeSlider" };
|
|
||||||
WebToggleButtonRelay muteToggleRelay{ "muteToggle" };
|
|
||||||
WebComboBoxRelay filterTypeComboRelay{ "filterTypeCombo" };
|
|
||||||
|
|
||||||
WebControlParameterIndexReceiver controlParameterIndexReceiver;
|
|
||||||
|
|
||||||
SinglePageBrowser webComponent{ WebBrowserComponent::Options{}
|
|
||||||
.withBackend(WebBrowserComponent::Options::Backend::webview2)
|
|
||||||
.withWinWebView2Options(WebBrowserComponent::Options::WinWebView2{}
|
|
||||||
.withUserDataFolder(File::getSpecialLocation(File::SpecialLocationType::tempDirectory)))
|
|
||||||
.withNativeIntegrationEnabled()
|
|
||||||
.withOptionsFrom(formantSliderRelay)
|
|
||||||
.withOptionsFrom(autoTuneSpeedSliderRelay)
|
|
||||||
.withOptionsFrom(autoTuneDepthSliderRelay)
|
|
||||||
.withOptionsFrom(portTimeSliderRelay)
|
|
||||||
.withOptionsFrom(muteToggleRelay)
|
|
||||||
.withOptionsFrom(filterTypeComboRelay)
|
|
||||||
.withOptionsFrom(controlParameterIndexReceiver)
|
|
||||||
.withNativeFunction("sayHello", [](auto& var, auto complete)
|
|
||||||
{
|
|
||||||
complete("Hello " + var[0].toString());
|
|
||||||
})
|
|
||||||
.withResourceProvider([this](const auto& url)
|
|
||||||
{
|
|
||||||
return getResource(url);
|
|
||||||
},
|
|
||||||
URL { localDevServerAddress }.getOrigin()) };
|
|
||||||
|
|
||||||
WebSliderParameterAttachment formantAttachment;
|
|
||||||
WebSliderParameterAttachment autoTuneSpeedAttachment;
|
|
||||||
WebSliderParameterAttachment autoTuneDepthAttachment;
|
|
||||||
WebSliderParameterAttachment portTimeAttachment;
|
|
||||||
WebToggleButtonParameterAttachment muteAttachment;
|
|
||||||
WebComboBoxParameterAttachment filterTypeAttachment;
|
|
||||||
|
|
||||||
std::deque<Array<var>> spectrumDataFrames;
|
|
||||||
|
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessorEditor)
|
|
||||||
};
|
|
||||||
|
|
||||||
static ZipFile* getZipFile()
|
|
||||||
{
|
|
||||||
static auto stream = createAssetInputStream("webviewplugin-gui_1.0.0.zip", AssertAssetExists::no);
|
|
||||||
|
|
||||||
if (stream == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
static ZipFile f{ stream.get(), false };
|
|
||||||
return &f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* getMimeForExtension(const String& extension)
|
|
||||||
{
|
|
||||||
static const std::unordered_map<String, const char*> mimeMap =
|
|
||||||
{
|
|
||||||
{ { "htm" }, "text/html" },
|
|
||||||
{ { "html" }, "text/html" },
|
|
||||||
{ { "txt" }, "text/plain" },
|
|
||||||
{ { "jpg" }, "image/jpeg" },
|
|
||||||
{ { "jpeg" }, "image/jpeg" },
|
|
||||||
{ { "svg" }, "image/svg+xml" },
|
|
||||||
{ { "ico" }, "image/vnd.microsoft.icon" },
|
|
||||||
{ { "json" }, "application/json" },
|
|
||||||
{ { "png" }, "image/png" },
|
|
||||||
{ { "css" }, "text/css" },
|
|
||||||
{ { "map" }, "application/json" },
|
|
||||||
{ { "js" }, "text/javascript" },
|
|
||||||
{ { "woff2" }, "font/woff2" }
|
|
||||||
};
|
|
||||||
|
|
||||||
if (const auto it = mimeMap.find(extension.toLowerCase()); it != mimeMap.end())
|
|
||||||
return it->second;
|
|
||||||
|
|
||||||
jassertfalse;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getExtension(String filename)
|
|
||||||
{
|
|
||||||
return filename.fromLastOccurrenceOf(".", false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto streamToVector(InputStream& stream)
|
|
||||||
{
|
|
||||||
std::vector<std::byte> result((size_t)stream.getTotalLength());
|
|
||||||
stream.setPosition(0);
|
|
||||||
[[maybe_unused]] const auto bytesRead = stream.read(result.data(), result.size());
|
|
||||||
jassert(bytesRead == (ssize_t)result.size());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<WebBrowserComponent::Resource> WebViewPluginAudioProcessorEditor::getResource(const String& url)
|
|
||||||
{
|
|
||||||
const auto urlToRetrive = url == "/" ? String{ "index.html" }
|
|
||||||
: url.fromFirstOccurrenceOf("/", false, false);
|
|
||||||
|
|
||||||
if (auto* archive = getZipFile())
|
|
||||||
{
|
|
||||||
if (auto* entry = archive->getEntry(urlToRetrive))
|
|
||||||
{
|
|
||||||
auto stream = rawToUniquePtr(archive->createStreamForEntry(*entry));
|
|
||||||
auto v = streamToVector(*stream);
|
|
||||||
auto mime = getMimeForExtension(getExtension(entry->filename).toLowerCase());
|
|
||||||
return WebBrowserComponent::Resource{ std::move(v),
|
|
||||||
std::move(mime) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (urlToRetrive == "index.html")
|
|
||||||
{
|
|
||||||
auto fallbackIndexHtml = createAssetInputStream("webviewplugin-gui-fallback.html");
|
|
||||||
return WebBrowserComponent::Resource{ streamToVector(*fallbackIndexHtml),
|
|
||||||
String { "text/html" } };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (urlToRetrive == "data.txt")
|
|
||||||
{
|
|
||||||
WebBrowserComponent::Resource resource;
|
|
||||||
static constexpr char testData[] = "testdata";
|
|
||||||
MemoryInputStream stream{ testData, numElementsInArray(testData) - 1, false };
|
|
||||||
return WebBrowserComponent::Resource{ streamToVector(stream), String { "text/html" } };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (urlToRetrive == "midNoteData.json")
|
|
||||||
{
|
|
||||||
|
|
||||||
juce::Array<var> notes;
|
|
||||||
int voice_num = 0;
|
|
||||||
for (auto& voice : processorRef.shifter.voices) {
|
|
||||||
if (voice.onoff_) {
|
|
||||||
auto obj = new DynamicObject();
|
|
||||||
obj->setProperty("voice", voice_num);
|
|
||||||
obj->setProperty("midi", voice.GetMidiNote());
|
|
||||||
notes.add(var(obj));
|
|
||||||
}
|
|
||||||
voice_num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicObject::Ptr d(new DynamicObject());
|
|
||||||
d->setProperty("notes", notes);
|
|
||||||
|
|
||||||
const auto s = JSON::toString(d.get());
|
|
||||||
MemoryInputStream stream{ s.getCharPointer(), s.getNumBytesAsUTF8(), false };
|
|
||||||
return WebBrowserComponent::Resource{ streamToVector(stream), String { "application/json" } };
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if JUCE_ANDROID
|
|
||||||
// The localhost is available on this address to the emulator
|
|
||||||
const String localDevServerAddress = "http://10.0.2.2:3000/";
|
|
||||||
#else
|
|
||||||
const String localDevServerAddress = "http://localhost:3000/";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool SinglePageBrowser::pageAboutToLoad(const String& newURL)
|
|
||||||
{
|
|
||||||
return newURL == localDevServerAddress || newURL == getResourceProviderRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
WebViewPluginAudioProcessorEditor::WebViewPluginAudioProcessorEditor(WebViewPluginAudioProcessor& p)
|
|
||||||
: AudioProcessorEditor(&p), processorRef(p),
|
|
||||||
formantAttachment(*processorRef.state.getParameter(ID::formantPreserve.getParamID()),
|
|
||||||
formantSliderRelay,
|
|
||||||
processorRef.state.undoManager),
|
|
||||||
autoTuneSpeedAttachment(*processorRef.state.getParameter(ID::autoTuneSpeed.getParamID()),
|
|
||||||
autoTuneSpeedSliderRelay,
|
|
||||||
processorRef.state.undoManager),
|
|
||||||
autoTuneDepthAttachment(*processorRef.state.getParameter(ID::autoTuneDepth.getParamID()),
|
|
||||||
autoTuneDepthSliderRelay,
|
|
||||||
processorRef.state.undoManager),
|
|
||||||
portTimeAttachment(*processorRef.state.getParameter(ID::portTime.getParamID()),
|
|
||||||
portTimeSliderRelay,
|
|
||||||
processorRef.state.undoManager),
|
|
||||||
muteAttachment(*processorRef.state.getParameter(ID::mute.getParamID()),
|
|
||||||
muteToggleRelay,
|
|
||||||
processorRef.state.undoManager),
|
|
||||||
filterTypeAttachment(*processorRef.state.getParameter(ID::filterType.getParamID()),
|
|
||||||
filterTypeComboRelay,
|
|
||||||
processorRef.state.undoManager)
|
|
||||||
{
|
|
||||||
addAndMakeVisible(webComponent);
|
|
||||||
|
|
||||||
webComponent.goToURL(localDevServerAddress);
|
|
||||||
//webComponent.goToURL (WebBrowserComponent::getResourceProviderRoot());
|
|
||||||
|
|
||||||
setSize(500, 500);
|
|
||||||
|
|
||||||
startTimerHz(60);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void WebViewPluginAudioProcessorEditor::paint(Graphics& g)
|
|
||||||
{
|
|
||||||
// (Our component is opaque, so we must completely fill the background with a solid colour)
|
|
||||||
g.fillAll(getLookAndFeel().findColour(ResizableWindow::backgroundColourId));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebViewPluginAudioProcessorEditor::resized()
|
|
||||||
{
|
|
||||||
webComponent.setBounds(getLocalBounds());
|
|
||||||
}
|
|
||||||
|
|
||||||
class WebViewPluginAudioProcessorWrapper : public WebViewPluginAudioProcessor
|
class WebViewPluginAudioProcessorWrapper : public WebViewPluginAudioProcessor
|
||||||
{
|
{
|
||||||
@ -711,3 +71,4 @@ public:
|
|||||||
return new WebViewPluginAudioProcessorEditor(*this);
|
return new WebViewPluginAudioProcessorEditor(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user