shithub: leaf

Download patch

ref: 1af1739d790f69201b7d85d18101f1a220e2483d
parent: 32bb7b96736d4d845eb53428a9d22b2dade022f5
author: mulshine <mulshine@princeton.edu>
date: Thu Jan 3 12:23:54 EST 2019

Dattorro reverb ugen working great.

--- a/LEAF/Inc/leaf-delay.h
+++ b/LEAF/Inc/leaf-delay.h
@@ -71,7 +71,7 @@
 int         tDelayL_setDelay    (tDelayL*  const, float delay);
 float       tDelayL_getDelay    (tDelayL*  const);
 void        tDelayL_tapIn       (tDelayL*  const, float in, uint32_t tapDelay);
-float       tDelayL_tapOut      (tDelayL*  const, uint32_t tapDelay);
+float       tDelayL_tapOut      (tDelayL*  const, float tapDelay);
 float       tDelayL_addTo       (tDelayL*  const, float value, uint32_t tapDelay);
 float       tDelayL_tick        (tDelayL*  const, float sample);
 float       tDelayL_getLastOut  (tDelayL*  const);
@@ -109,10 +109,7 @@
 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);
-void        tDelayA_setGain     (tDelayA*  const, float gain);
-float       tDelayA_getGain     (tDelayA*  const);
-
+float       tDelayA_getLastIn   (tDelayA*  const);
 
 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
--- a/LEAF/Inc/leaf-filter.h
+++ b/LEAF/Inc/leaf-filter.h
@@ -14,18 +14,44 @@
 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
 #include "leaf-globals.h"
-#include "leaf-math.h"
+#include "leaf-math.h"
+
+#include "leaf-delay.h"
 
-#include "leaf-wavetables.h"
+#include "leaf-wavetables.h"
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* tAllpass: Schroeder allpass. Comb-filter with feedforward and feedback. */
+typedef struct _tAllpass
+{
+    float gain;
+    
+    tDelayL delay;
+    
+    float lastOut;
+    
+} tAllpass;
+
+void        tAllpass_init           (tAllpass* const, float initDelay, uint32_t maxDelay);
+void        tAllpass_free           (tAllpass* const);
+
+float       tAllpass_tick           (tAllpass* const, float input);
+void        tAllpass_setGain        (tAllpass* const, float gain);
+void        tAllpass_setDelay       (tAllpass* const f, float delay);
 
+
 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
 /* tOnePole: OnePole filter, reimplemented from STK (Cook and Scavone). */
 typedef struct _tOnePole
 {
-    float gain;
-    float a0,a1;
+    float gain;
+    float a0,a1;
     float b0,b1;
+    
+    float coef;
+    
     float freq;
     
     float lastIn, lastOut;
--- a/LEAF/Inc/leaf-reverb.h
+++ b/LEAF/Inc/leaf-reverb.h
@@ -11,14 +11,16 @@
 #ifndef LEAFREVERB_H_INCLUDED
 #define LEAFREVERB_H_INCLUDED
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
 #include "leaf-globals.h"
 #include "leaf-math.h"
 
-#include "leaf-delay.h"
+#include "leaf-delay.h"
+#include "leaf-filter.h"
+#include "leaf-oscillator.h"
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
 /* PRCRev: Reverb, reimplemented from STK (Cook and Scavone). */
 typedef struct _tPRCRev
@@ -47,7 +49,7 @@
 // Set mix between dry input and wet output signal.
 void    tPRCRev_setMix  (tPRCRev* const, float mix);
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 
 /* NRev: Reverb, reimplemented from STK (Cook and Scavone). */
 typedef struct _tNRev
@@ -77,6 +79,61 @@
 // Set mix between dry input and wet output signal.
 void    tNRev_setMix    (tNRev*  const, float mix);
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+
+typedef struct _tDattorro
+{
+    float   predelay;
+    float   input_filter;
+    float   feedback_filter;
+    float   feedback_gain;
+    float   mix;
+    
+    float   size, t;
+    
+    float   f1_delay_2_last,
+            f2_delay_2_last;
+    
+    float   f1_last,
+            f2_last;
+    
+    // INPUT
+    tDelayL     in_delay;
+    tOnePole    in_filter;
+    tAllpass    in_allpass[4];
+    
+    // FEEDBACK 1
+    tAllpass    f1_allpass;
+    tDelayL     f1_delay_1;
+    tOnePole    f1_filter;
+    tDelayL     f1_delay_2;
+    tDelayL     f1_delay_3;
+    
+    tCycle      f1_lfo;
+    
+    // FEEDBACK 2
+    tAllpass    f2_allpass;
+    tDelayL     f2_delay_1;
+    tOnePole    f2_filter;
+    tDelayL     f2_delay_2;
+    tDelayL     f2_delay_3;
+    
+    tCycle      f2_lfo;
+
+} tDattorro;
+
+void    tDattorro_init              (tDattorro* const);
+void    tDattorro_free              (tDattorro* const);
+
+float   tDattorro_tick              (tDattorro* const, float input);
+
+void    tDattorro_setMix            (tDattorro* const, float mix);
+void    tDattorro_setSize           (tDattorro* const, float size);
+void    tDattorro_setInputDelay     (tDattorro* const, float preDelay);
+void    tDattorro_setInputFilter    (tDattorro* const, float freq);
+void    tDattorro_setFeedbackFilter (tDattorro* const, float freq);
+void    tDattorro_setFeedbackGain   (tDattorro* const, float gain);
+
 
 #endif  // LEAFREVERB_H_INCLUDED
--- a/LEAF/Src_cpp/leaf-delay.cpp
+++ b/LEAF/Src_cpp/leaf-delay.cpp
@@ -29,8 +29,6 @@
     
     d->buff = (float*) leaf_alloc(sizeof(float) * maxDelay);
     
-    d->delay = 0.0f;
-    
     d->inPoint = 0;
     d->outPoint = 0;
     
@@ -143,8 +141,6 @@
     
     d->buff = (float*) leaf_alloc(sizeof(float) * maxDelay);
     
-    d->delay = 0.0f;
-    
     d->gain = 1.0f;
     
     d->lastIn = 0.0f;
@@ -206,14 +202,28 @@
     return 0;
 }
 
-float tDelayL_tapOut (tDelayL* const d, uint32_t tapDelay)
+float tDelayL_tapOut (tDelayL* const d, float tapDelay)
 {
-    int32_t tap = d->inPoint - tapDelay - 1;
+    float tap = (float) d->inPoint - tapDelay - 1.f;
     
     // Check for wraparound.
-    while ( tap < 0 )   tap += d->maxDelay;
+    while ( tap < 0.f )   tap += (float)d->maxDelay;
+
+    float alpha = tap - (int)tap;
+    float omAlpha = 1.f - alpha;
+
+    int ptx = (int) tap;
+    
+    // First 1/2 of interpolation
+    float samp = d->buff[ptx] * omAlpha;
+    
+    // Second 1/2 of interpolation
+    if ((ptx + 1) < d->maxDelay)
+        samp += d->buff[ptx+1] * d->alpha;
+    else
+        samp += d->buff[0] * d->alpha;
     
-    return d->buff[tap];
+    return samp;
     
 }
 
@@ -273,8 +283,6 @@
     else                    d->delay = delay;
     
     d->buff = (float*) leaf_alloc(sizeof(float) * maxDelay);
-    
-    d->delay = 0.0f;
     
     d->gain = 1.0f;
     
--- a/LEAF/Src_cpp/leaf-filter.cpp
+++ b/LEAF/Src_cpp/leaf-filter.cpp
@@ -20,7 +20,44 @@
 #include "../Inc/leaf-wavetables.h"
 #include "../leaf.h"
 
-#endif
+#endif
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tAllpass_init(tAllpass* const f, float initDelay, uint32_t maxDelay)
+{
+    f->gain = 0.7f;
+    
+    f->lastOut = 0.0f;
+    
+    tDelayL_init(&f->delay, initDelay, maxDelay);
+}
+
+void    tAllpass_setDelay(tAllpass* const f, float delay)
+{
+    tDelayL_setDelay(&f->delay, delay);
+}
+
+void    tAllpass_free(tAllpass* const f)
+{
+    leaf_free(&f->delay);
+    leaf_free(f);
+}
+
+void    tAllpass_setGain(tAllpass* const f, float gain)
+{
+    f->gain = gain;
+}
+
+float   tAllpass_tick(tAllpass* const f, float input)
+{
+    float s1 = (-f->gain) * f->lastOut + input;
+    
+    float s2 = tDelayL_tick(&f->delay, s1) + (f->gain) * input;
+    
+    f->lastOut = s2;
+    
+    return f->lastOut;
+}
 
 void tButterworth_init(tButterworth* const f, int N, float f1, float f2)
 {
@@ -239,12 +276,12 @@
 }
 
 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tOnePole_init(tOnePole* const f, float thePole)
+void    tOnePole_init(tOnePole* const f, float freq)
 {
     f->gain = 1.0f;
     f->a0 = 1.0;
     
-    tOnePole_setPole(f, thePole);
+    tOnePole_setFreq(f, freq);
     
     f->lastIn = 0.0f;
     f->lastOut = 0.0f;
@@ -280,8 +317,11 @@
 
 void        tOnePole_setFreq        (tOnePole* const f, float freq)
 {
-    f->a1 = expf(-2.0 * PI * freq);
-    f->b0 = 1.0f - f->a1;
+    f->b0 = freq * TWO_PI * leaf.invSampleRate;
+    
+    f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
+    
+    f->a1 = 1.0f - f->b0;
 }
 
 void    tOnePole_setCoefficients(tOnePole* const f, float b0, float a1)
@@ -300,7 +340,7 @@
 float   tOnePole_tick(tOnePole* const f, float input)
 {
     float in = input * f->gain;
-    float out = (f->b0 * in) - (f->a1 * f->lastOut);
+    float out = (f->b0 * in) + (f->a1 * f->lastOut);
     
     f->lastIn = in;
     f->lastOut = out;
--- a/LEAF/Src_cpp/leaf-reverb.cpp
+++ b/LEAF/Src_cpp/leaf-reverb.cpp
@@ -248,12 +248,238 @@
     r->lastOut = out;
     
     return out;
-}
+}
 
-
-
 void     tNRevSampleRateChanged (tNRev* const r)
 {
     for (int i=0; i<6; i++)   r->combCoeffs[i] = pow(10.0, (-3.0 * tDelay_getDelay(r->combDelays[i]) * leaf.invSampleRate / r->t60 ));
+}
+
+// ======================================DATTORRO=========================================
+
+#define SAMP(in) (in*r->t)
+
+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 };
+
+void    tDattorro_init              (tDattorro* const r)
+{
+    tDattorro_setMix(r, 0.5f);
+    
+    tDattorro_setInputDelay(r,  5.f);
+    
+    tDattorro_setInputFilter(r, 1000.f);
+    
+    tDattorro_setFeedbackFilter(r, 1000.f);
+    
+    tDattorro_setFeedbackGain(r, 0.25f);
+    
+    tDattorro_setSize(r, 1.0f);
+    
+    // INPUT
+    tDelayL_init(&r->in_delay, 0.f, SAMP(200.f));
+    tOnePole_init(&r->in_filter, 1.f);
+    
+    for (int i = 0; i < 4; i++)
+    {
+        tAllpass_init(&r->in_allpass[i], in_allpass_delays[i], SAMP(20.f));
+        tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]);
+    }
+    
+    // FEEDBACK 1
+    tAllpass_init(&r->f1_allpass, SAMP(30.51f), SAMP(100.f));
+    tAllpass_setGain(&r->f1_allpass, 0.7f);
+    
+    tDelayL_init(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f));
+    tDelayL_init(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f));
+    tDelayL_init(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f));
+    
+    tOnePole_init(&r->f1_filter, 1.f);
+    
+    tCycle_init(&r->f1_lfo);
+    tCycle_setFreq(&r->f1_lfo, 0.1f);
+    
+    // FEEDBACK 2
+    tAllpass_init(&r->f2_allpass, SAMP(22.58f), SAMP(100.f));
+    tAllpass_setGain(&r->f2_allpass, 0.7f);
+    
+    tDelayL_init(&r->f2_delay_1, SAMP(149.62f), SAMP(200.0f));
+    tDelayL_init(&r->f2_delay_2, SAMP(60.48f), SAMP(100.0f));
+    tDelayL_init(&r->f2_delay_3, SAMP(106.28f), SAMP(200.0f));
+    
+    tOnePole_init(&r->f2_filter, 1.f);
+    
+    tCycle_init(&r->f2_lfo);
+    tCycle_setFreq(&r->f2_lfo, 0.07f);
+}
+
+void    tDattorro_free              (tDattorro* const r)
+{
+    // INPUT
+    tDelayL_free(&r->in_delay);
+    tOnePole_free(&r->in_filter);
+    
+    for (int i = 0; i < 4; i++)
+    {
+        tAllpass_free(&r->in_allpass[i]);
+    }
+    
+    // FEEDBACK 1
+    tAllpass_free(&r->f1_allpass);
+    
+    tDelayL_free(&r->f1_delay_1);
+    tDelayL_free(&r->f1_delay_2);
+    tDelayL_free(&r->f1_delay_3);
+    
+    tOnePole_free(&r->f1_filter);
+    
+    tCycle_free(&r->f1_lfo);
+    
+    // FEEDBACK 2
+    tAllpass_free(&r->f2_allpass);
+    
+    tDelayL_free(&r->f2_delay_1);
+    tDelayL_free(&r->f2_delay_2);
+    tDelayL_free(&r->f2_delay_3);
+    
+    tOnePole_free(&r->f2_filter);
+    
+    tCycle_free(&r->f2_lfo);
+    
+    leaf_free(r);
+}
+
+float   tDattorro_tick              (tDattorro* const r, float input)
+{
+    // INPUT
+    float in_sample = tDelayL_tick(&r->in_delay, input);
+    
+    in_sample = tOnePole_tick(&r->in_filter, in_sample);
+    
+    for (int i = 0; i < 4; i++)
+    {
+        in_sample = tAllpass_tick(&r->in_allpass[i], in_sample);
+    }
+    
+    // FEEDBACK 1
+    float f1_sample = in_sample + r->f2_last; // + f2_last_out;
+    
+    tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f));
+    
+    f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample);
+    
+    f1_sample = tDelayL_tick(&r->f1_delay_1, f1_sample);
+    
+    f1_sample = tOnePole_tick(&r->f1_filter, f1_sample);
+    
+    f1_sample = f1_sample + r->f1_delay_2_last * 0.5f;
+    
+    float f1_delay_2_sample = tDelayL_tick(&r->f1_delay_2, f1_sample * 0.5f);
+    
+    r->f1_delay_2_last = f1_delay_2_sample;
+    
+    f1_sample = r->f1_delay_2_last + f1_sample;
+    
+    f1_sample *= r->feedback_gain;
+    
+    r->f1_last = tDelayL_tick(&r->f1_delay_3, f1_sample);
+    
+    // FEEDBACK 2
+    float f2_sample = in_sample + r->f1_last;
+    
+    tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f));
+    
+    f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample);
+    
+    f2_sample = tDelayL_tick(&r->f2_delay_1, f2_sample);
+    
+    f2_sample = tOnePole_tick(&r->f2_filter, f2_sample);
+    
+    f2_sample = f2_sample + r->f2_delay_2_last * 0.5f;
+    
+    float f2_delay_2_sample = tDelayL_tick(&r->f2_delay_2, f2_sample * 0.5f);
+    
+    r->f2_delay_2_last = f2_delay_2_sample;
+    
+    f2_sample = r->f2_delay_2_last + f2_sample;
+    
+    f2_sample *= r->feedback_gain;
+    
+    r->f2_last = tDelayL_tick(&r->f2_delay_3, f2_sample);
+    
+    
+    // TAP OUT 1
+    f1_sample =     tDelayL_tapOut(&r->f1_delay_1, SAMP(8.9f)) +
+                    tDelayL_tapOut(&r->f1_delay_1, SAMP(99.8f));
+    
+    f1_sample -=    tDelayL_tapOut(&r->f1_delay_2, SAMP(64.2f));
+    
+    f1_sample +=    tDelayL_tapOut(&r->f1_delay_3, SAMP(67.f));
+    
+    f1_sample -=    tDelayL_tapOut(&r->f2_delay_1, SAMP(66.8f));
+    
+    f1_sample -=    tDelayL_tapOut(&r->f2_delay_2, SAMP(6.3f));
+    
+    f1_sample -=    tDelayL_tapOut(&r->f2_delay_3, SAMP(35.8f));
+    
+    f1_sample *=    0.14f;
+    
+    // TAP OUT 2
+    f2_sample =     tDelayL_tapOut(&r->f2_delay_1, SAMP(11.8f)) +
+                    tDelayL_tapOut(&r->f2_delay_1, SAMP(121.7f));
+    
+    f2_sample -=    tDelayL_tapOut(&r->f2_delay_2, SAMP(6.3f));
+    
+    f2_sample +=    tDelayL_tapOut(&r->f2_delay_3, SAMP(89.7f));
+    
+    f2_sample -=    tDelayL_tapOut(&r->f1_delay_1, SAMP(70.8f));
+    
+    f2_sample -=    tDelayL_tapOut(&r->f1_delay_2, SAMP(11.2f));
+    
+    f2_sample -=    tDelayL_tapOut(&r->f1_delay_3, SAMP(4.1f));
+    
+    f2_sample *=    0.14f;
+    
+    float sample = (f1_sample + f2_sample) * 0.5f;
+    
+    return (input * (1.0f - r->mix) + sample * r->mix);
+}
+
+void    tDattorro_setMix            (tDattorro* const r, float mix)
+{
+    r->mix = LEAF_clip(0.0f, mix, 1.0f);
+}
+
+void    tDattorro_setSize           (tDattorro* const r, float size)
+{
+    r->size = LEAF_clip(0.001f, size, 100.0f);
+    r->t = r->size * leaf.sampleRate * 0.001f;
+}
+
+void    tDattorro_setInputDelay     (tDattorro* const r, float preDelay)
+{
+    r->predelay = LEAF_clip(0.0f, preDelay, 200.0f);
+    
+    tDelayL_setDelay(&r->in_delay, SAMP(r->predelay));
+}
+
+void    tDattorro_setInputFilter    (tDattorro* const r, float freq)
+{
+    r->input_filter = LEAF_clip(0.0f, freq, 20000.0f);
+    
+    tOnePole_setFreq(&r->in_filter, r->input_filter);
+}
+
+void    tDattorro_setFeedbackFilter (tDattorro* const r, float freq)
+{
+    r->feedback_filter = LEAF_clip(0.0f, freq, 20000.0f);
+    
+    tOnePole_setFreq(&r->f1_filter, r->feedback_filter);
+    tOnePole_setFreq(&r->f2_filter, r->feedback_filter);
+}
+
+void    tDattorro_setFeedbackGain   (tDattorro* const r, float gain)
+{
+    r->feedback_gain = gain;
 }
 
--- a/LEAF_JUCEPlugin/Source/LEAFLink.cpp
+++ b/LEAF_JUCEPlugin/Source/LEAFLink.cpp
@@ -24,7 +24,8 @@
     "predelay",
     "input filter",
     "feedback filter",
-    "feedback gain"
+    "feedback gain",
+    "size"
 };
 
 std::vector<juce::String> cComboBoxNames =  std::vector<juce::String>
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ b/LEAF_JUCEPlugin/Source/MyTest.cpp
@@ -17,78 +17,20 @@
 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;
+tDattorro reverb;
 
-
 void    LEAFTest_init            (float sampleRate, int blockSize)
 {
     LEAF_init(sampleRate, blockSize, &randomNumberGenerator);
     
-    t = leaf.sampleRate * 0.001f;
+    tDattorro_init(&reverb);
     
-    // ==================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);
-    
-    // =============================================
+    setSliderValue("mix", reverb.mix);
+    setSliderValue("predelay", reverb.predelay / 200.0f);
+    setSliderValue("input filter", reverb.input_filter / 20000.0f);
+    setSliderValue("feedback filter", reverb.feedback_filter / 20000.0f);
+    setSliderValue("feedback gain", reverb.feedback_gain);
+    //setSliderValue("size", reverb.size / 4.0f);
     
     leaf_pool_report();
 }
@@ -96,146 +38,45 @@
 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;
-
+#define CLICK 0
 
-
 float   LEAFTest_tick            (float input)
 {
-    // ==================DATTORRO===================
     
-    // INPUT
-    float in_sample = tDelayL_tick(&in_delay, input);
+#if CLICK
+    input = 0.0f;
     
-    in_sample = tOnePole_tick(&in_filter, in_sample);
-    
-    for (int i = 0; i < 4; i++)
+    timer++;
+    if (timer == (1 * leaf.sampleRate))
     {
-        in_sample = tDelayA_tick(&in_allpass[i], in_sample);
+        timer = 0;
+        
+        input = 1.0f;
     }
-
-    // FEEDBACK 1
-    float f1_sample = in_sample + f2_last; // + f2_last_out;
+#endif
     
-    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 (input * (1.0f - mix) + sample * mix);
-     
+    return tDattorro_tick(&reverb, input);
 }
 
 void    LEAFTest_block           (void)
 {
     float val = getSliderValue("mix");
+    tDattorro_setMix(&reverb, val);
     
-    mix = val;
-    
     val = getSliderValue("predelay");
+    tDattorro_setInputDelay(&reverb, val * 200.0f);
     
-    predelay = (val * 200.f) * leaf.sampleRate * 0.001f;
-    tDelayL_setDelay(&in_delay, predelay);
-    
     val = getSliderValue("input filter");
+    tDattorro_setInputFilter(&reverb, val * 20000.0f);
     
-    input_filter =  val * 20000.f;
-    tOnePole_setFreq(&in_filter, input_filter);
-    
     val = getSliderValue("feedback filter");
+    tDattorro_setFeedbackFilter(&reverb, val * 20000.0f);
     
-    feedback_filter = val * 20000.f;
-    tOnePole_setFreq(&f1_filter, feedback_filter);
-    tOnePole_setFreq(&f2_filter, feedback_filter);
-    
     val = getSliderValue("feedback gain");
+    tDattorro_setFeedbackGain(&reverb, val);
     
-    feedback_gain = val;
+    //val = getSliderValue("size");
+    //tDattorro_setSize(&reverb, val * 4.0f);
 }
 
 void    LEAFTest_controllerInput (int cnum, float cval)