Prechádzať zdrojové kódy

Merged eq/dist and chorus/delay/reverb parts

LuigiBiasi-Athenagroup 6 mesiacov pred
rodič
commit
71d2e50e1c

+ 96 - 0
JUCE/CMLSProject/Source/CMLSChorus.cpp

@@ -0,0 +1,96 @@
+/*
+  ==============================================================================
+
+    CMLSChorus.cpp
+    Created: 1 May 2025 11:04:18pm
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#include "CMLSChorus.h"
+
+CMLSChorus::CMLSChorus() {
+    freqRange = new juce::NormalisableRange<float>(LFO_MIN_FREQ, LFO_MAX_FREQ);
+    depthRange = new juce::NormalisableRange<float>(LFO_MIN_DEPTH, LFO_MAX_DEPTH);
+}
+
+CMLSChorus::~CMLSChorus() {}
+
+void CMLSChorus::reset() {
+    delayLine1.reset();
+    delayLine2.reset();
+    dryWetMixer.reset();
+}
+
+void CMLSChorus::prepare(const juce::dsp::ProcessSpec& spec) {
+    delayLine1.prepare(spec);
+    delayLine2.prepare(spec);
+    delayLine1.setMix(1.0f);
+    delayLine2.setMix(1.0f);
+
+    delayLine1.setCentreDelay(DELAY_CENTER);
+    delayLine2.setCentreDelay(DELAY_CENTER);
+    delayLine1.setRate(LFO_MIN_FREQ);
+    delayLine1.setRate(LFO_MIN_FREQ + LFO_FREQ_DELTA);
+    delayLine1.setDepth(LFO_MIN_DEPTH);
+    delayLine2.setDepth(LFO_MIN_FREQ);
+
+    dryWetMixer.prepare(spec);
+    dryWetMixer.setMixingRule(juce::dsp::DryWetMixingRule::linear);
+}
+
+void CMLSChorus::process(const juce::dsp::ProcessContextReplacing<float>& context) {
+	auto audioBlock = context.getOutputBlock();
+	auto numChannels = audioBlock.getNumChannels();
+    const auto numSamples = audioBlock.getNumSamples();
+
+    // Initialize audio buffers
+    juce::AudioBuffer<float> firstStageWetBuffer(numChannels, numSamples);
+	juce::dsp::AudioBlock<float> firstStageWetBlock(firstStageWetBuffer);
+
+	juce::AudioBuffer<float> secondStageWetBuffer(numChannels, numSamples);
+	juce::dsp::AudioBlock<float> secondStageWetBlock(secondStageWetBuffer);
+
+    // Calculate wet signal
+    delayLine1.process(
+        juce::dsp::ProcessContextNonReplacing<float>(audioBlock, firstStageWetBlock)
+    );
+	delayLine2.process(
+		juce::dsp::ProcessContextNonReplacing<float>(audioBlock, secondStageWetBlock)
+	);
+
+    secondStageWetBlock += firstStageWetBlock;
+
+	// Apply the dry/wet mix
+    dryWetMixer.pushDrySamples(audioBlock);
+    dryWetMixer.mixWetSamples(secondStageWetBlock);
+
+    for (int channel = 0; channel < numChannels; ++channel) {
+        for (int sample = 0; sample < numSamples; ++sample) {
+            audioBlock.setSample(channel, sample, secondStageWetBlock.getSample(channel, sample));
+        }
+    }
+}
+
+void CMLSChorus::setDryWet(float value) {
+    dryWetMixer.setWetMixProportion(value);
+}
+
+void CMLSChorus::setAmount(float value) {
+    float freq = freqRange->convertFrom0to1(value);
+    float depth = depthRange->convertFrom0to1(value);
+
+    delayLine1.setRate(freq);
+    delayLine2.setRate(freq); //+ LFO_FREQ_DELTA
+    delayLine1.setDepth(depth);
+    delayLine2.setDepth(depth);
+}
+
+const float CMLSChorus::getDryWet() {
+	return this->dryWetProp;
+}
+
+const float CMLSChorus::getAmount() {
+	return this->amount;
+}

+ 47 - 0
JUCE/CMLSProject/Source/CMLSChorus.h

@@ -0,0 +1,47 @@
+/*
+  ==============================================================================
+
+    CMLSChorus.h
+    Created: 1 May 2025 11:04:18pm
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#pragma once
+
+#include <JuceHeader.h>
+
+#define DELAY_CENTER 0.015 // Center for delay in seconds
+#define LFO_MIN_FREQ 0.0f // Minimum frequency of the LFO
+#define LFO_MAX_FREQ 5.0f // Maximum frequency of the LFO
+#define LFO_FREQ_DELTA 0.3f // Frequency delta between the two LFOs
+#define LFO_MIN_DEPTH 0.0f // Minimum depth of the LFO
+#define LFO_MAX_DEPTH 5.0f // Maximum depth of the LFO
+
+class CMLSChorus : public juce::dsp::ProcessorBase {
+    public:
+		CMLSChorus();
+		~CMLSChorus() override;
+
+        void reset() override;
+        void prepare(const juce::dsp::ProcessSpec&);
+        void process(const juce::dsp::ProcessContextReplacing<float>&);
+
+        // Parameter getters and setters
+        void setDryWet(float value);
+        void setAmount(float value);
+
+        const float getDryWet();
+        const float getAmount();
+
+    private:
+        float dryWetProp = 0.0;
+		float amount = 0.0;
+
+        juce::dsp::Chorus<float> delayLine1; // 1st chorus delayline
+        juce::dsp::Chorus<float> delayLine2; // 2nd chorus delayline
+        juce::dsp::DryWetMixer<float> dryWetMixer; // Dry/Wet mixer
+        juce::NormalisableRange<float>* freqRange; // Range for LFOs frequencies
+        juce::NormalisableRange<float>* depthRange; // Range for LFOs depth
+};

+ 98 - 0
JUCE/CMLSProject/Source/CMLSDelay.cpp

@@ -0,0 +1,98 @@
+/*
+  ==============================================================================
+
+    CMLSDelay.cpp
+    Created: 3 May 2025 5:39:35pm
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#include "CMLSDelay.h"
+
+CMLSDelay::CMLSDelay() {
+	delayLengthRange = new juce::NormalisableRange<float>(0, MAX_DELAY_LENGTH);
+	feedbackRange = new juce::NormalisableRange<float>(MIN_FEEDBACK, MAX_FEEDBACK);
+
+	this->delayLength = 0.0f;
+	this->feedback = 0.0f;
+	this->amount = 0.0f;
+	this->dryWetProp = 0.0f;
+}
+
+CMLSDelay::~CMLSDelay() {}
+
+void CMLSDelay::reset() {
+}
+
+void CMLSDelay::prepare(const juce::dsp::ProcessSpec& spec) {
+	this->effectDelaySamples = spec.sampleRate * MAX_DELAY_LENGTH;
+	this->delayLine.setMaximumDelayInSamples(this->effectDelaySamples);
+	this->linearDelay.setMaximumDelayInSamples(this->effectDelaySamples);
+
+	this->delayLine.prepare(spec);
+	this->linearDelay.prepare(spec);
+	this->mixer.prepare(spec);
+
+	for (auto& volume : this->delayFeedbackVolume) {
+		volume.reset(spec.sampleRate, 0.05f);
+	}
+
+	this->mixer.reset();
+	this->mixer.setMixingRule(juce::dsp::DryWetMixingRule::linear);
+
+	std::fill(this->delayValue.begin(), this->delayValue.end(), 0.0f);
+	std::fill(this->lastDelayOutput.begin(), this->lastDelayOutput.end(), 0.0f);
+}
+
+void CMLSDelay::process(const juce::dsp::ProcessContextReplacing<float>& context) {
+	auto audioBlock = context.getOutputBlock();
+	auto numChannels = audioBlock.getNumChannels();
+	const auto numSamples = audioBlock.getNumSamples();
+
+	const auto& input = context.getInputBlock();
+	const auto& output = context.getOutputBlock();
+
+	this->mixer.pushDrySamples(input);
+
+	for (size_t channel = 0; channel < numChannels; ++channel) {
+		auto* samplesIn = input.getChannelPointer(channel);
+		auto* samplesOut = output.getChannelPointer(channel);
+
+		for (size_t sample = 0; sample < input.getNumSamples(); ++sample) {
+			auto input = samplesIn[sample] - this->lastDelayOutput[channel];
+			auto delayAmount = this->delayValue[channel];
+
+			this->linearDelay.pushSample(channel, input);
+			this->linearDelay.setDelay(delayAmount);
+			samplesOut[sample] = this->linearDelay.popSample(channel);
+
+			this->lastDelayOutput[channel] = samplesOut[sample] * this->delayFeedbackVolume[channel].getNextValue();
+		}
+	}
+
+	this->mixer.mixWetSamples(output);
+}
+
+void CMLSDelay::setDryWet(float value) {
+	this->dryWetProp = value;
+	this->mixer.setWetMixProportion(this->dryWetProp);
+}
+
+void CMLSDelay::setAmount(float value) {
+	this->delayLength = this->delayLengthRange->convertFrom0to1(value);
+	this->feedback = this->feedbackRange->convertFrom0to1(value);
+
+	std::fill(this->delayValue.begin(), this->delayValue.end(), this->delayLength * this->effectDelaySamples);
+	for (auto& volume : this->delayFeedbackVolume) {
+		volume.setTargetValue(this->feedback);
+	}
+}
+
+const float CMLSDelay::getDryWet() {
+	return this->dryWetProp;
+}
+
+const float CMLSDelay::getAmount() {
+	return this->amount;
+}

+ 56 - 0
JUCE/CMLSProject/Source/CMLSDelay.h

@@ -0,0 +1,56 @@
+/*
+  ==============================================================================
+
+    CMLSDelay.h
+    Created: 3 May 2025 5:39:35pm
+    Author:  Luigi
+	Ref. https://github.com/flipbug/simple-delay/tree/master
+
+  ==============================================================================
+*/
+
+#pragma once
+#include <JuceHeader.h>
+
+#define MAX_DELAY_LENGTH 1.0f // Maximum delay time in seconds
+#define MIN_FEEDBACK -100.0f
+#define MAX_FEEDBACK 0.0f
+
+class CMLSDelay : public juce::dsp::ProcessorBase
+{
+	public:
+		CMLSDelay();
+		~CMLSDelay() override;
+
+		void reset() override;
+		void prepare(const juce::dsp::ProcessSpec&) override;
+		void process(const juce::dsp::ProcessContextReplacing<float>&) override;
+	
+		// Parameter getters and setters
+		void setDryWet(float value);
+		void setAmount(float value);
+		const float getDryWet();
+		const float getAmount();
+
+	private:
+		float effectDelaySamples;
+
+		//Paramters
+		float dryWetProp;
+		float feedback;
+		float delayLength;
+		float amount;
+
+		// Normaliosable range
+		juce::NormalisableRange<float>* delayLengthRange;
+		juce::NormalisableRange<float>* feedbackRange;
+
+		//Delay Lines
+		juce::dsp::DelayLine<float> delayLine;
+		juce::dsp::DelayLine<float, juce::dsp::DelayLineInterpolationTypes::Linear> linearDelay;
+		juce::dsp::DryWetMixer<float> mixer;
+
+		std::array<float, 2> delayValue;
+		std::array<float, 2> lastDelayOutput;
+		std::array<juce::LinearSmoothedValue<float>, 2> delayFeedbackVolume;
+};

+ 40 - 0
JUCE/CMLSProject/Source/CMLSDistortion.cpp

@@ -0,0 +1,40 @@
+#include "CMLSDistortion.h"
+
+CMLSDistortion::CMLSDistortion() {}
+
+void CMLSDistortion::prepare(const juce::dsp::ProcessSpec& spec) {
+    inputGain.prepare(spec);
+    outputGain.prepare(spec);
+    inputGain.setGainDecibels(0.0f);
+    outputGain.setGainDecibels(0.0f);
+}
+
+void CMLSDistortion::reset() {
+    inputGain.reset();
+    outputGain.reset();
+}
+
+void CMLSDistortion::process(const juce::dsp::ProcessContextReplacing<float>& context) {
+    auto& block = context.getOutputBlock();
+    inputGain.process(context);
+
+    for (size_t ch = 0; ch < block.getNumChannels(); ++ch) {
+        auto* data = block.getChannelPointer(ch);
+        for (size_t i = 0; i < block.getNumSamples(); ++i) {
+            float dry = data[i];
+            float wet = std::tanh(data[i] * drive);  // soft clipping
+            data[i] = dry * (1.0f - mix) + wet * mix; // apply mix
+        }
+    }
+
+    outputGain.process(context);
+}
+
+void CMLSDistortion::setDrive(float newDrive) {
+    drive = newDrive;
+}
+
+void CMLSDistortion::setMix(float newMix)
+{
+    mix = juce::jlimit(0.0f, 1.0f, newMix); // between 0.0 and 1.0
+}

+ 23 - 0
JUCE/CMLSProject/Source/CMLSDistortion.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include <JuceHeader.h>
+
+class CMLSDistortion : public juce::dsp::ProcessorBase {
+public:
+    CMLSDistortion();
+    ~CMLSDistortion() override = default;
+
+    void prepare(const juce::dsp::ProcessSpec&) override;
+    void reset() override;
+    void process(const juce::dsp::ProcessContextReplacing<float>&) override;
+
+    void setDrive(float drive); // controls intensity
+    void setMix(float mix);     // controls the dry/wet mix ratio,how much of the distorted signal is mixed with the original signal
+                                // 0.0 = dry, 1.0 = full distortion
+
+private:
+    float drive = 1.0f;
+    float mix = 1.0f;
+
+    juce::dsp::Gain<float> inputGain, outputGain;
+};

+ 36 - 0
JUCE/CMLSProject/Source/CMLSEqualizer.cpp

@@ -0,0 +1,36 @@
+#include "CMLSEqualizer.h"
+
+CMLSEqualizer::CMLSEqualizer() {}
+
+void CMLSEqualizer::prepare(const juce::dsp::ProcessSpec& spec) {
+    sampleRate = spec.sampleRate;
+
+    lowBand.prepare(spec);
+    highBand.prepare(spec);
+
+    lowBand.reset();
+    highBand.reset();
+
+    setEqLowGain(0.0f);
+    setEqHighGain(0.0f);
+}
+
+void CMLSEqualizer::reset() {
+    lowBand.reset();
+    highBand.reset();
+}
+
+void CMLSEqualizer::process(const juce::dsp::ProcessContextReplacing<float>& context) {
+    lowBand.process(context);
+    highBand.process(context);
+}
+
+void CMLSEqualizer::setEqLowGain(float gain) {
+    *lowBand.state = *juce::dsp::IIR::Coefficients<float>::makeLowShelf(
+        sampleRate, 200.0f, 0.7f, juce::Decibels::decibelsToGain(gain));
+}
+
+void CMLSEqualizer::setEqHighGain(float gain) {
+    *highBand.state = *juce::dsp::IIR::Coefficients<float>::makeHighShelf(
+        sampleRate, 5000.0f, 0.7f, juce::Decibels::decibelsToGain(gain));
+}

+ 21 - 0
JUCE/CMLSProject/Source/CMLSEqualizer.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include <JuceHeader.h>
+
+class CMLSEqualizer : public juce::dsp::ProcessorBase {
+public:
+    CMLSEqualizer();
+    ~CMLSEqualizer() override = default;
+
+    void prepare(const juce::dsp::ProcessSpec&) override;
+    void reset() override;
+    void process(const juce::dsp::ProcessContextReplacing<float>&) override;
+
+    void setEqLowGain(float);
+    void setEqHighGain(float);
+
+private:
+    double sampleRate = 44100.0; // default, will be updated
+    juce::dsp::ProcessorDuplicator<juce::dsp::IIR::Filter<float>,
+        juce::dsp::IIR::Coefficients<float>> lowBand, highBand;
+};

+ 70 - 0
JUCE/CMLSProject/Source/CMLSProcessorChain.cpp

@@ -0,0 +1,70 @@
+/*
+  ==============================================================================
+
+    CMLSProcessorChain.cpp
+    Created: 12 May 2025 10:05:40am
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#include "CMLSProcessorChain.h"
+
+CMLSProcessorChain::CMLSProcessorChain()
+{}
+
+CMLSProcessorChain::~CMLSProcessorChain()
+{}
+
+void CMLSProcessorChain::reset()
+{
+	for (auto& processor : chain)
+	{
+		if (processor)
+			processor->reset();
+	}
+}
+
+void CMLSProcessorChain::prepare(const juce::dsp::ProcessSpec& spec)
+{
+	for (auto& processor : chain)
+	{
+		if (processor)
+			processor->prepare(spec);
+	}
+}
+
+void CMLSProcessorChain::process(const juce::dsp::ProcessContextReplacing<float>& context)
+{
+	for (int i = 0; i < this->chain.size(); ++i)
+	{
+		if (this->chain[i] && this->slots[i] == true)
+			this->chain[i]->process(context);
+	}
+}
+
+int CMLSProcessorChain::pushProcessor(juce::dsp::ProcessorBase& processor)
+{
+	chain.push_back(&processor);
+	slots.push_back(true);
+	return chain.size() - 1;
+}
+
+void CMLSProcessorChain::muteProcessrInSlot(int slot)
+{
+	slots[slot] = false;
+}
+
+void CMLSProcessorChain::unmuteProcessrInSlot(int slot)
+{
+	slots[slot] = true;
+}
+
+void CMLSProcessorChain::swapPlaces(int slot1, int slot2)
+{
+	if (slot1 < 0 || slot2 < 0 || slot1 >= chain.size() || slot2 >= chain.size())
+		return;
+
+	std::swap(chain[slot1], chain[slot2]);
+	std::swap(slots[slot1], slots[slot2]);
+}

+ 32 - 0
JUCE/CMLSProject/Source/CMLSProcessorChain.h

@@ -0,0 +1,32 @@
+/*
+  ==============================================================================
+
+    CMLSProcessorChain.h
+    Created: 12 May 2025 10:05:40am
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#pragma once
+#include <JuceHeader.h>
+
+class CMLSProcessorChain
+{
+	public:
+		CMLSProcessorChain();
+		~CMLSProcessorChain();
+
+		void reset();
+		void prepare(const juce::dsp::ProcessSpec&);
+		void process(const juce::dsp::ProcessContextReplacing<float>&);
+		
+		int pushProcessor(juce::dsp::ProcessorBase& processor);
+		void muteProcessrInSlot(int slot);
+		void unmuteProcessrInSlot(int slot);
+		void swapPlaces(int slot1, int slot2);
+	
+	private:
+		std::vector<bool> slots;
+		std::vector<juce::dsp::ProcessorBase*> chain;
+};

+ 56 - 0
JUCE/CMLSProject/Source/CMLSReverb.cpp

@@ -0,0 +1,56 @@
+#include "CMLSReverb.h";
+
+CMLSReverb::CMLSReverb()
+{
+    // Default parameters declaration
+    this->reverbParams.dryLevel = 1.0f;
+	this->reverbParams.wetLevel = 0.0f;
+	this->reverbParams.roomSize = 0.0f;
+	this->reverbParams.damping = 0.5f;
+	this->reverbParams.width = 0.0f;
+
+	this->reverb.setParameters(this->reverbParams);
+}
+
+CMLSReverb::~CMLSReverb() {}
+
+void CMLSReverb::reset() {
+	this->reverb.reset();
+}
+
+void CMLSReverb::prepare(const juce::dsp::ProcessSpec& spec) {
+	this->reverb.setSampleRate(spec.sampleRate);
+}
+
+void CMLSReverb::process(const juce::dsp::ProcessContextReplacing<float>& context) {
+	juce::dsp::AudioBlock<float> buffer = context.getOutputBlock();
+    this->reverb.processStereo(buffer.getChannelPointer(0), buffer.getChannelPointer(1), buffer.getNumSamples());
+}
+
+void CMLSReverb::setDryWet(float value)
+{
+	// Set the dry/wet mix value
+	this->reverbParams.wetLevel = value;
+	this->reverbParams.dryLevel = 1.0f - value;
+    this->reverb.setParameters(this->reverbParams);
+}
+
+void CMLSReverb::setRoomSize(float value)
+{
+	// Set the room size value
+	this->reverbParams.roomSize = value;
+    this->reverbParams.width = value / 2;
+	this->reverb.setParameters(this->reverbParams);
+}
+
+const float CMLSReverb::getDryWet()
+{
+	// Get the dry/wet mix value
+	return this->reverbParams.wetLevel;
+}
+
+const float CMLSReverb::getRoomSize()
+{
+	// Get the room size value
+	return this->reverbParams.roomSize;
+}

+ 24 - 0
JUCE/CMLSProject/Source/CMLSReverb.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include <JuceHeader.h>
+
+class CMLSReverb : public juce::dsp::ProcessorBase {
+    public:
+        CMLSReverb();
+        ~CMLSReverb() override;
+
+	    void reset() override;
+        void prepare(const juce::dsp::ProcessSpec&) override;
+		void process(const juce::dsp::ProcessContextReplacing<float>&) override;
+
+        // Parameter setters
+        void setDryWet(float value);
+        void setRoomSize(float value);
+
+        // Parameter getters
+	    const float getDryWet();
+	    const float getRoomSize();
+    private:
+        juce::Reverb reverb;
+        juce::Reverb::Parameters reverbParams;
+};

+ 34 - 0
JUCE/CMLSProject/Source/OSCReceiverWrapper.cpp

@@ -0,0 +1,34 @@
+/*
+  ==============================================================================
+
+    OSCReceiverWrapper.cpp
+    Created: 5 May 2025 2:34:15pm
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#include "OSCReceiverWrapper.h"
+
+OSCReceiverWrapper::OSCReceiverWrapper(int port, juce::AudioProcessor* pluginProcessor) {
+    this->connect(port);
+	this->pluginProcessor = pluginProcessor;
+}
+
+OSCReceiverWrapper::~OSCReceiverWrapper() {}
+
+void OSCReceiverWrapper::oscMessageReceived(const juce::OSCMessage& message)
+{
+    if (!message.isEmpty() && message.size() == 1) {
+	    auto address = message.getAddressPattern().toString();
+        auto argument = message[0].getString();
+
+        // Interpret each message
+		if (address == "/") {
+            //this->pluginProcessor->getCallbackLock...
+        }
+    }
+}
+
+void OSCReceiverWrapper::oscConnectionError(const juce::String& errorMessage)
+{}

+ 25 - 0
JUCE/CMLSProject/Source/OSCReceiverWrapper.h

@@ -0,0 +1,25 @@
+/*
+  ==============================================================================
+
+    OSCReceiverWrapper.h
+    Created: 5 May 2025 2:34:15pm
+    Author:  Luigi
+
+  ==============================================================================
+*/
+
+#pragma once
+#include <JuceHeader.h>
+
+class OSCReceiverWrapper : public juce::OSCReceiver,
+    private juce::OSCReceiver::ListenerWithOSCAddress<juce::String>
+{
+    public:
+        OSCReceiverWrapper(int port, juce::AudioProcessor* pluginProcessor);
+        ~OSCReceiverWrapper();
+
+		void oscMessageReceived(const juce::OSCMessage& message) override;
+		void oscConnectionError(const juce::String& errorMessage);
+    private:
+		juce::AudioProcessor* pluginProcessor;
+};

+ 187 - 0
JUCE/CMLSProject/Source/PluginEditor.cpp

@@ -0,0 +1,187 @@
+/*
+  ==============================================================================
+
+    This file contains the basic framework code for a JUCE plugin editor.
+
+  ==============================================================================
+*/
+
+#include "PluginProcessor.h"
+#include "PluginEditor.h"
+
+//==============================================================================
+CMLSProjectAudioProcessorEditor::CMLSProjectAudioProcessorEditor (CMLSProjectAudioProcessor& p)
+    : AudioProcessorEditor (&p), audioProcessor (p)
+{
+    // Make sure that before the constructor has finished, you've set the
+    // editor's size to whatever you need it to be.
+    setSize (400, 300);
+
+    // Add aliders to the editor (Equalizer)
+    this->equalizerLowGainSlider.setRange(0.0, 1.0);
+    this->equalizerLowGainSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->equalizerLowGainSlider.addListener(this);
+    this->equalizerLowGainLabel.setText("Equalizer Low Gain", juce::dontSendNotification);
+
+    addAndMakeVisible(this->equalizerLowGainSlider);
+    addAndMakeVisible(this->equalizerLowGainLabel);
+
+    this->equalizerHighGainSlider.setRange(0.0, 1.0);
+    this->equalizerHighGainSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->equalizerHighGainSlider.addListener(this);
+    this->equalizerHighGainLabel.setText("Equalizer High Gain", juce::dontSendNotification);
+
+    addAndMakeVisible(this->equalizerHighGainSlider);
+    addAndMakeVisible(this->equalizerHighGainLabel);
+
+    // Add aliders to the editor (Distortion)
+    this->distortionDriveSlider.setRange(0.0, 1.0);
+    this->distortionDriveSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->distortionDriveSlider.addListener(this);
+    this->distortionDriveLabel.setText("Distortion Drive", juce::dontSendNotification);
+
+    addAndMakeVisible(this->distortionDriveSlider);
+    addAndMakeVisible(this->distortionDriveLabel);
+
+    this->distortionMixSlider.setRange(0.0, 1.0);
+    this->distortionMixSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->distortionMixSlider.addListener(this);
+    this->distortionMixLabel.setText("Distortion Mix", juce::dontSendNotification);
+
+    addAndMakeVisible(this->distortionMixSlider);
+    addAndMakeVisible(this->distortionMixLabel);
+
+	// Add aliders to the editor (Chorus)
+    this->chorusDryWetSlider.setRange(0.0, 1.0);
+    this->chorusDryWetSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->chorusDryWetSlider.addListener(this);
+    this->chorusDryWetLabel.setText("Chorus Dry/Wet", juce::dontSendNotification);
+
+    addAndMakeVisible(this->chorusDryWetSlider);
+    addAndMakeVisible(this->chorusDryWetLabel);
+
+    this->chorusAmountSlider.setRange(0.0, 1.0);
+    this->chorusAmountSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->chorusAmountSlider.addListener(this);
+    this->chorusAmountLabel.setText("Chorus Amount", juce::dontSendNotification);
+
+    addAndMakeVisible(this->chorusAmountSlider);
+    addAndMakeVisible(this->chorusAmountLabel);
+
+    // Add sliders to the editor (Reverb)
+    this->reverbDryWetSlider.setRange(0.0, 1.0);
+    this->reverbDryWetSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->reverbDryWetSlider.addListener(this);
+    this->reverbDryWetLabel.setText("Reverb Dry/Wet", juce::dontSendNotification);
+
+    addAndMakeVisible(this->reverbDryWetSlider);
+    addAndMakeVisible(this->reverbDryWetLabel);
+
+    this->reverbRoomSizeSlider.setRange(0.0, 1.0);
+    this->reverbRoomSizeSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->reverbRoomSizeSlider.addListener(this);
+    this->reverbRoomSizeLabel.setText("Reverb Room Size", juce::dontSendNotification);
+
+    addAndMakeVisible(this->reverbRoomSizeSlider);
+    addAndMakeVisible(this->reverbRoomSizeLabel);
+
+	// Add sliders to the editor (Delay)
+    this->delayDryWetSlider.setRange(0.0, 1.0);
+    this->delayDryWetSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->delayDryWetSlider.addListener(this);
+    this->delayDryWetLabel.setText("Delay Dry/Wet", juce::dontSendNotification);
+
+    addAndMakeVisible(this->delayDryWetSlider);
+    addAndMakeVisible(this->delayDryWetLabel);
+
+    this->delayAmountSlider.setRange(0.0, 1.0);
+    this->delayAmountSlider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 100, 20);
+    this->delayAmountSlider.addListener(this);
+    this->delayAmountLabel.setText("Delay Amount", juce::dontSendNotification);
+
+    addAndMakeVisible(this->delayAmountSlider);
+    addAndMakeVisible(this->delayAmountLabel);
+}
+
+CMLSProjectAudioProcessorEditor::~CMLSProjectAudioProcessorEditor()
+{
+}
+
+//==============================================================================
+void CMLSProjectAudioProcessorEditor::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));
+}
+
+void CMLSProjectAudioProcessorEditor::resized()
+{
+	//titleLabel.setBounds(10, 10, getWidth() - 20, 20);
+    equalizerLowGainSlider.setBounds(130, 10, getWidth() - 130, 20);
+    equalizerLowGainLabel.setBounds(10, 10, 100, 20);
+    equalizerHighGainSlider.setBounds(130, 30, getWidth() - 130, 20);
+    equalizerHighGainLabel.setBounds(10, 30, 100, 20);
+
+    distortionDriveSlider.setBounds(130, 70, getWidth() - 130, 20);
+    distortionDriveLabel.setBounds(10, 70, 100, 20);
+    distortionMixSlider.setBounds(130, 90, getWidth() - 130, 20);
+    distortionMixLabel.setBounds(10, 90, 100, 20);
+
+    chorusDryWetSlider.setBounds(130, 130, getWidth() - 130, 20);
+    chorusDryWetLabel.setBounds(10, 130, 100, 20);
+    chorusAmountSlider.setBounds(130, 150, getWidth() - 130, 20);
+	chorusAmountLabel.setBounds(10, 150, 100, 20);
+
+    reverbDryWetSlider.setBounds(130, 190, getWidth() - 130, 20);
+	reverbDryWetLabel.setBounds(10, 190, 100, 20);
+    reverbRoomSizeSlider.setBounds(130, 210, getWidth() - 130, 20);
+	reverbRoomSizeLabel.setBounds(10, 210, 100, 20);
+
+    delayDryWetSlider.setBounds(130, 250, getWidth() - 130, 20);
+	delayDryWetLabel.setBounds(10, 250, 100, 20);
+    delayAmountSlider.setBounds(130, 270, getWidth() - 130, 20);
+	delayAmountLabel.setBounds(10, 270, 100, 20);
+}
+
+void CMLSProjectAudioProcessorEditor::sliderValueChanged(juce::Slider* slider){
+	if (slider == &this->chorusDryWetSlider)
+	{
+		this->audioProcessor.setChorusDryWet(slider->getValue());
+	}
+	else if (slider == &this->chorusAmountSlider)
+	{
+		this->audioProcessor.setChorusAmount(slider->getValue());
+	}
+	else if (slider == &this->reverbDryWetSlider)
+	{
+		this->audioProcessor.setReverbDryWet(slider->getValue());
+	}
+	else if (slider == &this->reverbRoomSizeSlider)
+	{
+		this->audioProcessor.setReverbRoomSize(slider->getValue());
+	}
+	else if (slider == &this->delayDryWetSlider)
+	{
+		this->audioProcessor.setDelayDryWet(slider->getValue());
+	}
+	else if (slider == &this->delayAmountSlider)
+	{
+		this->audioProcessor.setDelayAmount(slider->getValue());
+	}
+    else if (slider == &this->equalizerLowGainSlider)
+    {
+        this->audioProcessor.setEqLowGain(slider->getValue());
+    }
+    else if (slider == &this->equalizerHighGainSlider)
+    {
+        this->audioProcessor.setEqHighGain(slider->getValue());
+    }
+    else if (slider == &this->distortionDriveSlider)
+    {
+        this->audioProcessor.setDistortionDrive(slider->getValue());
+    }
+    else if (slider == &this->distortionMixSlider)
+    {
+        this->audioProcessor.setDistortionMix(slider->getValue());
+    }
+}

+ 70 - 0
JUCE/CMLSProject/Source/PluginEditor.h

@@ -0,0 +1,70 @@
+/*
+  ==============================================================================
+
+    This file contains the basic framework code for a JUCE plugin editor.
+
+  ==============================================================================
+*/
+
+#pragma once
+
+#include <JuceHeader.h>
+#include "PluginProcessor.h"
+
+//==============================================================================
+/**
+*/
+class CMLSProjectAudioProcessorEditor  : public juce::AudioProcessorEditor,
+                                         public juce::Slider::Listener
+{
+public:
+    CMLSProjectAudioProcessorEditor (CMLSProjectAudioProcessor&);
+    ~CMLSProjectAudioProcessorEditor() 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.
+    CMLSProjectAudioProcessor& audioProcessor;
+
+    // Title
+	juce::Label titleLabel;
+
+    // Equalizer
+    juce::Slider equalizerLowGainSlider;
+    juce::Label equalizerLowGainLabel;
+    juce::Slider equalizerHighGainSlider;
+    juce::Label equalizerHighGainLabel;
+
+    // Distortion
+    juce::Slider distortionDriveSlider;
+    juce::Label distortionDriveLabel;
+    juce::Slider distortionMixSlider;
+    juce::Label distortionMixLabel;
+
+    // Chorus
+    juce::Slider chorusDryWetSlider;
+    juce::Label chorusDryWetLabel;
+    juce::Slider chorusAmountSlider;
+    juce::Label chorusAmountLabel;
+
+    // Reverb
+	juce::Slider reverbDryWetSlider;
+	juce::Label reverbDryWetLabel;
+	juce::Slider reverbRoomSizeSlider;
+	juce::Label reverbRoomSizeLabel;
+
+	// Delay
+	juce::Slider delayDryWetSlider;
+	juce::Label delayDryWetLabel;
+	juce::Slider delayAmountSlider;
+	juce::Label delayAmountLabel;
+
+    // Method to call when the slider value changes
+    void sliderValueChanged(juce::Slider* slider) override;
+
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CMLSProjectAudioProcessorEditor)
+};

+ 251 - 0
JUCE/CMLSProject/Source/PluginProcessor.cpp

@@ -0,0 +1,251 @@
+/*
+  ==============================================================================
+
+    This file contains the basic framework code for a JUCE plugin processor.
+
+  ==============================================================================
+*/
+
+#include "PluginProcessor.h"
+#include "PluginEditor.h"
+
+//==============================================================================
+CMLSProjectAudioProcessor::CMLSProjectAudioProcessor()
+#ifndef JucePlugin_PreferredChannelConfigurations
+     : AudioProcessor (BusesProperties()
+                     #if ! JucePlugin_IsMidiEffect
+                      #if ! JucePlugin_IsSynth
+                       .withInput  ("Input",  juce::AudioChannelSet::stereo(), true)
+                      #endif
+                       .withOutput ("Output", juce::AudioChannelSet::stereo(), true)
+                     #endif
+                       )
+#endif
+{
+    // Chaining the effects
+	this->equalizer = new CMLSEqualizer();
+    this->distortion = new CMLSDistortion();
+    this->chorus = new CMLSChorus();
+    this->delay = new CMLSDelay();
+    this->reverb = new CMLSReverb();
+
+    this->processorChain.pushProcessor(*equalizer);
+    this->processorChain.pushProcessor(*distortion);
+    this->processorChain.pushProcessor(*chorus);
+    this->processorChain.pushProcessor(*delay);
+    this->processorChain.pushProcessor(*reverb);
+
+    this->processorChain.reset();
+}
+
+CMLSProjectAudioProcessor::~CMLSProjectAudioProcessor()
+{
+}
+
+//==============================================================================
+const juce::String CMLSProjectAudioProcessor::getName() const
+{
+    return JucePlugin_Name;
+}
+
+bool CMLSProjectAudioProcessor::acceptsMidi() const
+{
+   #if JucePlugin_WantsMidiInput
+    return true;
+   #else
+    return false;
+   #endif
+}
+
+bool CMLSProjectAudioProcessor::producesMidi() const
+{
+   #if JucePlugin_ProducesMidiOutput
+    return true;
+   #else
+    return false;
+   #endif
+}
+
+bool CMLSProjectAudioProcessor::isMidiEffect() const
+{
+   #if JucePlugin_IsMidiEffect
+    return true;
+   #else
+    return false;
+   #endif
+}
+
+double CMLSProjectAudioProcessor::getTailLengthSeconds() const
+{
+    return 0.0;
+}
+
+int CMLSProjectAudioProcessor::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 CMLSProjectAudioProcessor::getCurrentProgram()
+{
+    return 0;
+}
+
+void CMLSProjectAudioProcessor::setCurrentProgram (int index)
+{
+}
+
+const juce::String CMLSProjectAudioProcessor::getProgramName (int index)
+{
+    return {};
+}
+
+void CMLSProjectAudioProcessor::changeProgramName (int index, const juce::String& newName)
+{
+}
+
+//==============================================================================
+void CMLSProjectAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
+{
+    // Use this method as the place to do any pre-playback
+    // initialisation that you need..
+    juce::dsp::ProcessSpec spec;
+    spec.maximumBlockSize = samplesPerBlock;
+    spec.numChannels = getTotalNumOutputChannels();
+    spec.sampleRate = sampleRate;
+
+	this->processorChain.prepare(spec);
+}
+
+void CMLSProjectAudioProcessor::releaseResources()
+{
+    // When playback stops, you can use this as an opportunity to free up any
+    // spare memory, etc.
+}
+
+#ifndef JucePlugin_PreferredChannelConfigurations
+bool CMLSProjectAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
+{
+  #if JucePlugin_IsMidiEffect
+    juce::ignoreUnused (layouts);
+    return true;
+  #else
+    // This is the place where you check if the layout is supported.
+    // In this template code we only support mono or stereo.
+    // Some plugin hosts, such as certain GarageBand versions, will only
+    // load plugins that support stereo bus layouts.
+    if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
+     && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
+        return false;
+
+    // This checks if the input layout matches the output layout
+   #if ! JucePlugin_IsSynth
+    if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
+        return false;
+   #endif
+
+    return true;
+  #endif
+}
+#endif
+
+void CMLSProjectAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
+{
+    juce::ScopedNoDenormals noDenormals;
+    auto totalNumInputChannels  = getTotalNumInputChannels();
+    auto totalNumOutputChannels = getTotalNumOutputChannels();
+
+    const auto numChannels = juce::jmax(totalNumInputChannels, totalNumOutputChannels);
+
+    auto audioBlock = juce::dsp::AudioBlock<float>(buffer).getSubsetChannelBlock(0, (int)numChannels);
+    auto context = juce::dsp::ProcessContextReplacing<float>(audioBlock);
+
+    /* Processing */
+	this->processorChain.process(context);
+}
+
+//==============================================================================
+bool CMLSProjectAudioProcessor::hasEditor() const
+{
+    return true; // (change this to false if you choose to not supply an editor)
+}
+
+juce::AudioProcessorEditor* CMLSProjectAudioProcessor::createEditor()
+{
+    return new CMLSProjectAudioProcessorEditor (*this);
+}
+
+//==============================================================================
+void CMLSProjectAudioProcessor::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 CMLSProjectAudioProcessor::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 CMLSProjectAudioProcessor::muteEffectInSlot(int slot) {
+    this->processorChain.muteProcessrInSlot(slot);
+}
+
+void CMLSProjectAudioProcessor::unmuteEffectInSlot(int slot) {
+    this->processorChain.unmuteProcessrInSlot(slot);
+}
+
+void CMLSProjectAudioProcessor::swapEffectInSlot(int slot1, int slot2) {
+	this->processorChain.swapPlaces(slot1, slot2);
+}
+
+void CMLSProjectAudioProcessor::setEqLowGain(float value) {
+	((CMLSEqualizer*)this->equalizer)->setEqLowGain(value);
+}
+
+void CMLSProjectAudioProcessor::setEqHighGain(float value) {
+    ((CMLSEqualizer*)this->equalizer)->setEqHighGain(value);
+}
+
+void CMLSProjectAudioProcessor::setDistortionDrive(float value) {
+    ((CMLSDistortion*)this->distortion)->setDrive(value);
+}
+
+void CMLSProjectAudioProcessor::setDistortionMix(float value) {
+	((CMLSDistortion*)this->distortion)->setMix(value);
+}
+
+void CMLSProjectAudioProcessor::setChorusDryWet(float value) {
+    //auto& instance = this->processorChain.template get<0>();
+	//instance.setDryWet(value);
+	((CMLSChorus*)this->chorus)->setDryWet(value);
+}
+
+void CMLSProjectAudioProcessor::setChorusAmount(float value) {
+	((CMLSChorus*)this->chorus)->setAmount(value);
+}
+
+void CMLSProjectAudioProcessor::setReverbDryWet(float value) {
+    ((CMLSReverb*)this->reverb)->setDryWet(value);
+}
+
+void CMLSProjectAudioProcessor::setReverbRoomSize(float value) {
+	((CMLSReverb*)this->reverb)->setRoomSize(value);
+}
+
+void CMLSProjectAudioProcessor::setDelayDryWet(float value) {
+    ((CMLSDelay*)this->delay)->setDryWet(value);
+}
+
+void CMLSProjectAudioProcessor::setDelayAmount(float value) {
+    ((CMLSDelay*)this->delay)->setAmount(value);
+}
+
+//==============================================================================
+// This creates new instances of the plugin..
+juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
+{
+    return new CMLSProjectAudioProcessor();
+}

+ 101 - 0
JUCE/CMLSProject/Source/PluginProcessor.h

@@ -0,0 +1,101 @@
+/*
+  ==============================================================================
+
+    This file contains the basic framework code for a JUCE plugin processor.
+
+  ==============================================================================
+*/
+
+#pragma once
+
+#include <JuceHeader.h>
+#include "CMLSReverb.h"
+#include "CMLSDelay.h"
+#include "CMLSChorus.h"
+#include "CMLSProcessorChain.h"
+#include "CMLSEqualizer.h"
+#include "CMLSDistortion.h"
+
+//==============================================================================
+/**
+*/
+class CMLSProjectAudioProcessor  : public juce::AudioProcessor
+{
+public:
+    //==============================================================================
+    CMLSProjectAudioProcessor();
+    ~CMLSProjectAudioProcessor() 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;
+
+    // Mute/unmute slot by number
+    void muteEffectInSlot(int slot);
+    void unmuteEffectInSlot(int slot);
+	void swapEffectInSlot(int slot1, int slot2);
+
+    // Parameter controls
+    void setEqLowGain(float value);
+    void setEqHighGain(float value);
+
+    void setDistortionDrive(float value);
+    void setDistortionMix(float value);
+
+	void setChorusDryWet(float value);
+	void setChorusAmount(float value);
+
+	void setReverbDryWet(float value);
+	void setReverbRoomSize(float value);
+
+	void setDelayDryWet(float value);
+	void setDelayAmount(float value);
+
+private:
+    //==============================================================================
+    
+    // OSC message receiver
+	juce::OSCReceiver oscReceiver;
+
+    // Buffer for the incoming audio from the generators
+
+    // Effects processing chain
+    juce::dsp::ProcessorBase* equalizer;
+	juce::dsp::ProcessorBase* distortion;
+    juce::dsp::ProcessorBase* chorus;
+    juce::dsp::ProcessorBase* delay;
+    juce::dsp::ProcessorBase* reverb;
+
+	CMLSProcessorChain processorChain;
+
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CMLSProjectAudioProcessor)
+};