ref: 32bb7b96736d4d845eb53428a9d22b2dade022f5
parent: 9dffd7c97f0263f5207db0a08dd4ab2d6af5b21d
author: mulshine <mulshine@princeton.edu>
date: Wed Jan 2 13:09:19 EST 2019
Rought implementation of DATTORRO reverb ported from Tom Erbe's max patches.
--- a/LEAF/Inc/leaf-delay.h
+++ b/LEAF/Inc/leaf-delay.h
@@ -100,7 +100,7 @@
} tDelayA;
void tDelayA_init (tDelayA* const, float delay, uint32_t maxDelay);
-void tDelayA_free (tDelayA* const);
+void tDelayA_free (tDelayA* const);
int tDelayA_setDelay (tDelayA* const, float delay);
float tDelayA_getDelay (tDelayA* const);
@@ -109,7 +109,10 @@
float tDelayA_addTo (tDelayA* const, float value, uint32_t tapDelay);
float tDelayA_tick (tDelayA* const, float sample);
float tDelayA_getLastOut (tDelayA* const);
-float tDelayA_getLastIn (tDelayA* const);
+float tDelayA_getLastIn (tDelayA* const);
+void tDelayA_setGain (tDelayA* const, float gain);
+float tDelayA_getGain (tDelayA* const);
+
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
--- a/LEAF/Inc/leaf-filter.h
+++ b/LEAF/Inc/leaf-filter.h
@@ -25,7 +25,8 @@
{
float gain;
float a0,a1;
- float b0,b1;
+ float b0,b1;
+ float freq;
float lastIn, lastOut;
@@ -37,7 +38,8 @@
float tOnePole_tick (tOnePole* const, float input);
void tOnePole_setB0 (tOnePole* const, float b0);
void tOnePole_setA1 (tOnePole* const, float a1);
-void tOnePole_setPole (tOnePole* const, float thePole);
+void tOnePole_setPole (tOnePole* const, float thePole);
+void tOnePole_setFreq (tOnePole* const, float freq);
void tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
void tOnePole_setGain (tOnePole* const, float gain);
--- a/LEAF/Src_cpp/leaf-filter.cpp
+++ b/LEAF/Src_cpp/leaf-filter.cpp
@@ -276,6 +276,12 @@
else f->b0 = (1.0f + thePole);
f->a1 = -thePole;
+}
+
+void tOnePole_setFreq (tOnePole* const f, float freq)
+{
+ f->a1 = expf(-2.0 * PI * freq);
+ f->b0 = 1.0f - f->a1;
}
void tOnePole_setCoefficients(tOnePole* const f, float b0, float a1)
@@ -679,7 +685,7 @@
float a1,a2,a3,g,k;
g = tanf(PI * freq * leaf.invSampleRate);
- k = 1.0f/LEAF_clip(0.01f,Q,10.0f);
+ k = 1.0f/Q;
a1 = 1.0f/(1.0f+g*(g+k));
a2 = g*a1;
a3 = g*a2;
@@ -708,7 +714,7 @@
int tSVF_setQ(tSVF* const svf, float Q)
{
- svf->k = 1.0f/LEAF_clip(0.01f,Q,10.0f);
+ svf->k = 1.0f/Q;
svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
svf->a2 = svf->g * svf->a1;
svf->a3 = svf->g * svf->a2;
--- a/LEAF_JUCEPlugin/LEAF.jucer
+++ b/LEAF_JUCEPlugin/LEAF.jucer
@@ -21,8 +21,6 @@
<FILE id="O0YJRY" name="d_fft_mayer.c" compile="1" resource="0" file="../LEAF/Externals/d_fft_mayer.c"/>
<FILE id="L7c1sT" name="d_fft_mayer.cpp" compile="1" resource="0" file="../LEAF/Externals/d_fft_mayer.cpp"/>
<FILE id="HdG3WV" name="d_fft_mayer.h" compile="0" resource="0" file="../LEAF/Externals/d_fft_mayer.h"/>
- <FILE id="E7GkIZ" name="mpool.cpp" compile="1" resource="0" file="../LEAF/Externals/mpool.cpp"/>
- <FILE id="udMePt" name="mpool.h" compile="0" resource="0" file="../LEAF/Externals/mpool.h"/>
<FILE id="Hu4b98" name="trigtbl.h" compile="0" resource="0" file="../LEAF/Externals/trigtbl.h"/>
</GROUP>
<GROUP id="{0E2E673D-2AE5-AECB-4E28-A1EE29180BD2}" name="Inc">
--- a/LEAF_JUCEPlugin/Source/LEAFLink.cpp
+++ b/LEAF_JUCEPlugin/Source/LEAFLink.cpp
@@ -20,7 +20,11 @@
std::vector<juce::String> cSliderNames = std::vector<juce::String>
{
- "mix"
+ "mix",
+ "predelay",
+ "input filter",
+ "feedback filter",
+ "feedback gain"
};
std::vector<juce::String> cComboBoxNames = std::vector<juce::String>
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ b/LEAF_JUCEPlugin/Source/MyTest.cpp
@@ -14,45 +14,228 @@
static void leaf_pool_report(void);
static void leaf_pool_dump(void);
-static void run_pool_test(void);
+static void run_pool_test(void);
+
+
+// INPUT
+tDelayL in_delay;
+tOnePole in_filter;
+tDelayA in_allpass[4];
+float in_allpass_delays[4] = { 4.771f, 3.595f, 12.73f, 9.307f };
+float in_allpass_gains[4] = { 0.75f, 0.75f, 0.625f, 0.625f };
+
+// FEEDBACK 1
+tDelayA f1_allpass;
+tDelayL f1_delay_1;
+tOnePole f1_filter;
+tDelayL f1_delay_2;
+tDelayL f1_delay_3;
+
+tCycle f1_lfo;
+
+// FEEDBACK 2
+tDelayA f2_allpass;
+tDelayL f2_delay_1;
+tOnePole f2_filter;
+tDelayL f2_delay_2;
+tDelayL f2_delay_3;
+
+tCycle f2_lfo;
+
+float t;
-tSquare osc;
void LEAFTest_init (float sampleRate, int blockSize)
{
LEAF_init(sampleRate, blockSize, &randomNumberGenerator);
- tSquare_init(&osc);
- tSquare_setFreq(&osc, 110.0f);
+ t = leaf.sampleRate * 0.001f;
- tSquare_setTableSize(&osc, 4000);
-
+ // ==================DATTORRO===================
+ // INPUT
+ tDelayL_init(&in_delay, 0.f, 200.f*t);
+ tOnePole_init(&in_filter, 1.f);
+
+ for (int i = 0; i < 4; i++)
+ {
+ tDelayA_init(&in_allpass[i], in_allpass_delays[i], 20.f*t);
+ tDelayA_setGain(&in_allpass[i], in_allpass_gains[i]);
+ }
+
+ // FEEDBACK 1
+ tDelayA_init(&f1_allpass, 30.51f*t, 100.f*t);
+ tDelayA_setGain(&f1_allpass, 0.7f);
+
+ tDelayL_init(&f1_delay_1, 141.69f*t, 200.0f*t);
+ tDelayL_init(&f1_delay_2, 89.24f*t, 100.0f*t);
+ tDelayL_init(&f1_delay_3, 125.f*t, 200.0f*t);
+
+ tOnePole_init(&f1_filter, 1.f);
+
+ tCycle_init(&f1_lfo);
+ tCycle_setFreq(&f1_lfo, 0.1f);
+
+ // FEEDBACK 2
+ tDelayA_init(&f2_allpass, 22.58f*t, 100.f*t);
+ tDelayA_setGain(&f2_allpass, 0.7f);
+
+ tDelayL_init(&f2_delay_1, 149.62f*t, 200.0f*t);
+ tDelayL_init(&f2_delay_2, 60.48f*t, 100.0f*t);
+ tDelayL_init(&f2_delay_3, 106.28f*t, 200.0f*t);
+
+ tOnePole_init(&f2_filter, 1.f);
+
+ tCycle_init(&f2_lfo);
+ tCycle_setFreq(&f2_lfo, 0.07f);
+
+ // =============================================
+
leaf_pool_report();
}
int timer = 0;
+
+
+float f1_delay_2_last;
+float f2_delay_2_last;
+
+float f1_last;
+float f2_last;
+
+
+float mix;
+float predelay = 0.f;
+float input_filter = 1.;
+float feedback_filter = 1.f;
+float feedback_gain = 0.0f;
+
-float prev = 0.0;
float LEAFTest_tick (float input)
-{
- float sample = 0.0f;
-
- timer++;
- if (timer == (1 * leaf.sampleRate))
- {
- timer = 0;
+{
+ // ==================DATTORRO===================
+
+ // INPUT
+ float in_sample = tDelayL_tick(&in_delay, input);
+
+ in_sample = tOnePole_tick(&in_filter, in_sample);
+
+ for (int i = 0; i < 4; i++)
+ {
+ in_sample = tDelayA_tick(&in_allpass[i], in_sample);
}
+
+ // FEEDBACK 1
+ float f1_sample = in_sample + f2_last; // + f2_last_out;
- sample = 0.5 * tSquare_tick(&osc);
+ tDelayA_setDelay(&f1_allpass, 30.51f*t + tCycle_tick(&f1_lfo) * 4.0f);
+
+ f1_sample = tDelayA_tick(&f1_allpass, f1_sample);
+
+ f1_sample = tDelayL_tick(&f1_delay_1, f1_sample);
+
+ f1_sample = tOnePole_tick(&f1_filter, f1_sample);
+
+ f1_sample = f1_sample + f1_delay_2_last * 0.5f;
+
+ float f1_delay_2_sample = tDelayL_tick(&f1_delay_2, f1_sample * 0.5f);
+
+ f1_delay_2_last = f1_delay_2_sample;
+
+ f1_sample = f1_delay_2_last + f1_sample;
+
+ f1_sample *= feedback_gain;
+
+ f1_last = tDelayL_tick(&f1_delay_3, f1_sample);
+
+ // FEEDBACK 2
+ float f2_sample = in_sample + f1_last;
+
+ tDelayA_setDelay(&f2_allpass, 22.58f*t + tCycle_tick(&f2_lfo) * 4.0f);
+
+ f2_sample = tDelayA_tick(&f2_allpass, f2_sample);
+
+ f2_sample = tDelayL_tick(&f2_delay_1, f2_sample);
+
+ f2_sample = tOnePole_tick(&f2_filter, f2_sample);
+
+ f2_sample = f2_sample + f2_delay_2_last * 0.5f;
+
+ float f2_delay_2_sample = tDelayL_tick(&f2_delay_2, f2_sample * 0.5f);
+
+ f2_delay_2_last = f2_delay_2_sample;
+
+ f2_sample = f2_delay_2_last + f2_sample;
+
+ f2_sample *= feedback_gain;
+
+ f2_last = tDelayL_tick(&f2_delay_3, f2_sample);
+
+ // TAP OUT 1
+ f1_sample = tDelayL_tapOut(&f1_delay_1, 8.9f*t) +
+ tDelayL_tapOut(&f1_delay_1, 99.8f*t);
+
+ f1_sample -= tDelayL_tapOut(&f1_delay_2, 64.2f*t);
+
+ f1_sample += tDelayL_tapOut(&f1_delay_3, 67.f*t);
+
+ f1_sample -= tDelayL_tapOut(&f2_delay_1, 66.8f*t);
+
+ f1_sample -= tDelayL_tapOut(&f2_delay_2, 6.3f*t);
+
+ f1_sample -= tDelayL_tapOut(&f2_delay_3, 35.8f*t);
+
+ f1_sample *= 0.14;
+
+ // TAP OUT 2
+ f2_sample = tDelayL_tapOut(&f2_delay_1, 11.8f*t) +
+ tDelayL_tapOut(&f2_delay_1, 121.7f*t);
+
+ f2_sample -= tDelayL_tapOut(&f2_delay_2, 6.3f*t);
+
+ f2_sample += tDelayL_tapOut(&f2_delay_3, 89.7f*t);
+
+ f2_sample -= tDelayL_tapOut(&f1_delay_1, 70.8f*t);
+
+ f2_sample -= tDelayL_tapOut(&f1_delay_2, 11.2f*t);
+
+ f2_sample -= tDelayL_tapOut(&f1_delay_3, 4.1f*t);
+
+ f2_sample *= 0.14f;
+
+ float sample = (f1_sample + f2_sample) * 0.5f;
+
+ // =============================================
- return sample;
+ return (input * (1.0f - mix) + sample * mix);
}
void LEAFTest_block (void)
-{
- float val = getSliderValue("mix");
+{
+ float val = getSliderValue("mix");
+
+ mix = val;
+
+ val = getSliderValue("predelay");
+
+ predelay = (val * 200.f) * leaf.sampleRate * 0.001f;
+ tDelayL_setDelay(&in_delay, predelay);
+
+ val = getSliderValue("input filter");
+
+ input_filter = val * 20000.f;
+ tOnePole_setFreq(&in_filter, input_filter);
+
+ val = getSliderValue("feedback filter");
+
+ feedback_filter = val * 20000.f;
+ tOnePole_setFreq(&f1_filter, feedback_filter);
+ tOnePole_setFreq(&f2_filter, feedback_filter);
+
+ val = getSliderValue("feedback gain");
+
+ feedback_gain = val;
}
void LEAFTest_controllerInput (int cnum, float cval)