瀏覽代碼

Full implementation of chorus, reverb and delay. Only final parameter review needed.

LuigiBiasi-Athenagroup 7 月之前
父節點
當前提交
012073cc69

+ 2 - 2
JUCE/CMLSProject/Source/CMLSChorus.cpp

@@ -83,8 +83,8 @@ void CMLSChorus::setAmount(float value) {
 
     delayLine1.setRate(freq);
     delayLine2.setRate(freq); //+ LFO_FREQ_DELTA
-    delayLine1.setDepth(0.2);
-    delayLine2.setDepth(0.2);
+    delayLine1.setDepth(depth);
+    delayLine2.setDepth(depth);
 }
 
 const float CMLSChorus::getDryWet() {

+ 1 - 1
JUCE/CMLSProject/Source/CMLSChorus.h

@@ -37,7 +37,7 @@ class CMLSChorus : juce::dsp::ProcessorBase {
 
     private:
         float dryWetProp = 0.0;
-		    float amount = 0.0;
+		float amount = 0.0;
 
         juce::dsp::Chorus<float> delayLine1; // 1st chorus delayline
         juce::dsp::Chorus<float> delayLine2; // 2nd chorus delayline

+ 38 - 34
JUCE/CMLSProject/Source/CMLSDelay.cpp

@@ -12,14 +12,12 @@
 
 CMLSDelay::CMLSDelay() {
 	delayLengthRange = new juce::NormalisableRange<float>(0, MAX_DELAY_LENGTH);
-	feedbackRange = new juce::NormalisableRange<float>(0, MAX_FEEDBACK);
+	feedbackRange = new juce::NormalisableRange<float>(MIN_FEEDBACK, MAX_FEEDBACK);
 
 	this->delayLength = 0.0f;
-	this->feedback = 0.75f;
-	this->delayBufferLength = 1;
-
-	this->delayReadPosition = 0;
-	this->delayWritePosition = 0;
+	this->feedback = 0.0f;
+	this->amount = 0.0f;
+	this->dryWetProp = 0.0f;
 }
 
 CMLSDelay::~CMLSDelay() {}
@@ -28,16 +26,23 @@ void CMLSDelay::reset() {
 }
 
 void CMLSDelay::prepare(const juce::dsp::ProcessSpec& spec) {
-	this->delayBufferLength = (int) 2.0 * spec.sampleRate;
-	
-	if (this->delayBufferLength < 1) {
-		this->delayBufferLength = 1;
+	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->delayBuffer.setSize(spec.numChannels, this->delayBufferLength);
-	this->delayBuffer.clear();
+	this->mixer.reset();
+	this->mixer.setMixingRule(juce::dsp::DryWetMixingRule::linear);
 
-	this->delayReadPosition = (int)(this->delayWritePosition - (this->delayLength * spec.sampleRate) + this->delayBufferLength) % this->delayBufferLength;
+	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) {
@@ -45,44 +50,43 @@ void CMLSDelay::process(const juce::dsp::ProcessContextReplacing<float>& context
 	auto numChannels = audioBlock.getNumChannels();
 	const auto numSamples = audioBlock.getNumSamples();
 
-	int dpr, dpw;
+	const auto& input = context.getInputBlock();
+	const auto& output = context.getOutputBlock();
 
-	for (int channel = 0; channel < numChannels; ++channel) {
-		float* channelData = audioBlock.getChannelPointer(channel);
-		float* delayData = this->delayBuffer.getWritePointer(juce::jmin(channel, this->delayBuffer.getNumChannels() - 1));
+	this->mixer.pushDrySamples(input);
 
-		dpr = this->delayReadPosition;
-		dpw = this->delayWritePosition;
+	for (size_t channel = 0; channel < numChannels; ++channel) {
+		auto* samplesIn = input.getChannelPointer(channel);
+		auto* samplesOut = output.getChannelPointer(channel);
 
-		for (int sample = 0; sample < numSamples; sample++) {
-			const float in = channelData[sample];
-			float out = 0.0f;
+		for (size_t sample = 0; sample < input.getNumSamples(); ++sample) {
+			auto input = samplesIn[sample] - this->lastDelayOutput[channel];
+			auto delayAmount = this->delayValue[channel];
 
-			out = ((1-this->dryWetProp) * in + this->dryWetProp * delayData[dpr]);
-			delayData[dpw] = in + (this->feedback * delayData[dpr]);
+			this->linearDelay.pushSample(channel, input);
+			this->linearDelay.setDelay(delayAmount);
+			samplesOut[sample] = this->linearDelay.popSample(channel);
 
-			if (++dpr >= this->delayBufferLength) {
-				dpr = 0;
-			}
-			if (++dpw >= this->delayBufferLength) {
-				dpw = 0;
-			}
-
-			channelData[sample] = out;
+			this->lastDelayOutput[channel] = samplesOut[sample] * this->delayFeedbackVolume[channel].getNextValue();
 		}
 	}
 
-	this->delayReadPosition = dpr;
-	this->delayWritePosition = dpw;
+	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->delayLengthRange->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() {

+ 17 - 9
JUCE/CMLSProject/Source/CMLSDelay.h

@@ -13,7 +13,8 @@
 #include <JuceHeader.h>
 
 #define MAX_DELAY_LENGTH 1.0f // Maximum delay time in seconds
-#define MAX_FEEDBACK 1.0f
+#define MIN_FEEDBACK -100.0f
+#define MAX_FEEDBACK 0.0f
 
 class CMLSDelay : public juce::dsp::ProcessorBase
 {
@@ -32,17 +33,24 @@ class CMLSDelay : public juce::dsp::ProcessorBase
 		const float getAmount();
 
 	private:
-		float dryWetProp = 0.0f;
-		float amount = 0.0f;
+		float effectDelaySamples;
 
-		float delayLength;
+		//Paramters
+		float dryWetProp;
 		float feedback;
+		float delayLength;
+		float amount;
 
-		juce::AudioSampleBuffer delayBuffer;
-		int delayBufferLength;
-		int delayReadPosition;
-		int delayWritePosition;
-
+		// 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;
 };

+ 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;
+};