shithub: leaf

Download patch

ref: bc99f48aca15efd07cb81853172b95e83076314f
parent: b1b59893acc33c24f4c72d2531244c76d36b564c
author: spiricom <jeff@snyderphonics.com>
date: Tue Jan 21 18:28:01 EST 2020

updated tLivingString and probably tSampler

binary files a/.DS_Store b/.DS_Store differ
binary files a/LEAF/.DS_Store b/LEAF/.DS_Store differ
--- a/LEAF/Inc/leaf-delay.h
+++ b/LEAF/Inc/leaf-delay.h
@@ -150,6 +150,7 @@
     float       tTapeDelay_tapOut      (tTapeDelay* const d, float tapDelay);
     float       tTapeDelay_addTo       (tTapeDelay*  const, float value, uint32_t tapDelay);
     float       tTapeDelay_tick        (tTapeDelay*  const, float sample);
+    void  		tTapeDelay_incrementInPoint(tTapeDelay* const dl);
     float       tTapeDelay_getLastOut  (tTapeDelay*  const);
     float       tTapeDelay_getLastIn   (tTapeDelay*  const);
     
--- a/LEAF/Inc/leaf-reverb.h
+++ b/LEAF/Inc/leaf-reverb.h
@@ -61,8 +61,8 @@
         
         float inv_sr, inv_441;
         
-        tDelay allpassDelays[8];
-        tDelay combDelays[6];
+        tLinearDelay allpassDelays[8];
+        tLinearDelay combDelays[6];
         float allpassCoeff;
         float combCoeffs[6];
         float lowpassState;
@@ -77,6 +77,7 @@
     void    tNReverb_free      (tNReverb* const);
     
     float   tNReverb_tick      (tNReverb* const, float input);
+    void   tNReverb_tickStereo(tNReverb* const rev, float input, float* output);
     
     // Set reverb time in seconds.
     void    tNReverb_setT60    (tNReverb* const, float t60);
@@ -93,8 +94,8 @@
         float   feedback_filter;
         float   feedback_gain;
         float   mix;
+        uint32_t frozen;
         
-        
         float   size, size_max, t;
         
         float   f1_delay_2_last,
@@ -138,6 +139,7 @@
     float   tDattorroReverb_tick              (tDattorroReverb* const, float input);
     void    tDattorroReverb_tickStereo        (tDattorroReverb* const rev, float input, float* output);
     void    tDattorroReverb_setMix            (tDattorroReverb* const, float mix);
+    void    tDattorroReverb_setFreeze            (tDattorroReverb* const rev, uint32_t freeze);
     void    tDattorroReverb_setHP             (tDattorroReverb* const, float freq);
     void    tDattorroReverb_setSize           (tDattorroReverb* const, float size);
     void    tDattorroReverb_setInputDelay     (tDattorroReverb* const, float preDelay);
--- a/LEAF/Inc/leaf-sampling.h
+++ b/LEAF/Inc/leaf-sampling.h
@@ -35,8 +35,8 @@
         float* buff;
         
         uint32_t idx;
-        uint32_t length;
-        
+        uint32_t bufferLength;
+        uint32_t recordedLength;
         RecordMode mode;
         
         int active;
@@ -64,7 +64,8 @@
     
     void  tBuffer_clear (tBuffer* const);
     
-    uint32_t tBuffer_getLength(tBuffer* const);
+    uint32_t tBuffer_getBufferLength(tBuffer* const);
+    uint32_t tBuffer_getRecordedLength(tBuffer* const sb);
     
     //==============================================================================
     
@@ -92,6 +93,7 @@
         
         int32_t start, targetstart;
         int32_t end, targetend;
+
         uint32_t len;
         uint32_t cfxlen;
         float numticks;
@@ -118,7 +120,7 @@
     
     void    tSampler_setStart  (tSampler* const, int32_t start);
     void    tSampler_setEnd    (tSampler* const, int32_t end);
-    
+
     static void handleStartEndChange(tSampler* const sp);
 
     void 	tSampler_setCrossfadeLength  (tSampler* const sp, uint32_t length);
--- a/LEAF/Src/leaf-delay.c
+++ b/LEAF/Src/leaf-delay.c
@@ -552,6 +552,13 @@
     return d->lastOut;
 }
 
+void  tTapeDelay_incrementInPoint(tTapeDelay* const dl)
+{
+    _tTapeDelay* d = *dl;
+    // Increment input pointer modulo length.
+    if (++(d->inPoint) == d->maxDelay )    d->inPoint = 0;
+}
+
 
 void tTapeDelay_setRate(tTapeDelay* const dl, float rate)
 {
--- a/LEAF/Src/leaf-mempool.c
+++ b/LEAF/Src/leaf-mempool.c
@@ -71,8 +71,13 @@
     
     pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-header_size);
     
-    for (int i = 0; i < pool->head->size; i++) memory[i+header_size]=0;
+    for (int i = 0; i < pool->head->size; i++)
+	{
+		memory[i+header_size]=0;
+	}
 }
+
+
 
 void leaf_pool_init(char* memory, size_t size)
 {
--- a/LEAF/Src/leaf-physical.c
+++ b/LEAF/Src/leaf-physical.c
@@ -440,6 +440,7 @@
     p->curr=0.0f;
     tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
     tLivingString_setFreq(pl, freq);
+    p->freq = freq;
     tExpSmooth_init(&p->ppSmooth, pickPos, 0.01); // smoother for pick position
     tLivingString_setPickPos(pl, pickPos);
     p->prepIndex=prepIndex;
@@ -447,6 +448,7 @@
     tLinearDelay_init(&p->delUF,p->waveLengthInSamples, 2400);
     tLinearDelay_init(&p->delUB,p->waveLengthInSamples, 2400);
     tLinearDelay_init(&p->delLB,p->waveLengthInSamples, 2400);
+    p->dampFreq = dampFreq;
     tOnePole_init(&p->bridgeFilter, dampFreq);
     tOnePole_init(&p->nutFilter, dampFreq);
     tOnePole_init(&p->prepFilterU, dampFreq);
@@ -454,6 +456,7 @@
     tHighpass_init(&p->DCblockerU,13);
     tHighpass_init(&p->DCblockerL,13);
     p->decay=decay;
+    p->prepIndex = prepIndex;
     tFeedbackLeveler_init(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode);
     tFeedbackLeveler_init(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode);
     p->levMode=levMode;
--- a/LEAF/Src/leaf-reverb.c
+++ b/LEAF/Src/leaf-reverb.c
@@ -149,20 +149,16 @@
     
     for ( i=0; i<6; i++ )
     {
-        tDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f);
+    	tLinearDelay_init(&r->combDelays[i], lengths[i], lengths[i] * 2.0f);
         r->combCoeffs[i] = pow(10.0, (-3 * lengths[i] * leaf.invSampleRate / t60));
     }
     
     for ( i=0; i<8; i++ )
     {
-        tDelay_init(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f);
+    	tLinearDelay_init(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2.0f);
     }
+
     
-    for ( i=0; i<2; i++ )
-    {
-        tDelay_setDelay(&r->combDelays[i], lengths[i+2]);
-    }
-    
     tNReverb_setT60(rev, t60);
     r->allpassCoeff = 0.7f;
     r->mix = 0.3f;
@@ -174,12 +170,12 @@
     
     for (int i = 0; i < 6; i++)
     {
-        tDelay_free(&r->combDelays[i]);
+    	tLinearDelay_free(&r->combDelays[i]);
     }
     
     for (int i = 0; i < 8; i++)
     {
-        tDelay_free(&r->allpassDelays[i]);
+    	tLinearDelay_free(&r->allpassDelays[i]);
     }
     
     leaf_free(r);
@@ -193,7 +189,7 @@
     
     r->t60 = t60;
     
-    for (int i=0; i<6; i++)   r->combCoeffs[i] = pow(10.0, (-3.0 * tDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / t60 ));
+    for (int i=0; i<6; i++)   r->combCoeffs[i] = pow(10.0, (-3.0 * tLinearDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / t60 ));
     
 }
 
@@ -208,60 +204,114 @@
     _tNReverb* r = *rev;
     r->lastIn = input;
     
-    float temp, temp0, temp1, temp2, out;
+    float temp, temp0, temp1, temp2, temp3, out;
     int i;
     
     temp0 = 0.0;
     for ( i=0; i<6; i++ )
     {
-        temp = input + (r->combCoeffs[i] * tDelay_getLastOut(&r->combDelays[i]));
-        temp0 += tDelay_tick(&r->combDelays[i],temp);
+        temp = input + (r->combCoeffs[i] * tLinearDelay_getLastOut(&r->combDelays[i]));
+        temp0 += tLinearDelay_tick(&r->combDelays[i],temp);
     }
     
     for ( i=0; i<3; i++ )
     {
-        temp = tDelay_getLastOut(&r->allpassDelays[i]);
+        temp = tLinearDelay_getLastOut(&r->allpassDelays[i]);
         temp1 = r->allpassCoeff * temp;
         temp1 += temp0;
-        tDelay_tick(&r->allpassDelays[i], temp1);
+        tLinearDelay_tick(&r->allpassDelays[i], temp1);
         temp0 = -(r->allpassCoeff * temp1) + temp;
     }
     
     // One-pole lowpass filter.
     r->lowpassState = 0.7f * r->lowpassState + 0.3f * temp0;
-    temp = tDelay_getLastOut(&r->allpassDelays[3]);
+
+    temp = tLinearDelay_getLastOut(&r->allpassDelays[3]);
     temp1 = r->allpassCoeff * temp;
     temp1 += r->lowpassState;
-    tDelay_tick(&r->allpassDelays[3], temp1 );
+    tLinearDelay_tick(&r->allpassDelays[3], temp1 );
     temp1 = -(r->allpassCoeff * temp1) + temp;
     
-    temp = tDelay_getLastOut(&r->allpassDelays[4]);
+    temp = tLinearDelay_getLastOut(&r->allpassDelays[4]);
     temp2 = r->allpassCoeff * temp;
     temp2 += temp1;
-    tDelay_tick(&r->allpassDelays[4], temp2 );
-    out = r->mix * ( -( r->allpassCoeff * temp2 ) + temp );
+    tLinearDelay_tick(&r->allpassDelays[4], temp2 );
+    out = -( r->allpassCoeff * temp2 ) + temp ;
     
-    /*
-     temp = tLinearDelayGetLastOut(&r->allpassDelays[5]);
+    //the other channel in stereo version below
+/*
+     temp = tLinearDelay_getLastOut(&r->allpassDelays[5]);
      temp3 = r->allpassCoeff * temp;
      temp3 += temp1;
-     tLinearDelayTick(&r->allpassDelays[5], temp3 );
-     lastFrame_[1] = effectMix_*( - ( r->allpassCoeff * temp3 ) + temp );
-     */
-    
+     tLinearDelay_tick(&r->allpassDelays[5], temp3 );
+     out = r->mix *( - ( r->allpassCoeff * temp3 ) + temp );
+*/
+
     temp = ( 1.0f - r->mix ) * input;
-    
+
     out += temp;
-    
+
     r->lastOut = out;
-    
+
     return out;
 }
 
+void   tNReverb_tickStereo(tNReverb* const rev, float input, float* output)
+{
+    _tNReverb* r = *rev;
+    r->lastIn = input;
+
+    float temp, temp0, temp1, temp2, temp3, out;
+    int i;
+
+    temp0 = 0.0;
+    for ( i=0; i<6; i++ )
+    {
+        temp = input + (r->combCoeffs[i] * tLinearDelay_getLastOut(&r->combDelays[i]));
+        temp0 += tLinearDelay_tick(&r->combDelays[i],temp);
+    }
+
+    for ( i=0; i<3; i++ )
+    {
+        temp = tLinearDelay_getLastOut(&r->allpassDelays[i]);
+        temp1 = r->allpassCoeff * temp;
+        temp1 += temp0;
+        tLinearDelay_tick(&r->allpassDelays[i], temp1);
+        temp0 = -(r->allpassCoeff * temp1) + temp;
+    }
+
+    // One-pole lowpass filter.
+    r->lowpassState = 0.7f * r->lowpassState + 0.3f * temp0;
+
+    temp = tLinearDelay_getLastOut(&r->allpassDelays[3]);
+    temp1 = r->allpassCoeff * temp;
+    temp1 += r->lowpassState;
+    tLinearDelay_tick(&r->allpassDelays[3], temp1 );
+    temp1 = -(r->allpassCoeff * temp1) + temp;
+
+    float drymix = ( 1.0f - r->mix ) * input;
+
+    temp = tLinearDelay_getLastOut(&r->allpassDelays[4]);
+    temp2 = r->allpassCoeff * temp;
+    temp2 += temp1;
+    tLinearDelay_tick(&r->allpassDelays[4], temp2 );
+    output[0] = -( r->allpassCoeff * temp2 ) + temp + drymix;
+    out = output[0];
+
+
+    temp = tLinearDelay_getLastOut(&r->allpassDelays[5]);
+    temp3 = r->allpassCoeff * temp;
+    temp3 += temp1;
+    tLinearDelay_tick(&r->allpassDelays[5], temp3 );
+    output[1] = r->mix *( - ( r->allpassCoeff * temp3 ) + temp + drymix);
+
+    r->lastOut = out;
+}
+
 void     tNReverbSampleRateChanged (tNReverb* const rev)
 {
     _tNReverb* r = *rev;
-    for (int i=0; i<6; i++)   r->combCoeffs[i] = pow(10.0, (-3.0 * tDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / r->t60 ));
+    for (int i=0; i<6; i++)   r->combCoeffs[i] = pow(10.0, (-3.0 * tLinearDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / r->t60 ));
 }
 
 // ======================================DATTORRO=========================================
@@ -279,7 +329,7 @@
     r->size_max = 2.0f;
     r->size = 1.f;
     r->t = r->size * leaf.sampleRate * 0.001f;
-    
+    r->frozen = 0;
     // INPUT
     tTapeDelay_init(&r->in_delay, 0.f, SAMP(200.f));
     tOnePole_init(&r->in_filter, 1.f);
@@ -381,67 +431,75 @@
 {
     _tDattorroReverb* r = *rev;
     
-    // INPUT
-    float in_sample = tTapeDelay_tick(&r->in_delay, input);
-    
-    in_sample = tOnePole_tick(&r->in_filter, in_sample);
-    
-    for (int i = 0; i < 4; i++)
+
+    float in_sample, f1_sample,f1_delay_2_sample,  f2_sample, f2_delay_2_sample;
+
+    if (r->frozen)
     {
-        in_sample = tAllpass_tick(&r->in_allpass[i], in_sample);
-    }
+    	input = 0.0f;
+    	//r->f1_last = 0.0f;
+    	//r->f2_last = 0.0f;
+	}
+	// INPUT
+	in_sample = tTapeDelay_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
+	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 = tTapeDelay_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;
+
+	f1_delay_2_sample = tTapeDelay_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 = tHighpass_tick(&r->f1_hp, f1_sample);
+
+	f1_sample *= r->feedback_gain;
+
+	r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample);
+
+	// FEEDBACK 2
+	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 = tTapeDelay_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;
+
+	f2_delay_2_sample = tTapeDelay_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 = tHighpass_tick(&r->f2_hp, f2_sample);
+
+	f2_sample *= r->feedback_gain;
+
+	r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_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 = tTapeDelay_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 = tTapeDelay_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 = tHighpass_tick(&r->f1_hp, f1_sample);
-    
-    f1_sample *= r->feedback_gain;
-    
-    r->f1_last = tTapeDelay_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 = tTapeDelay_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 = tTapeDelay_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 = tHighpass_tick(&r->f2_hp, f2_sample);
-    
-    f2_sample *= r->feedback_gain;
-    
-    r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample);
-    
-    
     // TAP OUT 1
     f1_sample =     tTapeDelay_tapOut(&r->f1_delay_1, SAMP(8.9f)) +
     tTapeDelay_tapOut(&r->f1_delay_1, SAMP(99.8f));
@@ -482,72 +540,86 @@
 void   tDattorroReverb_tickStereo              (tDattorroReverb* const rev, float input, float* output)
 {
     _tDattorroReverb* r = *rev;
+    float in_sample, f1_sample,f1_delay_2_sample,  f2_sample, f2_delay_2_sample;
 
-    // INPUT
-    float in_sample = tTapeDelay_tick(&r->in_delay, input);
-
-    in_sample = tOnePole_tick(&r->in_filter, in_sample);
-
-    for (int i = 0; i < 4; i++)
+    if (r->frozen)
     {
-        in_sample = tAllpass_tick(&r->in_allpass[i], in_sample);
+    	input = 0.0f;
+    	//r->f1_last = 0.0f;
+    	//r->f2_last = 0.0f;
     }
+	// INPUT
+	in_sample = tTapeDelay_tick(&r->in_delay, input);
 
-    // FEEDBACK 1
-    float f1_sample = in_sample + r->f2_last; // + f2_last_out;
+	in_sample = tOnePole_tick(&r->in_filter, in_sample);
 
-    tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f));
+	for (int i = 0; i < 4; i++)
+	{
+		in_sample = tAllpass_tick(&r->in_allpass[i], in_sample);
+	}
 
-    f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample);
 
-    f1_sample = tTapeDelay_tick(&r->f1_delay_1, f1_sample);
+		// FEEDBACK 1
+		f1_sample = in_sample + r->f2_last; // + f2_last_out;
 
-    f1_sample = tOnePole_tick(&r->f1_filter, f1_sample);
+		tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f));
 
-    f1_sample = f1_sample + r->f1_delay_2_last * 0.5f;
+		f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample);
 
-    float f1_delay_2_sample = tTapeDelay_tick(&r->f1_delay_2, f1_sample * 0.5f);
+		f1_sample = tTapeDelay_tick(&r->f1_delay_1, f1_sample);
 
-    r->f1_delay_2_last = f1_delay_2_sample;
+		f1_sample = tOnePole_tick(&r->f1_filter, f1_sample);
 
-    f1_sample = r->f1_delay_2_last + f1_sample;
+		f1_sample = f1_sample + r->f1_delay_2_last * 0.5f;
 
-    f1_sample = tHighpass_tick(&r->f1_hp, f1_sample);
+		f1_delay_2_sample = tTapeDelay_tick(&r->f1_delay_2, f1_sample * 0.5f);
 
-    f1_sample *= r->feedback_gain;
+		r->f1_delay_2_last = f1_delay_2_sample;
 
-    f1_sample = tanhf(f1_sample);
+		f1_sample = r->f1_delay_2_last + f1_sample;
 
-    r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample);
+		f1_sample = tHighpass_tick(&r->f1_hp, f1_sample);
 
-    // FEEDBACK 2
-    float f2_sample = in_sample + r->f1_last;
+		f1_sample *= r->feedback_gain;
 
-    tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f));
+		if (r->frozen)
+		{
+			f1_sample = 0.0f;
+		}
 
-    f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample);
+		r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample);
 
-    f2_sample = tTapeDelay_tick(&r->f2_delay_1, f2_sample);
+		// FEEDBACK 2
+		f2_sample = in_sample + r->f1_last;
 
-    f2_sample = tOnePole_tick(&r->f2_filter, f2_sample);
+		tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f));
 
-    f2_sample = f2_sample + r->f2_delay_2_last * 0.5f;
+		f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample);
 
-    float f2_delay_2_sample = tTapeDelay_tick(&r->f2_delay_2, f2_sample * 0.5f);
+		f2_sample = tTapeDelay_tick(&r->f2_delay_1, f2_sample);
 
-    r->f2_delay_2_last = f2_delay_2_sample;
+		f2_sample = tOnePole_tick(&r->f2_filter, f2_sample);
 
-    f2_sample = r->f2_delay_2_last + f2_sample;
+		f2_sample = f2_sample + r->f2_delay_2_last * 0.5f;
 
-    f2_sample = tHighpass_tick(&r->f2_hp, f2_sample);
+		f2_delay_2_sample = tTapeDelay_tick(&r->f2_delay_2, f2_sample * 0.5f);
 
-    f2_sample *= r->feedback_gain;
+		r->f2_delay_2_last = f2_delay_2_sample;
 
-    f2_sample = tanhf(f2_sample);
+		f2_sample = r->f2_delay_2_last + f2_sample;
 
-    r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample);
+		f2_sample = tHighpass_tick(&r->f2_hp, f2_sample);
 
+		f2_sample *= r->feedback_gain;
 
+		if (r->frozen)
+		{
+			f2_sample = 0.0f;
+		}
+		r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample);
+
+
+
     // TAP OUT 1
     f1_sample =     tTapeDelay_tapOut(&r->f1_delay_1, SAMP(8.9f)) +
     tTapeDelay_tapOut(&r->f1_delay_1, SAMP(99.8f));
@@ -589,6 +661,35 @@
 {
     _tDattorroReverb* r = *rev;
     r->mix = LEAF_clip(0.0f, mix, 1.0f);
+}
+
+void    tDattorroReverb_setFreeze            (tDattorroReverb* const rev, uint32_t freeze)
+{
+    _tDattorroReverb* r = *rev;
+    r->frozen = freeze;
+    if (freeze)
+    {
+    	tAllpass_setGain(&r->f2_allpass, 1.0f);
+    	tAllpass_setGain(&r->f1_allpass, 1.0f);
+		for (int i = 0; i < 4; i++)
+		{
+
+			//tAllpass_setGain(&r->in_allpass[i], 1.0f);
+		}
+    	tCycle_setFreq(&r->f1_lfo, 0.0f);
+    	tCycle_setFreq(&r->f2_lfo, 0.0f);
+    }
+    else
+    {
+    	tAllpass_setGain(&r->f2_allpass, 0.7f);
+    	tAllpass_setGain(&r->f1_allpass, 0.7f);
+    	for (int i = 0; i < 4; i++)
+		{
+    		 //tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]);
+		}
+    	tCycle_setFreq(&r->f1_lfo, 0.1f);
+    	tCycle_setFreq(&r->f2_lfo, 0.07f);
+    }
 }
 
 
--- a/LEAF/Src/leaf-sampling.c
+++ b/LEAF/Src/leaf-sampling.c
@@ -30,7 +30,8 @@
     
     s->buff = (float*) leaf_alloc( sizeof(float) * length);
     
-    s->length = length;
+    s->bufferLength = length;
+    s->recordedLength = 0;
     s->active = 0;
     s->idx = 0;
     s->mode = RecordOneShot;
@@ -44,8 +45,8 @@
 
     s->buff = (float*) mpool_alloc( sizeof(float) * length, pool);
 
-    s->length = length;
-    s->active = 0;
+    s->bufferLength = length;
+    s->recordedLength = 0;
     s->idx = 0;
     s->mode = RecordOneShot;
 
@@ -79,7 +80,7 @@
         
         s->idx += 1;
         
-        if (s->idx >= s->length)
+        if (s->idx >= s->bufferLength)
         {
             if (s->mode == RecordOneShot)
             {
@@ -96,17 +97,18 @@
 void  tBuffer_read(tBuffer* const sb, float* buff, uint32_t len)
 {
     _tBuffer* s = *sb;
-    for (int i = 0; i < s->length; i++)
+    for (int i = 0; i < s->bufferLength; i++)
     {
         if (i < len)    s->buff[i] = buff[i];
         else            s->buff[i] = 0.f;
     }
+    s->recordedLength = len;
 }
 
 float tBuffer_get (tBuffer* const sb, int idx)
 {
     _tBuffer* s = *sb;
-    if ((idx < 0) || (idx >= s->length)) return 0.f;
+    if ((idx < 0) || (idx >= s->bufferLength)) return 0.f;
     return s->buff[idx];
 }
 
@@ -121,6 +123,7 @@
 {
     _tBuffer* s = *sb;
     s->active = 0;
+    s->recordedLength = s->idx;
 }
 
 int   tBuffer_getRecordPosition(tBuffer* const sb)
@@ -138,18 +141,24 @@
 void  tBuffer_clear (tBuffer* const sb)
 {
     _tBuffer* s = *sb;
-    for (int i = 0; i < s->length; i++)
+    for (int i = 0; i < s->bufferLength; i++)
     {
         s->buff[i] = 0.f;
     }
 }
 
-uint32_t tBuffer_getLength(tBuffer* const sb)
+uint32_t tBuffer_getBufferLength(tBuffer* const sb)
 {
     _tBuffer* s = *sb;
-    return s->length;
+    return s->bufferLength;
 }
 
+uint32_t tBuffer_getRecordedLength(tBuffer* const sb)
+{
+    _tBuffer* s = *sb;
+    return s->recordedLength;
+}
+
 //================================tSampler=====================================
 
 static void handleStartEndChange(tSampler* const sp);
@@ -156,8 +165,6 @@
 
 static void attemptStartEndChange(tSampler* const sp);
 
-static void updateStartEnd(tSampler* const sp);
-
 void tSampler_init(tSampler* const sp, tBuffer* const b)
 {
     _tSampler* p = *sp = (_tSampler*) leaf_alloc(sizeof(_tSampler));
@@ -168,7 +175,7 @@
     p->active = 0;
     
     p->start = 0;
-    p->end = p->samp->length - 1;
+    p->end = p->samp->bufferLength - 1;
     
     p->len = p->end - p->start;
     
@@ -205,8 +212,17 @@
     _tBuffer* s = *b;
     
     p->samp = s;
+
+    p->start = 0;
+    p->end = p->samp->bufferLength - 1;
+
+    p->len = p->end - p->start;
+
+    p->idx = 0.f;
 }
 
+volatile uint32_t errorState = 0;
+
 float tSampler_tick        (tSampler* const sp)
 {
     _tSampler* p = *sp;
@@ -227,46 +243,22 @@
 
     float* buff = p->samp->buff;
 
-    int dir = p->bnf * p->dir * p->flip;
     
+
     int idx, revidx;
     float alpha, revalpha;
 
-    int32_t start = p->start, end = p->end;
+    int32_t start = p->start;
+    int32_t end = p->end;
     if (p->flip < 0)
     {
         start = p->end;
         end = p->start;
     }
-    if (p->mode == PlayLoop)
-    {
 
-        while((int)p->idx < start)
-        {
-            p->idx += (float)(p->len);
-        }
-        while((int)p->idx > end)
-        {
 
-            p->idx -= (float)(p->len);
-        }
-    }
-    else // == PlayBackAndForth
-    {
-        if (p->idx < start)
-        {
-            p->bnf = -p->bnf;
-            p->idx = start;
-        }
-        else if (p->idx > end)
-        {
-            p->bnf = -p->bnf;
-            p->idx = end;
-        }
-    }
 
-
-    
+    int dir = p->bnf * p->dir * p->flip;
     idx = (int) p->idx;
     alpha = p->idx - idx;
     
@@ -280,7 +272,7 @@
     uint32_t cfxlen = p->cfxlen;
     if (p->len < cfxlen) cfxlen = p->len * 0.25f;//p->len;
     
-    int length = p->samp->length;
+    int length = p->samp->recordedLength;
     
     if (dir > 0)
     {			// num samples (hopping the increment size) to end of loop
@@ -291,25 +283,23 @@
 		numticks = (revidx-start) * p->iinc;
     }
 
-
-
-	if (cfxlen > 0) // necessary to avoid divide by zero, also a waste of computation otherwise
+	// Check dir (direction) to interpolate properly
+	if (dir > 0)
 	{
+		// FORWARD NORMAL SAMPLE
+		int i1 = ((idx-1) < 0) ? 0 : idx-1;
+		int i3 = ((idx+1) >= length) ? (idx) : (idx+1);
+		int i4 = ((idx+2) >= length) ? (length-1) : (idx+2);
 
-		// Check dir (direction) to interpolate properly
-		if (dir > 0)
+		sample =     LEAF_interpolate_hermite_x (buff[i1],
+											   buff[idx],
+											   buff[i3],
+											   buff[i4],
+											   alpha);
+
+		if (cfxlen > 0)// necessary to avoid divide by zero, also a waste of computation otherwise
 		{
-			// FORWARD NORMAL SAMPLE
-			int i1 = ((idx-1) < 0) ? 0 : idx-1;
-			int i3 = ((idx+1) >= length) ? (idx) : (idx+1);
-			int i4 = ((idx+2) >= length) ? (length-1) : (idx+2);
 
-			sample =     LEAF_interpolate_hermite (buff[i1],
-												   buff[idx],
-												   buff[i3],
-												   buff[i4],
-												   alpha);
-
 			if (p->mode == PlayLoop)
 			{
 
@@ -351,24 +341,31 @@
 				}
 
 			}
-
 		}
-		else
-		{
-			// REVERSE
-			int i1 = ((revidx+1) >= length) ? (length-1) : revidx+1;
-			int i3 = ((revidx-1) < 0) ? revidx : (revidx-1);
-			int i4 = ((revidx-2) < 0) ? 0 : (revidx-2);
+	    else
+	    {
+	    	g2 = 0.0f;
+	    }
 
-			sample =     LEAF_interpolate_hermite_x (buff[i1],
-												   buff[revidx],
-												   buff[i3],
-												   buff[i4],
-												   revalpha);
+	}
+	else
+	{
+		// REVERSE
+		int i1 = ((revidx+1) >= length) ? (length-1) : revidx+1;
+		int i3 = ((revidx-1) < 0) ? revidx : (revidx-1);
+		int i4 = ((revidx-2) < 0) ? 0 : (revidx-2);
 
+		sample =     LEAF_interpolate_hermite_x (buff[i1],
+											   buff[revidx],
+											   buff[i3],
+											   buff[i4],
+											   revalpha);
 
 
 
+		if (cfxlen > 0)// necessary to avoid divide by zero, also a waste of computation otherwise
+		{
+
 			if (p->mode == PlayLoop)
 			{
 				if (numticks <= (float) cfxlen)
@@ -375,8 +372,12 @@
 				{
 					// CROSSFADE SAMPLE
 					int cdx = end + (numticks * p->inc);
-					if (cdx > p->samp->length - 2)
+					if (cdx > length - 2)
 					{
+
+						//the problem with the click is here --- at some point it crosses this threshold and jumps from a point near the boundary to a point far away from the boundary - that's not correct
+						///// ooooops
+
 						cdx = end - (numticks * p->inc);
 
 						i1 = ((cdx-1) < 0) ? 0 : cdx-1;
@@ -403,22 +404,51 @@
 					}
 					g2 = (float) (cfxlen - numticks) / (float) cfxlen;
 				}
+
 			}
 		}
+	    else
+	    {
+	    	g2 = 0.0f;
+	    }
+
 	}
-    else
-    {
-    	g2 = 0.0f;
-    }
+
+
     
-    
     float inc = fmod(p->inc, p->len);
     p->idx += (dir * inc);
 
+    //handle start and end cases for looping and back and forth modes
+    if (p->mode == PlayLoop)
+    {
 
+        while((int)p->idx < start)
+        {
+            p->idx += (float)(p->len);
+        }
+        while((int)p->idx > end)
+        {
 
-    //    attemptStartEndChange(sp);
+            p->idx -= (float)(p->len);
+        }
+    }
+    else // == PlayBackAndForth
+    {
+        if (p->idx < start)
+        {
+            p->bnf = -p->bnf;
+            p->idx = start + 1;
+        }
+        else if (p->idx > end)
+        {
+            p->bnf = -p->bnf;
+            p->idx = end - 1;
+        }
+    }
 
+
+    //handle very short fade out for end of one-shot normal playback
     if (p->mode == PlayNormal)
     {
         if (numticks < (0.007f * leaf.sampleRate))
@@ -463,11 +493,14 @@
         }
     }
 
+    if (fabsf(sample-p->last) > 0.1f)
+    {
+    	errorState = 1;
+    }
 
     p->last = sample;
     
 
-
     return p->last;
 }
 
@@ -532,11 +565,11 @@
 static void handleStartEndChange(tSampler* const sp)
 {
     _tSampler* p = *sp;
-    
+
     p->len = abs(p->end - p->start);
 
     if (p->len < (p->cfxlen * 0.25f)) p->cfxlen = p->len * 0.25f;
-    
+
     if (p->start > p->end)
     {
         p->flip = -1;
@@ -562,32 +595,6 @@
     }
 }
 
-static void updateStartEnd(tSampler* const sp)
-{
-    _tSampler* p = *sp;
-
-
-
-    if (p->targetstart >= 0)
-    {
-        if (p->targetstart != p->end)
-        {
-        	p->start = p->targetstart;
-        	handleStartEndChange(sp);
-        	p->targetstart = -1;
-        }
-    }
-    if (p->targetend >= 0)
-    {
-        if (p->targetend != p->start)
-        {
-			p->end = p->targetend;
-			handleStartEndChange(sp);
-			p->targetend = -1;
-        }
-    }
-}
-
 void tSampler_setStart     (tSampler* const sp, int32_t start)
 {
     _tSampler* p = *sp;
@@ -611,7 +618,7 @@
 
     	int dir = p->bnf * p->dir * tempflip;
         uint32_t cfxlen = (p->len < p->cfxlen) ? 0 : p->cfxlen;
-        if (tempflip > 0 && dir > 0) // start is start and we're playing forward
+        if ((tempflip > 0) && (dir > 0)) // start is start and we're playing forward
         {
             if (((start > p->idx) || (p->end-p->idx <= cfxlen)) && (start > p->end))// start given is after current index or we're in a crossfade
             {
@@ -619,7 +626,7 @@
                 return;
             }
         }
-        else if (tempflip < 0 && dir < 0) // start is end and we're playing in reverse
+        else if ((tempflip < 0) && (dir < 0)) // start is end and we're playing in reverse
         {
             if (((start < p->idx) || (p->idx-p->end <= cfxlen)) && (start < p->end))// start given is before current index or we're in a crossfade
             {
@@ -629,7 +636,7 @@
         }
     }
 
-	p->start = LEAF_clipInt(0, start, p->samp->length - 1);
+	p->start = LEAF_clipInt(0, start, p->samp->recordedLength - 1);
 	handleStartEndChange(sp);
 	p->targetstart = -1;
 
@@ -676,7 +683,7 @@
             }
         }
     }
-    p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
+    p->end = LEAF_clipInt(0, end, (p->samp->recordedLength - 1));
     handleStartEndChange(sp);
     p->targetend = -1;
 }
--- a/LEAF/Src/leaf.c
+++ b/LEAF/Src/leaf.c
@@ -21,6 +21,7 @@
 LEAF leaf;
 
 void LEAF_init(float sr, int blocksize, char* memory, size_t memorysize, float(*random)(void))
+
 {
     leaf_pool_init(memory, memorysize);