shithub: leaf

Download patch

ref: c3197de0732d863167944ca00c82f3e7165c8409
parent: a90cbc5b8eac9a63d3e0bbe8f326af7adf44b395
author: Matthew Wang <mjw7@princeton.edu>
date: Mon May 4 14:11:24 EDT 2020

sampler tweaks

--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -1,11 +1,11 @@
 /*==============================================================================
+ 
+ leaf-math.c
+ Created: 22 Jan 2017 7:02:56pm
+ Author:  Michael R Mulshine
+ 
+ ==============================================================================*/
 
-    leaf-math.c
-    Created: 22 Jan 2017 7:02:56pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
 #if _WIN32 || _WIN64
 
 #include "..\Inc\leaf-math.h"
@@ -26,18 +26,18 @@
 // This is a fast approximation to log2() found on http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html credited to this post https://community.arm.com/developer/tools-software/tools/f/armds-forum/4292/cmsis-dsp-new-functionality-proposal/22621#22621
 // Y = C[0]*F*F*F + C[1]*F*F + C[2]*F + C[3] + E;
 float log2f_approx(float X) {
-  float Y, F;
-  int E;
-  F = frexpf(fabsf(X), &E);
-  Y = 1.23149591368684f;
-  Y *= F;
-  Y += -4.11852516267426f;
-  Y *= F;
-  Y += 6.02197014179219f;
-  Y *= F;
-  Y += -3.13396450166353f;
-  Y += E;
-  return(Y);
+    float Y, F;
+    int E;
+    F = frexpf(fabsf(X), &E);
+    Y = 1.23149591368684f;
+    Y *= F;
+    Y += -4.11852516267426f;
+    Y *= F;
+    Y += 6.02197014179219f;
+    Y *= F;
+    Y += -3.13396450166353f;
+    Y += E;
+    return(Y);
 }
 
 float interpolate3max(float *buf, const int peakindex)
@@ -91,33 +91,33 @@
 }
 
 double fastexp(double x) {
-  x = 1.0 + (x * 0.0009765625);
-  x *= x; x *= x; x *= x; x *= x;
-  x *= x; x *= x; x *= x; x *= x;
-  x *= x; x *= x;
-  return x;
+    x = 1.0 + (x * 0.0009765625);
+    x *= x; x *= x; x *= x; x *= x;
+    x *= x; x *= x; x *= x; x *= x;
+    x *= x; x *= x;
+    return x;
 }
 
 float fastexpf(float x) {
-  x = 1.0f + (x * 0.0009765625f);
-  x *= x; x *= x; x *= x; x *= x;
-  x *= x; x *= x; x *= x; x *= x;
-  x *= x; x *= x;
-  return x;
+    x = 1.0f + (x * 0.0009765625f);
+    x *= x; x *= x; x *= x; x *= x;
+    x *= x; x *= x; x *= x; x *= x;
+    x *= x; x *= x;
+    return x;
 }
 
 double fasterexp(double x) {
-  x = 1.0 + (x * 0.00390625);
-  x *= x; x *= x; x *= x; x *= x;
-  x *= x; x *= x; x *= x; x *= x;
-  return x;
+    x = 1.0 + (x * 0.00390625);
+    x *= x; x *= x; x *= x; x *= x;
+    x *= x; x *= x; x *= x; x *= x;
+    return x;
 }
 
 float fasterexpf(float x) {
-  x = 1.0f + (x * 0.00390625f);
-  x *= x; x *= x; x *= x; x *= x;
-  x *= x; x *= x; x *= x; x *= x;
-  return x;
+    x = 1.0f + (x * 0.00390625f);
+    x *= x; x *= x; x *= x; x *= x;
+    x *= x; x *= x; x *= x; x *= x;
+    return x;
 }
 
 // fast floating-point exp2 function taken from Robert Bristow Johnson's
@@ -153,52 +153,52 @@
 
 
 /*
-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
-*/
+ 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));
+    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;
-	else if (n == 1) return in;
-	else return 2.0f * in * LEAF_chebyshevT(in, n-1) - LEAF_chebyshevT(in, n-2);
+    if (n == 0) return 1;
+    else if (n == 1) return in;
+    else return 2.0f * in * LEAF_chebyshevT(in, n-1) - LEAF_chebyshevT(in, n-2);
 }
 
 #if !(_WIN32 || _WIN64)
 float LEAF_CompoundChebyshevT(float in, int n, float* amps){
-	float T[n+1];
-	T[0] = 1.0f;
-	T[1] = in;
-	for (int i = 2; i <= n; ++i)
-		T[i] = 2*in*T[i-1] - T[i-2];
-	float out = 0;
-	float amp = 0;
-	for (int i = 0; i < n; ++i){
-		out += amps[i]*T[i+1];
-		amp += amps[i];
-	}
-	return out / amp ;
+    float T[n+1];
+    T[0] = 1.0f;
+    T[1] = in;
+    for (int i = 2; i <= n; ++i)
+        T[i] = 2*in*T[i-1] - T[i-2];
+    float out = 0;
+    float amp = 0;
+    for (int i = 0; i < n; ++i){
+        out += amps[i]*T[i+1];
+        amp += amps[i];
+    }
+    return out / amp ;
 }
 #endif
 
 float LEAF_frequencyToMidi(float f)
 {
-	return (69.0f + 12.0f * log2(f * INV_440));
+    return (69.0f + 12.0f * log2(f * INV_440));
 }
 
 // Jones shaper
-float LEAF_shaper(float input, float m_drive) 
+float LEAF_shaper(float input, float m_drive)
 {
     float fx = input * 2.0f;    // prescale
     float w, c, xc, xc2, xc4;
-
+    
     xc = LEAF_clip(-SQRT8, fx, SQRT8);
     xc2 = xc*xc;
     c = 0.5f*fx*(3.0f - (xc2));
@@ -225,14 +225,14 @@
 
 float LEAF_bitwise_xor(float input, uint32_t op)
 {
-	union unholy_t unholy;
-	unholy.f = input;
+    union unholy_t unholy;
+    unholy.f = input;
     unholy.i = (unholy.i ^ op);
     
     return unholy.f;
 }
 
-float LEAF_reedTable(float input, float offset, float slope) 
+float LEAF_reedTable(float input, float offset, float slope)
 {
     float output = offset + (slope * input);
     if ( output > 1.0f) output = 1.0f;
@@ -240,28 +240,28 @@
     return output;
 }
 
-float   LEAF_softClip(float val, float thresh) 
+float   LEAF_softClip(float val, float thresh)
 {
-	float x;
-	
-	if(val > thresh)
-	{
-			x = thresh / val;
-			return (1.0f - x) * (1.0f - thresh) + thresh;
-	}
-	else if(val < -thresh)
-	{
-			x = -thresh / val;
-			return -((1.0f - x) * (1.0f - thresh) + thresh);
-	}
-	else
-	{
-		return val;
-	}
+    float x;
+    
+    if(val > thresh)
+    {
+        x = thresh / val;
+        return (1.0f - x) * (1.0f - thresh) + thresh;
+    }
+    else if(val < -thresh)
+    {
+        x = -thresh / val;
+        return -((1.0f - x) * (1.0f - thresh) + thresh);
+    }
+    else
+    {
+        return val;
+    }
 }
 
-float   LEAF_clip(float min, float val, float max) 
-	{
+float   LEAF_clip(float min, float val, float max)
+{
     
     if (val < min) {
         return min;
@@ -274,10 +274,17 @@
 
 int   LEAF_clipInt(int min, int val, int max)
 {
-    if (val < min) {
-        return min;
-    } else if (val > max) {
-        return max;
+    int tempmin = min;
+    int tempmax = max;
+    if (min > max)
+    {
+        tempmin = max;
+        tempmax = min;
+    }
+    if (val < tempmin) {
+        return tempmin;
+    } else if (val > tempmax) {
+        return tempmax;
     } else {
         return val;
     }
@@ -407,12 +414,12 @@
 float LEAF_interpolate_hermite (float A, float B, float C, float D, float alpha)
 {
     alpha = LEAF_clip(0.0f, alpha, 1.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;
 }
 
@@ -422,14 +429,14 @@
 //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;
+    // 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]
@@ -436,14 +443,14 @@
 float LEAF_interpolation_linear (float A, float B, float alpha)
 {
     alpha = LEAF_clip(0.0f, alpha, 1.0f);
-
+    
     float omAlpha = 1.0f - alpha;
-
+    
     // First 1/2 of interpolation
     float out = A * omAlpha;
-
+    
     out += B * alpha;
-
+    
     return out;
 }
 
@@ -518,31 +525,31 @@
 
 float atodb(float a)
 {
-	return 20.0f*log10f(a);
+    return 20.0f*log10f(a);
 }
 
 float dbtoa(float db)
 {
-	return powf(10.0f, db * 0.05f);
-	//return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
+    return powf(10.0f, db * 0.05f);
+    //return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
 }
 
 
 float fastdbtoa(float db)
 {
-	//return powf(10.0f, db * 0.05f);
-	return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
+    //return powf(10.0f, db * 0.05f);
+    return expf(0.115129254649702f * db); //faster version from http://openaudio.blogspot.com/2017/02/faster-log10-and-pow.html
 }
 
 
 float maximum (float num1, float num2)
 {
-	return (num1 > num2 ) ? num1 : num2;
+    return (num1 > num2 ) ? num1 : num2;
 }
 
 float minimum (float num1, float num2)
 {
-	return (num1 < num2 ) ? num1 : num2;
+    return (num1 < num2 ) ? num1 : num2;
 }
 
 
--- a/LEAF/Src/leaf-sampling.c
+++ b/LEAF/Src/leaf-sampling.c
@@ -173,7 +173,7 @@
     p->active = 0;
     
     p->start = 0;
-    p->end = p->samp->bufferLength - 1;
+    p->end = 0;
     
     p->len = p->end - p->start;
     
@@ -232,17 +232,19 @@
     
     if (p->active == 0)         return 0.f;
     
+    attemptStartEndChange(sp);
+    
     if ((p->inc == 0.0f) || (p->len < 2))
     {
-        p->inCrossfade = 0;
+        //        p->inCrossfade = 1;
         return p->last;
     }
     
-    attemptStartEndChange(sp);
-    
     float sample = 0.0f;
     float cfxsample = 0.0f;
     float crossfadeMix = 0.0f;
+    float flipsample = 0.0f;
+    float flipMix = 0.0f;
     
     float* buff = p->samp->buff;
     
@@ -280,7 +282,7 @@
     i4 = (i4 < length*(1-rev)) ? i4 + (length * rev) : i4 - (length * (1-rev));
     
     sample = LEAF_interpolate_hermite_x (buff[i1],
-                                         buff[idx],
+                                         buff[i2],
                                          buff[i3],
                                          buff[i4],
                                          alpha);
@@ -293,13 +295,50 @@
     if (start >= cfxlen) fadeLeftStart = start - cfxlen;
     uint32_t fadeLeftEnd = fadeLeftStart + cfxlen;
     
-    uint32_t fadeRightEnd = end + (fadeLeftEnd - start);
-    if (fadeRightEnd >= length) fadeRightEnd = length - 1;
+    uint32_t fadeRightEnd = end;// + (fadeLeftEnd - start);
+    //    if (fadeRightEnd >= length) fadeRightEnd = length - 1;
     uint32_t fadeRightStart = fadeRightEnd - cfxlen;
     
-    p->inCrossfade = 0;
     if (p->mode == PlayLoop)
     {
+        
+        int offset = 0;
+        int cdx = 0;
+        if ((fadeLeftStart <= idx) && (idx <= fadeLeftEnd))
+        {
+            offset = fadeLeftEnd - idx;
+            cdx = fadeRightEnd - offset;
+            p->inCrossfade = 1;
+        }
+        else if ((fadeRightStart <= idx) && (idx <= fadeRightEnd))
+        {
+            offset = idx - fadeRightStart;
+            cdx = fadeLeftStart + offset;
+            p->inCrossfade = 1;
+        }
+        else p->inCrossfade = 0;
+        
+        if (p->inCrossfade)
+        {
+            int c1 = cdx-(1*dir);
+            int c2 = cdx;
+            int c3 = cdx+(1*dir);
+            int c4 = cdx+(2*dir);
+            
+            // Wrap as needed
+            c1 = (c1 < length * rev) ? c1 + (length * (1-rev)) : c1 - (length * rev);
+            c2 = (c2 < length * rev) ? c2 + (length * (1-rev)) : c2 - (length * rev);
+            c3 = (c3 < length * (1-rev)) ? c3 + (length * rev) : c3 - (length * (1-rev));
+            c4 = (c4 < length * (1-rev)) ? c4 + (length * rev) : c4 - (length * (1-rev));
+            
+            cfxsample = LEAF_interpolate_hermite_x (buff[c1],
+                                                    buff[c2],
+                                                    buff[c3],
+                                                    buff[c4],
+                                                    alpha);
+            crossfadeMix = (float) offset / (float) cfxlen;
+        }
+        
         float flipLength = fabsf(p->flipIdx - p->flipStart);
         if (flipLength > cfxlen)
         {
@@ -331,58 +370,29 @@
             f3 = (f3 < length*rev) ? f3 + (length * (1-rev)) : f3 - (length * rev);
             f4 = (f4 < length*rev) ? f4 + (length * (1-rev)) : f4 - (length * rev);
             
-            cfxsample = LEAF_interpolate_hermite_x (buff[f1],
-                                                    buff[fdx],
-                                                    buff[f3],
-                                                    buff[f4],
-                                                    falpha);
-            crossfadeMix = (float) (cfxlen - flipLength) / (float) cfxlen;
+            flipsample = LEAF_interpolate_hermite_x (buff[f1],
+                                                     buff[f2],
+                                                     buff[f3],
+                                                     buff[f4],
+                                                     falpha);
+            flipMix = (float) (cfxlen - flipLength) / (float) cfxlen;
         }
-        else
-        {
-            int offset = 0;
-            int cdx = 0;
-            if ((fadeLeftStart <= idx) && (idx <= fadeLeftEnd))
-            {
-                offset = fadeLeftEnd - idx;
-                cdx = fadeRightEnd - offset;
-                p->inCrossfade = 1;
-            }
-            else if ((fadeRightStart <= idx) && (idx <= fadeRightEnd))
-            {
-                offset = idx - fadeRightStart;
-                cdx = fadeLeftStart + offset;
-                p->inCrossfade = 1;
-            }
-            
-            if (p->inCrossfade)
-            {
-                int c1 = cdx-(1*dir);
-                int c2 = cdx;
-                int c3 = cdx+(1*dir);
-                int c4 = cdx+(2*dir);
-                
-                // Wrap as needed
-                c1 = (c1 < length * rev) ? c1 + (length * (1-rev)) : c1 - (length * rev);
-                c2 = (c2 < length * rev) ? c2 + (length * (1-rev)) : c2 - (length * rev);
-                c3 = (c3 < length * (1-rev)) ? c3 + (length * rev) : c3 - (length * (1-rev));
-                c4 = (c4 < length * (1-rev)) ? c4 + (length * rev) : c4 - (length * (1-rev));
-                
-                cfxsample = LEAF_interpolate_hermite_x (buff[c1],
-                                                        buff[c2],
-                                                        buff[c3],
-                                                        buff[c4],
-                                                        alpha);
-                crossfadeMix = (float) offset / (float) cfxlen;
-            }
-        }
     }
     
     float inc = fmod(p->inc, p->len);
     p->idx += (dir * inc);
-    if (p->flipIdx >= 0)
+    if (p->flipStart >= 0)
     {
         p->flipIdx += (-dir * inc);
+        if((int)p->flipIdx < 0)
+        {
+            p->idx += (float)length;
+        }
+        if((int)p->idx >= length)
+        {
+            
+            p->idx -= (float)length;
+        }
     }
     
     if (p->mode == PlayLoop)
@@ -421,7 +431,7 @@
         }
     }
     
-    sample = (sample * (1.0f - crossfadeMix)) + (cfxsample * crossfadeMix);
+    sample = ((sample * (1.0f - crossfadeMix)) + (cfxsample * crossfadeMix)) * (1.0f - flipMix) + (flipsample * flipMix);
     
     sample = sample * tRamp_tick(&p->gain);
     
@@ -580,7 +590,7 @@
         uint32_t cfxlen = p->cfxlen;
         if (p->len * 0.25f < cfxlen) cfxlen = p->len * 0.25f;
         
-        if (p->inCrossfade)
+        if (p->inCrossfade || p->flipStart >= 0)
         {
             p->targetstart = start;
             return;
@@ -603,9 +613,12 @@
         }
     }
     
-    if (tempflip != p->flip && p->flipIdx < 0) p->flipIdx = 0;
+    if (tempflip != p->flip && p->flipStart < 0)
+    {
+        p->flipIdx = 0;
+    }
     
-    p->start = LEAF_clipInt(0, start, p->samp->recordedLength - 1);
+    p->start = LEAF_clipInt(0, start, p->samp->recordedLength-1);
     handleStartEndChange(sp);
     p->targetstart = -1;
     
@@ -639,7 +652,7 @@
         uint32_t cfxlen = p->cfxlen;
         if (p->len * 0.25f < cfxlen) cfxlen = p->len * 0.25f;
         
-        if (p->inCrossfade)
+        if (p->inCrossfade || p->flipStart >= 0)
         {
             p->targetend = end;
             return;
@@ -662,9 +675,12 @@
         }
     }
     
-    if (tempflip != p->flip && p->flipIdx < 0) p->flipIdx = 0;
+    if (tempflip != p->flip && p->flipStart < 0)
+    {
+        p->flipIdx = 0;
+    }
     
-    p->end = LEAF_clipInt(0, end, (p->samp->recordedLength - 1));
+    p->end = LEAF_clipInt(0, end, p->samp->recordedLength-1);
     handleStartEndChange(sp);
     p->targetend = -1;
 }