shithub: leaf

Download patch

ref: 0a2afe1224107c36481c4c050b3040591a9fc35c
parent: d6c2c038a8b5daf840e749fd92deee4090f30856
author: Matthew Wang <Matthew@nat-oitwireless-inside-vapornet100-10-9-53-29.princeton.edu>
date: Wed Dec 18 12:43:15 EST 2019

sampling debugging

--- a/LEAF/Src/leaf-sampling.c
+++ b/LEAF/Src/leaf-sampling.c
@@ -128,6 +128,12 @@
 
 //================================tSampler=====================================
 
+static void handleStartEndChange(tSampler* const sp);
+
+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));
@@ -183,23 +189,17 @@
     
     if (p->active == 0)         return 0.f;
     
-    if (p->targetstart >= 0)
-    {
-        tSampler_setStart(sp, p->targetstart);
-    }
-    if (p->targetend >= 0)
-    {
-        tSampler_setEnd(sp, p->targetend);
-    }
-    
     if ((p->inc == 0.0f) || (p->len < 4))
     {
+        updateStartEnd(sp);
         return p->last;
     }
     
+    //    attemptStartEndChange(sp);
+    
     float sample = 0.f;
     float cfxsample = 0.f;
-    int numsamps;
+    float numticks;
     float g1 = 1.f, g2 = 0.f;
     
     float* buff = p->samp->buff;
@@ -206,20 +206,17 @@
     
     int dir = p->bnf * p->dir * p->flip;
     
-    int idx;
-    float alpha;
+    int idx, revidx;
+    float alpha, revalpha;
     
-    if (dir > 0)
-    {
-        idx = (int) p->idx;
-        alpha = p->idx - idx;
-    }
-    else
-    {
-        idx = (int) (p->idx+1.f); // we think this is because flooring on int works different when reading backwards
-        alpha = (p->idx+1.f) - idx;
-    }
     
+    idx = (int) p->idx;
+    alpha = p->idx - idx;
+    
+    revidx = idx + 1;// we think this is because flooring on int works different when reading backwards
+    revalpha = 1.f - alpha;
+    
+    
     int32_t start = p->start, end = p->end;
     if (p->flip < 0)
     {
@@ -228,15 +225,17 @@
     }
     
     uint32_t cfxlen = p->cfxlen;
-    if (p->len < cfxlen) cfxlen = p->len;
+    if (p->len < cfxlen) cfxlen = 0;//p->len;
     
+    int length = p->samp->length;
+    
     // Check dir (direction) to interpolate properly
     if (dir > 0)
     {
         // FORWARD NORMAL SAMPLE
-        int i1 = (idx-1) < p->start ? p->end : idx-1;
-        int i3 = (idx+1) == p->end ? p->start : (idx+1);
-        int i4 = (idx+2) > p->end ? p->start+1 : ((idx+2) == p->end ? p->start : (idx+2));
+        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],
@@ -245,87 +244,149 @@
                                                alpha);
         
         // num samples to end of loop
-        numsamps = p->end-idx;
+        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 (numsamps <= cfxlen)
-            //            {
-            //                // CROSSFADE SAMPLE
-            //                int cdx = p->start + cfxlen - numsamps;
-            //
-            //                i1 = (cdx-1) < p->start ? p->end-1 : cdx-1;
-            //                i3 = (cdx+1) == p->end ? p->start : (cdx+1);
-            //                i4 = (cdx+2) > p->end ? p->start+1 : ((cdx+2) == p->end ? p->start : (cdx+2));
-            //
-            //                cfxsample =     LEAF_interpolate_hermite (buff[i1],
-            //                                                          buff[cdx],
-            //                                                          buff[i3],
-            //                                                          buff[i4],
-            //                                                          alpha);
-            //
-            //                g2 = (float) (cfxlen - numsamps) / (float) cfxlen;
-            //            }
+            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;
+            }
         }
     }
     else
     {
         // REVERSE
-        int i1 = (idx+1) > p->end ? p->start : idx+1;
-        int i3 = (idx-1) == p->start ? p->end : (idx-1);
-        int i4 = (idx-2) < p->start ? p->end-1 : ((idx-2) == p->start ? p->end : (idx-2));
+        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[idx],
+                                               buff[revidx],
                                                buff[i3],
                                                buff[i4],
-                                               alpha);
+                                               revalpha);
         
-        numsamps = idx-p->start;
+        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 (numsamps <= cfxlen)
-            //            {
-            //                // CROSSFADE SAMPLE
-            //                int cdx = p->end - cfxlen + numsamps;
-            //
-            //                i1 = (cdx+1) > p->end ? p->start+1 : cdx+1;
-            //                i3 = (cdx-1) == p->start ? p->end : (cdx-1);
-            //                i4 = (cdx-2) < p->start ? p->end-1 : ((cdx-2) == p->start ? p->end : (cdx-2));
-            //
-            //                cfxsample =     LEAF_interpolate_hermite (buff[i1],
-            //                                                          buff[cdx],
-            //                                                          buff[i3],
-            //                                                          buff[i4],
-            //                                                          alpha);
-            //
-            //                g2 = (float) (cfxlen - numsamps) / (float) cfxlen;
-            //            }
+            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;
+            }
         }
     }
     
+    
     float inc = fmod(p->inc, p->len);
     p->idx += (dir * inc);
     
+    //    attemptStartEndChange(sp);
+    
     if (p->mode == PlayNormal)
     {
-        if (numsamps < (0.007f * leaf.sampleRate))
+        if (numticks < (0.007f * leaf.sampleRate))
         {
             tRamp_setDest(&p->gain, 0.f);
             p->active = -1;
         }
     }
-    else if (p->mode == PlayLoop )
+    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);
         }
     }
@@ -333,11 +394,13 @@
     {
         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;
         }
@@ -458,24 +521,67 @@
     }
 }
 
-void tSampler_setStart     (tSampler* const sp, int32_t start)
+static void attemptStartEndChange(tSampler* const sp)
 {
     _tSampler* p = *sp;
     
-    int dir = p->bnf * p->dir * p->flip;
-    uint32_t cfxlen = (p->len < p->cfxlen) ? p->len : p->cfxlen;
-    if (dir > 0 && ((start > p->idx) || !(p->end-p->idx > cfxlen)))
+    // Try to update start/end if needed
+    if (p->targetstart >= 0)
     {
-        p->targetstart = start;
+        tSampler_setStart(sp, p->targetstart);
     }
-    else
+    if (p->targetend >= 0)
     {
-        p->start = LEAF_clipInt(0, start, p->samp->length - 1);
+        tSampler_setEnd(sp, p->targetend);
+    }
+}
+
+static void updateStartEnd(tSampler* const sp)
+{
+    _tSampler* p = *sp;
+    if (p->targetstart >= 0)
+    {
+        p->start = p->targetstart;
         handleStartEndChange(sp);
         p->targetstart = -1;
     }
+    if (p->targetend >= 0)
+    {
+        p->end = p->targetend;
+        handleStartEndChange(sp);
+        p->targetend = -1;
+    }
+}
+
+void tSampler_setStart     (tSampler* const sp, int32_t start)
+{
+    _tSampler* p = *sp;
     
+    if (p->active)
+    {
+        int dir = p->bnf * p->dir * p->flip;
+        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 ((start > p->idx) || (p->end-p->idx <= cfxlen)) // 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
+        {
+            if ((start < p->idx) || (p->idx-p->end <= cfxlen)) // start given is before current index or we're in a crossfade
+            {
+                p->targetstart = start;
+                return;
+            }
+        }
+    }
     
+    p->start = LEAF_clipInt(0, start, p->samp->length - 1);
+    handleStartEndChange(sp);
+    p->targetstart = -1;
 }
 
 void tSampler_setEnd       (tSampler* const sp, int32_t end)
@@ -482,20 +588,31 @@
 {
     _tSampler* p = *sp;
     
-    int dir = p->bnf * p->dir * p->flip;
-    uint32_t cfxlen = (p->len < p->cfxlen) ? p->len : p->cfxlen;
-    if (dir <= 0 && ((end < p->idx) || !(p->idx-p->start > cfxlen)))
+    if (p->active)
     {
-        p->targetend = end;
+        int dir = p->bnf * p->dir * p->flip;
+        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 ((end < p->idx) || (p->idx-p->start <= cfxlen)) // 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
+        {
+            if ((end > p->idx) || (p->start-p->idx <= cfxlen)) // end given is after current index or we're in a crossfade
+            {
+                p->targetend = end;
+                return;
+            }
+        }
     }
-    else
-    {
-        p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
-        handleStartEndChange(sp);
-        p->targetend = -1;
-    }
     
-    
+    p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
+    handleStartEndChange(sp);
+    p->targetend = -1;
 }
 
 void tSampler_setRate      (tSampler* const sp, float rate)
--- a/LEAF_JUCEPlugin/JuceLibraryCode/AppConfig.h
+++ b/LEAF_JUCEPlugin/JuceLibraryCode/AppConfig.h
@@ -47,6 +47,8 @@
 
 #define JUCE_USE_DARK_SPLASH_SCREEN 1
 
+#define JUCE_PROJUCER_VERSION 0x50405
+
 //==============================================================================
 #define JUCE_MODULE_AVAILABLE_juce_audio_basics             1
 #define JUCE_MODULE_AVAILABLE_juce_audio_devices            1
--- a/LEAF_JUCEPlugin/JuceLibraryCode/JuceHeader.h
+++ b/LEAF_JUCEPlugin/JuceLibraryCode/JuceHeader.h
@@ -31,6 +31,15 @@
 #include <juce_video/juce_video.h>
 
 
+#if defined (JUCE_PROJUCER_VERSION) && JUCE_PROJUCER_VERSION < JUCE_VERSION
+ /** If you've hit this error then the version of the Projucer that was used to generate this project is
+     older than the version of the JUCE modules being included. To fix this error, re-save your project
+     using the latest version of the Projucer or, if you aren't using the Projucer to manage your project,
+     remove the JUCE_PROJUCER_VERSION define from the AppConfig.h file.
+ */
+ #error "This project was last saved using an outdated version of the Projucer! Re-save this project with the latest version to fix this error."
+#endif
+
 #if ! DONT_SET_USING_JUCE_NAMESPACE
  // If your code uses a lot of JUCE classes, then this will obviously save you
  // a lot of typing, but can be disabled by setting DONT_SET_USING_JUCE_NAMESPACE.
--- a/LEAF_JUCEPlugin/LEAF.jucer
+++ b/LEAF_JUCEPlugin/LEAF.jucer
@@ -8,7 +8,7 @@
               pluginIsSynth="0" pluginWantsMidiIn="1" pluginProducesMidiOut="0"
               pluginIsMidiEffectPlugin="0" pluginEditorRequiresKeys="0" pluginAUExportPrefix="LEAFAU"
               pluginRTASCategory="" aaxIdentifier="com.pumusic.LEAF" pluginAAXCategory="2"
-              jucerVersion="5.4.4" companyName="Princeton University" companyEmail="mrmulshine@gmail.com"
+              jucerVersion="5.4.5" companyName="Princeton University" companyEmail="mrmulshine@gmail.com"
               displaySplashScreen="1" reportAppUsage="1" splashScreenColour="Dark"
               buildStandalone="1" enableIAA="0" cppLanguageStandard="11" companyCopyright="Princeton University"
               pluginFormats="buildVST,buildAU,buildStandalone" pluginCharacteristicsValue="pluginWantsMidiIn">