From 1c23e3a1d0b77734fb48d36ef1f0e49c171aa165 Mon Sep 17 00:00:00 2001 From: ed Date: Wed, 22 Oct 2025 16:58:14 +0000 Subject: [PATCH] Upload files to "Source" --- Source/PluginProcessor.cpp | 584 ++++++++++++++++++------------------- Source/PluginProcessor.h | 191 ++++++------ 2 files changed, 366 insertions(+), 409 deletions(-) diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 0d548b1..a6babf4 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -1,308 +1,276 @@ -/* - ============================================================================== - - 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); - //sp.waveform = parameters.getRawParameterValue("waveform"); - -// === Chorus === - parameters.addParameterListener("chorus_rate", this); - parameters.addParameterListener("chorus_depth", this); - parameters.addParameterListener("chorus_centre", this); - parameters.addParameterListener("chorus_feedback", this); - parameters.addParameterListener("chorus_mix", this); - - sp.chorusRate = parameters.getRawParameterValue("chorus_rate"); - sp.chorusDepth = parameters.getRawParameterValue("chorus_depth"); - sp.chorusCentre = parameters.getRawParameterValue("chorus_centre"); - sp.chorusFeedback = parameters.getRawParameterValue("chorus_feedback"); - sp.chorusMix = parameters.getRawParameterValue("chorus_mix"); - - // === Delay === - parameters.addParameterListener("delay_delay", this); - sp.delayTime = parameters.getRawParameterValue("delay_delay"); - - // === Reverb === - parameters.addParameterListener("reverb_roomSize", this); - parameters.addParameterListener("reverb_damping", this); - parameters.addParameterListener("reverb_wetLevel", this); - parameters.addParameterListener("reverb_dryLevel", this); - parameters.addParameterListener("reverb_width", this); - parameters.addParameterListener("reverb_freezeMode", this); - - sp.reverbRoomSize = parameters.getRawParameterValue("reverb_roomSize"); - sp.reverbDamping = parameters.getRawParameterValue("reverb_damping"); - sp.reverbWetLevel = parameters.getRawParameterValue("reverb_wetLevel"); - sp.reverbDryLevel = parameters.getRawParameterValue("reverb_dryLevel"); - sp.reverbWidth = parameters.getRawParameterValue("reverb_width"); - sp.reverbFreezeMode = parameters.getRawParameterValue("reverb_freezeMode"); - - // === ADSR === - parameters.addParameterListener("adsr_attack", this); - parameters.addParameterListener("adsr_decay", this); - parameters.addParameterListener("adsr_sustain", this); - parameters.addParameterListener("adsr_release", this); - - sp.adsrAttack = parameters.getRawParameterValue("adsr_attack"); - sp.adsrDecay = parameters.getRawParameterValue("adsr_decay"); - sp.adsrSustain = parameters.getRawParameterValue("adsr_sustain"); - sp.adsrRelease = parameters.getRawParameterValue("adsr_release"); - - // === Flanger === - parameters.addParameterListener("flanger_rate", this); - parameters.addParameterListener("flanger_depth", this); - parameters.addParameterListener("flanger_feedback", this); - parameters.addParameterListener("flanger_dryMix", this); - parameters.addParameterListener("flanger_phase", this); - parameters.addParameterListener("flanger_delay", this); - - sp.flangerRate = parameters.getRawParameterValue("flanger_rate"); - sp.flangerDepth = parameters.getRawParameterValue("flanger_depth"); - sp.flangerFeedback = parameters.getRawParameterValue("flanger_feedback"); - sp.flangerDryMix = parameters.getRawParameterValue("flanger_dryMix"); - sp.flangerPhase = parameters.getRawParameterValue("flanger_phase"); - sp.flangerDelay = parameters.getRawParameterValue("flanger_delay"); - - // === Filter === - parameters.addParameterListener("filter_cutoff", this); - parameters.addParameterListener("filter_resonance", this); - parameters.addParameterListener("filter_type", this); - parameters.addParameterListener("filter_drive", this); - parameters.addParameterListener("filter_mod", this); - parameters.addParameterListener("filter_key", this); - - sp.filterCutoff = parameters.getRawParameterValue("filter_cutoff"); - sp.filterResonance = parameters.getRawParameterValue("filter_resonance"); - sp.filterType = parameters.getRawParameterValue("filter_type"); - sp.filterDrive = parameters.getRawParameterValue("filter_drive"); - sp.filterMod = parameters.getRawParameterValue("filter_mod"); - sp.filterKey = parameters.getRawParameterValue("filter_key"); - - // === Distortion === - parameters.addParameterListener("distortion_drive", this); - parameters.addParameterListener("distortion_mix", this); - parameters.addParameterListener("distortion_bias", this); - parameters.addParameterListener("distortion_tone", this); - parameters.addParameterListener("distortion_shape", this); - - sp.distortionDrive = parameters.getRawParameterValue("distortion_drive"); - sp.distortionMix = parameters.getRawParameterValue("distortion_mix"); - sp.distortionBias = parameters.getRawParameterValue("distortion_bias"); - sp.distortionTone = parameters.getRawParameterValue("distortion_tone"); - sp.distortionShape = parameters.getRawParameterValue("distortion_shape"); - - - - parameters.addParameterListener("master", this); - parameters.addParameterListener("lowEQ", this); - parameters.addParameterListener("midEQ", this); - parameters.addParameterListener("highEQ", this); - - sp.masterDbls = parameters.getRawParameterValue("master"); - sp.lowGainDbls = parameters.getRawParameterValue("lowEQ"); - sp.midGainDbls = parameters.getRawParameterValue("midEQ"); - sp.highGainDbls = parameters.getRawParameterValue("highEQ"); -} - -NeuralSynthAudioProcessor::~NeuralSynthAudioProcessor() -{ -} - -//============================================================================== -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(); -} - -void NeuralSynthAudioProcessor::buildParams(std::vector> ¶ms, const std::string& paramGroup) { - const auto& paramGroupSettings = PARAM_SETTINGS.at(paramGroup); - - for (const auto& [name, paramSettings] : paramGroupSettings) { - params.push_back(std::make_unique(paramGroup + "_" + name, paramSettings.label, - juce::NormalisableRange(paramSettings.min, paramSettings.max, paramSettings.interval), - paramSettings.defValue)); - } -} - -juce::AudioProcessorValueTreeState::ParameterLayout NeuralSynthAudioProcessor::createParameterLayout() -{ - std::vector> params; - - params.push_back(std::make_unique( - "waveform", "Waveform", - juce::StringArray{ "Sine", "Saw", "Square", "Triangle" }, 0)); - - buildParams(params, "adsr"); - buildParams(params, "chorus"); - buildParams(params, "delay"); - buildParams(params, "reverb"); - buildParams(params, "flanger"); - buildParams(params, "distortion"); - buildParams(params, "filter"); - - params.push_back(std::make_unique("master", "Master", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.1f)); - - params.push_back(std::make_unique("lowEQ", "Low Gain", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.5f)); - params.push_back(std::make_unique("midEQ", "Mid EQ", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.8f)); - params.push_back(std::make_unique("highEQ", "High EQ", - juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 1.0f)); - - return { params.begin(), params.end() }; -} \ No newline at end of file +#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); + // Wavetable params + sp.wtOn = parameters.getRawParameterValue("wt_on"); + sp.wtMorph = parameters.getRawParameterValue("wt_morph"); + + // === Per-panel bypass (default OFF) === + sp.chorusOn = parameters.getRawParameterValue("chorus_on"); + sp.delayOn = parameters.getRawParameterValue("delay_on"); + sp.reverbOn = parameters.getRawParameterValue("reverb_on"); + sp.flangerOn = parameters.getRawParameterValue("flanger_on"); + sp.distortionOn = parameters.getRawParameterValue("distortion_on"); + sp.filterOn = parameters.getRawParameterValue("filter_on"); + sp.eqOn = parameters.getRawParameterValue("eq_on"); + + // === Chorus === + parameters.addParameterListener("chorus_rate", this); + parameters.addParameterListener("chorus_depth", this); + parameters.addParameterListener("chorus_centre", this); + parameters.addParameterListener("chorus_feedback", this); + parameters.addParameterListener("chorus_mix", this); + + sp.chorusRate = parameters.getRawParameterValue("chorus_rate"); + sp.chorusDepth = parameters.getRawParameterValue("chorus_depth"); + sp.chorusCentre = parameters.getRawParameterValue("chorus_centre"); + sp.chorusFeedback = parameters.getRawParameterValue("chorus_feedback"); + sp.chorusMix = parameters.getRawParameterValue("chorus_mix"); + + // === Delay === + parameters.addParameterListener("delay_delay", this); + sp.delayTime = parameters.getRawParameterValue("delay_delay"); + + // === Reverb === + parameters.addParameterListener("reverb_roomSize", this); + parameters.addParameterListener("reverb_damping", this); + parameters.addParameterListener("reverb_wetLevel", this); + parameters.addParameterListener("reverb_dryLevel", this); + parameters.addParameterListener("reverb_width", this); + parameters.addParameterListener("reverb_freezeMode", this); + + sp.reverbRoomSize = parameters.getRawParameterValue("reverb_roomSize"); + sp.reverbDamping = parameters.getRawParameterValue("reverb_damping"); + sp.reverbWetLevel = parameters.getRawParameterValue("reverb_wetLevel"); + sp.reverbDryLevel = parameters.getRawParameterValue("reverb_dryLevel"); + sp.reverbWidth = parameters.getRawParameterValue("reverb_width"); + sp.reverbFreezeMode= parameters.getRawParameterValue("reverb_freezeMode"); + + // === Amp ADSR === + parameters.addParameterListener("adsr_attack", this); + parameters.addParameterListener("adsr_decay", this); + parameters.addParameterListener("adsr_sustain", this); + parameters.addParameterListener("adsr_release", this); + + sp.adsrAttack = parameters.getRawParameterValue("adsr_attack"); + sp.adsrDecay = parameters.getRawParameterValue("adsr_decay"); + sp.adsrSustain = parameters.getRawParameterValue("adsr_sustain"); + sp.adsrRelease = parameters.getRawParameterValue("adsr_release"); + + // === Filter Env === + parameters.addParameterListener("fenv_attack", this); + parameters.addParameterListener("fenv_decay", this); + parameters.addParameterListener("fenv_sustain", this); + parameters.addParameterListener("fenv_release", this); + parameters.addParameterListener("fenv_amount", this); + + sp.fenvAttack = parameters.getRawParameterValue("fenv_attack"); + sp.fenvDecay = parameters.getRawParameterValue("fenv_decay"); + sp.fenvSustain = parameters.getRawParameterValue("fenv_sustain"); + sp.fenvRelease = parameters.getRawParameterValue("fenv_release"); + sp.fenvAmount = parameters.getRawParameterValue("fenv_amount"); + + // === Filter base === + parameters.addParameterListener("filter_cutoff", this); + parameters.addParameterListener("filter_resonance", this); + parameters.addParameterListener("filter_type", this); + parameters.addParameterListener("filter_drive", this); + parameters.addParameterListener("filter_mod", this); + parameters.addParameterListener("filter_key", this); + + sp.filterCutoff = parameters.getRawParameterValue("filter_cutoff"); + sp.filterResonance = parameters.getRawParameterValue("filter_resonance"); + sp.filterType = parameters.getRawParameterValue("filter_type"); + sp.filterDrive = parameters.getRawParameterValue("filter_drive"); + sp.filterMod = parameters.getRawParameterValue("filter_mod"); + sp.filterKey = parameters.getRawParameterValue("filter_key"); + + // === Distortion === + parameters.addParameterListener("distortion_drive", this); + parameters.addParameterListener("distortion_mix", this); + parameters.addParameterListener("distortion_bias", this); + parameters.addParameterListener("distortion_tone", this); + parameters.addParameterListener("distortion_shape", this); + + sp.distortionDrive = parameters.getRawParameterValue("distortion_drive"); + sp.distortionMix = parameters.getRawParameterValue("distortion_mix"); + sp.distortionBias = parameters.getRawParameterValue("distortion_bias"); + sp.distortionTone = parameters.getRawParameterValue("distortion_tone"); + sp.distortionShape = parameters.getRawParameterValue("distortion_shape"); + + // === Master / EQ === + parameters.addParameterListener("master", this); + parameters.addParameterListener("lowEQ", this); + parameters.addParameterListener("midEQ", this); + parameters.addParameterListener("highEQ", this); + + sp.masterDbls = parameters.getRawParameterValue("master"); + sp.lowGainDbls = parameters.getRawParameterValue("lowEQ"); + sp.midGainDbls = parameters.getRawParameterValue("midEQ"); + sp.highGainDbls = parameters.getRawParameterValue("highEQ"); +} + +NeuralSynthAudioProcessor::~NeuralSynthAudioProcessor() = default; + +//============================================================================== +const juce::String NeuralSynthAudioProcessor::getName() const { return JucePlugin_Name; } + +bool NeuralSynthAudioProcessor::acceptsMidi() const +{ + #if JucePlugin_WantsMidiInput + return true; + #else + return false; + #endif +} + +bool NeuralSynthAudioProcessor::producesMidi() const +{ + #if JucePlugin_ProducesMidiOutput + return true; + #else + return false; + #endif +} + +bool NeuralSynthAudioProcessor::isMidiEffect() const +{ + #if JucePlugin_IsMidiEffect + return true; + #else + return false; + #endif +} + +double NeuralSynthAudioProcessor::getTailLengthSeconds() const { return 0.0; } + +int NeuralSynthAudioProcessor::getNumPrograms() { return 1; } +int NeuralSynthAudioProcessor::getCurrentProgram() { return 0; } +void NeuralSynthAudioProcessor::setCurrentProgram (int) {} +const juce::String NeuralSynthAudioProcessor::getProgramName (int) { return {}; } +void NeuralSynthAudioProcessor::changeProgramName (int, const juce::String&) {} + +//============================================================================== +void NeuralSynthAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) +{ + audioEngine.prepare({ sampleRate, (juce::uint32)samplesPerBlock, 2 }); +} + +void NeuralSynthAudioProcessor::releaseResources() {} + +bool NeuralSynthAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const +{ + if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() + && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo()) + return false; + + return true; +} + +void NeuralSynthAudioProcessor::processBlock(juce::AudioSampleBuffer& buffer, juce::MidiBuffer& midiMessages) +{ + const int newWaveform = sp.waveform.exchange(-1); + + if (newWaveform != -1) { + audioEngine.applyToVoices([newWaveform](NeuralSynthVoice* v) + { + v->changeWaveform(newWaveform); + }); + } + + juce::ScopedNoDenormals noDenormals; + auto totalNumInputChannels = getTotalNumInputChannels(); + auto totalNumOutputChannels = getTotalNumOutputChannels(); + + for (int i = totalNumInputChannels; i < totalNumOutputChannels; ++i) + buffer.clear(i, 0, buffer.getNumSamples()); + + audioEngine.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples()); + scopeDataCollector.process(buffer.getReadPointer(0), (size_t)buffer.getNumSamples()); +} + +//============================================================================== +bool NeuralSynthAudioProcessor::hasEditor() const { return true; } + +juce::AudioProcessorEditor* NeuralSynthAudioProcessor::createEditor() +{ + return new NeuralSynthAudioProcessorEditor (*this); +} + +//============================================================================== +void NeuralSynthAudioProcessor::getStateInformation (juce::MemoryBlock& destData) { juce::ignoreUnused(destData); } +void NeuralSynthAudioProcessor::setStateInformation (const void* data, int sizeInBytes) { juce::ignoreUnused(data, sizeInBytes); } + +void NeuralSynthAudioProcessor::parameterChanged(const juce::String& id, float newValue) +{ + juce::ignoreUnused(newValue); + if (id == "waveform") + sp.waveform.store((int)newValue, std::memory_order_release); +} + +//============================================================================== +// This creates new instances of the plugin.. +juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { return new NeuralSynthAudioProcessor(); } + +void NeuralSynthAudioProcessor::buildParams(std::vector>& params, const std::string& paramGroup) { + const auto& paramGroupSettings = PARAM_SETTINGS.at(paramGroup); + + for (const auto& [name, s] : paramGroupSettings) { + params.push_back(std::make_unique( + paramGroup + "_" + name, s.label, + juce::NormalisableRange(s.min, s.max, s.interval), + s.defValue)); + } +} + +juce::AudioProcessorValueTreeState::ParameterLayout NeuralSynthAudioProcessor::createParameterLayout() +{ + std::vector> params; + + params.push_back(std::make_unique( + "waveform", "Waveform", + juce::StringArray{ "Sine", "Saw", "Square", "Triangle" }, 0)); + // --- Wavetable on/off + morph position (0..15) --- + params.push_back(std::make_unique("wt_on", "Wavetable On", true)); + params.push_back(std::make_unique( + "wt_morph", "WT Morph", + juce::NormalisableRange(0.0f, 15.0f, 0.001f), 0.0f)); + + + // Per-panel bypass toggles (default OFF) + params.push_back(std::make_unique("chorus_on", "Chorus On", false)); + params.push_back(std::make_unique("delay_on", "Delay On", false)); + params.push_back(std::make_unique("reverb_on", "Reverb On", false)); + params.push_back(std::make_unique("flanger_on", "Flanger On", false)); + params.push_back(std::make_unique("distortion_on", "Distortion On", false)); + params.push_back(std::make_unique("filter_on", "Filter On", false)); + params.push_back(std::make_unique("eq_on", "EQ On", false)); + + buildParams(params, "adsr"); + buildParams(params, "fenv"); + buildParams(params, "chorus"); + buildParams(params, "delay"); + buildParams(params, "reverb"); + buildParams(params, "flanger"); + buildParams(params, "distortion"); + buildParams(params, "filter"); + + params.push_back(std::make_unique("master", "Master", + juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.1f)); + + params.push_back(std::make_unique("lowEQ", "Low Gain", + juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.5f)); + params.push_back(std::make_unique("midEQ", "Mid EQ", + juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 0.8f)); + params.push_back(std::make_unique("highEQ", "High EQ", + juce::NormalisableRange(-24.0f, 24.0f, 0.1f), 1.0f)); + + return { params.begin(), params.end() }; +} diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 3e95a2a..c5eafb6 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -1,101 +1,90 @@ -/* - ============================================================================== - - This file contains the basic framework code for a JUCE plugin processor. - - ============================================================================== -*/ - -#pragma once - -#include -#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; - bool isBusesLayoutSupported(const BusesLayout& layouts) const; - -#ifndef JucePlugin_PreferredChannelConfigurations - bool isBusesLayoutSupported(const BusesLayout& layouts) const override; -#endif - - void processBlock(juce::AudioBuffer&, 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; - - void buildParams(std::vector>& params, const std::string& paramGroup); - - juce::MidiMessageCollector& getMidiMessageCollector() noexcept { return midiMessageCollector; } - - juce::MidiMessageCollector midiMessageCollector; - juce::AudioProcessorValueTreeState parameters; - juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout(); - - AudioBufferQueue& getAudioBufferQueue() noexcept { return audioBufferQueue; } - - AudioBufferQueue& getChorusAudioBufferQueue() noexcept { return chorusBufferQueue; } - AudioBufferQueue& getDelayAudioBufferQueue() noexcept { return delayBufferQueue; } - AudioBufferQueue& getReverbAudioBufferQueue() noexcept { return reverbBufferQueue; } - - AudioBufferQueue& getFlangerAudioBufferQueue() noexcept { return flangerBufferQueue; } - AudioBufferQueue& getDistortionAudioBufferQueue() noexcept { return distortionBufferQueue; } - AudioBufferQueue& getFilterAudioBufferQueue() noexcept { return filterBufferQueue; } - -private: - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NeuralSynthAudioProcessor) - - NeuralAudioEngine audioEngine; - AudioBufferQueue audioBufferQueue; - - AudioBufferQueue chorusBufferQueue; - AudioBufferQueue delayBufferQueue; - AudioBufferQueue reverbBufferQueue; - - AudioBufferQueue flangerBufferQueue; - AudioBufferQueue distortionBufferQueue; - AudioBufferQueue filterBufferQueue; - - ScopeDataCollector scopeDataCollector{ audioBufferQueue }; - - NeuralSharedParams sp; -}; +#pragma once + +#include +#include "AudioBufferQueue.h" +#include "AudioEngine.h" +#include "ScopeDataCollector.h" +#include "NeuralSharedParams.h" + +//============================================================================== +// Processor +class NeuralSynthAudioProcessor : public juce::AudioProcessor, + private juce::AudioProcessorValueTreeState::Listener +{ +public: + NeuralSynthAudioProcessor(); + ~NeuralSynthAudioProcessor() override; + + // AudioProcessor overrides + void prepareToPlay(double sampleRate, int samplesPerBlock) override; + void releaseResources() override; + +#ifndef JucePlugin_PreferredChannelConfigurations + bool isBusesLayoutSupported(const BusesLayout& layouts) const override; +#endif + + void processBlock(juce::AudioBuffer&, juce::MidiBuffer&) override; + + // Editor + juce::AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; + + // Info + const juce::String getName() const override; + bool acceptsMidi() const override; + bool producesMidi() const override; + bool isMidiEffect() const override; + double getTailLengthSeconds() const override; + + // Programs + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram(int index) override; + const juce::String getProgramName(int index) override; + void changeProgramName(int index, const juce::String& newName) override; + + // State + void getStateInformation(juce::MemoryBlock& destData) override; + void setStateInformation(const void* data, int sizeInBytes) override; + + // Parameters + void parameterChanged(const juce::String& id, float newValue) override; + void buildParams(std::vector>& params, + const std::string& paramGroup); + juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout(); + + // Utilities + juce::MidiMessageCollector& getMidiMessageCollector() noexcept { return midiMessageCollector; } + AudioBufferQueue& getAudioBufferQueue() noexcept { return audioBufferQueue; } + + AudioBufferQueue& getChorusAudioBufferQueue() noexcept { return chorusBufferQueue; } + AudioBufferQueue& getDelayAudioBufferQueue() noexcept { return delayBufferQueue; } + AudioBufferQueue& getReverbAudioBufferQueue() noexcept { return reverbBufferQueue; } + AudioBufferQueue& getFlangerAudioBufferQueue() noexcept { return flangerBufferQueue; } + AudioBufferQueue& getDistortionAudioBufferQueue() noexcept { return distortionBufferQueue; } + AudioBufferQueue& getFilterAudioBufferQueue() noexcept { return filterBufferQueue; } + + // Public members (by JUCE convention) + juce::MidiMessageCollector midiMessageCollector; + juce::AudioProcessorValueTreeState parameters; + +private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralSynthAudioProcessor) + + // ---- IMPORTANT ORDER FIX ---- + // Objects are constructed in THIS order. 'sp' must come BEFORE audioEngine. + NeuralSharedParams sp; // <— construct first + NeuralAudioEngine audioEngine; // needs a valid reference to 'sp' + + // Meter/scope queues + AudioBufferQueue audioBufferQueue; + AudioBufferQueue chorusBufferQueue; + AudioBufferQueue delayBufferQueue; + AudioBufferQueue reverbBufferQueue; + AudioBufferQueue flangerBufferQueue; + AudioBufferQueue distortionBufferQueue; + AudioBufferQueue filterBufferQueue; + + // Scope collector (uses audioBufferQueue, so declare after it) + ScopeDataCollector scopeDataCollector { audioBufferQueue }; +};