commit 2a94da6329d51ed83cacb6a7f485fe2778ad821e
parent 98490f256def869a332452e70824fcd028e9718b
Author: jatinchowdhury18 <[email protected]>
Date: Mon, 1 Jun 2020 16:10:41 -0700
Flutter wow (#34)
* Set up separate wow/flutter params
* Separate wow and flutter processing
* Improved wow processing
Co-authored-by: jatinchowdhury18 <[email protected]>
Diffstat:
11 files changed, 106 insertions(+), 36 deletions(-)
diff --git a/Plugin/Source/GUI/gui.xml b/Plugin/Source/GUI/gui.xml
@@ -77,12 +77,21 @@
slider-textbox="textbox-below" max-height="200"/>
</View>
</View>
- <View flex-direction="column">
- <Label max-height="40" text="Flutter" justification="centred" font-size="18"/>
- <Slider caption="Depth" parameter="depth" slider-type="rotary" slider-textbox="textbox-below"
- max-height="200"/>
- <Slider caption="Rate" parameter="rate" slider-textbox="textbox-below"
- slider-type="rotary" max-height="200"/>
+ <View display="tabbed" padding="0">
+ <View tab-caption="Flutter" flex-direction="column">
+ <Label max-height="40" text="Flutter" justification="centred" font-size="18"/>
+ <Slider caption="Depth" parameter="depth" slider-type="rotary" slider-textbox="textbox-below"
+ max-height="200"/>
+ <Slider caption="Rate" parameter="rate" slider-textbox="textbox-below"
+ slider-type="rotary" max-height="200"/>
+ </View>
+ <View tab-caption="Wow" flex-direction="column">
+ <Label max-height="40" text="Wow" justification="centred" font-size="18"/>
+ <Slider caption="Depth" parameter="wow_depth" slider-type="rotary" slider-textbox="textbox-below"
+ max-height="200"/>
+ <Slider caption="Rate" parameter="wow_rate" slider-textbox="textbox-below"
+ slider-type="rotary" max-height="200"/>
+ </View>
</View>
</View>
<presets max-height="30" margin="0" padding="0"/>
diff --git a/Plugin/Source/GUI/preset_save_gui.xml b/Plugin/Source/GUI/preset_save_gui.xml
@@ -77,13 +77,21 @@
slider-textbox="textbox-below" max-height="200"/>
</View>
</View>
- <View flex-direction="column">
- <Label max-height="40" text="Flutter" justification="centred" font-size="18"/>
- <Slider caption="Depth" parameter="depth" slider-type="rotary" slider-textbox="textbox-below"
- max-height="200"/>
- <Slider caption="Rate" parameter="rate" slider-textbox="textbox-below"
- slider-type="rotary" max-height="200"/>
- <TextButton max-height="50" text="Save" onClick="savepreset"/>
+ <View display="tabbed" padding="0">
+ <View tab-caption="Flutter" flex-direction="column">
+ <Label max-height="40" text="Flutter" justification="centred" font-size="18"/>
+ <Slider caption="Depth" parameter="depth" slider-type="rotary" slider-textbox="textbox-below"
+ max-height="200"/>
+ <Slider caption="Rate" parameter="rate" slider-textbox="textbox-below"
+ slider-type="rotary" max-height="200"/>
+ </View>
+ <View tab-caption="Wow" flex-direction="column">
+ <Label max-height="40" text="Wow" justification="centred" font-size="18"/>
+ <Slider caption="Depth" parameter="wow_depth" slider-type="rotary" slider-textbox="textbox-below"
+ max-height="200"/>
+ <Slider caption="Rate" parameter="wow_rate" slider-textbox="textbox-below"
+ slider-type="rotary" max-height="200"/>
+ </View>
</View>
</View>
<presets max-height="30" margin="0" padding="0"/>
diff --git a/Plugin/Source/Presets/Default.xml b/Plugin/Source/Presets/Default.xml
@@ -20,6 +20,8 @@
<PARAM id="speed" value="15.00000095367432"/>
<PARAM id="thick" value="9.999999974752427e-7"/>
<PARAM id="width" value="0.5"/>
+ <PARAM id="wow_depth" value="0.0"/>
+ <PARAM id="wow_rate" value="0.25"/>
<PARAM id="preset" value="0"/>
</Parameters>
</Preset>
diff --git a/Plugin/Source/Presets/LoFi.xml b/Plugin/Source/Presets/LoFi.xml
@@ -20,6 +20,8 @@
<PARAM id="speed" value="7.500000476837158"/>
<PARAM id="thick" value="0.004999995231628418"/>
<PARAM id="width" value="0.5999999642372131"/>
+ <PARAM id="wow_depth" value="0.0"/>
+ <PARAM id="wow_rate" value="0.25"/>
<PARAM id="preset" value="3"/>
</Parameters>
</Preset>
diff --git a/Plugin/Source/Presets/OldTape.xml b/Plugin/Source/Presets/OldTape.xml
@@ -20,6 +20,8 @@
<PARAM id="speed" value="15.00000095367432"/>
<PARAM id="thick" value="9.999999974752427e-7"/>
<PARAM id="width" value="0.5"/>
+ <PARAM id="wow_depth" value="0.0"/>
+ <PARAM id="wow_rate" value="0.25"/>
<PARAM id="preset" value="4"/>
</Parameters>
</Preset>
diff --git a/Plugin/Source/Presets/TC260.xml b/Plugin/Source/Presets/TC260.xml
@@ -20,6 +20,8 @@
<PARAM id="speed" value="15.00000095367432"/>
<PARAM id="thick" value="0.004748197738081217"/>
<PARAM id="width" value="0.3599999845027924"/>
+ <PARAM id="wow_depth" value="0.2"/>
+ <PARAM id="wow_rate" value="0.2"/>
<PARAM id="preset" value="1"/>
</Parameters>
</Preset>
diff --git a/Plugin/Source/Presets/Underbiased.xml b/Plugin/Source/Presets/Underbiased.xml
@@ -20,6 +20,8 @@
<PARAM id="speed" value="15.00000095367432"/>
<PARAM id="thick" value="9.999999974752427e-7"/>
<PARAM id="width" value="0.04999999701976776"/>
+ <PARAM id="wow_depth" value="0.0"/>
+ <PARAM id="wow_rate" value="0.25"/>
<PARAM id="preset" value="5"/>
</Parameters>
</Preset>
diff --git a/Plugin/Source/Presets/WoozyChorus.xml b/Plugin/Source/Presets/WoozyChorus.xml
@@ -20,6 +20,8 @@
<PARAM id="speed" value="15.00000095367432"/>
<PARAM id="thick" value="9.999999974752427e-7"/>
<PARAM id="width" value="0.5"/>
+ <PARAM id="wow_depth" value="0.8"/>
+ <PARAM id="wow_rate" value="0.5"/>
<PARAM id="preset" value="2"/>
</Parameters>
</Preset>
diff --git a/Plugin/Source/Processors/Timing_Effects/DelayProcessor.h b/Plugin/Source/Processors/Timing_Effects/DelayProcessor.h
@@ -22,7 +22,7 @@ public:
private:
enum
{
- maxDelaySeconds = 1,
+ maxDelaySeconds = 5,
};
SmoothedValue<float, ValueSmoothingTypes::Linear> length = 0.0f;
diff --git a/Plugin/Source/Processors/Timing_Effects/Flutter.cpp b/Plugin/Source/Processors/Timing_Effects/Flutter.cpp
@@ -1,18 +1,32 @@
#include "Flutter.h"
+namespace
+{
+ constexpr float depthSlewMin = 0.001f;
+}
+
Flutter::Flutter (AudioProcessorValueTreeState& vts)
{
- rate = vts.getRawParameterValue ("rate");
- depth = vts.getRawParameterValue ("depth");
+ flutterRate = vts.getRawParameterValue ("rate");
+ flutterDepth = vts.getRawParameterValue ("depth");
+
+ wowRate = vts.getRawParameterValue ("wow_rate");
+ wowDepth = vts.getRawParameterValue ("wow_depth");
+
+ depthSlewWow[0].setCurrentAndTargetValue (*wowDepth);
+ depthSlewWow[1].setCurrentAndTargetValue (*wowDepth);
- depthSlew[0].setCurrentAndTargetValue (*depth);
- depthSlew[1].setCurrentAndTargetValue (*depth);
+ depthSlewFlutter[0].setCurrentAndTargetValue (*flutterDepth);
+ depthSlewFlutter[1].setCurrentAndTargetValue (*flutterDepth);
}
void Flutter::createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params)
{
params.push_back (std::make_unique<AudioParameterFloat> ("rate", "Rate", 0.0f, 1.0f, 0.3f));
params.push_back (std::make_unique<AudioParameterFloat> ("depth", "Depth", 0.0f, 1.0f, 0.0f));
+
+ params.push_back (std::make_unique<AudioParameterFloat> ("wow_rate", "Rate", 0.0f, 1.0f, 0.25f));
+ params.push_back (std::make_unique<AudioParameterFloat> ("wow_depth", "Depth", 0.0f, 1.0f, 0.0f));
}
void Flutter::prepareToPlay (double sampleRate, int samplesPerBlock)
@@ -23,9 +37,14 @@ void Flutter::prepareToPlay (double sampleRate, int samplesPerBlock)
{
delay[ch].prepareToPlay (sampleRate, samplesPerBlock);
delay[ch].setLengthMs (0.f);
- depthSlew[ch].reset (10000);
- depthSlew[ch].setCurrentAndTargetValue (0.001f);
+ depthSlewWow[ch].reset (10000);
+ depthSlewWow[ch].setCurrentAndTargetValue (depthSlewMin);
+
+ depthSlewFlutter[ch].reset (10000);
+ depthSlewFlutter[ch].setCurrentAndTargetValue (depthSlewMin);
+
+ wowPhase[ch] = 0.0f;
phase1[ch] = 0.0f;
phase2[ch] = 0.0f;
phase3[ch] = 0.0f;
@@ -34,12 +53,13 @@ void Flutter::prepareToPlay (double sampleRate, int samplesPerBlock)
dcBlocker[ch].calcCoefs (10.0f, 0.707f);
}
+ wowAmp = 1000.0f * 1000.0f / (float) sampleRate;
amp1 = -230.0f * 1000.0f / (float) sampleRate;
amp2 = -80.0f * 1000.0f / (float) sampleRate;
amp3 = -99.0f * 1000.0f / (float) sampleRate;
dcOffset = 350.0f * 1000.0f / (float) sampleRate;
- isOff = depthSlew[0].getTargetValue() == 0.0f;
+ isOff = true;
dryBuffer.setSize (2, samplesPerBlock);
}
@@ -47,16 +67,24 @@ void Flutter::processBlock (AudioBuffer<float>& buffer, MidiBuffer& /*midiMessag
{
ScopedNoDenormals noDenormals;
- auto curDepth = powf (*depth * 81.0f / 625.0f, 0.5f);
- depthSlew[0].setTargetValue (jmax (0.001f, curDepth));
- depthSlew[1].setTargetValue (jmax (0.001f, curDepth));
+ auto curDepthWow = powf (*wowDepth, 0.5f);
+ depthSlewWow[0].setTargetValue (jmax (depthSlewMin, curDepthWow));
+ depthSlewWow[1].setTargetValue (jmax (depthSlewMin, curDepthWow));
+
+ auto curDepthFlutter = powf (*flutterDepth * 81.0f / 625.0f, 0.5f);
+ depthSlewFlutter[0].setTargetValue (jmax (depthSlewMin, curDepthFlutter));
+ depthSlewFlutter[1].setTargetValue (jmax (depthSlewMin, curDepthFlutter));
+
+ auto wowFreq = powf (4.5, *wowRate) - 1.0f;
+ angleDeltaWow = MathConstants<float>::twoPi * wowFreq / fs;
- auto freq = 0.1f * powf (1000.0f, *rate);
- angleDelta1 = MathConstants<float>::twoPi * 1.0f * freq / fs;
- angleDelta2 = MathConstants<float>::twoPi * 2.0f * freq / fs;
- angleDelta3 = MathConstants<float>::twoPi * 3.0f * freq / fs;
+ auto flutterFreq = 0.1f * powf (1000.0f, *flutterRate);
+ angleDelta1 = MathConstants<float>::twoPi * 1.0f * flutterFreq / fs;
+ angleDelta2 = MathConstants<float>::twoPi * 2.0f * flutterFreq / fs;
+ angleDelta3 = MathConstants<float>::twoPi * 3.0f * flutterFreq / fs;
- bool shouldTurnOff = depthSlew[0].getTargetValue() == 0.001f;
+ bool shouldTurnOff = depthSlewWow[0].getTargetValue() == depthSlewMin
+ && depthSlewFlutter[0].getTargetValue() == depthSlewMin;
if (! isOff && ! shouldTurnOff) // process normally
{
processWetBuffer (buffer);
@@ -98,19 +126,23 @@ void Flutter::processWetBuffer (AudioBuffer<float>& buffer)
auto* x = buffer.getWritePointer (ch);
for (int n = 0; n < buffer.getNumSamples(); ++n)
{
+ wowPhase[ch] += angleDeltaWow;
phase1[ch] += angleDelta1;
phase2[ch] += angleDelta2;
phase3[ch] += angleDelta3;
- auto lfo = amp1 * cosf (phase1[ch] + phaseOff1)
+ auto wowLFO = depthSlewWow[ch].getNextValue() * wowAmp * cosf (wowPhase[ch]);
+ auto flutterLFO = depthSlewFlutter[ch].getNextValue()
+ * (amp1 * cosf (phase1[ch] + phaseOff1)
+ amp2 * cosf (phase2[ch] + phaseOff2)
- + amp3 * cosf (phase3[ch] + phaseOff3)
- + dcOffset;
+ + amp3 * cosf (phase3[ch] + phaseOff3));
- delay[ch].setLengthMs (depthSlew[ch].getNextValue() * lfo);
+ delay[ch].setLengthMs (wowLFO + flutterLFO + dcOffset + depthSlewWow[ch].getCurrentValue() * wowAmp);
x[n] = delay[ch].delay (x[n]);
}
+ while (wowPhase[ch] >= MathConstants<float>::twoPi)
+ wowPhase[ch] -= MathConstants<float>::twoPi;
while (phase1[ch] >= MathConstants<float>::twoPi)
phase1[ch] -= MathConstants<float>::twoPi;
while (phase2[ch] >= MathConstants<float>::twoPi)
@@ -127,6 +159,7 @@ void Flutter::processBypassed (AudioBuffer<float>& buffer)
delay[ch].setLengthMs (0.0f);
for (int n = 0; n < buffer.getNumSamples(); ++n)
{
+ wowPhase[ch] += angleDeltaWow;
phase1[ch] += angleDelta1;
phase2[ch] += angleDelta2;
phase3[ch] += angleDelta3;
@@ -134,6 +167,8 @@ void Flutter::processBypassed (AudioBuffer<float>& buffer)
delay[ch].delay (0.0f);
}
+ while (wowPhase[ch] >= MathConstants<float>::twoPi)
+ wowPhase[ch] -= MathConstants<float>::twoPi;
while (phase1[ch] >= MathConstants<float>::twoPi)
phase1[ch] -= MathConstants<float>::twoPi;
while (phase2[ch] >= MathConstants<float>::twoPi)
diff --git a/Plugin/Source/Processors/Timing_Effects/Flutter.h b/Plugin/Source/Processors/Timing_Effects/Flutter.h
@@ -19,16 +19,20 @@ public:
void processBypassed (AudioBuffer<float>& buffer);
private:
- std::atomic<float>* rate = nullptr;
- std::atomic<float>* depth = nullptr;
+ std::atomic<float>* flutterRate = nullptr;
+ std::atomic<float>* flutterDepth = nullptr;
+ std::atomic<float>* wowRate = nullptr;
+ std::atomic<float>* wowDepth = nullptr;
bool isOff = false;
AudioBuffer<float> dryBuffer;
+ float wowPhase[2] = { 0.0f, 0.0f };
float phase1[2] = { 0.0f, 0.0f };
float phase2[2] = { 0.0f, 0.0f };
float phase3[2] = { 0.0f, 0.0f };
+ float wowAmp = 0.0f;
float amp1 = 0.0f;
float amp2 = 0.0f;
float amp3 = 0.0f;
@@ -39,11 +43,13 @@ private:
const float phaseOff2 = 13.0f * MathConstants<float>::pi / 4.0f;
const float phaseOff3 = -MathConstants<float>::pi / 10.0f;
+ float angleDeltaWow = 0.0f;
float angleDelta1 = 0.0f;
float angleDelta2 = 0.0f;
float angleDelta3 = 0.0f;
- SmoothedValue<float, ValueSmoothingTypes::Multiplicative> depthSlew[2];
+ SmoothedValue<float, ValueSmoothingTypes::Multiplicative> depthSlewWow[2];
+ SmoothedValue<float, ValueSmoothingTypes::Multiplicative> depthSlewFlutter[2];
DelayProcessor delay[2];
TransformerHPF dcBlocker[2];