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;
}