From 0e139421eaf1d21970a36f303de996190c93affd Mon Sep 17 00:00:00 2001 From: Vincent Berthiaume Date: Sat, 14 Dec 2024 11:56:40 -0500 Subject: [PATCH] wip -- attempt to get cross-fading to work with 3 effects. We are switching between them in the right order, but there's glitching --- source/DSP/PhatEffectsProcessor.hpp | 105 ++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 29 deletions(-) diff --git a/source/DSP/PhatEffectsProcessor.hpp b/source/DSP/PhatEffectsProcessor.hpp index 52b4447..c4436c8 100644 --- a/source/DSP/PhatEffectsProcessor.hpp +++ b/source/DSP/PhatEffectsProcessor.hpp @@ -30,7 +30,7 @@ enum class EffectType { verb = 0, chorus, - // phaser, + phaser, transitioning }; @@ -73,9 +73,13 @@ class EffectsCrossfadeProcessor //TODO: probagate back the failure to change the effect //first reverse the smoothedGain. If we're not at one of the extremes, we got a double click which we'll ignore if (smoothedGain.getTargetValue() == 1.) + { smoothedGain.setTargetValue (0.); + } else if (smoothedGain.getTargetValue() == 0.) + { smoothedGain.setTargetValue (1.); + } else { jassertfalse; @@ -85,6 +89,8 @@ class EffectsCrossfadeProcessor if (curEffect == EffectType::verb) curEffect = EffectType::chorus; else if (curEffect == EffectType::chorus) + curEffect = EffectType::phaser; + else if (curEffect == EffectType::phaser) curEffect = EffectType::verb; else jassertfalse; @@ -101,52 +107,57 @@ class EffectsCrossfadeProcessor void process (const juce::AudioBuffer& previousEffectBuffer, const juce::AudioBuffer& nextEffectBuffer, - juce::AudioBuffer& outputBuffer) + juce::AudioBuffer& outputBuffer) { jassert (previousEffectBuffer.getNumChannels() == nextEffectBuffer.getNumChannels() && nextEffectBuffer.getNumChannels() == outputBuffer.getNumChannels()); jassert (previousEffectBuffer.getNumSamples() == nextEffectBuffer.getNumSamples() && nextEffectBuffer.getNumSamples() == outputBuffer.getNumSamples()); const auto channels = outputBuffer.getNumChannels(); - const auto samples = outputBuffer.getNumSamples(); - //TODO: compare floating points bro? - const auto needToInverse = smoothedGain.getTargetValue() == 1; + const auto samples = outputBuffer.getNumSamples(); - for (int channel = 0; channel < channels; ++channel) + if (const auto needToInverse = smoothedGain.getTargetValue() == 1; needToInverse) { - for (int sample = 0; sample < samples; ++sample) + for (int channel = 0; channel < channels; ++channel) { - //TODO: get this outta the loop lmao - if (needToInverse) + for (int sample = 0; sample < samples; ++sample) { - //get individual samples + // Get individual samples const auto prev = previousEffectBuffer.getSample (channel, sample); const auto next = nextEffectBuffer.getSample (channel, sample); - //mix and send to output - const auto gain = 1 - smoothedGain.getNextValue(); - auto output = prev * gain + next * (1.0 - gain); + // Mix and send to output + const auto gain = 1 - smoothedGain.getNextValue(); + const auto output = static_cast (prev * gain + next * (1 - gain)); outputBuffer.setSample (channel, sample, static_cast (output)); } - else + } + } + else + { + for (int channel = 0; channel < channels; ++channel) + { + for (int sample = 0; sample < samples; ++sample) { - //get individual samples + // Get individual samples const auto prev = nextEffectBuffer.getSample (channel, sample); const auto next = previousEffectBuffer.getSample (channel, sample); - //mix and send to output - const auto gain = smoothedGain.getNextValue(); - auto output = prev * gain + next * (1.0 - gain); + // Mix and send to output + const auto gain = smoothedGain.getNextValue(); + const auto output = static_cast (prev * gain + next * (1 - gain)); outputBuffer.setSample (channel, sample, static_cast (output)); } } } } -private: - juce::SmoothedValue smoothedGain; - - //TODO: this needs to be stored and retreived from the state EffectType curEffect = EffectType::verb; + + private: + juce::SmoothedValue smoothedGain; + + //TODO: this needs to be stored and retrieved from the state + //EffectType curEffect = EffectType::verb; }; //================================================== @@ -190,6 +201,14 @@ class EffectsProcessor { chorusWrapper->processor.setRate (static_cast (99.9) * newValue); } + else if (curEffect == EffectType::phaser) + { + phaserWrapper->processor.setRate (static_cast (99.9) * newValue); + } + else + { + jassertfalse; + } } else if (parameterID == ProPhatParameterIds::effectParam2ID.getParamID()) { @@ -203,6 +222,15 @@ class EffectsProcessor chorusWrapper->processor.setDepth (newValue); chorusWrapper->processor.setMix (newValue); } + else if (curEffect == EffectType::phaser) + { + phaserWrapper->processor.setDepth (newValue); + phaserWrapper->processor.setMix (newValue); + } + else + { + jassertfalse; + } } else jassertfalse; //unknown effect parameter! @@ -222,17 +250,34 @@ class EffectsProcessor { //copy the OG buffer into the individual processor ones fade_buffer1 = buffer; - fade_buffer2 = buffer; - - //make the individual blocks and process auto audioBlock1 { juce::dsp::AudioBlock (fade_buffer1).getSubBlock ((size_t) startSample, (size_t) numSamples) }; auto context1 { juce::dsp::ProcessContextReplacing (audioBlock1) }; - //TODO: this needs to use the current and the next effect - verbWrapper->process (context1); + fade_buffer2 = buffer; auto audioBlock2 { juce::dsp::AudioBlock (fade_buffer2).getSubBlock ((size_t) startSample, (size_t) numSamples) }; auto context2 { juce::dsp::ProcessContextReplacing (audioBlock2) }; - chorusWrapper->process (context2); + + //do the crossfade based on the actual current effect -- which is actually now the NEXT effect lol + const auto nextEffect = effectCrossFader.curEffect; + switch (nextEffect) + { + case EffectType::verb: + phaserWrapper->process (context1); + verbWrapper->process (context2); + break; + case EffectType::chorus: + verbWrapper->process (context1); + chorusWrapper->process (context2); + break; + case EffectType::phaser: + chorusWrapper->process (context1); + phaserWrapper->process (context2); + break; + case EffectType::transitioning: + default: + jassertfalse; + break; + } //crossfade the 2 effects effectCrossFader.process (fade_buffer1, fade_buffer2, buffer); @@ -247,12 +292,14 @@ class EffectsProcessor verbWrapper->process (context); else if (currentEffectType == EffectType::chorus) chorusWrapper->process (context); + else if (currentEffectType == EffectType::phaser) + phaserWrapper->process (context); else jassertfalse; //unknown effect!! } private: - std::unique_ptr, T>> chorusWrapper; + std::unique_ptr, T>> chorusWrapper; std::unique_ptr, T>> phaserWrapper;