shithub: leaf

Download patch

ref: 866c7c185fdce7993d21d05fbc76a09558c5b4d5
parent: 19a991d12e072f63f39deaa24ae083d6ca417b71
author: spiricom <jeff@snyderphonics.com>
date: Sun Jan 5 16:22:30 EST 2020

fixed sampler and made other changes

binary files a/.DS_Store b/.DS_Store differ
binary files a/LEAF/.DS_Store b/LEAF/.DS_Store differ
binary files a/LEAF/Inc/.DS_Store b/LEAF/Inc/.DS_Store differ
--- a/LEAF/Inc/leaf-effects.h
+++ b/LEAF/Inc/leaf-effects.h
@@ -14,7 +14,7 @@
 #endif
     
     //==============================================================================
-    
+#include "leaf-dynamics.h"
 #include "leaf-global.h"
 #include "leaf-math.h"
 #include "leaf-analysis.h"
@@ -241,9 +241,6 @@
     //==============================================================================
     
     
-#define FORD 7
-#define FORMANT_BUFFER_SIZE 2048
-    
     typedef struct _tFormantShifter
     {
         int ford;
@@ -267,6 +264,10 @@
         unsigned int cbi;
         float shiftFactor;
         float intensity, invIntensity;
+        tHighpass hp;
+        tHighpass hp2;
+        tFeedbackLeveler fbl1;
+        tFeedbackLeveler fbl2;
         
     } _tFormantShifter;
     
--- a/LEAF/Inc/leaf-math.h
+++ b/LEAF/Inc/leaf-math.h
@@ -70,6 +70,8 @@
 #define INV_TWO_TO_7             0.0078125f
 #define TWO_TO_8                     256.f
 #define INV_TWO_TO_8             0.00390625f
+#define TWO_TO_9                     512.f
+#define INV_TWO_TO_9             0.001953125f
 #define TWO_TO_10                 1024.f
 #define INV_TWO_TO_10         0.0009765625f
 #define TWO_TO_11                 2048.f
@@ -88,6 +90,9 @@
 #define TWO_TO_32        4294967296.0f
 #define INV_TWO_TO_32    0.000000000232831f
     
+
+#define LOGTEN 2.302585092994
+
     // Jones shaper
     float LEAF_shaper     (float input, float m_drive);
     float LEAF_reedTable  (float input, float offset, float slope);
@@ -119,6 +124,7 @@
     
     // Hermite interpolation
     float LEAF_interpolate_hermite (float A, float B, float C, float D, float t);
+    float LEAF_interpolate_hermite_x(float yy0, float yy1, float yy2, float yy3, float xx);
     float LEAF_interpolation_linear (float A, float B, float t);
     
     float interpolate3max(float *buf, const int peakindex);
@@ -134,8 +140,11 @@
     
     float fastexp2f(float f);
     
-#define LOGTEN 2.302585092994
     
+    void LEAF_crossfade(float fade, float* volumes);
+
+
+
     float fast_mtof(float f);
 
     float fastexpf(float x);
--- a/LEAF/Inc/leaf-sampling.h
+++ b/LEAF/Inc/leaf-sampling.h
@@ -91,7 +91,7 @@
         int32_t end, targetend;
         uint32_t len;
         uint32_t cfxlen;
-        
+        float numticks;
         PlayMode mode;
         int retrigger;
         
@@ -116,7 +116,9 @@
     void    tSampler_setStart  (tSampler* const, int32_t start);
     void    tSampler_setEnd    (tSampler* const, int32_t end);
     
-    void    tSampler_setCrossfadeLength  (tSampler* const p, uint32_t length);
+    static void handleStartEndChange(tSampler* const sp);
+
+    void 	tSampler_setCrossfadeLength  (tSampler* const sp, uint32_t length);
     
     void    tSampler_setRate   (tSampler* const, float rate);
     
@@ -129,4 +131,3 @@
 #endif // LEAF_SAMPLING_H_INCLUDED
 
 //==============================================================================
-
binary files a/LEAF/Src/.DS_Store b/LEAF/Src/.DS_Store differ
--- a/LEAF/Src/leaf-distortion.c
+++ b/LEAF/Src/leaf-distortion.c
@@ -1,8 +1,8 @@
 //
-//  leaf-oversampler.c
+//  leaf-distortion.c
 //  LEAF
 //
-//  Created by Matthew Wang and Joshua Becker on 2/28/19.
+//  Created by Jeff Snyder, Matthew Wang, Michael Mulshine, and Joshua Becker
 //  Copyright © 2019 Princeton University. All rights reserved.
 //
 
@@ -16,6 +16,8 @@
 #include "../Inc/leaf-distortion.h"
 #include "../Inc/leaf-tables.h"
 
+//testing
+#include "gpio.h"
 
 #endif
 
@@ -62,7 +64,7 @@
 {
     double thresh, w, expw, p, r, s, err;
     // Error threshold
-    thresh = 10e-10;
+    thresh = 10e-12;
     // Initial guess (use previous value)
     w = ln;
     
@@ -77,10 +79,15 @@
         err = (p/(r-(p*s)));
         
         if (fabs(err)<thresh) {
+
         	break;
         }
         
         w = w - err;
+        if (i == 999)
+        {
+        	//HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_SET);
+        }
 
     }
     return w;
--- a/LEAF/Src/leaf-effects.c
+++ b/LEAF/Src/leaf-effects.c
@@ -645,7 +645,7 @@
     _tAutotune* r = *rt;
     
     float tempPeriod = tPeriodDetection_findPeriod(&r->pd, sample);
-    if (tempPeriod < 1000.0f) //to avoid trying to follow consonants
+    if (tempPeriod < 1000.0f) //to avoid trying to follow consonants JS
 	{
 		r->inputPeriod = tempPeriod;
 	}
@@ -1253,6 +1253,7 @@
 //============================================================================================================
 // FORMANTSHIFTER
 //============================================================================================================
+// algorithm from Tom Baran's autotalent code.
 
 void tFormantShifter_init(tFormantShifter* const fsr, int bufsize, int order)
 {
@@ -1286,6 +1287,10 @@
     fs->cbi = 0;
     fs->intensity = 1.0f;
 	fs->invIntensity = 1.0f;
+	tHighpass_init(&fs->hp, 20.0f);
+	tHighpass_init(&fs->hp2, 20.0f);
+	tFeedbackLeveler_init(&fs->fbl1, 0.8f, .005f, 0.125, 1);
+	tFeedbackLeveler_init(&fs->fbl2, 0.8f, .005f, 0.125, 1);
 }
 
 void tFormantShifter_free(tFormantShifter* const fsr)
@@ -1305,6 +1310,10 @@
         leaf_free(fs->fbuff[i]);
     }
     leaf_free(fs->fbuff);
+    tHighpass_free(&fs->hp);
+    tHighpass_free(&fs->hp2);
+	tFeedbackLeveler_free(&fs->fbl1);
+	tFeedbackLeveler_free(&fs->fbl2);
     leaf_free(fs);
 }
 
@@ -1317,9 +1326,10 @@
 float tFormantShifter_remove(tFormantShifter* const fsr, float in)
 {
     _tFormantShifter* fs = *fsr;
+    in = tFeedbackLeveler_tick(&fs->fbl1, in);
+    in = tHighpass_tick(&fs->hp, tanhf(in * fs->intensity));
     
-    in *= fs->intensity;
-    
+
     float fa, fb, fc, foma, falph, ford, flamb, tf, fk;
     int ti4;
     ford = fs->ford;
@@ -1361,10 +1371,9 @@
 {
     _tFormantShifter* fs = *fsr;
     
-    float fa, fb, fc, falph, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
+    float fa, fb, fc, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
     int ti4;
     ford = fs->ford;
-    falph = fs->falph;
 
     flpa = fs->flpa;
     flamb = fs->flamb;
@@ -1451,7 +1460,9 @@
     fs->fmute = (1.0f-tf2) + tf2*fs->fmute;
     // now tf is signal output
     // ...and we're done messing with formants
-    
+    tf = tFeedbackLeveler_tick(&fs->fbl2, tf);
+    //tf = tHighpass_tick(&fs->hp2, tanhf(tf));
+
     return tf;
 }
 
@@ -1465,7 +1476,13 @@
 void tFormantShifter_setIntensity(tFormantShifter* const fsr, float intensity)
 {
     _tFormantShifter* fs = *fsr;
+
+
+
     fs->intensity = intensity;
+
+    tFeedbackLeveler_setTargetLevel(&fs->fbl1, intensity);
+    tFeedbackLeveler_setTargetLevel(&fs->fbl2, intensity);
     //make sure you don't divide by zero, doofies
     if (fs->intensity != 0.0f)
     {
--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -120,6 +120,19 @@
     }
 }
 
+
+/*
+you pass in a float array to get back two indexes representing the volumes of the left (index 0) and right (index 1) channels
+when t is -1, volumes[0] = 0, volumes[1] = 1
+when t = 0, volumes[0] = 0.707, volumes[1] = 0.707 (equal-power cross fade)
+when t = 1, volumes[0] = 1, volumes[1] = 0
+*/
+
+void LEAF_crossfade(float fade, float* volumes) {
+  volumes[0] = sqrtf(0.5f * (1.0f + fade));
+  volumes[1] = sqrtf(0.5f * (1.0f - fade));
+}
+
 // dope af
 float LEAF_chebyshevT(float in, int n){
 	if (n == 0) return 1;
@@ -363,12 +376,28 @@
 {
     alpha = LEAF_clip(0.0f, alpha, 1.0f);
 
-    float a = -A/2.0f + (3.0f*B)/2.0f - (3.0f*C)/2.0f + D/2.0f;
-    float b = A - (5.0f*B)/2.0f + 2.0f*C - D / 2.0f;
-    float c = -A/2.0f + C/2.0f;
+    float a = -A*0.5f + (3.0f*B)*0.5f - (3.0f*C)*0.5f + D*0.5f;
+    float b = A - (5.0f*B)*0.5f + 2.0f*C - D * 0.5f;
+    float c = -A*0.5f + C*0.5f;
     float d = B;
 
     return a*alpha*alpha*alpha + b*alpha*alpha + c*alpha + d;
+}
+
+
+// from http://www.musicdsp.org/archive.php?classid=5#93
+//xx is alpha (fractional part of sample value)
+//grabbed this from Tom Erbe's Delay pd code
+float LEAF_interpolate_hermite_x(float yy0, float yy1, float yy2, float yy3, float xx)
+{
+        // 4-point, 3rd-order Hermite (x-form)
+        float c0 = yy1;
+        float c1 = 0.5f * (yy2 - yy0);
+        float y0my1 = yy0 - yy1;
+        float c3 = (yy1 - yy2) + 0.5f * (yy3 - y0my1 - yy2);
+        float c2 = y0my1 + c1 - c3;
+
+        return ((c3 * xx + c2) * xx + c1) * xx + c0;
 }
 
 // alpha, [0.0, 1.0]
--- a/LEAF/Src/leaf-mempool.c
+++ b/LEAF/Src/leaf-mempool.c
@@ -281,6 +281,6 @@
 
 void leaf_mempool_overrun(void)
 {
-
+	//TODO: we should set up some kind of leaf_error method that reaches user space to notify library users of things that failed.
 }
 
--- a/LEAF/Src/leaf-sampling.c
+++ b/LEAF/Src/leaf-sampling.c
@@ -19,6 +19,7 @@
 #include "../Inc/leaf-sampling.h"
 #include "../leaf.h"
 
+
 #endif
 
 //==============================================================================
@@ -188,28 +189,61 @@
     _tSampler* p = *sp;
     
     if (p->active == 0)         return 0.f;
-    
-    if ((p->inc == 0.0f) || (p->len < 4))
+
+    if ((p->inc == 0.0f) || (p->len == 0))
     {
-        updateStartEnd(sp);
         return p->last;
     }
-    
-    //    attemptStartEndChange(sp);
-    
+
+    attemptStartEndChange(sp);
+
     float sample = 0.f;
     float cfxsample = 0.f;
     float numticks;
     float g1 = 1.f, g2 = 0.f;
-    
+
     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;
+    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;
+        }
+    }
+
+
     
-    
     idx = (int) p->idx;
     alpha = p->idx - idx;
     
@@ -217,157 +251,151 @@
     revalpha = 1.f - alpha;
     
     
-    int32_t start = p->start, end = p->end;
-    if (p->flip < 0)
-    {
-        start = p->end;
-        end = p->start;
-    }
+
+
     
     uint32_t cfxlen = p->cfxlen;
-    if (p->len < cfxlen) cfxlen = 0;//p->len;
+    if (p->len < cfxlen) cfxlen = p->len * 0.25f;//p->len;
     
     int length = p->samp->length;
     
-    // Check dir (direction) to interpolate properly
     if (dir > 0)
+    {			// num samples (hopping the increment size) to end of loop
+		numticks = (end-idx) * p->iinc;
+    }
+    else
     {
-        // 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);
-        
-        // num samples to end of loop
-        numticks = (end-idx) * p->iinc;
-        //        if (numticks > cfxlen)
-        //        {
-        //            updateStartEnd(sp);
-        //            start = p->start;
-        //            end = p->end;
-        //            if (p->flip < 0)
-        //            {
-        //                start = p->end;
-        //                end = p->start;
-        //            }
-        //            numticks = (end-idx) * p->iinc;
-        //        }
-        //numsamps = (dir > 0) ? (end - idx) : (idx - start);
-        //numsamps *= p->iinc;
-        
-        if (p->mode == PlayLoop)
-        {
-            if (numticks <= (float) cfxlen)
-            {
-                // CROSSFADE SAMPLE
-                int cdx = start - numticks * p->inc;
-                if (cdx < 1)
-                {
-                    cdx = -cdx;
-                    
-                    i1 = ((cdx+1) >= length) ? (length-1) : cdx+1;
-                    i3 = ((cdx-1) < 0) ? cdx : (cdx-1);
-                    i4 = ((cdx-2) < 0) ? 0 : (cdx-2);
-                    
-                    cfxsample =     LEAF_interpolate_hermite (buff[i1],
-                                                              buff[cdx],
-                                                              buff[i3],
-                                                              buff[i4],
-                                                              revalpha);
-                }
-                else
-                {
-                    i1 = ((cdx-1) < 0) ? 0 : cdx-1;
-                    i3 = ((cdx+1) >= length) ? (cdx) : (cdx+1);
-                    i4 = ((cdx+2) >= length) ? (length-1) : (cdx+2);
-                    
-                    cfxsample =     LEAF_interpolate_hermite (buff[i1],
-                                                              buff[cdx],
-                                                              buff[i3],
-                                                              buff[i4],
-                                                              alpha);
-                }
-                g2 = (float) (cfxlen - numticks) / (float) cfxlen;
-            }
-        }
+		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);
+
+			sample =     LEAF_interpolate_hermite (buff[i1],
+												   buff[idx],
+												   buff[i3],
+												   buff[i4],
+												   alpha);
+
+			if (p->mode == PlayLoop)
+			{
+
+
+
+				if (numticks <= (float) cfxlen)
+				{
+					// CROSSFADE SAMPLE
+					int cdx = start - (numticks * p->inc);
+					if (cdx < 1)
+					{
+						cdx = -cdx;
+
+						i1 = ((cdx+1) >= length) ? (length-1) : cdx+1;
+						i3 = ((cdx-1) < 0) ? cdx : (cdx-1);
+						i4 = ((cdx-2) < 0) ? 0 : (cdx-2);
+
+						cfxsample =     LEAF_interpolate_hermite_x (buff[i1],
+																  buff[cdx],
+																  buff[i3],
+																  buff[i4],
+																  revalpha);
+					}
+					else
+					{
+						i1 = ((cdx-1) < 0) ? 0 : cdx-1;
+						i3 = ((cdx+1) >= length) ? (cdx) : (cdx+1);
+						i4 = ((cdx+2) >= length) ? (length-1) : (cdx+2);
+
+						cfxsample =     LEAF_interpolate_hermite_x (buff[i1],
+																  buff[cdx],
+																  buff[i3],
+																  buff[i4],
+																  alpha);
+					}
+
+					g2 = (float) (cfxlen - numticks) / (float) cfxlen;
+
+				}
+
+			}
+
+		}
+		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 (p->mode == PlayLoop)
+			{
+				if (numticks <= (float) cfxlen)
+				{
+					// CROSSFADE SAMPLE
+					int cdx = end + (numticks * p->inc);
+					if (cdx > p->samp->length - 2)
+					{
+						cdx = end - (numticks * p->inc);
+
+						i1 = ((cdx-1) < 0) ? 0 : cdx-1;
+						i3 = ((cdx+1) >= length) ? (cdx) : (cdx+1);
+						i4 = ((cdx+2) >= length) ? (length-1) : (cdx+2);
+
+						cfxsample =     LEAF_interpolate_hermite_x (buff[i1],
+																  buff[cdx],
+																  buff[i3],
+																  buff[i4],
+																  revalpha);
+					}
+					else
+					{
+						i1 = ((cdx+1) >= length) ? (length-1) : cdx+1;
+						i3 = ((cdx-1) < 0) ? cdx : (cdx-1);
+						i4 = ((cdx-2) < 0) ? 0 : (cdx-2);
+
+						cfxsample =     LEAF_interpolate_hermite_x (buff[i1],
+																  buff[cdx],
+																  buff[i3],
+																  buff[i4],
+																  alpha);
+					}
+					g2 = (float) (cfxlen - numticks) / (float) cfxlen;
+				}
+			}
+		}
+	}
     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 (buff[i1],
-                                               buff[revidx],
-                                               buff[i3],
-                                               buff[i4],
-                                               revalpha);
-        
-        numticks = (revidx-start) * p->iinc;
-        
-        // still get clicks i think because updating start/end can put us in the middle of a crossfade
-        //        if (numticks > cfxlen)
-        //        {
-        //            updateStartEnd(sp);
-        //            start = p->start;
-        //            end = p->end;
-        //            if (p->flip < 0)
-        //            {
-        //                start = p->end;
-        //                end = p->start;
-        //            }
-        //            numticks = (revidx-start) * p->iinc;
-        //        }
-        
-        if (p->mode == PlayLoop)
-        {
-            if (numticks <= (float) cfxlen)
-            {
-                // CROSSFADE SAMPLE
-                int cdx = end + numticks * p->inc;
-                if (cdx > p->samp->length - 2)
-                {
-                    cdx = end - numticks * p->inc;
-                    
-                    i1 = ((cdx-1) < 0) ? 0 : cdx-1;
-                    i3 = ((cdx+1) >= length) ? (cdx) : (cdx+1);
-                    i4 = ((cdx+2) >= length) ? (length-1) : (cdx+2);
-                    
-                    cfxsample =     LEAF_interpolate_hermite (buff[i1],
-                                                              buff[cdx],
-                                                              buff[i3],
-                                                              buff[i4],
-                                                              alpha);
-                }
-                else
-                {
-                    i1 = ((cdx+1) >= length) ? (length-1) : cdx+1;
-                    i3 = ((cdx-1) < 0) ? cdx : (cdx-1);
-                    i4 = ((cdx-2) < 0) ? 0 : (cdx-2);
-                    
-                    cfxsample =     LEAF_interpolate_hermite (buff[i1],
-                                                              buff[cdx],
-                                                              buff[i3],
-                                                              buff[i4],
-                                                              revalpha);
-                }
-                g2 = (float) (cfxlen - numticks) / (float) cfxlen;
-            }
-        }
+    	g2 = 0.0f;
     }
     
     
     float inc = fmod(p->inc, p->len);
     p->idx += (dir * inc);
-    
+
+
+
     //    attemptStartEndChange(sp);
-    
+
     if (p->mode == PlayNormal)
     {
         if (numticks < (0.007f * leaf.sampleRate))
@@ -376,36 +404,7 @@
             p->active = -1;
         }
     }
-    else if (p->mode == PlayLoop)
-    {
-        // mike's suggestion: make sure idx is within bounds of start and end (instead of targetstart/targetend stuff)
-        if (idx < start)
-        {
-            updateStartEnd(sp);
-            p->idx += (float)(p->len);
-        }
-        else if (idx > end)
-        {
-            updateStartEnd(sp);
-            p->idx -= (float)(p->len);
-        }
-    }
-    else // == PlayBackAndForth
-    {
-        if (p->idx < start)
-        {
-            updateStartEnd(sp);
-            p->bnf = -p->bnf;
-            p->idx = start;
-        }
-        else if (p->idx > end)
-        {
-            updateStartEnd(sp);
-            p->bnf = -p->bnf;
-            p->idx = end;
-        }
-    }
-    
+
     g1 = 1.f - g2;
     
     sample = sample * g1 + cfxsample * g2;
@@ -440,9 +439,12 @@
             
         }
     }
-    
+
+
     p->last = sample;
     
+
+
     return p->last;
 }
 
@@ -458,7 +460,7 @@
     
     uint32_t cfxlen = LEAF_clip(0, length, 1000);
     
-    //if (cfxlen > p->len)  cfxlen = p->len * 0.25f;
+    if (cfxlen > (p->len * 0.25f))  cfxlen = p->len * 0.25f;
     
     p->cfxlen = cfxlen;
 }
@@ -491,6 +493,7 @@
             if (p->flip > 0)    p->idx = p->end;
             else                p->idx = p->start;
         }
+        handleStartEndChange(&p);
     }
 }
 
@@ -508,9 +511,9 @@
     _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->len < p->cfxlen) p->cfxlen = p->len * 0.9f;
-    
     if (p->start > p->end)
     {
         p->flip = -1;
@@ -539,17 +542,26 @@
 static void updateStartEnd(tSampler* const sp)
 {
     _tSampler* p = *sp;
+
+
+
     if (p->targetstart >= 0)
     {
-        p->start = p->targetstart;
-        handleStartEndChange(sp);
-        p->targetstart = -1;
+        if (p->targetstart != p->end)
+        {
+        	p->start = p->targetstart;
+        	handleStartEndChange(sp);
+        	p->targetstart = -1;
+        }
     }
     if (p->targetend >= 0)
     {
-        p->end = p->targetend;
-        handleStartEndChange(sp);
-        p->targetend = -1;
+        if (p->targetend != p->start)
+        {
+			p->end = p->targetend;
+			handleStartEndChange(sp);
+			p->targetend = -1;
+        }
     }
 }
 
@@ -556,22 +568,37 @@
 void tSampler_setStart     (tSampler* const sp, int32_t start)
 {
     _tSampler* p = *sp;
-    
-    if (p->active)
+
+    int tempflip;
+    if (start == p->end)
     {
-        int dir = p->bnf * p->dir * p->flip;
+    	return;
+    }
+   // if (p->active)
+    {
+
+        if (start > p->end)
+        {
+            tempflip = -1;
+        }
+        else
+        {
+            tempflip = 1;
+        }
+
+    	int dir = p->bnf * p->dir * tempflip;
         uint32_t cfxlen = (p->len < p->cfxlen) ? 0 : p->cfxlen;
-        if (p->flip > 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 given is after current index or we're in a crossfade
+            if (((start > p->idx) || (p->end-p->idx <= cfxlen)) && (start > p->end))// start given is after current index or we're in a crossfade
             {
                 p->targetstart = start;
                 return;
             }
         }
-        else if (p->flip < 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 given is before current index or we're in a crossfade
+            if (((start < p->idx) || (p->idx-p->end <= cfxlen)) && (start < p->end))// start given is before current index or we're in a crossfade
             {
                 p->targetstart = start;
                 return;
@@ -578,31 +605,48 @@
             }
         }
     }
-    
-    p->start = LEAF_clipInt(0, start, p->samp->length - 1);
-    handleStartEndChange(sp);
-    p->targetstart = -1;
+
+	p->start = LEAF_clipInt(0, start, p->samp->length - 1);
+	handleStartEndChange(sp);
+	p->targetstart = -1;
+
 }
 
 void tSampler_setEnd       (tSampler* const sp, int32_t end)
 {
     _tSampler* p = *sp;
-    
-    if (p->active)
+
+    int tempflip;
+
+    if (end == p->start)
     {
-        int dir = p->bnf * p->dir * p->flip;
+    	return;
+    }
+    //if (p->active)
+    {
+
+
+        if (p->start > end)
+        {
+            tempflip = -1;
+        }
+        else
+        {
+        	tempflip = 1;
+        }
+    	int dir = p->bnf * p->dir * tempflip;
         uint32_t cfxlen = (p->len < p->cfxlen) ? 0 : p->cfxlen;
-        if (p->flip > 0 && dir < 0) // end is end and we're playing in reverse
+        if (tempflip > 0 && dir < 0) // end is end and we're playing in reverse
         {
-            if ((end < p->idx) || (p->idx-p->start <= cfxlen)) // end given is before current index or we're in a crossfade
+            if (((end < p->idx) || (p->idx-p->start <= cfxlen)) && (end < p->start)) // end given is before current index or we're in a crossfade
             {
                 p->targetend = end;
                 return;
             }
         }
-        else if (p->flip < 0 && dir > 0) // end is start and we're playing forward
+        else if (tempflip < 0 && dir > 0) // end is start and we're playing forward
         {
-            if ((end > p->idx) || (p->start-p->idx <= cfxlen)) // end given is after current index or we're in a crossfade
+            if (((end > p->idx) || (p->start-p->idx <= cfxlen)) && (end > p->start)) // end given is after current index or we're in a crossfade
             {
                 p->targetend = end;
                 return;
@@ -609,7 +653,6 @@
             }
         }
     }
-    
     p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
     handleStartEndChange(sp);
     p->targetend = -1;
@@ -628,8 +671,8 @@
     {
         p->dir = 1;
     }
-    
-    p->inc = rate; //LEAF_clip(0.f, rate, 8.0f); any reason to clip this?
+
+    p->inc = rate;
     p->iinc = 1.f / p->inc;
 }
 
--- a/LEAF/leaf.h
+++ b/LEAF/leaf.h
@@ -45,6 +45,7 @@
 #include "./Inc/leaf-mempool.h"
 #include "./Inc/leaf-tables.h"
 #include "./Inc/leaf-distortion.h"
+#include "./Inc/leaf-dynamics.h"
 #include "./Inc/leaf-oscillators.h"
 #include "./Inc/leaf-filters.h"
 #include "./Inc/leaf-delay.h"
@@ -51,7 +52,6 @@
 #include "./Inc/leaf-reverb.h"
 #include "./Inc/leaf-effects.h"
 #include "./Inc/leaf-envelopes.h"
-#include "./Inc/leaf-dynamics.h"
 #include "./Inc/leaf-analysis.h"
 #include "./Inc/leaf-instruments.h"
 #include "./Inc/leaf-midi.h"