shithub: leaf

Download patch

ref: 382ddd1e8d09ecc06f4bd7e02e274e7fdcda63ee
parent: d634fb3b428b1cc7bc1f06b39a2ef43f8cc17f2c
author: Matthew Wang <mjw7@princeton.edu>
date: Fri Aug 7 12:04:58 EDT 2020

mostly working minblep sampler

--- a/TestPlugin/Source/MyTest.cpp
+++ b/TestPlugin/Source/MyTest.cpp
@@ -14,21 +14,6 @@
 static void leaf_pool_dump(void);
 static void run_pool_test(void);
 
-tNoise noise;
-tSVF bp1;
-tSVF bp2;
-tFormantShifter fs;
-
-tSampler samp;
-tBuffer buff;
-tEnvelope env;
-
-tAutotune at;
-
-tPhasor phasor;
-
-tHighpass hipass;
-
 tMBSaw bsaw;
 tMBTriangle btri;
 tMBPulse bpulse;
@@ -42,6 +27,9 @@
 
 tCycle sine;
 
+tBuffer samp;
+tMBSampler sampler;
+
 float gain;
 float dtime;
 bool buttonState;
@@ -53,7 +41,7 @@
 float* bufIn;
 float* bufOut;
 
-#define MSIZE 500000
+#define MSIZE 2048000
 char memory[MSIZE];
 
 void    LEAFTest_init            (float sampleRate, int blockSize)
@@ -76,6 +64,12 @@
     
     tCycle_init(&sine);
     tCycle_setFreq(&sine, 100);
+    
+    tBuffer_init(&samp, 5.0f * leaf.sampleRate);
+    tMBSampler_init(&sampler, &samp);
+    
+    tMBSampler_setMode(&sampler, PlayLoop);
+    tMBSampler_setEnd(&sampler, samp->bufferLength);
 }
 
 inline double getSawFall(double angle) {
@@ -90,6 +84,11 @@
 float lastFreq;
 float   LEAFTest_tick            (float input)
 {
+    tBuffer_tick(&samp, input);
+    
+    return tMBSampler_tick(&sampler);
+    
+    
 //    tMBSaw_setFreq(&bsaw, x);
 //    tMBTriangle_setFreq(&btri, x);
 //    tMBPulse_setFreq(&bpulse, x);
@@ -102,21 +101,21 @@
 //    return tMBPulse_tick(&bpulse);
 
     
-    float freq = 1.0f/tPeriodDetection_tick(&pd, input) * leaf.sampleRate;
-    tPitchDetector_tick(&detector, input);
-    float altFreq = tPitchDetector_getFrequency(&detector);
-    
-    if (fabsf(1.0f - (freq / altFreq)) < 0.05f)
-//    if (tZeroCrossingCounter_tick(&zc, input) < 0.05 && freq > 0.0f)
-    {
-        tCycle_setFreq(&sine, altFreq);
-    }
-
-    float g = tEnvelopeFollower_tick(&ef, input);
-    
-    lastFreq = freq;
-    
-    return tCycle_tick(&sine) * g * 2.0f + input;
+//    float freq = 1.0f/tPeriodDetection_tick(&pd, input) * leaf.sampleRate;
+//    tPitchDetector_tick(&detector, input);
+//    float altFreq = tPitchDetector_getFrequency(&detector);
+//
+//    if (fabsf(1.0f - (freq / altFreq)) < 0.05f)
+////    if (tZeroCrossingCounter_tick(&zc, input) < 0.05 && freq > 0.0f)
+//    {
+//        tCycle_setFreq(&sine, altFreq);
+//    }
+//
+//    float g = tEnvelopeFollower_tick(&ef, input);
+//
+//    lastFreq = freq;
+//
+//    return tCycle_tick(&sine) * g * 2.0f + input;
 }
 
 int firstFrame = 1;
@@ -129,37 +128,27 @@
         DBG(tPitchDetector_getFrequency(&detector));
         DBG(tPitchDetector_getPeriodicity(&detector));
     }
-    //    if (firstFrame == 1)
-    //    {
-    //        tBuffer_record(&buff); // starts recording
-    //        tSampler_play(&samp); // start spitting samples out
-    //        firstFrame = 0;
-    //    }
     
-    float val = getSliderValue("mod freq");
+    float val = getSliderValue("on/off");
     
-    x = val;
+    if (val > 0.5f && !sampler->active)
+    {
+        tBuffer_record(&samp);
+        tMBSampler_play(&sampler);
+    }
+    else if (val < 0.5f && sampler->active)
+    {
+        tMBSampler_stop(&sampler);
+    }
     
-        
+    val = getSliderValue("mod freq");
     
-    //    a = val * tBuffer_getBufferLength(&buff);
+    tMBSampler_setStart(&sampler, val * 5.0f * leaf.sampleRate);
+
     
-//    DBG("start: " + String(a));
-    
     val = getSliderValue("mod depth");
     
-    y = val * 2.0f - 1.0f;
-//    DBG(String(y));
-    //    b = val * tBuffer_getBufferLength(&buff);
-    
-//    DBG("rate: " + String(b));
-    //
-    //    tSampler_setStart(&samp, a);
-    //    tSampler_setEnd(&samp, b);
-    //    tSampler_setRate(&samp, b);
-    
-    //    tFormantShifter_setShiftFactor(&fs, x);
-    //    tFormantShifter_setIntensity(&fs, y);
+    tMBSampler_setRate(&sampler, val * 8.0f - 4.0f);
     
 }
 
--- a/leaf/Inc/leaf-math.h
+++ b/leaf/Inc/leaf-math.h
@@ -225,6 +225,10 @@
     
     float median3f(float a, float b, float c);
 
+    void place_step_dd(float *buffer, int index, float phase, float w, float scale);
+
+    void place_slope_dd(float *buffer, int index, float phase, float w, float slope_delta);
+
     /*! @} */
 
     //==============================================================================
--- a/leaf/Inc/leaf-sampling.h
+++ b/leaf/Inc/leaf-sampling.h
@@ -352,6 +352,108 @@
     void    tAutoSampler_setWindowSize      (tAutoSampler* const, uint32_t size);
     void    tAutoSampler_setCrossfadeLength (tAutoSampler* const, uint32_t length);
     void    tAutoSampler_setRate            (tAutoSampler* const, float rate);
+
+
+/*!
+     @defgroup tMBSampler tMBSampler
+     @ingroup sampling
+     @brief
+     @{
+     
+     @fn void    tMBSampler_init               (tMBSampler* const, tBuffer* const)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_initToPool         (tMBSampler* const, tBuffer* const, tMempool* const)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_free               (tMBSampler* const)
+     @brief
+     @param
+     
+     @fn float   tMBSampler_tick               (tMBSampler* const)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setSample          (tMBSampler* const, tBuffer* const)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setMode            (tMBSampler* const, PlayMode mode)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_play               (tMBSampler* const)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_stop               (tMBSampler* const)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setStart           (tMBSampler* const, int32_t start)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setEnd             (tMBSampler* const, int32_t end)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setLength             (tMBSampler* const, int32_t length)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setCrossfadeLength (tMBSampler* const sp, uint32_t length)
+     @brief
+     @param
+     
+     @fn void    tMBSampler_setRate            (tMBSampler* const, float rate)
+     @brief
+     @param
+     
+     @} */
+    
+#define FILLEN 256
+
+    typedef struct _tMBSampler
+    {
+        tMempool mempool;
+        
+        tBuffer samp;
+        PlayMode mode;
+        int active;
+        
+        tExpSmooth gain;
+        
+        float    out;
+        float    last_delta;
+        float    amp;
+        float    last_amp;
+        float    syncin;
+        float   _p, _w, _z;
+        float   _last_w;
+        float   _f [FILLEN + STEP_DD_PULSE_LENGTH];
+        int     _j;
+        
+        int     start, end;
+    } _tMBSampler;
+    
+    typedef _tMBSampler* tMBSampler;
+    
+    void    tMBSampler_init               (tMBSampler* const, tBuffer* const);
+    void    tMBSampler_initToPool         (tMBSampler* const, tBuffer* const, tMempool* const);
+    void    tMBSampler_free               (tMBSampler* const);
+    
+    float   tMBSampler_tick               (tMBSampler* const);
+    void    tMBSampler_setSample          (tMBSampler* const, tBuffer* const);
+    void    tMBSampler_setMode            (tMBSampler* const, PlayMode mode);
+    void    tMBSampler_play               (tMBSampler* const);
+    void    tMBSampler_stop               (tMBSampler* const);
+    void    tMBSampler_setStart           (tMBSampler* const, int32_t start);
+    void    tMBSampler_setEnd             (tMBSampler* const, int32_t end);
+    void    tMBSampler_setLength          (tMBSampler* const, int32_t length);
+    void    tMBSampler_setRate            (tMBSampler* const, float rate);
     
 #ifdef __cplusplus
 }
--- a/leaf/Src/leaf-math.c
+++ b/leaf/Src/leaf-math.c
@@ -786,3 +786,51 @@
 {
     return fmax(fmin(a, b), fmin(fmax(a, b), c));
 }
+
+/// MINBLEPS
+
+// https://github.com/MrBlueXav/Dekrispator_v2 blepvco.c
+
+
+void place_step_dd(float *buffer, int index, float phase, float w, float scale)
+{
+    float r;
+    int i;
+    
+    r = MINBLEP_PHASES * phase / w;
+    i = floorf(r); //rintf(r - 0.5f); is there a reason to use rintf here
+    r -= (float)i;
+    i &= MINBLEP_PHASE_MASK;  /* extreme modulation can cause i to be out-of-range */
+    /* this would be better than the above, but more expensive:
+     *  while (i < 0) {
+     *    i += MINBLEP_PHASES;
+     *    index++;
+     *  }
+     */
+    
+    while (i < MINBLEP_PHASES * STEP_DD_PULSE_LENGTH) {
+        buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta);
+        i += MINBLEP_PHASES;
+        index++;
+    }
+}
+//----------------------------------------------------------------------------------------------------------
+
+void place_slope_dd(float *buffer, int index, float phase, float w, float slope_delta)
+{
+    float r;
+    int i;
+    
+    r = MINBLEP_PHASES * phase / w;
+    i = rintf(r - 0.5f);
+    r -= (float)i;
+    i &= MINBLEP_PHASE_MASK;  /* extreme modulation can cause i to be out-of-range */
+    
+    slope_delta *= w;
+    
+    while (i < MINBLEP_PHASES * SLOPE_DD_PULSE_LENGTH) {
+        buffer[index] += slope_delta * (slope_dd_table[i] + r * (slope_dd_table[i + 1] - slope_dd_table[i]));
+        i += MINBLEP_PHASES;
+        index++;
+    }
+}
--- a/leaf/Src/leaf-oscillators.c
+++ b/leaf/Src/leaf-oscillators.c
@@ -868,53 +868,7 @@
 }
 
 
-/// MINBLEPS
 
-// https://github.com/MrBlueXav/Dekrispator_v2 blepvco.c
-
-
-static void place_step_dd(float *buffer, int index, float phase, float w, float scale)
-{
-    float r;
-    int i;
-    
-    r = MINBLEP_PHASES * phase / w;
-    i = rintf(r - 0.5f);
-    r -= (float)i;
-    i &= MINBLEP_PHASE_MASK;  /* extreme modulation can cause i to be out-of-range */
-    /* this would be better than the above, but more expensive:
-     *  while (i < 0) {
-     *    i += MINBLEP_PHASES;
-     *    index++;
-     *  }
-     */
-    
-    while (i < MINBLEP_PHASES * STEP_DD_PULSE_LENGTH) {
-        buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta);
-        i += MINBLEP_PHASES;
-        index++;
-    }
-}
-//----------------------------------------------------------------------------------------------------------
-
-static void place_slope_dd(float *buffer, int index, float phase, float w, float slope_delta)
-{
-    float r;
-    int i;
-    
-    r = MINBLEP_PHASES * phase / w;
-    i = rintf(r - 0.5f);
-    r -= (float)i;
-    i &= MINBLEP_PHASE_MASK;  /* extreme modulation can cause i to be out-of-range */
-    
-    slope_delta *= w;
-    
-    while (i < MINBLEP_PHASES * SLOPE_DD_PULSE_LENGTH) {
-        buffer[index] += slope_delta * (slope_dd_table[i] + r * (slope_dd_table[i + 1] - slope_dd_table[i]));
-        i += MINBLEP_PHASES;
-        index++;
-    }
-}
 //----------------------------------------------------------------------------------------------------------
 
 void tMBPulse_init(tMBPulse* const osc)
--- a/leaf/Src/leaf-sampling.c
+++ b/leaf/Src/leaf-sampling.c
@@ -875,3 +875,285 @@
 {
     ;
 }
+
+
+
+void tMBSampler_init(tMBSampler* const sp, tBuffer* const b)
+{
+    tMBSampler_initToPool(sp, b, &leaf.mempool);
+}
+
+void tMBSampler_initToPool(tMBSampler* const sp, tBuffer* const b, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tMBSampler* c = *sp = (_tMBSampler*) mpool_alloc(sizeof(_tMBSampler), m);
+    c->mempool = m;
+    
+    c->samp = *b;
+    
+    c->mode = PlayLoop;
+    c->active = 0;
+        
+    tExpSmooth_initToPool(&c->gain, 0.0f, 0.01f, mp);
+    
+    c->amp = 1.0f;
+    c->_p = 0.0f;
+    c->_w = 1.0f;
+    c->syncin = 0.0f;
+    c->_z = 0.0f;
+    c->_j = 0;
+    memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float));
+
+    c->start = 0;
+    tMBSampler_setEnd(sp, c->samp->bufferLength);
+}
+
+void tMBSampler_free (tMBSampler* const sp)
+{
+    _tMBSampler* p = *sp;
+    
+    tExpSmooth_free(&p->gain);
+    
+    mpool_free((char*)p, p->mempool);
+}
+
+void tMBSampler_setSample (tMBSampler* const sp, tBuffer* const b)
+{
+    _tMBSampler* p = *sp;
+    
+    p->samp = *b;;
+    
+    p->start = 0;
+    tMBSampler_setEnd(sp, p->samp->bufferLength);
+    
+    p->_p = 0.0f;
+}
+
+
+
+float tMBSampler_tick        (tMBSampler* const sp)
+{
+    _tMBSampler* c = *sp;
+    
+    if (c->gain->curr == 0.0f && !c->active) return 0.0f;
+    if (c->_w == 0.0f) return c->out;
+    
+    int start, end, length;
+    float* buff;
+    int    j;
+    float  syncin;
+    float  a, p, w, z;
+    syncin  = c->syncin;
+        
+    start = c->start;
+    end = c->end;
+
+    buff = c->samp->buff;
+    
+    p = c->_p;  /* position */
+    w = c->_w;  /* rate */
+    z = c->_z;  /* low pass filter state */
+    j = c->_j;  /* index into buffer _f */
+    
+    length = end - start;
+
+    //a = 0.2 + 0.8 * vco->_port [FILT];
+    a = 0.5f; // when a = 1, LPfilter is disabled
+    
+    p += w;
+    
+    float next;
+    
+//    if (syncin >= 1e-20f) {  /* sync to master */
+//
+//        float eof_offset = (syncin - 1e-20f) * w;
+//        float p_at_reset = p - eof_offset;
+//        p = eof_offset;
+//
+//        /* place any DD that may have occurred in subsample before reset */
+//        if (p_at_reset >= end) {
+//            while (p_at_reset >= (float) end) p_at_reset -= (float) length;
+//
+//            float f = p_at_reset + eof_offset;
+//            int i = (int) f;
+//            f -= i;
+//            float n = buff[i] * (1.0f - f) + buff[i+1] * f;
+//
+//            place_step_dd(c->_f, j, p_at_reset + eof_offset, w,
+//                          n - c->out);
+//            place_slope_dd(c->_f, j, p_at_reset + eof_offset, w, (n - c->out) - c->last_delta);
+//        }
+//
+//        float f = p_at_reset;
+//        int i = (int) f;
+//        f -= i;
+//        next = buff[i] * (1.0f - f) + buff[i+1] * f;
+//
+//        /* now place reset DD */
+//        place_step_dd(c->_f, j, p, w, next - c->out);
+//        place_slope_dd(c->_f, j, p, w, (next - c->out) - c->last_delta);
+//
+//    } else
+    if (w > 0.0f) {
+    
+        if (p >= (float) end) {  /* normal phase reset */
+        
+            // start and end are never negative and end must also be greater than start
+            // so this loop is fine
+            while (p >= (float) end) p -= (float) length;
+            
+            float f = p;
+            int i = (int) f;
+            f -= i;
+            next = buff[i] * (1.0f - f) + buff[i+1] * f;
+            
+            place_step_dd(c->_f, j, p - start, w, next - c->out);
+            place_slope_dd(c->_f, j, p - start, w, (next - c->out) - c->last_delta);
+            
+            if (c->mode == PlayNormal) c->active = 0;
+            else if (c->mode == PlayBackAndForth) w = -w;
+        }
+//        else if (p < (float) start) { /* start has been set ahead of the current phase */
+//
+//            p = (float) start;
+//            next = buff[start];
+//
+//            place_step_dd(c->_f, j, p, w, next - c->last);
+//            place_slope_dd(c->_f, j, p, w, (next - c->last) - c->last_delta);
+//        }
+        else {
+            
+            float f = p;
+            int i = (int) f;
+            f -= i;
+            next = buff[i] * (1.0f - f) + buff[i+1] * f;
+        }
+
+        if (c->_last_w < 0.0f)
+        {
+            place_slope_dd(c->_f, j, p - start, w, (next - c->out) - c->last_delta);
+        }
+        
+    } else { // if (w < 0.0f) {
+        
+        if (p < (float) start) {
+        
+            while (p < (float) start) p += (float) length;
+            
+            float f = p;
+            int i = (int) f;
+            f -= i;
+            next = buff[i] * (1.0f - f) + buff[i+1] * f;
+            
+            place_step_dd(c->_f, j, end - p, w, next - c->out);
+            place_slope_dd(c->_f, j, end - p, w, (next - c->out) - c->last_delta);
+            
+            if (c->mode == PlayNormal) c->active = 0;
+            else if (c->mode == PlayBackAndForth) w = -w;
+        }
+//        else if (p >= (float) end) {
+//
+//            p = (float) end - 1;
+//            next = buff[end - 1];
+//            place_step_dd(c->_f, j, p, w, next - c->last);
+//            place_slope_dd(c->_f, j, p, w, (next - c->last) - c->last_delta);
+//        }
+        else {
+            
+            float f = p;
+            int i = (int) f;
+            f -= i;
+            next = buff[i] * (1.0f - f) + buff[i+1] * f;
+        }
+        
+        if (c->_last_w > 0.0f)
+        {
+            place_slope_dd(c->_f, j, end - p, w, (next - c->out) - c->last_delta);
+        }
+    }
+    
+    c->_f[j + DD_SAMPLE_DELAY] += next;
+    
+    z += a * (c->_f[j] - z); // LP filtering
+    next = c->amp * z;
+    
+    c->last_delta = next - c->out;
+    
+    c->out = next;
+    
+    if (++j == FILLEN)
+    {
+        j = 0;
+        memcpy (c->_f, c->_f + FILLEN, STEP_DD_PULSE_LENGTH * sizeof (float));
+        memset (c->_f + STEP_DD_PULSE_LENGTH, 0,  FILLEN * sizeof (float));
+    }
+    
+    c->_p = p;
+    c->_w = c->_last_w = w;
+    c->_z = z;
+    c->_j = j;
+    
+    return c->out * tExpSmooth_tick(&c->gain);
+}
+
+void tMBSampler_setMode      (tMBSampler* const sp, PlayMode mode)
+{
+    _tMBSampler* p = *sp;
+    p->mode = mode;
+}
+
+void tMBSampler_play         (tMBSampler* const sp)
+{
+    _tMBSampler* p = *sp;
+    
+    if (p->active > 0)
+    {
+        p->syncin = 1e-20f;
+    }
+    tExpSmooth_setDest(&p->gain, 1.0f);
+    p->active = 1;
+    p->_p = p->start;
+    p->_z = 0.0f;
+    p->_j = 0;
+}
+
+void tMBSampler_stop         (tMBSampler* const sp)
+{
+    _tMBSampler* p = *sp;
+    
+    tExpSmooth_setDest(&p->gain, 0.0f);
+    p->active = 0;
+}
+
+void tMBSampler_setStart     (tMBSampler* const sp, int32_t start)
+{
+    _tMBSampler* p = *sp;
+    
+    if (start > p->end - 1) p->start = p->end - 1;
+    else if (start < 0) p->start = 0;
+    else p->start = start;
+}
+
+void tMBSampler_setEnd       (tMBSampler* const sp, int32_t end)
+{
+    _tMBSampler* p = *sp;
+    
+    if (end < p->start + 1) p->end = p->start + 1;
+    // always leave a trailing sample after the end
+    else if (end >= p->samp->bufferLength) p->end = p->samp->bufferLength - 1;
+    else p->end = end;
+}
+
+void    tMBSampler_setLength    (tMBSampler* const sp, int32_t length)
+{
+    _tMBSampler* p = *sp;
+    tMBSampler_setEnd(sp, p->start + length);
+}
+
+void tMBSampler_setRate      (tMBSampler* const sp, float rate)
+{
+    _tMBSampler* p = *sp;
+    
+    p->_w = rate;
+}
+