commit b2b7a6d72cb03d833ac0a88f4ebcbb6a58bedd32
parent 8095754ad2c94f93e8e3e9cb50622866d39cf01d
Author: keith <kbloemer89@gmail.com>
Date: Thu, 12 Aug 2021 06:24:59 -0500
Added Delay and Reverb using juce dsp class
Diffstat:
8 files changed, 446 insertions(+), 9 deletions(-)
diff --git a/NeuralPi.jucer b/NeuralPi.jucer
@@ -17,6 +17,7 @@
<FILE id="VgCJPH" name="AmpOSCReceiver.h" compile="0" resource="0"
file="Source/AmpOSCReceiver.h"/>
<FILE id="HvJFu8" name="CabSim.h" compile="0" resource="0" file="Source/CabSim.h"/>
+ <FILE id="gT1tOY" name="Delay.h" compile="0" resource="0" file="Source/Delay.h"/>
<FILE id="s1HQuK" name="Eq4Band.cpp" compile="1" resource="0" file="Source/Eq4Band.cpp"/>
<FILE id="xtLEtv" name="Eq4Band.h" compile="0" resource="0" file="Source/Eq4Band.h"/>
<FILE id="hNjQV9" name="PluginEditor.cpp" compile="1" resource="0"
diff --git a/Source/AmpOSCReceiver.h b/Source/AmpOSCReceiver.h
@@ -54,6 +54,16 @@ public:
return irValue;
}
+ Value& getDelayValue()
+ {
+ return delayValue;
+ }
+
+ Value& getReverbValue()
+ {
+ return reverbValue;
+ }
+
void changePort (int port)
{
if (! connect (port))
@@ -90,6 +100,8 @@ private:
presenceAddressPattern = "/parameter/" + ampName + "/Presence";
modelAddressPattern = "/parameter/" + ampName + "/Model";
irAddressPattern = "/parameter/" + ampName + "/Ir";
+ reverbAddressPattern = "/parameter/" + ampName + "/Reverb";
+ delayAddressPattern = "/parameter/" + ampName + "/Delay";
}
void oscMessageReceived(const OSCMessage& message) override
@@ -134,7 +146,14 @@ private:
{
irValue.setValue(jlimit(0.0f, 1.0f, message[0].getFloat32()));
}
-
+ else if (message.getAddressPattern().matches(reverbAddressPattern))
+ {
+ reverbValue.setValue(jlimit(0.0f, 1.0f, message[0].getFloat32()));
+ }
+ else if (message.getAddressPattern().matches(delayAddressPattern))
+ {
+ delayValue.setValue(jlimit(0.0f, 1.0f, message[0].getFloat32()));
+ }
}
}
@@ -149,6 +168,8 @@ private:
String presenceAddressPattern {"/parameter/elk_juce_example/Presence"};
String modelAddressPattern {"/parameter/elk_juce_example/Model"};
String irAddressPattern {"/parameter/elk_juce_example/Ir"};
+ String delayAddressPattern {"/parameter/elk_juce_example/Delay"};
+ String reverbAddressPattern {"/parameter/elk_juce_example/Reverb"};
Value gainValue {0.5f};
Value masterValue {0.5f};
@@ -160,6 +181,9 @@ private:
Value modelValue {0.0f};
Value irValue {0.0f};
+ Value delayValue {0.0f};
+ Value reverbValue {0.0f};
+
bool connected = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AmpOSCReceiver)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
@@ -2,6 +2,7 @@
target_sources(NeuralPi PRIVATE
AmpOSCReceiver.h
+ Delay.h
Eq4Band.cpp
Eq4Band.h
PluginEditor.cpp
diff --git a/Source/Delay.h b/Source/Delay.h
@@ -0,0 +1,215 @@
+/*
+ ==============================================================================
+
+ Delay
+
+ ==============================================================================
+*/
+#include "../JuceLibraryCode/JuceHeader.h"
+
+#pragma once
+
+//==============================================================================
+template <typename Type>
+class DelayLine
+{
+public:
+ void clear() noexcept
+ {
+ std::fill (rawData.begin(), rawData.end(), Type (0));
+ }
+
+ size_t size() const noexcept
+ {
+ return rawData.size();
+ }
+
+ void resize (size_t newValue)
+ {
+ rawData.resize (newValue);
+ leastRecentIndex = 0;
+ }
+
+ Type back() const noexcept
+ {
+ return rawData[leastRecentIndex];
+ }
+
+ Type get (size_t delayInSamples) const noexcept
+ {
+ jassert (delayInSamples >= 0 && delayInSamples < size());
+
+ return rawData[(leastRecentIndex + 1 + delayInSamples) % size()]; // [3]
+ }
+
+ /** Set the specified sample in the delay line */
+ void set (size_t delayInSamples, Type newValue) noexcept
+ {
+ jassert (delayInSamples >= 0 && delayInSamples < size());
+
+ rawData[(leastRecentIndex + 1 + delayInSamples) % size()] = newValue; // [4]
+ }
+
+ /** Adds a new value to the delay line, overwriting the least recently added sample */
+ void push (Type valueToAdd) noexcept
+ {
+ rawData[leastRecentIndex] = valueToAdd; // [1]
+ leastRecentIndex = leastRecentIndex == 0 ? size() - 1 : leastRecentIndex - 1; // [2]
+ }
+
+private:
+ std::vector<Type> rawData;
+ size_t leastRecentIndex = 0;
+};
+
+//==============================================================================
+template <typename Type, size_t maxNumChannels = 2>
+class Delay
+{
+public:
+ //==============================================================================
+ Delay()
+ {
+ setMaxDelayTime (2.0f);
+ setDelayTime (0, 0.7f);
+ setDelayTime (1, 0.5f);
+ setWetLevel (0.8f);
+ setFeedback (0.5f);
+ }
+
+ //==============================================================================
+ void prepare (const juce::dsp::ProcessSpec& spec)
+ {
+ jassert (spec.numChannels <= maxNumChannels);
+ sampleRate = (Type) spec.sampleRate;
+ updateDelayLineSize();
+ updateDelayTime();
+
+ //filterCoefs = juce::dsp::IIR::Coefficients<Type>::makeFirstOrderLowPass (sampleRate, Type (1e3));
+ filterCoefs = juce::dsp::IIR::Coefficients<Type>::makeFirstOrderHighPass (sampleRate, Type (1e3));
+
+ for (auto& f : filters)
+ {
+ f.prepare (spec);
+ f.coefficients = filterCoefs;
+ }
+ }
+
+ //==============================================================================
+ void reset() noexcept
+ {
+ for (auto& f : filters)
+ f.reset(); // [5]
+
+ for (auto& dline : delayLines)
+ dline.clear(); // [6]
+ }
+
+ //==============================================================================
+ size_t getNumChannels() const noexcept
+ {
+ return delayLines.size();
+ }
+
+ //==============================================================================
+ void setMaxDelayTime (Type newValue)
+ {
+ jassert (newValue > Type (0));
+ maxDelayTime = newValue;
+ updateDelayLineSize(); // [1]
+ }
+
+ //==============================================================================
+ void setFeedback (Type newValue) noexcept
+ {
+ jassert (newValue >= Type (0) && newValue <= Type (1));
+ feedback = newValue;
+ }
+
+ //==============================================================================
+ void setWetLevel (Type newValue) noexcept
+ {
+ jassert (newValue >= Type (0) && newValue <= Type (1));
+ wetLevel = newValue;
+ }
+
+ //==============================================================================
+ void setDelayTime (size_t channel, Type newValue)
+ {
+ if (channel >= getNumChannels())
+ {
+ jassertfalse;
+ return;
+ }
+
+ jassert (newValue >= Type (0));
+ delayTimes[channel] = newValue;
+
+ updateDelayTime(); // [3]
+ }
+
+ //==============================================================================
+ template <typename ProcessContext>
+ void process (const ProcessContext& context) noexcept
+ {
+ auto& inputBlock = context.getInputBlock();
+ auto& outputBlock = context.getOutputBlock();
+ auto numSamples = outputBlock.getNumSamples();
+ auto numChannels = outputBlock.getNumChannels();
+
+ jassert (inputBlock.getNumSamples() == numSamples);
+ jassert (inputBlock.getNumChannels() == numChannels);
+
+ for (size_t ch = 0; ch < numChannels; ++ch)
+ {
+ auto* input = inputBlock .getChannelPointer (ch);
+ auto* output = outputBlock.getChannelPointer (ch);
+ auto& dline = delayLines[ch];
+ auto delayTime = delayTimesSample[ch];
+ auto& filter = filters[ch];
+
+ for (size_t i = 0; i < numSamples; ++i)
+ {
+ //auto delayedSample = dline.get (delayTime);
+ auto delayedSample = filter.processSample (dline.get (delayTime));
+ auto inputSample = input[i];
+ auto dlineInputSample = std::tanh (inputSample + feedback * delayedSample);
+ dline.push (dlineInputSample);
+ auto outputSample = inputSample + wetLevel * delayedSample;
+ output[i] = outputSample;
+ }
+ }
+ }
+
+private:
+ //==============================================================================
+ std::array<DelayLine<Type>, maxNumChannels> delayLines;
+ std::array<size_t, maxNumChannels> delayTimesSample;
+ std::array<Type, maxNumChannels> delayTimes;
+ Type feedback { Type (0) };
+ Type wetLevel { Type (0) };
+
+ std::array<juce::dsp::IIR::Filter<Type>, maxNumChannels> filters;
+ typename juce::dsp::IIR::Coefficients<Type>::Ptr filterCoefs;
+
+ Type sampleRate { Type (44.1e3) };
+ Type maxDelayTime { Type (2) };
+
+ //==============================================================================
+ void updateDelayLineSize()
+ {
+ auto delayLineSizeSamples = (size_t) std::ceil (maxDelayTime * sampleRate);
+
+ for (auto& dline : delayLines)
+ dline.resize (delayLineSizeSamples); // [2]
+ }
+
+ //==============================================================================
+ void updateDelayTime() noexcept
+ {
+ for (size_t ch = 0; ch < maxNumChannels; ++ch)
+ delayTimesSample[ch] = (size_t) juce::roundToInt (delayTimes[ch] * sampleRate);
+ }
+
+ JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Delay)
+};
+\ No newline at end of file
diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp
@@ -381,6 +381,82 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
}
};
+ addAndMakeVisible(ampDelayKnob);
+ ampDelayKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
+ ampDelayKnob.setNumDecimalPlacesToDisplay(1);
+ ampDelayKnob.addListener(this);
+ ampDelayKnob.setRange(0.0, 1.0);
+ ampDelayKnob.setValue(0.0);
+ ampDelayKnob.setSliderStyle(juce::Slider::SliderStyle::RotaryVerticalDrag);
+ ampDelayKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
+ ampDelayKnob.setNumDecimalPlacesToDisplay(2);
+ ampDelayKnob.setDoubleClickReturnValue(true, 0.0);
+
+ auto delayValue = getParameterValue(delayName);
+ Slider& delaySlider = getDelaySlider();
+ delaySlider.setValue(delayValue, NotificationType::dontSendNotification);
+
+ ampDelayKnob.onValueChange = [this]
+ {
+ const float sliderValue = static_cast<float> (getDelaySlider().getValue());
+ const float delayValue = getParameterValue(delayName);
+
+ if (!approximatelyEqual(delayValue, sliderValue))
+ {
+ setParameterValue(delayName, sliderValue);
+
+ // create and send an OSC message with an address and a float value:
+ float value = static_cast<float> (getDelaySlider().getValue());
+
+ if (!oscSender.send(delayAddressPattern, value))
+ {
+ updateOutConnectedLabel(false);
+ }
+ else
+ {
+ DBG("Sent value " + String(value) + " to AP " + delayAddressPattern);
+ }
+ }
+ };
+
+ addAndMakeVisible(ampReverbKnob);
+ ampReverbKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
+ ampReverbKnob.setNumDecimalPlacesToDisplay(1);
+ ampReverbKnob.addListener(this);
+ ampReverbKnob.setRange(0.0, 1.0);
+ ampReverbKnob.setValue(0.0);
+ ampReverbKnob.setSliderStyle(juce::Slider::SliderStyle::RotaryVerticalDrag);
+ ampReverbKnob.setTextBoxStyle(juce::Slider::TextEntryBoxPosition::TextBoxBelow, false, 50, 20);
+ ampReverbKnob.setNumDecimalPlacesToDisplay(2);
+ ampReverbKnob.setDoubleClickReturnValue(true, 0.0);
+
+ auto reverbValue = getParameterValue(reverbName);
+ Slider& reverbSlider = getReverbSlider();
+ reverbSlider.setValue(reverbValue, NotificationType::dontSendNotification);
+
+ ampReverbKnob.onValueChange = [this]
+ {
+ const float sliderValue = static_cast<float> (getReverbSlider().getValue());
+ const float reverbValue = getParameterValue(reverbName);
+
+ if (!approximatelyEqual(reverbValue, sliderValue))
+ {
+ setParameterValue(reverbName, sliderValue);
+
+ // create and send an OSC message with an address and a float value:
+ float value = static_cast<float> (getReverbSlider().getValue());
+
+ if (!oscSender.send(reverbAddressPattern, value))
+ {
+ updateOutConnectedLabel(false);
+ }
+ else
+ {
+ DBG("Sent value " + String(value) + " to AP " + reverbAddressPattern);
+ }
+ }
+ };
+
addAndMakeVisible(GainLabel);
GainLabel.setText("Gain", juce::NotificationType::dontSendNotification);
GainLabel.setJustificationType(juce::Justification::centred);
@@ -401,6 +477,13 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
PresenceLabel.setText("Presence", juce::NotificationType::dontSendNotification);
PresenceLabel.setJustificationType(juce::Justification::centred);
+ addAndMakeVisible(DelayLabel);
+ DelayLabel.setText("Delay", juce::NotificationType::dontSendNotification);
+ DelayLabel.setJustificationType(juce::Justification::centred);
+ addAndMakeVisible(ReverbLabel);
+ ReverbLabel.setText("Reverb", juce::NotificationType::dontSendNotification);
+ ReverbLabel.setJustificationType(juce::Justification::centred);
+
auto font = GainLabel.getFont();
float height = font.getHeight();
font.setHeight(height); // 0.75);
@@ -410,6 +493,8 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
MidLabel.setFont(font);
TrebleLabel.setFont(font);
PresenceLabel.setFont(font);
+ DelayLabel.setFont(font);
+ ReverbLabel.setFont(font);
// Name controls:
addAndMakeVisible(ampNameLabel);
@@ -456,7 +541,7 @@ NeuralPiAudioProcessorEditor::NeuralPiAudioProcessorEditor (NeuralPiAudioProcess
connectSender();
// Size of plugin GUI
- setSize(260, 455);
+ setSize(345, 455);
}
NeuralPiAudioProcessorEditor::~NeuralPiAudioProcessorEditor()
@@ -481,12 +566,12 @@ void NeuralPiAudioProcessorEditor::resized()
{
// This is generally where you'll want to lay out the positions of any
// subcomponents in your editor..
- modelSelect.setBounds(11, 10, 234, 25);
- loadButton.setBounds(19, 74, 100, 25);
+ modelSelect.setBounds(11, 10, 270, 25);
+ loadButton.setBounds(11, 74, 100, 25);
modelKnob.setBounds(140, 40, 75, 95);
- irSelect.setBounds(11, 42, 234, 25);
- loadIR.setBounds(125, 74, 100, 25);
+ irSelect.setBounds(11, 42, 270, 25);
+ loadIR.setBounds(120, 74, 100, 25);
irButton.setBounds(248, 42, 257, 25);
lstmButton.setBounds(248, 10, 257, 25);
@@ -496,14 +581,20 @@ void NeuralPiAudioProcessorEditor::resized()
ampBassKnob.setBounds(10, 250, 75, 95);
ampMidKnob.setBounds(95, 250, 75, 95);
ampTrebleKnob.setBounds(180, 250, 75, 95);
- ampPresenceKnob.setBounds(180, 120, 75, 95);
+ ampPresenceKnob.setBounds(265, 250, 75, 95);
+
+ ampDelayKnob.setBounds(180, 120, 75, 95);
+ ampReverbKnob.setBounds(265, 120, 75, 95);
GainLabel.setBounds(6, 108, 80, 10);
LevelLabel.setBounds(93, 108, 80, 10);
BassLabel.setBounds(6, 238, 80, 10);
MidLabel.setBounds(91, 238, 80, 10);
TrebleLabel.setBounds(178, 238, 80, 10);
- PresenceLabel.setBounds(178, 108, 80, 10);
+ PresenceLabel.setBounds(265, 238, 80, 10);
+
+ DelayLabel.setBounds(178, 108, 80, 10);
+ ReverbLabel.setBounds(265, 108, 80, 10);
addAndMakeVisible(ampNameLabel);
ampNameField.setEditable(true, true, true);
@@ -681,6 +772,16 @@ Slider& NeuralPiAudioProcessorEditor::getPresenceSlider()
return ampPresenceKnob;
}
+Slider& NeuralPiAudioProcessorEditor::getDelaySlider()
+{
+ return ampDelayKnob;
+}
+
+Slider& NeuralPiAudioProcessorEditor::getReverbSlider()
+{
+ return ampReverbKnob;
+}
+
Slider& NeuralPiAudioProcessorEditor::getModelSlider()
{
return modelKnob;
@@ -730,6 +831,8 @@ void NeuralPiAudioProcessorEditor::buildAddressPatterns()
midAddressPattern = "/parameter/" + ampName + "/Mid";
trebleAddressPattern = "/parameter/" + ampName + "/Treble";
presenceAddressPattern = "/parameter/" + ampName + "/Presence";
+ delayAddressPattern = "/parameter/" + ampName + "/Delay";
+ reverbAddressPattern = "/parameter/" + ampName + "/Reverb";
modelAddressPattern = "/parameter/" + ampName + "/Model";
irAddressPattern = "/parameter/" + ampName + "/Ir";
}
@@ -863,6 +966,22 @@ void NeuralPiAudioProcessorEditor::valueChanged(Value& value)
NotificationType::sendNotification);
}
}
+ if (value.refersToSameSourceAs(oscReceiver.getDelayValue()))
+ {
+ if (!approximatelyEqual(static_cast<double> (value.getValue()), getDelaySlider().getValue()))
+ {
+ getDelaySlider().setValue(static_cast<double> (value.getValue()),
+ NotificationType::sendNotification);
+ }
+ }
+ else if (value.refersToSameSourceAs(oscReceiver.getReverbValue()))
+ {
+ if (!approximatelyEqual(static_cast<double> (value.getValue()), getReverbSlider().getValue()))
+ {
+ getReverbSlider().setValue(static_cast<double> (value.getValue()),
+ NotificationType::sendNotification);
+ }
+ }
else if (value.refersToSameSourceAs(oscReceiver.getModelValue()))
{
if (!approximatelyEqual(static_cast<double> (value.getValue()), getModelSlider().getValue()))
@@ -889,6 +1008,8 @@ void NeuralPiAudioProcessorEditor::timerCallback()
getMidSlider().setValue(getParameterValue(midName), NotificationType::dontSendNotification);
getTrebleSlider().setValue(getParameterValue(trebleName), NotificationType::dontSendNotification);
getPresenceSlider().setValue(getParameterValue(presenceName), NotificationType::dontSendNotification);
+ getDelaySlider().setValue(getParameterValue(delayName), NotificationType::dontSendNotification);
+ getReverbSlider().setValue(getParameterValue(reverbName), NotificationType::dontSendNotification);
getModelSlider().setValue(getParameterValue(modelName), NotificationType::dontSendNotification);
getIrSlider().setValue(getParameterValue(irName), NotificationType::dontSendNotification);
}
diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h
@@ -51,6 +51,8 @@ public:
String midAddressPattern{ "/parameter/NeuralPi/Mid" };
String trebleAddressPattern{ "/parameter/NeuralPi/Treble" };
String presenceAddressPattern{ "/parameter/NeuralPi/Presence" };
+ String delayAddressPattern{ "/parameter/NeuralPi/Delay" };
+ String reverbAddressPattern{ "/parameter/NeuralPi/Reverb" };
const String gainName{ "gain" };
const String masterName{ "master" };
@@ -58,6 +60,8 @@ public:
const String midName{ "mid" };
const String trebleName{ "treble" };
const String presenceName{ "presence" };
+ const String delayName{ "delay" };
+ const String reverbName{ "reverb" };
const String modelName{ "model" };
const String irName{ "ir" };
@@ -82,6 +86,8 @@ private:
Slider ampMidKnob;
Slider ampTrebleKnob;
Slider ampPresenceKnob;
+ Slider ampDelayKnob;
+ Slider ampReverbKnob;
Label GainLabel;
Label LevelLabel;
@@ -89,6 +95,8 @@ private:
Label MidLabel;
Label TrebleLabel;
Label PresenceLabel;
+ Label DelayLabel;
+ Label ReverbLabel;
File test_file;
File model_folder;
@@ -137,6 +145,8 @@ private:
Slider& getMidSlider();
Slider& getTrebleSlider();
Slider& getPresenceSlider();
+ Slider& getDelaySlider();
+ Slider& getReverbSlider();
Label& getOutPortNumberField();
Label& getInPortNumberField();
diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp
@@ -52,6 +52,8 @@ NeuralPiAudioProcessor::NeuralPiAudioProcessor()
addParameter(presenceParam = new AudioParameterFloat(PRESENCE_ID, PRESENCE_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.01f), 0.5f));
addParameter(modelParam = new AudioParameterFloat(MODEL_ID, MODEL_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.001f), 0.0f));
addParameter(irParam = new AudioParameterFloat(IR_ID, IR_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.001f), 0.0f));
+ addParameter(delayParam = new AudioParameterFloat(DELAY_ID, DELAY_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.001f), 0.0f));
+ addParameter(reverbParam = new AudioParameterFloat(REVERB_ID, REVERB_NAME, NormalisableRange<float>(0.0f, 1.0f, 0.001f), 0.0f));
}
@@ -135,6 +137,9 @@ void NeuralPiAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlo
// Set up IR
cabSimIR.prepare(spec);
+
+ // fx chain
+ fxChain.prepare(spec);
}
void NeuralPiAudioProcessor::releaseResources()
@@ -177,6 +182,9 @@ void NeuralPiAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffe
const int numInputChannels = getTotalNumInputChannels();
const int sampleRate = getSampleRate();
+ auto block = dsp::AudioBlock<float>(buffer).getSingleChannelBlock(0);
+ auto context = juce::dsp::ProcessContextReplacing<float>(block);
+
// Amp =============================================================================
if (amp_state == 1) {
auto gain = static_cast<float> (gainParam->get());
@@ -187,6 +195,9 @@ void NeuralPiAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffe
auto treble = (static_cast<float> (trebleParam->get() - 0.5) * 24.0);
auto presence = (static_cast<float> (presenceParam->get() - 0.5) * 24.0);
+ auto delay = (static_cast<float> (delayParam->get()));
+ auto reverb = (static_cast<float> (reverbParam->get()));
+
auto model = static_cast<float> (modelParam->get());
model_index = getModelIndex(model);
@@ -221,9 +232,16 @@ void NeuralPiAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffe
}
// Master Volume
- buffer.applyGain(master * 1.5);
+ buffer.applyGain(master);
+
+ // Process Delay, and Reverb
+ set_delayParams(delay);
+ set_reverbParams(reverb);
+ fxChain.process(context);
}
+
+
// process DC blocker
auto monoBlock = dsp::AudioBlock<float>(buffer).getSingleChannelBlock(0);
dcBlocker.process(dsp::ProcessContextReplacing<float>(monoBlock));
@@ -256,6 +274,8 @@ void NeuralPiAudioProcessor::getStateInformation(MemoryBlock& destData)
stream.writeFloat(*presenceParam);
stream.writeFloat(*modelParam);
stream.writeFloat(*irParam);
+ stream.writeFloat(*delayParam);
+ stream.writeFloat(*reverbParam);
}
void NeuralPiAudioProcessor::setStateInformation(const void* data, int sizeInBytes)
@@ -270,6 +290,8 @@ void NeuralPiAudioProcessor::setStateInformation(const void* data, int sizeInByt
presenceParam->setValueNotifyingHost(stream.readFloat());
modelParam->setValueNotifyingHost(stream.readFloat());
irParam->setValueNotifyingHost(stream.readFloat());
+ delayParam->setValueNotifyingHost(stream.readFloat());
+ reverbParam->setValueNotifyingHost(stream.readFloat());
}
int NeuralPiAudioProcessor::getModelIndex(float model_param)
@@ -461,6 +483,28 @@ void NeuralPiAudioProcessor::set_ampEQ(float bass_slider, float mid_slider, floa
eq4band.setParameters(bass_slider, mid_slider, treble_slider, presence_slider);
}
+void NeuralPiAudioProcessor::set_delayParams(float paramValue)
+{
+ auto& del = fxChain.template get<delayIndex>();
+ del.setWetLevel(paramValue);
+ del.setDelayTime(0, paramValue);
+ del.setFeedback(paramValue);
+}
+
+
+void NeuralPiAudioProcessor::set_reverbParams(float paramValue)
+{
+ auto& rev = fxChain.template get<reverbIndex>();
+ rev_params = rev.getParameters();
+
+ // Sets reverb params as a function of a single reverb param value ( 0.0 to 1.0)
+ rev_params.wetLevel = paramValue;
+ rev_params.damping = 1.0 - paramValue; // decay is inverse of damping
+ rev_params.roomSize= paramValue;
+
+ rev.setParameters(rev_params);
+}
+
float NeuralPiAudioProcessor::convertLogScale(float in_value, float x_min, float x_max, float y_min, float y_max)
{
float b = log(y_max / y_min) / (x_max - x_min);
diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h
@@ -13,6 +13,7 @@
#include "AmpOSCReceiver.h"
#include "Eq4Band.h"
#include "CabSim.h"
+#include "Delay.h"
#pragma once
@@ -34,6 +35,10 @@
#define TREBLE_NAME "Treble"
#define PRESENCE_ID "presence"
#define PRESENCE_NAME "Presence"
+#define DELAY_ID "delay"
+#define DELAY_NAME "Delay"
+#define REVERB_ID "reverb"
+#define REVERB_NAME "Reverb"
//==============================================================================
/**
@@ -86,6 +91,8 @@ public:
void installTones();
void set_ampEQ(float bass_slider, float mid_slider, float treble_slider, float presence_slider);
+ void set_delayParams(float paramValue);
+ void set_reverbParams(float paramValue);
float convertLogScale(float in_value, float x_min, float x_max, float y_min, float y_max);
@@ -125,6 +132,8 @@ public:
RT_LSTM LSTM;
+ juce::dsp::Reverb::Parameters rev_params;
+
private:
var dummyVar;
Eq4Band eq4band; // Amp EQ
@@ -137,12 +146,23 @@ private:
AudioParameterFloat* presenceParam;
AudioParameterFloat* modelParam;
AudioParameterFloat* irParam;
+ AudioParameterFloat* delayParam;
+ AudioParameterFloat* reverbParam;
dsp::IIR::Filter<float> dcBlocker;
// IR processing
CabSim cabSimIR;
+ // Effects
+ enum
+ {
+ delayIndex,
+ reverbIndex
+ };
+
+ juce::dsp::ProcessorChain<Delay<float>, juce::dsp::Reverb> fxChain;
+
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NeuralPiAudioProcessor)
};