Initial plugin version

This commit is contained in:
Timothy Scully
2025-06-23 00:16:47 +01:00
commit 01d446af2d
61 changed files with 1658 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
Builds
NeuralSynth Installer.exe

View File

@@ -0,0 +1,49 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
This is the header file that your files should include in order to get all the
JUCE library headers. You should avoid including the JUCE headers directly in
your own source files, because that wouldn't pick up the correct configuration
options for your app.
*/
#pragma once
#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_audio_devices/juce_audio_devices.h>
#include <juce_audio_formats/juce_audio_formats.h>
#include <juce_audio_plugin_client/juce_audio_plugin_client.h>
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_utils/juce_audio_utils.h>
#include <juce_core/juce_core.h>
#include <juce_data_structures/juce_data_structures.h>
#include <juce_dsp/juce_dsp.h>
#include <juce_events/juce_events.h>
#include <juce_graphics/juce_graphics.h>
#include <juce_gui_basics/juce_gui_basics.h>
#include <juce_gui_extra/juce_gui_extra.h>
#if defined (JUCE_PROJUCER_VERSION) && JUCE_PROJUCER_VERSION < JUCE_VERSION
/** If you've hit this error then the version of the Projucer that was used to generate this project is
older than the version of the JUCE modules being included. To fix this error, re-save your project
using the latest version of the Projucer or, if you aren't using the Projucer to manage your project,
remove the JUCE_PROJUCER_VERSION define.
*/
#error "This project was last saved using an outdated version of the Projucer! Re-save this project with the latest version to fix this error."
#endif
#if ! JUCE_DONT_DECLARE_PROJECTINFO
namespace ProjectInfo
{
const char* const projectName = "NeuralSynth";
const char* const companyName = "";
const char* const versionString = "1.0.0";
const int versionNumber = 0x10000;
}
#endif

View File

@@ -0,0 +1,162 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#pragma once
//==============================================================================
// Audio plugin settings..
#ifndef JucePlugin_Build_VST
#define JucePlugin_Build_VST 0
#endif
#ifndef JucePlugin_Build_VST3
#define JucePlugin_Build_VST3 1
#endif
#ifndef JucePlugin_Build_AU
#define JucePlugin_Build_AU 1
#endif
#ifndef JucePlugin_Build_AUv3
#define JucePlugin_Build_AUv3 0
#endif
#ifndef JucePlugin_Build_AAX
#define JucePlugin_Build_AAX 0
#endif
#ifndef JucePlugin_Build_Standalone
#define JucePlugin_Build_Standalone 1
#endif
#ifndef JucePlugin_Build_Unity
#define JucePlugin_Build_Unity 0
#endif
#ifndef JucePlugin_Build_LV2
#define JucePlugin_Build_LV2 0
#endif
#ifndef JucePlugin_Enable_IAA
#define JucePlugin_Enable_IAA 0
#endif
#ifndef JucePlugin_Enable_ARA
#define JucePlugin_Enable_ARA 0
#endif
#ifndef JucePlugin_Name
#define JucePlugin_Name "NeuralSynth"
#endif
#ifndef JucePlugin_Desc
#define JucePlugin_Desc "NeuralSynth"
#endif
#ifndef JucePlugin_Manufacturer
#define JucePlugin_Manufacturer "yourcompany"
#endif
#ifndef JucePlugin_ManufacturerWebsite
#define JucePlugin_ManufacturerWebsite "www.yourcompany.com"
#endif
#ifndef JucePlugin_ManufacturerEmail
#define JucePlugin_ManufacturerEmail ""
#endif
#ifndef JucePlugin_ManufacturerCode
#define JucePlugin_ManufacturerCode 0x4d616e75
#endif
#ifndef JucePlugin_PluginCode
#define JucePlugin_PluginCode 0x4d73347a
#endif
#ifndef JucePlugin_IsSynth
#define JucePlugin_IsSynth 0
#endif
#ifndef JucePlugin_WantsMidiInput
#define JucePlugin_WantsMidiInput 0
#endif
#ifndef JucePlugin_ProducesMidiOutput
#define JucePlugin_ProducesMidiOutput 0
#endif
#ifndef JucePlugin_IsMidiEffect
#define JucePlugin_IsMidiEffect 0
#endif
#ifndef JucePlugin_EditorRequiresKeyboardFocus
#define JucePlugin_EditorRequiresKeyboardFocus 0
#endif
#ifndef JucePlugin_Version
#define JucePlugin_Version 1.0.0
#endif
#ifndef JucePlugin_VersionCode
#define JucePlugin_VersionCode 0x10000
#endif
#ifndef JucePlugin_VersionString
#define JucePlugin_VersionString "1.0.0"
#endif
#ifndef JucePlugin_VSTUniqueID
#define JucePlugin_VSTUniqueID JucePlugin_PluginCode
#endif
#ifndef JucePlugin_VSTCategory
#define JucePlugin_VSTCategory kPlugCategEffect
#endif
#ifndef JucePlugin_Vst3Category
#define JucePlugin_Vst3Category "Fx"
#endif
#ifndef JucePlugin_AUMainType
#define JucePlugin_AUMainType 'aufx'
#endif
#ifndef JucePlugin_AUSubType
#define JucePlugin_AUSubType JucePlugin_PluginCode
#endif
#ifndef JucePlugin_AUExportPrefix
#define JucePlugin_AUExportPrefix NeuralSynthAU
#endif
#ifndef JucePlugin_AUExportPrefixQuoted
#define JucePlugin_AUExportPrefixQuoted "NeuralSynthAU"
#endif
#ifndef JucePlugin_AUManufacturerCode
#define JucePlugin_AUManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_CFBundleIdentifier
#define JucePlugin_CFBundleIdentifier com.yourcompany.NeuralSynth
#endif
#ifndef JucePlugin_AAXIdentifier
#define JucePlugin_AAXIdentifier com.yourcompany.NeuralSynth
#endif
#ifndef JucePlugin_AAXManufacturerCode
#define JucePlugin_AAXManufacturerCode JucePlugin_ManufacturerCode
#endif
#ifndef JucePlugin_AAXProductId
#define JucePlugin_AAXProductId JucePlugin_PluginCode
#endif
#ifndef JucePlugin_AAXCategory
#define JucePlugin_AAXCategory 0
#endif
#ifndef JucePlugin_AAXDisableBypass
#define JucePlugin_AAXDisableBypass 0
#endif
#ifndef JucePlugin_AAXDisableMultiMono
#define JucePlugin_AAXDisableMultiMono 0
#endif
#ifndef JucePlugin_IAAType
#define JucePlugin_IAAType 0x61757278
#endif
#ifndef JucePlugin_IAASubType
#define JucePlugin_IAASubType JucePlugin_PluginCode
#endif
#ifndef JucePlugin_IAAName
#define JucePlugin_IAAName "yourcompany: NeuralSynth"
#endif
#ifndef JucePlugin_VSTNumMidiInputs
#define JucePlugin_VSTNumMidiInputs 16
#endif
#ifndef JucePlugin_VSTNumMidiOutputs
#define JucePlugin_VSTNumMidiOutputs 16
#endif
#ifndef JucePlugin_ARAContentTypes
#define JucePlugin_ARAContentTypes 0
#endif
#ifndef JucePlugin_ARATransformationFlags
#define JucePlugin_ARATransformationFlags 0
#endif
#ifndef JucePlugin_ARAFactoryID
#define JucePlugin_ARAFactoryID "com.yourcompany.NeuralSynth.factory"
#endif
#ifndef JucePlugin_ARADocumentArchiveID
#define JucePlugin_ARADocumentArchiveID "com.yourcompany.NeuralSynth.aradocumentarchive.1.0.0"
#endif
#ifndef JucePlugin_ARACompatibleArchiveIDs
#define JucePlugin_ARACompatibleArchiveIDs ""
#endif

View File

@@ -0,0 +1,12 @@
Important Note!!
================
The purpose of this folder is to contain files that are auto-generated by the Projucer,
and ALL files in this folder will be mercilessly DELETED and completely re-written whenever
the Projucer saves your project.
Therefore, it's a bad idea to make any manual changes to the files in here, or to
put any of your own files in here if you don't want to lose them. (Of course you may choose
to add the folder's contents to your version-control system so that you can re-merge your own
modifications after the Projucer has saved its changes).

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_basics/juce_audio_basics.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_basics/juce_audio_basics.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_devices/juce_audio_devices.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_devices/juce_audio_devices.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_formats/juce_audio_formats.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_formats/juce_audio_formats.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_ARA.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_LV2.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_Unity.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_VST2.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_plugin_client/juce_audio_plugin_client_VST3.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_processors/juce_audio_processors.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_processors/juce_audio_processors.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_processors/juce_audio_processors_ara.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_processors/juce_audio_processors_lv2_libs.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_utils/juce_audio_utils.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_audio_utils/juce_audio_utils.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_core/juce_core.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_core/juce_core.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_core/juce_core_CompilationTime.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_data_structures/juce_data_structures.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_data_structures/juce_data_structures.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_dsp/juce_dsp.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_dsp/juce_dsp.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_events/juce_events.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_events/juce_events.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_graphics/juce_graphics.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_graphics/juce_graphics.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_graphics/juce_graphics_Harfbuzz.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_graphics/juce_graphics_Sheenbidi.c>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_gui_basics/juce_gui_basics.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_gui_basics/juce_gui_basics.mm>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_gui_extra/juce_gui_extra.cpp>

View File

@@ -0,0 +1,8 @@
/*
IMPORTANT! This file is auto-generated each time you save your
project - if you alter its contents, your changes may be overwritten!
*/
#include <juce_gui_extra/juce_gui_extra.mm>

98
NeuralSynth.iss Normal file
View File

@@ -0,0 +1,98 @@
[Setup]
AppName=NeuralSynth
AppVersion=1.0.0
DefaultDirName={pf}\NeuralSynth
DefaultGroupName=NeuralSynth
Compression=lzma2
SolidCompression=yes
OutputDir=.\
ArchitecturesInstallIn64BitMode=x64
OutputBaseFilename=NeuralSynth Installer
;LicenseFile=license.rtf
SetupLogging=yes
[Types]
Name: "full"; Description: "Full installation"
Name: "custom"; Description: "Custom installation"; Flags: iscustom
[Components]
Name: "app"; Description: "Standalone application (.exe)"; Types: full custom;
;Name: "vst2_32"; Description: "32-bit VST2 Plugin (.dll)"; Types: full custom;
;Name: "vst2_64"; Description: "64-bit VST2 Plugin (.dll)"; Types: full custom; Check: Is64BitInstallMode;
;Name: "vst3_32"; Description: "32-bit VST3 Plugin (.vst3)"; Types: full custom;
Name: "vst3_64"; Description: "64-bit VST3 Plugin (.vst3)"; Types: full custom; Check: Is64BitInstallMode;
;Name: "rtas_32"; Description: "32-bit RTAS Plugin (.dpm)"; Types: full custom;
;Name: "aax_32"; Description: "32-bit AAX Plugin (.aaxplugin)"; Types: full custom;
;Name: "aax_64"; Description: "64-bit AAX Plugin (.aaxplugin)"; Types: full custom; Check: Is64BitInstallMode;
;Name: "manual"; Description: "User guide"; Types: full custom; Flags: fixed
[Files]
;Source: "..\build-win\app\Win32\bin\NeuralSynth.exe"; DestDir: "{app}"; Check: not Is64BitInstallMode; Components:app; Flags: ignoreversion;
Source: "Builds\VisualStudio2022\x64\Release\Standalone Plugin\NeuralSynth.exe"; DestDir: "{app}"; Check: Is64BitInstallMode; Components:app; Flags: ignoreversion;
;Source: "..\build-win\vst2\Win32\bin\NeuralSynth.dll"; DestDir: {code:GetVST2Dir_32}; Check: not Is64BitInstallMode; Components:vst2_32; Flags: ignoreversion;
;Source: "..\build-win\vst2\Win32\bin\NeuralSynth.dll"; DestDir: {code:GetVST2Dir_32}; Check: Is64BitInstallMode; Components:vst2_32; Flags: ignoreversion;
;Source: "..\build-win\vst2\x64\bin\NeuralSynth.dll"; DestDir: {code:GetVST2Dir_64}; Check: Is64BitInstallMode; Components:vst2_64; Flags: ignoreversion;
;Source: "..\build-win\vst3\Win32\bin\NeuralSynth.vst3"; DestDir: "{cf}\VST3\"; Check: not Is64BitInstallMode; Components:vst3_32; Flags: ignoreversion;
;Source: "..\build-win\vst3\Win32\bin\NeuralSynth.vst3"; DestDir: "{cf32}\VST3\"; Check: Is64BitInstallMode; Components:vst3_32; Flags: ignoreversion;
Source: "Builds\VisualStudio2022\x64\Release\VST3\NeuralSynth.vst3\Contents\x86_64-win\NeuralSynth.vst3"; DestDir: "{cf64}\VST3\"; Check: Is64BitInstallMode; Components:vst3_64; Flags: ignoreversion;
;Source: "..\build-win\rtas\bin\NeuralSynth.dpm"; DestDir: "{cf32}\Digidesign\DAE\Plug-Ins\"; Components:rtas_32; Flags: ignoreversion;
;Source: "..\build-win\rtas\bin\NeuralSynth.dpm.rsr"; DestDir: "{cf32}\Digidesign\DAE\Plug-Ins\"; Components:rtas_32; Flags: ignoreversion;
;Source: "..\build-win\aax\bin\NeuralSynth.aaxplugin\*.*"; DestDir: "{cf32}\Avid\Audio\Plug-Ins\NeuralSynth.aaxplugin\"; Components:aax_32; Flags: ignoreversion recursesubdirs;
;Source: "..\build-win\aax\bin\NeuralSynth.aaxplugin\*.*"; DestDir: "{cf}\Avid\Audio\Plug-Ins\NeuralSynth.aaxplugin\"; Components:aax_64; Flags: ignoreversion recursesubdirs;
;Source: "..\manual\NeuralSynth_manual.pdf"; DestDir: "{app}"
;Source: "changelog.txt"; DestDir: "{app}"
;Source: "readmewin.rtf"; DestDir: "{app}"; DestName: "readme.rtf"; Flags: isreadme
[Icons]
Name: "{group}\NeuralSynth"; Filename: "{app}\NeuralSynth.exe"
;Name: "{group}\User guide"; Filename: "{app}\NeuralSynth_manual.pdf"
;Name: "{group}\Changelog"; Filename: "{app}\changelog.txt"
;Name: "{group}\readme"; Filename: "{app}\readme.rtf"
Name: "{group}\Uninstall NeuralSynth"; Filename: "{app}\unins000.exe"
;[Dirs]
;Name: {cf}\Digidesign\DAE\Plugins\
[Code]
var
OkToCopyLog : Boolean;
VST3DirPage_32: TInputDirWizardPage;
VST3DirPage_64: TInputDirWizardPage;
procedure InitializeWizard;
begin
if IsWin64 then begin
VST3DirPage_64 := CreateInputDirPage(wpSelectDir,
'Confirm 64-Bit VST3 Plugin Directory', '',
'Select the folder in which setup should install the 64-bit VST3 Plugin, then click Next.',
False, '');
VST3DirPage_64.Add('');
VST3DirPage_64.Values[0] := ExpandConstant('{reg:HKLM\SOFTWARE\VST,VSTPluginsPath|{pf}\Common Files\VST3}\');
end;
end;
function GetVST3Dir_64(Param: String): String;
begin
Result := VST3DirPage_64.Values[0]
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssDone then
OkToCopyLog := True;
end;
procedure DeinitializeSetup();
begin
if OkToCopyLog then
FileCopy (ExpandConstant ('{log}'), ExpandConstant ('{app}\InstallationLogFile.log'), FALSE);
RestartReplace (ExpandConstant ('{log}'), '');
end;
[UninstallDelete]
Type: files; Name: "{app}\InstallationLogFile.log"

67
NeuralSynth.jucer Normal file
View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<JUCERPROJECT id="ms4Z8E" name="NeuralSynth" projectType="audioplug" useAppConfig="0"
addUsingNamespaceToJuceHeader="0" jucerFormatVersion="1">
<MAINGROUP id="UQstsW" name="NeuralSynth">
<GROUP id="{D5B48DA9-9A47-914A-8C72-EE5E8DD868A3}" name="Source">
<FILE id="CjJ141" name="NeuralSharedParams.h" compile="0" resource="0"
file="Source/NeuralSharedParams.h"/>
<FILE id="ZrdRl1" name="AudioBufferQueue.h" compile="0" resource="0"
file="Source/AudioBufferQueue.h"/>
<FILE id="Hb5OB3" name="AudioEngine.h" compile="0" resource="0" file="Source/AudioEngine.h"/>
<FILE id="a6xhJu" name="ScopeComponent.h" compile="0" resource="0"
file="Source/ScopeComponent.h"/>
<FILE id="wgVoPS" name="ScopeDataCollector.h" compile="0" resource="0"
file="Source/ScopeDataCollector.h"/>
<FILE id="TdVLvo" name="SynthVoice.cpp" compile="1" resource="0" file="Source/SynthVoice.cpp"/>
<FILE id="hiZs4t" name="SynthVoice.h" compile="0" resource="0" file="Source/SynthVoice.h"/>
<FILE id="NO4X6C" name="PluginProcessor.cpp" compile="1" resource="0"
file="Source/PluginProcessor.cpp"/>
<FILE id="DFiJq3" name="PluginProcessor.h" compile="0" resource="0"
file="Source/PluginProcessor.h"/>
<FILE id="XWK3op" name="PluginEditor.cpp" compile="1" resource="0"
file="Source/PluginEditor.cpp"/>
<FILE id="MO8827" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
</GROUP>
</MAINGROUP>
<MODULES>
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"
useGlobalPath="1"/>
<MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_dsp" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
<MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
</MODULES>
<JUCEOPTIONS JUCE_STRICT_REFCOUNTEDPOINTER="1" JUCE_VST3_CAN_REPLACE_VST2="0"/>
<EXPORTFORMATS>
<VS2022 targetFolder="Builds/VisualStudio2022">
<CONFIGURATIONS>
<CONFIGURATION isDebug="1" name="Debug" targetName="NeuralSynth"/>
<CONFIGURATION isDebug="0" name="Release" targetName="NeuralSynth"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_audio_basics" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_audio_devices" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_audio_formats" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_audio_plugin_client" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_audio_processors" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_audio_utils" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_core" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_data_structures" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_dsp" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_events" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_graphics" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_gui_basics" path="../../../../../JUCE/modules"/>
<MODULEPATH id="juce_gui_extra" path="../../../../../JUCE/modules"/>
</MODULEPATHS>
</VS2022>
</EXPORTFORMATS>
</JUCERPROJECT>

49
Source/AudioBufferQueue.h Normal file
View File

@@ -0,0 +1,49 @@
#pragma once
//==============================================================================
template <typename SampleType>
class AudioBufferQueue
{
public:
//==============================================================================
static constexpr size_t order = 9;
static constexpr size_t bufferSize = 1U << order;
static constexpr size_t numBuffers = 5;
//==============================================================================
void push(const SampleType* dataToPush, size_t numSamples)
{
jassert(numSamples <= bufferSize);
int start1, size1, start2, size2;
abstractFifo.prepareToWrite(1, start1, size1, start2, size2);
jassert(size1 <= 1);
jassert(size2 == 0);
if (size1 > 0)
juce::FloatVectorOperations::copy(buffers[(size_t)start1].data(), dataToPush, (int)juce::jmin(bufferSize, numSamples));
abstractFifo.finishedWrite(size1);
}
//==============================================================================
void pop(SampleType* outputBuffer)
{
int start1, size1, start2, size2;
abstractFifo.prepareToRead(1, start1, size1, start2, size2);
jassert(size1 <= 1);
jassert(size2 == 0);
if (size1 > 0)
juce::FloatVectorOperations::copy(outputBuffer, buffers[(size_t)start1].data(), (int)bufferSize);
abstractFifo.finishedRead(size1);
}
private:
//==============================================================================
juce::AbstractFifo abstractFifo{ numBuffers };
std::array<std::array<SampleType, bufferSize>, numBuffers> buffers;
};

43
Source/AudioEngine.h Normal file
View File

@@ -0,0 +1,43 @@
#pragma once
#include "SynthVoice.h"
#include <JuceHeader.h>
class NeuralAudioEngine : public juce::MPESynthesiser
{
public:
static constexpr auto maxNumVoices = 4;
//==============================================================================
NeuralAudioEngine(NeuralSharedParams &sp)
{
for (auto i = 0; i < maxNumVoices; ++i)
addVoice(new NeuralSynthVoice(sp));
setVoiceStealingEnabled(true);
}
//==============================================================================
void prepare(const juce::dsp::ProcessSpec& spec) noexcept
{
setCurrentPlaybackSampleRate(spec.sampleRate);
for (auto* v : voices)
dynamic_cast<NeuralSynthVoice*> (v)->prepare(spec);
}
//==============================================================================
template <typename VoiceFunc>
void applyToVoices(VoiceFunc&& fn) noexcept
{
for (auto* v : voices)
fn(dynamic_cast<NeuralSynthVoice*> (v));
}
private:
//==============================================================================
void renderNextSubBlock(juce::AudioBuffer<float>& outputAudio, int startSample, int numSamples) override
{
MPESynthesiser::renderNextSubBlock(outputAudio, startSample, numSamples);
}
};

View File

@@ -0,0 +1,23 @@
/*
==============================================================================
NeuralSharedParams.h
Created: 21 Jun 2025 7:53:02am
Author: timot
==============================================================================
*/
#pragma once
#include <atomic>
struct NeuralSharedParams
{
std::atomic<int> waveform{ -1 };
std::atomic<float>* attack;
std::atomic<float>* decay;
std::atomic<float>* sustain;
std::atomic<float>* release;
};

101
Source/PluginEditor.cpp Normal file
View File

@@ -0,0 +1,101 @@
/*
==============================================================================
This file contains the basic framework code for a JUCE plugin editor.
==============================================================================
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "ScopeComponent.h"
//==============================================================================
NeuralSynthAudioProcessorEditor::NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor& p)
: AudioProcessorEditor (&p), audioProcessor (p), scopeComponent(audioProcessor.getAudioBufferQueue())
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setSize(400, 500);
auto& tree = audioProcessor.parameters;
auto area = getLocalBounds();
scopeComponent.setTopLeftPosition(0, 0);
scopeComponent.setSize(400, 200);
addAndMakeVisible(scopeComponent);
attackAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "attack", attackSlider);
decayAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "decay", decaySlider);
sustainAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "sustain", sustainSlider);
releaseAttachment = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(tree, "release", releaseSlider);
addAndMakeVisible(waveformSelector);
waveformSelector.setTopLeftPosition(15, 225);
int leftPosition = 15;
const int sliderWidth = 60;
for (auto* slider : { &attackSlider, &decaySlider, &sustainSlider, &releaseSlider })
{
slider->setSliderStyle(juce::Slider::Rotary);
slider->setTextBoxStyle(juce::Slider::TextBoxBelow, false, sliderWidth, 20);
addAndMakeVisible(*slider);
slider->setTopLeftPosition(leftPosition, 250);
leftPosition += (sliderWidth + 40);
}
waveformSelector.addItem("Sine", 1);
waveformSelector.addItem("Saw", 2);
waveformSelector.addItem("Square", 3);
waveformSelector.addItem("Triangle", 4);
// Attach to parameter
waveformAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ComboBoxAttachment>(
audioProcessor.parameters, "waveform", waveformSelector);
addAndMakeVisible(midiKeyboardComponent);
//scopeComponent.setSize(area.getWidth(), area.getHeight());
midiKeyboardComponent.setMidiChannel(2);
midiKeyboardState.addListener(&audioProcessor.getMidiMessageCollector());
midiKeyboardComponent.setBounds(area.removeFromTop(80).reduced(8));
midiKeyboardComponent.setTopLeftPosition(8, 420);
}
NeuralSynthAudioProcessorEditor::~NeuralSynthAudioProcessorEditor()
{
}
//==============================================================================
void NeuralSynthAudioProcessorEditor::paint (juce::Graphics& g)
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
//g.setColour (juce::Colours::white);
//g.setFont (juce::FontOptions (15.0f));
//g.drawFittedText ("Hello World!", getLocalBounds(), juce::Justification::centred, 1);
}
void NeuralSynthAudioProcessorEditor::resized()
{
// This is generally where you'll want to lay out the positions of any
// subcomponents in your editor..
auto bounds = getLocalBounds().reduced(20);
auto row = bounds.removeFromTop(150);
int knobWidth = row.getWidth() / 4;
attackSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
decaySlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
sustainSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
releaseSlider.setBounds(row.removeFromLeft(knobWidth).reduced(10));
waveformSelector.setBounds(20, 20, 120, 30);
}

48
Source/PluginEditor.h Normal file
View File

@@ -0,0 +1,48 @@
/*
==============================================================================
This file contains the basic framework code for a JUCE plugin editor.
==============================================================================
*/
#pragma once
#include <JuceHeader.h>
#include "PluginProcessor.h"
#include "ScopeComponent.h"
//==============================================================================
/**
*/
class NeuralSynthAudioProcessorEditor : public juce::AudioProcessorEditor
{
public:
NeuralSynthAudioProcessorEditor (NeuralSynthAudioProcessor&);
~NeuralSynthAudioProcessorEditor() override;
//==============================================================================
void paint (juce::Graphics&) override;
void resized() override;
private:
// This reference is provided as a quick way for your editor to
// access the processor object that created it.
NeuralSynthAudioProcessor& audioProcessor;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthAudioProcessorEditor)
juce::ComboBox waveformSelector;
std::unique_ptr<juce::AudioProcessorValueTreeState::ComboBoxAttachment> waveformAttachment;
juce::Slider attackSlider, decaySlider, sustainSlider, releaseSlider;
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> attackAttachment;
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> decayAttachment;
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> sustainAttachment;
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> releaseAttachment;
juce::MidiKeyboardState midiKeyboardState;
juce::MidiKeyboardComponent midiKeyboardComponent{ midiKeyboardState, juce::MidiKeyboardComponent::horizontalKeyboard };
ScopeComponent<float> scopeComponent;
};

201
Source/PluginProcessor.cpp Normal file
View File

@@ -0,0 +1,201 @@
/*
==============================================================================
This file contains the basic framework code for a JUCE plugin processor.
==============================================================================
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
//==============================================================================
NeuralSynthAudioProcessor::NeuralSynthAudioProcessor() : parameters(*this, nullptr, "PARAMETERS", createParameterLayout())
, AudioProcessor(BusesProperties().withOutput("Output", juce::AudioChannelSet::stereo(), true))
, audioEngine(sp)
{
parameters.addParameterListener("waveform", this);
parameters.addParameterListener("attack", this);
parameters.addParameterListener("decay", this);
parameters.addParameterListener("sustain", this);
parameters.addParameterListener("release", this);
sp.attack = parameters.getRawParameterValue("attack");
sp.decay = parameters.getRawParameterValue("decay");
sp.sustain = parameters.getRawParameterValue("sustain");
sp.release = parameters.getRawParameterValue("release");
}
NeuralSynthAudioProcessor::~NeuralSynthAudioProcessor()
{
}
//==============================================================================
const juce::String NeuralSynthAudioProcessor::getName() const
{
return JucePlugin_Name;
}
bool NeuralSynthAudioProcessor::acceptsMidi() const
{
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}
bool NeuralSynthAudioProcessor::producesMidi() const
{
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}
bool NeuralSynthAudioProcessor::isMidiEffect() const
{
#if JucePlugin_IsMidiEffect
return true;
#else
return false;
#endif
}
double NeuralSynthAudioProcessor::getTailLengthSeconds() const
{
return 0.0;
}
int NeuralSynthAudioProcessor::getNumPrograms()
{
return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
// so this should be at least 1, even if you're not really implementing programs.
}
int NeuralSynthAudioProcessor::getCurrentProgram()
{
return 0;
}
void NeuralSynthAudioProcessor::setCurrentProgram (int index)
{
}
const juce::String NeuralSynthAudioProcessor::getProgramName (int index)
{
return {};
}
void NeuralSynthAudioProcessor::changeProgramName (int index, const juce::String& newName)
{
}
//==============================================================================
void NeuralSynthAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
audioEngine.prepare({ sampleRate, (juce::uint32)samplesPerBlock, 2 });
midiMessageCollector.reset(sampleRate);
}
void NeuralSynthAudioProcessor::releaseResources()
{
// When playback stops, you can use this as an opportunity to free up any
// spare memory, etc.
}
bool NeuralSynthAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
{
// This is the place where you check if the layout is supported.
// In this template code we only support mono or stereo.
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
return false;
return true;
}
void NeuralSynthAudioProcessor::processBlock(juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiMessages)
{
const int newWaveform = sp.waveform.exchange(-1);
if (newWaveform != -1) {
audioEngine.applyToVoices([newWaveform](NeuralSynthVoice* v)
{
v->changeWaveform(newWaveform);
});
}
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
midiMessageCollector.removeNextBlockOfMessages(midiMessages, buffer.getNumSamples());
for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear(i, 0, buffer.getNumSamples());
audioEngine.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
scopeDataCollector.process(buffer.getReadPointer(0), (size_t)buffer.getNumSamples());
}
//==============================================================================
bool NeuralSynthAudioProcessor::hasEditor() const
{
return true; // (change this to false if you choose to not supply an editor)
}
juce::AudioProcessorEditor* NeuralSynthAudioProcessor::createEditor()
{
return new NeuralSynthAudioProcessorEditor (*this);
}
//==============================================================================
void NeuralSynthAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
}
void NeuralSynthAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
}
void NeuralSynthAudioProcessor::parameterChanged(const juce::String& id, float newValue)
{
if (id == "waveform")
sp.waveform.store((int)newValue, std::memory_order_release);
}
//==============================================================================
// This creates new instances of the plugin..
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
{
return new NeuralSynthAudioProcessor();
}
juce::AudioProcessorValueTreeState::ParameterLayout NeuralSynthAudioProcessor::createParameterLayout()
{
std::vector<std::unique_ptr<juce::RangedAudioParameter>> params;
params.push_back(std::make_unique<juce::AudioParameterChoice>(
"waveform", "Waveform",
juce::StringArray{ "Sine", "Saw", "Square", "Triangle" }, 0));
// Start/end/interval
params.push_back(std::make_unique<juce::AudioParameterFloat>("attack", "Attack",
juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 0.1f));
params.push_back(std::make_unique<juce::AudioParameterFloat>("decay", "Decay",
juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 0.5f));
params.push_back(std::make_unique<juce::AudioParameterFloat>("sustain", "Sustain",
juce::NormalisableRange<float>(0.0f, 1.0f, 0.01f), 0.8f));
params.push_back(std::make_unique<juce::AudioParameterFloat>("release", "Release",
juce::NormalisableRange<float>(0.01f, 1.0f, 0.01f), 1.0f));
return { params.begin(), params.end() };
}

80
Source/PluginProcessor.h Normal file
View File

@@ -0,0 +1,80 @@
/*
==============================================================================
This file contains the basic framework code for a JUCE plugin processor.
==============================================================================
*/
#pragma once
#include <JuceHeader.h>
#include "AudioBufferQueue.h"
#include "AudioEngine.h"
#include "ScopeDataCollector.h"
#include "NeuralSharedParams.h"
//==============================================================================
/**
*/
class NeuralSynthAudioProcessor : public juce::AudioProcessor,
private juce::AudioProcessorValueTreeState::Listener
{
public:
//==============================================================================
NeuralSynthAudioProcessor();
~NeuralSynthAudioProcessor() override;
//==============================================================================
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
void releaseResources() override;
#ifndef JucePlugin_PreferredChannelConfigurations
bool isBusesLayoutSupported(const BusesLayout& layouts) const override;
#endif
void processBlock(juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
//==============================================================================
juce::AudioProcessorEditor* createEditor() override;
bool hasEditor() const override;
//==============================================================================
const juce::String getName() const override;
bool acceptsMidi() const override;
bool producesMidi() const override;
bool isMidiEffect() const override;
double getTailLengthSeconds() const override;
//==============================================================================
int getNumPrograms() override;
int getCurrentProgram() override;
void setCurrentProgram(int index) override;
const juce::String getProgramName(int index) override;
void changeProgramName(int index, const juce::String& newName) override;
//==============================================================================
void getStateInformation(juce::MemoryBlock& destData) override;
void setStateInformation(const void* data, int sizeInBytes) override;
//==============================================================================
void parameterChanged(const juce::String& id, float newValue) override;
juce::MidiMessageCollector& getMidiMessageCollector() noexcept { return midiMessageCollector; }
juce::MidiMessageCollector midiMessageCollector;
juce::AudioProcessorValueTreeState parameters;
juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
AudioBufferQueue<float>& getAudioBufferQueue() noexcept { return audioBufferQueue; }
private:
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NeuralSynthAudioProcessor)
NeuralAudioEngine audioEngine;
AudioBufferQueue<float> audioBufferQueue;
ScopeDataCollector<float> scopeDataCollector{ audioBufferQueue };
NeuralSharedParams sp;
};

102
Source/ScopeComponent.h Normal file
View File

@@ -0,0 +1,102 @@
#pragma once
#include "AudioBufferQueue.h"
//==============================================================================
template <typename SampleType>
class ScopeComponent : public juce::Component,
private juce::Timer
{
public:
using Queue = AudioBufferQueue<SampleType>;
//==============================================================================
ScopeComponent(Queue& queueToUse)
: audioBufferQueue(queueToUse)
{
sampleData.fill(SampleType(0));
setFramesPerSecond(30);
}
//==============================================================================
void setFramesPerSecond(int framesPerSecond)
{
jassert(framesPerSecond > 0 && framesPerSecond < 1000);
startTimerHz(framesPerSecond);
}
//==============================================================================
void paint(juce::Graphics& g) override
{
g.fillAll(juce::Colours::black);
g.setColour(juce::Colours::white);
auto area = getLocalBounds();
auto h = (SampleType)area.getHeight();
auto w = (SampleType)area.getWidth();
// Oscilloscope
auto scopeRect = juce::Rectangle<SampleType>{ SampleType(0), SampleType(0), w, h / 2 };
plot(sampleData.data(), sampleData.size(), g, scopeRect, SampleType(1), h / 4);
// Spectrum
auto spectrumRect = juce::Rectangle<SampleType>{ SampleType(0), h / 2, w, h / 2 };
plot(spectrumData.data(), spectrumData.size() / 4, g, spectrumRect);
}
//==============================================================================
void resized() override {}
private:
//==============================================================================
Queue& audioBufferQueue;
std::array<SampleType, Queue::bufferSize> sampleData;
juce::dsp::FFT fft{ Queue::order };
using WindowFun = juce::dsp::WindowingFunction<SampleType>;
WindowFun windowFun{ (size_t)fft.getSize(), WindowFun::hann };
std::array<SampleType, 2 * Queue::bufferSize> spectrumData;
//==============================================================================
void timerCallback() override
{
audioBufferQueue.pop(sampleData.data());
juce::FloatVectorOperations::copy(spectrumData.data(), sampleData.data(), (int)sampleData.size());
auto fftSize = (size_t)fft.getSize();
jassert(spectrumData.size() == 2 * fftSize);
windowFun.multiplyWithWindowingTable(spectrumData.data(), fftSize);
fft.performFrequencyOnlyForwardTransform(spectrumData.data());
static constexpr auto mindB = SampleType(-160);
static constexpr auto maxdB = SampleType(0);
for (auto& s : spectrumData)
s = juce::jmap(juce::jlimit(mindB, maxdB, juce::Decibels::gainToDecibels(s) - juce::Decibels::gainToDecibels(SampleType(fftSize))), mindB, maxdB, SampleType(0), SampleType(1));
repaint();
}
//==============================================================================
static void plot(const SampleType* data,
size_t numSamples,
juce::Graphics& g,
juce::Rectangle<SampleType> rect,
SampleType scaler = SampleType(1),
SampleType offset = SampleType(0))
{
auto w = rect.getWidth();
auto h = rect.getHeight();
auto right = rect.getRight();
auto center = rect.getBottom() - offset;
auto gain = h * scaler;
for (size_t i = 1; i < numSamples; ++i)
g.drawLine({ juce::jmap(SampleType(i - 1), SampleType(0), SampleType(numSamples - 1), SampleType(right - w), SampleType(right)),
center - gain * data[i - 1],
juce::jmap(SampleType(i), SampleType(0), SampleType(numSamples - 1), SampleType(right - w), SampleType(right)),
center - gain * data[i] });
}
};

View File

@@ -0,0 +1,62 @@
#pragma once
template <typename SampleType>
class ScopeDataCollector
{
public:
//==============================================================================
ScopeDataCollector(AudioBufferQueue<SampleType>& queueToUse)
: audioBufferQueue(queueToUse)
{
}
//==============================================================================
void process(const SampleType* data, size_t numSamples)
{
size_t index = 0;
if (state == State::waitingForTrigger)
{
while (index++ < numSamples)
{
auto currentSample = *data++;
if (currentSample >= triggerLevel && prevSample < triggerLevel)
{
numCollected = 0;
state = State::collecting;
break;
}
prevSample = currentSample;
}
}
if (state == State::collecting)
{
while (index++ < numSamples)
{
buffer[numCollected++] = *data++;
if (numCollected == buffer.size())
{
audioBufferQueue.push(buffer.data(), buffer.size());
state = State::waitingForTrigger;
prevSample = SampleType(100);
break;
}
}
}
}
private:
//==============================================================================
AudioBufferQueue<SampleType>& audioBufferQueue;
std::array<SampleType, AudioBufferQueue<SampleType>::bufferSize> buffer;
size_t numCollected;
SampleType prevSample = SampleType(100);
static constexpr auto triggerLevel = SampleType(0.05);
enum class State { waitingForTrigger, collecting } state{ State::waitingForTrigger };
};

107
Source/SynthVoice.cpp Normal file
View File

@@ -0,0 +1,107 @@
#include "SynthVoice.h"
//==============================================================================
NeuralSynthVoice::NeuralSynthVoice(NeuralSharedParams& sp) : shared(sp) {}
//==============================================================================
void NeuralSynthVoice::prepare(const juce::dsp::ProcessSpec& spec)
{
setWaveform(0);
tempBlock = juce::dsp::AudioBlock<float>(heapBlock, spec.numChannels, spec.maximumBlockSize);
processorChain.prepare(spec);
adsr.setSampleRate(spec.sampleRate);
}
//==============================================================================
void NeuralSynthVoice::noteStarted()
{
auto velocity = getCurrentlyPlayingNote().noteOnVelocity.asUnsignedFloat();
auto freqHz = (float)getCurrentlyPlayingNote().getFrequencyInHertz();
processorChain.get<synthIndex>().setFrequency(freqHz, true);
juce::ADSR::Parameters p;
p.attack = shared.attack->load();
p.decay = shared.decay->load();
p.sustain = shared.sustain->load();
p.release = shared.release->load();
adsr.setParameters(p);
adsr.noteOn();
}
//==============================================================================
void NeuralSynthVoice::notePitchbendChanged()
{
auto freqHz = (float)getCurrentlyPlayingNote().getFrequencyInHertz();
processorChain.get<synthIndex>().setFrequency(freqHz, true);
}
//==============================================================================
void NeuralSynthVoice::noteStopped(bool allowTailOff)
{
adsr.noteOff(); //Triggers release phase
}
//==============================================================================
void NeuralSynthVoice::notePressureChanged() {}
void NeuralSynthVoice::noteTimbreChanged() {}
void NeuralSynthVoice::noteKeyStateChanged() {}
//==============================================================================
void NeuralSynthVoice::renderNextBlock(juce::AudioBuffer<float>& outputBuffer, int startSample, int numSamples)
{
if (!adsr.isActive())
clearCurrentNote();
if (waveform != -1) {
setWaveform(waveform);
waveform = -1;
}
auto block = tempBlock.getSubBlock(0, (size_t)numSamples);
block.clear();
juce::dsp::ProcessContextReplacing<float> context(block);
processorChain.process(context);
// 3. Apply ADSR envelope to tempBlock
std::vector<float*> channelPtrs;
for (size_t ch = 0; ch < tempBlock.getNumChannels(); ++ch)
channelPtrs.push_back(tempBlock.getChannelPointer(ch));
juce::AudioBuffer<float> buffer(channelPtrs.data(),
static_cast<int>(tempBlock.getNumChannels()),
static_cast<int>(tempBlock.getNumSamples()));
adsr.applyEnvelopeToBuffer(buffer, 0, numSamples);
juce::dsp::AudioBlock<float>(outputBuffer)
.getSubBlock((size_t)startSample, (size_t)numSamples)
.add(tempBlock);
}
void NeuralSynthVoice::setWaveform(int waveformType)
{
auto& osc = processorChain.template get<synthIndex>();
switch (waveformType)
{
case 0:
osc.initialise([](float x) { return std::sin(x); });
break;
case 1:
osc.initialise([](float x) { return x / juce::MathConstants<float>::pi; }); // Saw
break;
case 2:
osc.initialise([](float x) { return x < 0.0f ? -1.0f : 1.0f; }); // Square
break;
case 3:
osc.initialise([](float x) {
return 2.0f * std::abs(2.0f * (x / juce::MathConstants<float>::twoPi) - 1.0f) - 1.0f;
}); // Triangle
break;
}
}

100
Source/SynthVoice.h Normal file
View File

@@ -0,0 +1,100 @@
#pragma once
#include <JuceHeader.h>
#include "NeuralSharedParams.h"
#include <iostream>
/*struct ADSRProcessor : public juce::dsp::ProcessorBase
{
// -----------------------------------------------------------------
void prepare(const juce::dsp::ProcessSpec& spec) override
{
adsr.setSampleRate(spec.sampleRate);
}
void reset() override { adsr.reset(); }
void process(const juce::dsp::ProcessContextReplacing<float> &ctx) override
{
DBG("Processing...");
auto& outputBlock = context.getOutputBlock();
const auto numSamples = (int)outputBlock.getNumSamples();
const auto numChannels = (int)outputBlock.getNumChannels();
// Wrap the outputBlock into AudioBuffer
for (int ch = 0; ch < numChannels; ++ch)
buffer.setWritePointer(ch, outputBlock.getChannelPointer(ch));
adsr.applyEnvelopeToBuffer(buffer, 0, numSamples);
}
// -----------------------------------------------------------------
// These two are NOT part of the ProcessorBase interface <20> they are
// your private hooks that the voice will call on note events.
void noteOn(const juce::ADSR::Parameters& p) {
adsr.setParameters(p); adsr.noteOn();
}
void noteOff() { adsr.noteOff(); }
private:
juce::ADSR adsr;
juce::AudioBuffer<float> buffer;
};*/
//==============================================================================
class NeuralSynthVoice : public juce::MPESynthesiserVoice
{
public:
NeuralSynthVoice(NeuralSharedParams& sp);
//==============================================================================
void prepare(const juce::dsp::ProcessSpec& spec);
//==============================================================================
void noteStarted() override;
//==============================================================================
void notePitchbendChanged() override;
//==============================================================================
void noteStopped(bool) override;
//==============================================================================
void notePressureChanged();
void noteTimbreChanged();
void noteKeyStateChanged();
//==============================================================================
void renderNextBlock(juce::AudioBuffer<float>& outputBuffer, int startSample, int numSamples);
void setWaveform(int waveformType);
void changeWaveform(int waveform) noexcept {
this->waveform = waveform;
}
private:
//==============================================================================
juce::HeapBlock<char> heapBlock;
juce::dsp::AudioBlock<float> tempBlock;
enum
{
synthIndex
};
juce::dsp::ProcessorChain<
juce::dsp::Oscillator<float>
> processorChain;
juce::ADSR adsr;
NeuralSharedParams& shared;
static constexpr size_t lfoUpdateRate = 100;
static inline float msToSecs(float ms) { return ms * 0.001f; }
std::atomic<int> waveform { -1 };
};