ref: e28e39c0a93bee134f72005825280341e4470e35
parent: 9d82b87d6add3910d6e23699ff28166b0b14e6fd
author: mulshine <mulshine@princeton.edu>
date: Wed Jan 16 12:36:43 EST 2019
Added custom tTapeDelay object.
--- a/LEAF/Inc/leaf-delay.h
+++ b/LEAF/Inc/leaf-delay.h
@@ -111,6 +111,39 @@
float tDelayA_getLastOut (tDelayA* const);
float tDelayA_getLastIn (tDelayA* const);
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Linear interpolating delay with fixed read and write pointers, variable rate. */
+typedef struct _tTapeDelay
+{
+ float gain;
+ float* buff;
+
+ float lastOut, lastIn;
+
+ uint32_t inPoint;
+ uint32_t outPoint;
+
+ uint32_t maxDelay;
+
+ float delay, inc, idx;
+
+ float alpha, omAlpha, coeff;
+
+ float apInput;
+
+} tTapeDelay;
+
+void tTapeDelay_init (tTapeDelay* const, float delay, uint32_t maxDelay);
+void tTapeDelay_free (tTapeDelay* const);
+
+int tTapeDelay_setDelay (tTapeDelay* const, float delay);
+float tTapeDelay_getDelay (tTapeDelay* const);
+void tTapeDelay_tapIn (tTapeDelay* const, float in, uint32_t tapDelay);
+float tTapeDelay_tapOut (tTapeDelay* const, uint32_t tapDelay);
+float tTapeDelay_addTo (tTapeDelay* const, float value, uint32_t tapDelay);
+float tTapeDelay_tick (tTapeDelay* const, float sample);
+float tTapeDelay_getLastOut (tTapeDelay* const);
+float tTapeDelay_getLastIn (tTapeDelay* const);
#endif // LEAFDELAY_H_INCLUDED
--- a/LEAF/Inc/leaf-math.h
+++ b/LEAF/Inc/leaf-math.h
@@ -89,6 +89,11 @@
// dope af
float LEAF_chebyshevT(float in, int n);
float LEAF_CompoundChebyshevT(float in, int n, float* amps);
+
+
+// Hermite interpolation
+float LEAF_interpolate_hermite (float A, float B, float C, float D, float t);
+float LEAF_interpolation_linear (float A, float B, float t);
static inline float interpolate3max(float *buf, const int peakindex)
{
--- a/LEAF/Inc/leaf-reverb.h
+++ b/LEAF/Inc/leaf-reverb.h
@@ -81,7 +81,6 @@
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
typedef struct _tDattorro
{
float predelay;
@@ -90,13 +89,14 @@
float feedback_gain;
float mix;
- float size, t;
+ float size, size_max, t;
+
float f1_delay_2_last,
- f2_delay_2_last;
+ f2_delay_2_last;
float f1_last,
- f2_last;
+ f2_last;
// INPUT
tDelayL in_delay;
@@ -109,6 +109,7 @@
tOnePole f1_filter;
tDelayL f1_delay_2;
tDelayL f1_delay_3;
+ tHighpass f1_hp;
tCycle f1_lfo;
@@ -118,9 +119,10 @@
tOnePole f2_filter;
tDelayL f2_delay_2;
tDelayL f2_delay_3;
+ tHighpass f2_hp;
tCycle f2_lfo;
-
+
} tDattorro;
void tDattorro_init (tDattorro* const);
@@ -133,7 +135,6 @@
void tDattorro_setInputDelay (tDattorro* const, float preDelay);
void tDattorro_setInputFilter (tDattorro* const, float freq);
void tDattorro_setFeedbackFilter (tDattorro* const, float freq);
-void tDattorro_setFeedbackGain (tDattorro* const, float gain);
-
+void tDattorro_setFeedbackGain (tDattorro* const, float gain);
#endif // LEAFREVERB_H_INCLUDED
--- a/LEAF/Src_cpp/leaf-delay.cpp
+++ b/LEAF/Src_cpp/leaf-delay.cpp
@@ -63,9 +63,9 @@
int tDelay_setDelay (tDelay* const d, uint32_t delay)
{
- if (delay >= d->maxDelay) d->delay = d->maxDelay;
- else d->delay = delay;
+ d->delay = LEAF_clip(0.0f, delay, d->maxDelay);
+
// read chases write
if ( d->inPoint >= delay ) d->outPoint = d->inPoint - d->delay;
else d->outPoint = d->maxDelay + d->inPoint - d->delay;
@@ -163,29 +163,26 @@
d->buff[d->inPoint] = input * d->gain;
// Increment input pointer modulo length.
- if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
+ if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
+
+
+ uint32_t idx = (uint32_t) d->outPoint;
+
+ d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
+ d->buff[idx],
+ d->buff[(idx + 1) % d->maxDelay],
+ d->buff[(idx + 2) % d->maxDelay],
+ d->alpha);
+ // Increment output pointer modulo length
+ if ( (++d->outPoint) >= d->maxDelay ) d->outPoint = 0;
- // First 1/2 of interpolation
- d->lastOut = d->buff[d->outPoint] * d->omAlpha;
-
- // Second 1/2 of interpolation
- if (d->outPoint + 1 < d->maxDelay)
- d->lastOut += d->buff[d->outPoint+1] * d->alpha;
- else
- d->lastOut += d->buff[0] * d->alpha;
-
- // Increment output pointer modulo length.
- if ( ++(d->outPoint) == d->maxDelay ) d->outPoint = 0;
-
return d->lastOut;
}
int tDelayL_setDelay (tDelayL* const d, float delay)
-{
- if (delay < 0.0f) d->delay = 0.0f;
- else if (delay <= d->maxDelay) d->delay = delay;
- else d->delay = d->maxDelay;
+{
+ d->delay = LEAF_clip(0.0f, delay, d->maxDelay);
float outPointer = d->inPoint - d->delay;
@@ -326,10 +323,9 @@
int tDelayA_setDelay (tDelayA* const d, float delay)
{
- if (delay < 0.5f) d->delay = 0.5f;
- else if (delay <= d->maxDelay) d->delay = delay;
- else d->delay = d->maxDelay;
+ d->delay = LEAF_clip(0.5f, delay, d->maxDelay);
+
// outPoint chases inPoint
float outPointer = (float)d->inPoint - d->delay + 1.0f;
@@ -413,5 +409,156 @@
float tDelayA_getGain (tDelayA* const d)
{
return d->gain;
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TapeDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void tTapeDelay_init (tTapeDelay* const d, float delay, uint32_t maxDelay)
+{
+ d->maxDelay = maxDelay;
+
+ d->delay = LEAF_clip(0.0f, delay, d->maxDelay);
+
+ d->buff = (float*) leaf_alloc(sizeof(float) * maxDelay);
+
+ d->gain = 1.0f;
+
+ d->lastIn = 0.0f;
+ d->lastOut = 0.0f;
+
+ d->idx = 0.0f;
+ d->inc = 1.0f;
+ d->inPoint = 0;
+ d->outPoint = 0;
+
+ tTapeDelay_setDelay(d, 1);
+}
+
+void tTapeDelay_free(tTapeDelay* const d)
+{
+ leaf_free(d->buff);
+ leaf_free(d);
+}
+
+int count = 0;
+
+#define SMOOTH_FACTOR 10.f
+
+float tTapeDelay_tick (tTapeDelay* const d, float input)
+{
+ d->buff[d->inPoint] = input * d->gain;
+
+ // Increment input pointer modulo length.
+ if (++(d->inPoint) == d->maxDelay ) d->inPoint = 0;
+
+ int idx = (int) d->idx;
+ d->alpha = d->idx - idx;
+
+ d->lastOut = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
+ d->buff[idx],
+ d->buff[(idx + 1) % d->maxDelay],
+ d->buff[(idx + 2) % d->maxDelay],
+ d->alpha);
+
+ float diff = (d->inPoint - d->idx);
+ while (diff < 0.f) diff += d->maxDelay;
+
+ d->inc = 1.0f + (diff - d->delay) / d->delay * SMOOTH_FACTOR;
+
+ d->idx += d->inc;
+
+ if (d->idx >= d->maxDelay) d->idx = 0.f;
+
+ if ( ++(d->outPoint) >= d->maxDelay ) d->outPoint -= d->maxDelay;
+
+ return d->lastOut;
+}
+
+
+void tTapeDelay_setRate(tTapeDelay* const d, float rate)
+{
+ d->inc = rate;
+}
+
+int tTapeDelay_setDelay (tTapeDelay* const d, float delay)
+{
+ d->delay = LEAF_clip(0.0f, delay, d->maxDelay);
+
+
+ float outPointer = d->inPoint - d->delay;
+
+ while ( outPointer < 0 )
+ outPointer += d->maxDelay; // modulo maximum length
+
+ d->outPoint = (uint32_t) outPointer; // integer part
+
+
+ return 0;
+}
+
+float tTapeDelay_tapOut (tTapeDelay* const d, float tapDelay)
+{
+ float tap = (float) d->inPoint - tapDelay - 1.f;
+
+ // Check for wraparound.
+ while ( tap < 0.f ) tap += (float)d->maxDelay;
+
+ int idx = (int) tap;
+
+ float alpha = tap - idx;
+
+ float samp = LEAF_interpolate_hermite (d->buff[((idx - 1) + d->maxDelay) % d->maxDelay],
+ d->buff[idx],
+ d->buff[(idx + 1) % d->maxDelay],
+ d->buff[(idx + 2) % d->maxDelay],
+ d->alpha);
+
+ return samp;
+
+}
+
+void tTapeDelay_tapIn (tTapeDelay* const d, float value, uint32_t tapDelay)
+{
+ int32_t tap = d->inPoint - tapDelay - 1;
+
+ // Check for wraparound.
+ while ( tap < 0 ) tap += d->maxDelay;
+
+ d->buff[tap] = value;
+}
+
+float tTapeDelay_addTo (tTapeDelay* const d, float value, uint32_t tapDelay)
+{
+ int32_t tap = d->inPoint - tapDelay - 1;
+
+ // Check for wraparound.
+ while ( tap < 0 ) tap += d->maxDelay;
+
+ return (d->buff[tap] += value);
+}
+
+float tTapeDelay_getDelay (tTapeDelay *d)
+{
+ return d->delay;
+}
+
+float tTapeDelay_getLastOut (tTapeDelay* const d)
+{
+ return d->lastOut;
+}
+
+float tTapeDelay_getLastIn (tTapeDelay* const d)
+{
+ return d->lastIn;
+}
+
+void tTapeDelay_setGain (tTapeDelay* const d, float gain)
+{
+ if (gain < 0.0f) d->gain = 0.0f;
+ else d->gain = gain;
+}
+
+float tTapeDelay_getGain (tTapeDelay* const d)
+{
+ return d->gain;
}
--- a/LEAF/Src_cpp/leaf-math.cpp
+++ b/LEAF/Src_cpp/leaf-math.cpp
@@ -231,4 +231,34 @@
if( f <= -1500.0f ) return (0);
else if( f > 1499.0f ) return (LEAF_midiToFrequency(1499.0f));
else return ( powf(2.0f, (f - 69.0f) / 12.0f) * 440.0f );
-}
+}
+
+
+// alpha, [0.0, 1.0]
+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/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 d = B;
+
+ return a*alpha*alpha*alpha + b*alpha*alpha + c*alpha + d;
+}
+
+// alpha, [0.0, 1.0]
+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;
+}
+
--- a/LEAF/Src_cpp/leaf-reverb.cpp
+++ b/LEAF/Src_cpp/leaf-reverb.cpp
@@ -262,9 +262,12 @@
float in_allpass_delays[4] = { 4.771f, 3.595f, 12.73f, 9.307f };
float in_allpass_gains[4] = { 0.75f, 0.75f, 0.625f, 0.625f };
+
void tDattorro_init (tDattorro* const r)
{
- tDattorro_setSize(r, 1.0f);
+ r->size_max = 2.0f;
+ r->size = 1.f;
+ r->t = r->size * leaf.sampleRate * 0.001f;
// INPUT
tDelayL_init(&r->in_delay, 0.f, SAMP(200.f));
@@ -272,33 +275,37 @@
for (int i = 0; i < 4; i++)
{
- tAllpass_init(&r->in_allpass[i], in_allpass_delays[i], SAMP(20.f));
+ tAllpass_init(&r->in_allpass[i], SAMP(in_allpass_delays[i]), SAMP(20.f)); // * r->size_max
tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]);
}
// FEEDBACK 1
- tAllpass_init(&r->f1_allpass, SAMP(30.51f), SAMP(100.f));
+ tAllpass_init(&r->f1_allpass, SAMP(30.51f), SAMP(100.f)); // * r->size_max
tAllpass_setGain(&r->f1_allpass, 0.7f);
- tDelayL_init(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f));
- tDelayL_init(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f));
- tDelayL_init(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f));
+ tDelayL_init(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f) * r->size_max + 1);
+ tDelayL_init(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f) * r->size_max + 1);
+ tDelayL_init(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f) * r->size_max + 1);
tOnePole_init(&r->f1_filter, 1.f);
+ tHighpass_init(&r->f1_hp, 20.f);
+
tCycle_init(&r->f1_lfo);
tCycle_setFreq(&r->f1_lfo, 0.1f);
// FEEDBACK 2
- tAllpass_init(&r->f2_allpass, SAMP(22.58f), SAMP(100.f));
+ tAllpass_init(&r->f2_allpass, SAMP(22.58f), SAMP(100.f)); // * r->size_max
tAllpass_setGain(&r->f2_allpass, 0.7f);
- tDelayL_init(&r->f2_delay_1, SAMP(149.62f), SAMP(200.0f));
- tDelayL_init(&r->f2_delay_2, SAMP(60.48f), SAMP(100.0f));
- tDelayL_init(&r->f2_delay_3, SAMP(106.28f), SAMP(200.0f));
+ tDelayL_init(&r->f2_delay_1, SAMP(149.62f), SAMP(200.f) * r->size_max + 1);
+ tDelayL_init(&r->f2_delay_2, SAMP(60.48f), SAMP(100.f) * r->size_max + 1);
+ tDelayL_init(&r->f2_delay_3, SAMP(106.28f), SAMP(200.f) * r->size_max + 1);
tOnePole_init(&r->f2_filter, 1.f);
+ tHighpass_init(&r->f2_hp, 20.f);
+
tCycle_init(&r->f2_lfo);
tCycle_setFreq(&r->f2_lfo, 0.07f);
@@ -313,6 +320,8 @@
tDattorro_setFeedbackFilter(r, 5000.f);
tDattorro_setFeedbackGain(r, 0.4f);
+
+
}
void tDattorro_free (tDattorro* const r)
@@ -382,6 +391,8 @@
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 = tDelayL_tick(&r->f1_delay_3, f1_sample);
@@ -405,6 +416,8 @@
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 = tDelayL_tick(&r->f2_delay_3, f2_sample);
@@ -412,7 +425,7 @@
// TAP OUT 1
f1_sample = tDelayL_tapOut(&r->f1_delay_1, SAMP(8.9f)) +
- tDelayL_tapOut(&r->f1_delay_1, SAMP(99.8f));
+ tDelayL_tapOut(&r->f1_delay_1, SAMP(99.8f));
f1_sample -= tDelayL_tapOut(&r->f1_delay_2, SAMP(64.2f));
@@ -428,7 +441,7 @@
// TAP OUT 2
f2_sample = tDelayL_tapOut(&r->f2_delay_1, SAMP(11.8f)) +
- tDelayL_tapOut(&r->f2_delay_1, SAMP(121.7f));
+ tDelayL_tapOut(&r->f2_delay_1, SAMP(121.7f));
f2_sample -= tDelayL_tapOut(&r->f2_delay_2, SAMP(6.3f));
@@ -454,8 +467,31 @@
void tDattorro_setSize (tDattorro* const r, float size)
{
- r->size = LEAF_clip(0.001f, size, 100.0f);
+ r->size = LEAF_clip(0.01f, size*r->size_max, r->size_max);
r->t = r->size * leaf.sampleRate * 0.001f;
+
+ /*
+ for (int i = 0; i < 4; i++)
+ {
+ tAllpass_setDelay(&r->in_allpass[i], SAMP(in_allpass_delays[i]));
+ }
+ */
+
+ // FEEDBACK 1
+ //tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f));
+
+ tDelayL_setDelay(&r->f1_delay_1, SAMP(141.69f));
+ tDelayL_setDelay(&r->f1_delay_2, SAMP(89.24f));
+ tDelayL_setDelay(&r->f1_delay_3, SAMP(125.f));
+
+ // maybe change rate of SINE LFO's when size changes?
+
+ // FEEDBACK 2
+ //tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f));
+
+ tDelayL_setDelay(&r->f2_delay_1, SAMP(149.62f));
+ tDelayL_setDelay(&r->f2_delay_2, SAMP(60.48f));
+ tDelayL_setDelay(&r->f2_delay_3, SAMP(106.28f));
}
void tDattorro_setInputDelay (tDattorro* const r, float preDelay)
@@ -483,5 +519,4 @@
void tDattorro_setFeedbackGain (tDattorro* const r, float gain)
{
r->feedback_gain = gain;
-}
-
+}
--- a/LEAF/leaf.h
+++ b/LEAF/leaf.h
@@ -9,7 +9,13 @@
*/
#ifndef LEAF_H_INCLUDED
-#define LEAF_H_INCLUDED
+#define LEAF_H_INCLUDED
+
+#define DEBUG 1
+
+#if DEBUG
+#include "../JuceLibraryCode/JuceHeader.h"
+#endif
#if _WIN32 || _WIN64
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ b/LEAF_JUCEPlugin/Source/MyTest.cpp
@@ -18,6 +18,12 @@
tDattorro reverb;
+
+tTapeDelay delay;
+
+float size;
+tRamp dtime;
+
void LEAFTest_init (float sampleRate, int blockSize)
{
@@ -24,14 +30,20 @@
LEAF_init(sampleRate, blockSize, &randomNumberGenerator);
tDattorro_init(&reverb);
+
+ //tTapeDelay_init(&delay, 0.5f * leaf.sampleRate, leaf.sampleRate);
+ tRamp_init(&dtime, 500.0f, 1);
+
+
setSliderValue("mix", reverb.mix);
setSliderValue("predelay", reverb.predelay / 200.0f);
setSliderValue("input filter", reverb.input_filter / 20000.0f);
setSliderValue("feedback filter", reverb.feedback_filter / 20000.0f);
setSliderValue("feedback gain", reverb.feedback_gain);
- //setSliderValue("size", reverb.size / 4.0f);
+ setSliderValue("size", reverb.size / 4.0f);
+
leaf_pool_report();
}
@@ -53,12 +65,20 @@
input = 1.0f;
}
#endif
+ //tTapeDelay_setDelay(&delay, tRamp_tick(&dtime));
+ //return tTapeDelay_tick(&delay, input);
+
+
+ tDattorro_setSize(&reverb, tRamp_tick(&dtime));
+
return tDattorro_tick(&reverb, input);
+
}
void LEAFTest_block (void)
{
+
float val = getSliderValue("mix");
tDattorro_setMix(&reverb, val);
@@ -74,8 +94,13 @@
val = getSliderValue("feedback gain");
tDattorro_setFeedbackGain(&reverb, val);
- //val = getSliderValue("size");
- //tDattorro_setSize(&reverb, val * 4.0f);
+ val = getSliderValue("size");
+ tRamp_setDest(&dtime, val * reverb.size_max);
+
+
+ //float val = getSliderValue("size");
+ //tRamp_setDest(&dtime, val * leaf.sampleRate + 1);
+
}
void LEAFTest_controllerInput (int cnum, float cval)