History

added some fixes to several leaf objects and major bug fix to tSampler

spiricom committed 6 years ago

Commit 23faeb01 parent 53a6d7a10 files · +516 −85Browse files

Unified · Split

10 files
  1. leaf/Inc/leaf-filters.h +4 −1
  2. leaf/Inc/leaf-math.h +7 −0
  3. leaf/Inc/leaf-mempool.h +1 −1
  4. leaf/Inc/leaf-sampling.h +13 −3
  5. leaf/Src/leaf-analysis.c +1 −1
  6. leaf/Src/leaf-effects.c +2 −2
  7. leaf/Src/leaf-filters.c +70 −54
  8. leaf/Src/leaf-math.c +41 −1
  9. leaf/Src/leaf-mempool.c +4 −3
  10. leaf/Src/leaf-sampling.c +373 −19
leaf/Inc/leaf-filters.h+4−1
@@ -1012,13 +1012,16 @@ extern "C" { · 1011 unmodified lines
10121012 float tVZFilter_tick (tVZFilter* const, float input);
10131013 float tVZFilter_tickEfficient (tVZFilter* const vf, float in);
10141014 void tVZFilter_calcCoeffs (tVZFilter* const);
1015+ void tVZFilter_calcCoeffsEfficientBP (tVZFilter* const);
10151016 void tVZFilter_setBandwidth (tVZFilter* const, float bandWidth);
10161017 void tVZFilter_setFreq (tVZFilter* const, float freq);
10171018 void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw);
1019+ void tVZFilter_setFreqAndBandwidthEfficientBP (tVZFilter* const vf, float freq, float bw);
10181020 void tVZFilter_setGain (tVZFilter* const, float gain);
1021+
10191022 void tVZFilter_setType (tVZFilter* const, VZFilterType type);
10201023 float tVZFilter_BandwidthToR (tVZFilter* const vf, float B);
1021−
1024+ float tVZFilter_BandwidthToREfficientBP(tVZFilter* const vf, float B);
10221025
10231026 /*!
10241027 @defgroup tdiodefilter tDiodeFilter
leaf/Inc/leaf-math.h+7−0
@@ -138,6 +138,13 @@ extern "C" { · 137 unmodified lines
138138 float fastcosf(float fAngle);
139139
140140 float fastercosf(float fAngle);
141+
142+ float fasttanf (float fAngle);
143+
144+
145+ float fastertanf(float fAngle);
146+
147+
141148 // alternative implementation for abs()
142149 // REQUIRES: 32 bit integers
143150 int fastabs_int(int in);
leaf/Inc/leaf-mempool.h+1−1
@@ -112,7 +112,7 @@ extern "C" { · 111 unmodified lines
112112 @param size The size of the chuck of memory to be used as a mempool.
113113 @param poolTo A pointer to the tMempool to which a tMempool should be initialized.
114114 */
115− void tMempool_initToPool (tMempool* const pool, char* memory, size_t size, tMempool* const poolTo);
115+ void tMempool_initToPool (tMempool* const mp, char* memory, size_t size, tMempool* const mem, LEAF* const leaf);
116116
117117 /*!
118118 @} */
leaf/Inc/leaf-sampling.h+13−3
@@ -122,6 +122,8 @@ extern "C" { · 121 unmodified lines
122122 uint32_t idx;
123123 uint32_t bufferLength;
124124 uint32_t recordedLength;
125+ uint32_t channels;
126+ uint32_t sampleRate;
125127 RecordMode mode;
126128
127129 int active;
@@ -130,7 +132,7 @@ extern "C" { · 2 unmodified lines
130132 typedef _tBuffer* tBuffer;
131133
132134 void tBuffer_init (tBuffer* const, uint32_t length, LEAF* const leaf);
133− void tBuffer_initToPool (tBuffer* const, uint32_t length, tMempool* const);
135+ void tBuffer_initToPool (tBuffer* const sb, uint32_t length, tMempool* const mp, LEAF* const leaf);
134136 void tBuffer_free (tBuffer* const);
135137
136138 void tBuffer_tick (tBuffer* const, float sample);
@@ -138,6 +140,7 @@ extern "C" { · 1 unmodified line
138140 float tBuffer_get (tBuffer* const, int idx);
139141 void tBuffer_record (tBuffer* const);
140142 void tBuffer_stop (tBuffer* const);
143+ void tBuffer_setBuffer (tBuffer* const sb, float* externalBuffer, int length, int channels, int sampleRate);
141144 int tBuffer_getRecordPosition (tBuffer* const);
142145 void tBuffer_setRecordPosition (tBuffer* const, int pos);
143146 void tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
@@ -224,6 +227,12 @@ extern "C" { · 80 unmodified lines
224227
225228 tBuffer samp;
226229
230+ float leafInvSampleRate;
231+ float leafSampleRate;
232+ float ticksPerSevenMs;
233+ float rateFactor;
234+ uint32_t channels;
235+
227236 tRamp gain;
228237
229238 float idx;
@@ -254,10 +263,11 @@ extern "C" { · 24 unmodified lines
254263 typedef _tSampler* tSampler;
255264
256265 void tSampler_init (tSampler* const, tBuffer* const, LEAF* const leaf);
257− void tSampler_initToPool (tSampler* const, tBuffer* const, tMempool* const);
266+ void tSampler_initToPool (tSampler* const sp, tBuffer* const b, tMempool* const mp, LEAF* const leaf);
258267 void tSampler_free (tSampler* const);
259268
260269 float tSampler_tick (tSampler* const);
270+ float tSampler_tickStereo (tSampler* const sp, float* outputArray);
261271 void tSampler_setSample (tSampler* const, tBuffer* const);
262272 void tSampler_setMode (tSampler* const, PlayMode mode);
263273 void tSampler_play (tSampler* const);
@@ -343,7 +353,7 @@ extern "C" { · 79 unmodified lines
343353 typedef _tAutoSampler* tAutoSampler;
344354
345355 void tAutoSampler_init (tAutoSampler* const, tBuffer* const, LEAF* const leaf);
346− void tAutoSampler_initToPool (tAutoSampler* const, tBuffer* const, tMempool* const);
356+ void tAutoSampler_initToPool (tAutoSampler* const as, tBuffer* const b, tMempool* const mp, LEAF* const leaf);
347357 void tAutoSampler_free (tAutoSampler* const);
348358
349359 float tAutoSampler_tick (tAutoSampler* const, float input);
leaf/Src/leaf-analysis.c+1−1
@@ -10,7 +10,7 @@ · 9 unmodified lines
1010
1111 #include "..\Inc\leaf-analysis.h"
1212 #include "..\Externals\d_fft_mayer.h"
13−
13+#include <intrin.h>
1414 #else
1515
1616 #include "../Inc/leaf-analysis.h"
leaf/Src/leaf-effects.c+2−2
@@ -288,7 +288,7 @@ void tTalkbox_lpc(float *buf, float *car, double* dl, double* Rt, int32_t n, int · 287 unmodified lines
288288 {
289289 // for(i=0; i<n; i++)
290290 // {
291− buf[i] = 0.0f;
291+ buf[0] = 0.0f;
292292 return;
293293 // }
294294 }
@@ -618,7 +618,7 @@ void tTalkboxFloat_lpc(float *buf, float *car, float* dl, float* Rt, int32_t n, · 323 unmodified lines
618618 {
619619 // for(i=0; i<n; i++)
620620 // {
621− buf[i] = 0.0f;
621+ buf[0] = 0.0f;
622622 return;
623623 // }
624624 }
leaf/Src/leaf-filters.c+70−54
@@ -1321,37 +1321,6 @@ float tVZFilter_tickEfficient (tVZFilter* const vf, float in) · 1320 unmodified lines
13211321
13221322 }
13231323
1324−float tVZFilter_tickEfficientBP (tVZFilter* const vf, float in)
1325−{
1326− _tVZFilter* f = *vf;
1327−
1328− float yL, yB, yH;
1329−
1330− // compute highpass output via Eq. 5.1:
1331− yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
1332−
1333− // compute bandpass output by applying 1st integrator to highpass output:
1334− yB = (f->g*yH) + f->s1;
1335− f->s1 = f->g*yH + yB; // state update in 1st integrator
1336−
1337− // compute lowpass output by applying 2nd integrator to bandpass output:
1338− yL = (f->g*yB) + f->s2;
1339− f->s2 = f->g*yB + yL; // state update in 2nd integrator
1340−
1341− //according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
1342− //
1343− //seems like that might look like this:
1344− // y = tanh(g*x) + s; // output computation
1345− // s = g*x + y; // state update
1346−
1347− //instead of this:
1348− // y = g*x + s; // output computation
1349− // s = g*x + y; // state update
1350−
1351− return f->cL*yL + f->cB*yB + f->cH*yH;
1352−
1353−}
1354−
13551324
13561325 void tVZFilter_calcCoeffs (tVZFilter* const vf)
13571326 {
@@ -1458,6 +1427,18 @@ void tVZFilter_calcCoeffs (tVZFilter* const vf) · 100 unmodified lines
14581427 f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
14591428 }
14601429
1430+void tVZFilter_calcCoeffsEfficientBP (tVZFilter* const vf)
1431+{
1432+
1433+ _tVZFilter* f = *vf;
1434+ f->g = fastertanf(PI * f->fc * f->inv_sr); // embedded integrator gain (Fig 3.11)
1435+ f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
1436+ f->cB = f->R2;
1437+ f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
1438+}
1439+
1440+
1441+
14611442
14621443 void tVZFilter_setBandwidth (tVZFilter* const vf, float B)
14631444 {
@@ -1483,14 +1464,28 @@ void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, · 19 unmodified lines
14831464 tVZFilter_calcCoeffs(vf);
14841465 }
14851466
1467+void tVZFilter_setFreqAndBandwidthEfficientBP (tVZFilter* const vf, float freq, float bw)
1468+{
1469+ _tVZFilter* f = *vf;
1470+ LEAF* leaf = f->mempool->leaf;
1471+
1472+ f->B = LEAF_clip(0.0f,bw, 100.0f);
1473+ f->fc = LEAF_clip(0.0f, freq, 0.5f * leaf->sampleRate);
1474+ tVZFilter_calcCoeffsEfficientBP(vf);
1475+}
1476+
1477+
1478+
14861479 void tVZFilter_setGain (tVZFilter* const vf, float gain)
14871480 {
14881481 _tVZFilter* f = *vf;
1489− f->G = LEAF_clip(0.000001f, gain, 100.0f);
1482+ f->G = LEAF_clip(0.000001f, gain, 4000.0f);
14901483 f->invG = 1.0f/f->G;
14911484 tVZFilter_calcCoeffs(vf);
14921485 }
14931486
1487+
1488+
14941489 void tVZFilter_setMorph (tVZFilter* const vf, float morph)
14951490 {
14961491 _tVZFilter* f = *vf;
@@ -1516,6 +1511,18 @@ float tVZFilter_BandwidthToR(tVZFilter* const vf, float B) · 19 unmodified lines
15161511 return sqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
15171512 }
15181513
1514+float tVZFilter_BandwidthToREfficientBP(tVZFilter* const vf, float B)
1515+{
1516+ _tVZFilter* f = *vf;
1517+ float fl = f->fc*fastPowf(2.0f, -B * 0.5f); // lower bandedge frequency (in Hz)
1518+ float gl = fastertanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
1519+ float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies
1520+ // unwarped: r = pow(2, -B/2) -> approximation for low
1521+ // center-frequencies
1522+ return fastsqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
1523+}
1524+
1525+
15191526
15201527
15211528 void tDiodeFilter_init (tDiodeFilter* const vf, float cutoff, float resonance, LEAF* const leaf)
@@ -1557,13 +1564,22 @@ float tanhXdX(float x) · 35 unmodified lines
15571564 {
15581565 float a = x*x;
15591566 // IIRC I got this as Pade-approx for tanh(sqrt(x))/sqrt(x)
1560− return ((a + 105.0f)*a + 945.0f) / ((15.0f*a + 420.0f)*a + 945.0f);
1567+ float testVal = ((15.0f*a + 420.0f)*a + 945.0f);
1568+ float output = 1.0f;
1569+
1570+ if (testVal!= 0.0f)
1571+ {
1572+ output = testVal;
1573+
1574+ }
1575+ return ((a + 105.0f)*a + 945.0f) / output;
15611576 }
15621577
15631578 float tDiodeFilter_tick (tDiodeFilter* const vf, float in)
15641579 {
15651580 _tDiodeFilter* f = *vf;
15661581
1582+ int errorCheck = 0;
15671583 // the input x[n+1] is given by 'in', and x[n] by zi
15681584 // input with half delay
15691585 float ih = 0.5f * (in + f->zi);
@@ -1579,24 +1595,24 @@ float tDiodeFilter_tick (tDiodeFilter* const vf, float in) · 9 unmodified lines
15791595
15801596 // This formula gives the result for y3 thanks to MATLAB
15811597 float y3 = (f->s2 + f->s3 + t2*(f->s1 + f->s2 + f->s3 + t1*(f->s0 + f->s1 + f->s2 + f->s3 + t0*in)) + t1*(2.0f*f->s2 + 2.0f*f->s3))*t3 + f->s3 + 2.0f*f->s3*t1 + t2*(2.0f*f->s3 + 3.0f*f->s3*t1);
1582−// if (isnan(y3))
1583−// {
1584−// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
1585−// }
1598+ if (isnan(y3))
1599+ {
1600+ errorCheck = 1;
1601+ }
15861602 float tempy3denom = (t4 + t1*(2.0f*t4 + 4.0f) + t2*(t4 + t1*(t4 + f->r*t0 + 4.0f) + 3.0f) + 2.0f)*t3 + t4 + t1*(2.0f*t4 + 2.0f) + t2*(2.0f*t4 + t1*(3.0f*t4 + 3.0f) + 2.0f) + 1.0f;
1587−// if (isnan(tempy3denom))
1588−// {
1589−// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
1590−// }
1603+ if (isnan(tempy3denom))
1604+ {
1605+ errorCheck = 2;
1606+ }
15911607 if (tempy3denom == 0.0f)
15921608 {
15931609 tempy3denom = 0.000001f;
15941610 }
15951611 y3 = y3 / tempy3denom;
1596−// if (isnan(y3))
1597−// {
1598−// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
1599−// }
1612+ if (isnan(y3))
1613+ {
1614+ errorCheck = 3;
1615+ }
16001616 if (t1 == 0.0f)
16011617 {
16021618 t1 = 0.000001f;
@@ -1617,15 +1633,15 @@ float tDiodeFilter_tick (tDiodeFilter* const vf, float in) · 14 unmodified lines
16171633
16181634 // update state
16191635 f->s0 += 2.0f * (t0*xx + t1*(y1-y0));
1620−// if (isnan(f->s0))
1621−// {
1622−// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
1623−// }
1624−
1625−// if (isinf(f->s0))
1626−// {
1627−// __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
1628−// }
1636+ if (isnan(f->s0))
1637+ {
1638+ errorCheck = 4;
1639+ }
1640+
1641+ if (isinf(f->s0))
1642+ {
1643+ errorCheck = 5;
1644+ }
16291645 f->s1 += 2.0f * (t2*(y2-y1) - t1*(y1-y0));
16301646 f->s2 += 2.0f * (t3*(y3-y2) - t2*(y2-y1));
16311647 f->s3 += 2.0f * (-t4*(y3) - t3*(y3-y2));
leaf/Src/leaf-math.c+41−1
@@ -99,7 +99,47 @@ float fastercosf(float fAngle) · 98 unmodified lines
9999 return fResult;
100100 }
101101
102+float fasttanf (float fAngle)
103+{
104+ float fASqr = fAngle*fAngle;
105+ float fResult = 9.5168091e-03f;
106+ fResult *= fASqr;
107+ fResult += 2.900525e-03f;
108+ fResult *= fASqr;
109+ fResult += 2.45650893e-02f;
110+ fResult *= fASqr;
111+ fResult += 5.33740603e-02f;
112+ fResult *= fASqr;
113+ fResult += 1.333923995e-01f;
114+ fResult *= fASqr;
115+ fResult += 3.333314036e-01f;
116+ fResult *= fASqr;
117+ fResult += 1.0f;
118+ fResult *= fAngle;
119+ return fResult;
120+}
102121
122+float fastertanf(float fAngle)
123+{
124+ float fASqr = fAngle*fAngle;
125+ float fResult = 2.033e-01f;
126+ fResult *= fASqr;
127+ fResult += 3.1755e-01f;
128+ fResult *= fASqr;
129+ fResult += 1.0f;
130+ fResult *= fAngle;
131+ return fResult;
132+}
133+
134+// from Heng Li, a combination of inverse square root (see wiki) and inversion: https://bits.stephan-brumme.com/inverse.html
135+float fastsqrtf(float x)
136+{
137+ union { float f; uint32_t i; } z = { x };
138+ z.i = 0x5f3759df - (z.i >> 1);
139+ z.f *= (1.5f - (x * 0.5f * z.f * z.f));
140+ z.i = 0x7EEEEEEE - z.i;
141+ return z.f;
142+}
103143
104144 // alternative implementation for abs()
105145 // REQUIRES: 32 bit integers
@@ -114,7 +154,7 @@ int fastabs_int(int in){ · 8 unmodified lines
114154
115155 // alternative implementation for abs()
116156 // REQUIRES: 32 bit floats
117−inline float fastabsf(float f)
157+float fastabsf(float f)
118158 {
119159 union
120160 {
leaf/Src/leaf-mempool.c+4−3
@@ -410,7 +410,7 @@ static inline void delink_node(mpool_node_t* node) · 409 unmodified lines
410410
411411 void tMempool_init(tMempool* const mp, char* memory, size_t size, LEAF* const leaf)
412412 {
413− tMempool_initToPool(mp, memory, size, &leaf->mempool);
413+ tMempool_initToPool(mp, memory, size, &leaf->mempool, leaf);
414414 }
415415
416416 void tMempool_free(tMempool* const mp)
@@ -420,10 +420,11 @@ void tMempool_free(tMempool* const mp) · 3 unmodified lines
420420 mpool_free((char*)m, m->mempool);
421421 }
422422
423−void tMempool_initToPool (tMempool* const mp, char* memory, size_t size, tMempool* const mem)
423+void tMempool_initToPool (tMempool* const mp, char* memory, size_t size, tMempool* const mem, LEAF* const leaf)
424424 {
425425 _tMempool* mm = *mem;
426426 _tMempool* m = *mp = (_tMempool*) mpool_alloc(sizeof(_tMempool), mm);
427−
427+ m->leaf = leaf;
428428 mpool_create (memory, size, m);
429429 }
430+
leaf/Src/leaf-sampling.c+373−19
@@ -26,17 +26,18 @@ · 25 unmodified lines
2626
2727 void tBuffer_init (tBuffer* const sb, uint32_t length, LEAF* const leaf)
2828 {
29− tBuffer_initToPool(sb, length, &leaf->mempool);
29+ tBuffer_initToPool(sb, length, &leaf->mempool, leaf);
3030 }
3131
32−void tBuffer_initToPool (tBuffer* const sb, uint32_t length, tMempool* const mp)
32+void tBuffer_initToPool (tBuffer* const sb, uint32_t length, tMempool* const mp, LEAF* const leaf)
3333 {
3434 _tMempool* m = *mp;
3535 _tBuffer* s = *sb = (_tBuffer*) mpool_alloc(sizeof(_tBuffer), m);
3636 s->mempool = m;
3737
3838 s->buff = (float*) mpool_alloc( sizeof(float) * length, m);
39−
39+ s->sampleRate = leaf->sampleRate;
40+ s->channels = 1;
4041 s->bufferLength = length;
4142 s->recordedLength = 0;
4243 s->active = 0;
@@ -136,6 +137,17 @@ void tBuffer_clear (tBuffer* const sb) · 93 unmodified lines
136137
137138 }
138139
140+void tBuffer_setBuffer(tBuffer* const sb, float* externalBuffer, int length, int channels, int sampleRate)
141+{
142+ _tBuffer* s = *sb;
143+
144+ s->buff = externalBuffer;
145+ s->channels = channels;
146+ s->sampleRate = sampleRate;
147+ s->recordedLength = length/channels;
148+ s->bufferLength = s->recordedLength;
149+}
150+
139151 uint32_t tBuffer_getBufferLength(tBuffer* const sb)
140152 {
141153 _tBuffer* s = *sb;
@@ -168,10 +180,10 @@ static void attemptStartEndChange(tSampler* const sp); · 26 unmodified lines
168180
169181 void tSampler_init(tSampler* const sp, tBuffer* const b, LEAF* const leaf)
170182 {
171− tSampler_initToPool(sp, b, &leaf->mempool);
183+ tSampler_initToPool(sp, b, &leaf->mempool, leaf);
172184 }
173185
174−void tSampler_initToPool(tSampler* const sp, tBuffer* const b, tMempool* const mp)
186+void tSampler_initToPool(tSampler* const sp, tBuffer* const b, tMempool* const mp, LEAF* const leaf)
175187 {
176188 _tMempool* m = *mp;
177189 _tSampler* p = *sp = (_tSampler*) mpool_alloc(sizeof(_tSampler), m);
@@ -179,18 +191,36 @@ void tSampler_initToPool(tSampler* const sp, tBuffer* const b, tMempool* const m · 1 unmodified line
179191
180192 _tBuffer* s = *b;
181193
194+ p->leafInvSampleRate = leaf->invSampleRate;
195+ p->leafSampleRate = leaf->sampleRate;
196+ p->ticksPerSevenMs = 0.007f * p->leafSampleRate;
197+ p->rateFactor = s->sampleRate * p->leafInvSampleRate;
198+ p->channels = s->channels;
199+
200+
182201 p->samp = s;
183202
184203 p->active = 0;
185204
186205 p->start = 0;
187− p->end = 0;
206+ p->end = p->samp->bufferLength - 1;
188207
189208 p->len = p->end - p->start;
190209
191210 p->idx = 0.f;
192− p->inc = 1.f;
193− p->iinc = 1.f;
211+ float rate = p->rateFactor; //adjust for sampling rate of buffer (may be different from leaf.sampleRate if audio file was loaded form SD card)
212+ if (rate < 0.f)
213+ {
214+ rate = -rate;
215+ p->dir = -1;
216+ }
217+ else
218+ {
219+ p->dir = 1;
220+ }
221+
222+ p->inc = rate;
223+ p->iinc = 1.f / p->inc;
194224
195225 p->dir = 1;
196226 p->flip = 1;
@@ -200,7 +230,7 @@ void tSampler_initToPool(tSampler* const sp, tBuffer* const b, tMempool* const m · 3 unmodified lines
200230
201231 p->cfxlen = 500; // default 300 sample crossfade
202232
203− tRamp_initToPool(&p->gain, 7.0f, 1, mp);
233+ tRamp_initToPool(&p->gain, 5.0f, 1, mp);
204234 tRamp_setVal(&p->gain, 0.f);
205235
206236 p->targetstart = -1;
@@ -226,6 +256,10 @@ void tSampler_setSample (tSampler* const sp, tBuffer* const b) · 19 unmodified lines
226256
227257 p->samp = s;
228258
259+
260+ p->rateFactor = s->sampleRate * p->leafInvSampleRate;
261+ p->channels = s->channels;
262+
229263 p->start = 0;
230264 p->end = p->samp->bufferLength - 1;
231265
@@ -452,7 +486,7 @@ float tSampler_tick (tSampler* const sp) · 220 unmodified lines
452486 p->idx = myEnd;
453487 }
454488 float ticksToEnd = rev ? ((idx - myStart) * p->iinc) : ((myEnd - idx) * p->iinc);
455− if (ticksToEnd < (0.007f * leaf->sampleRate))
489+ if ((ticksToEnd < p->ticksPerSevenMs) && (p->active == 1))
456490 {
457491 tRamp_setDest(&p->gain, 0.f);
458492 p->active = -1;
@@ -500,6 +534,299 @@ float tSampler_tick (tSampler* const sp) · 41 unmodified lines
500534 return p->last;
501535 }
502536
537+
538+float tSampler_tickStereo (tSampler* const sp, float* outputArray)
539+{
540+ _tSampler* p = *sp;
541+ LEAF* leaf = p->mempool->leaf;
542+
543+ attemptStartEndChange(sp);
544+
545+ if (p->active == 0) return 0.f;
546+
547+ if ((p->inc == 0.0f) || (p->len < 2))
548+ {
549+ // p->inCrossfade = 1;
550+ return p->last;
551+ }
552+
553+ float cfxsample[2] = {0.0f, 0.0f};
554+ float crossfadeMix = 0.0f;
555+ float flipsample[2] = {0.0f, 0.0f};
556+ float flipMix = 0.0f;
557+
558+ float* buff = p->samp->buff;
559+
560+ // Variables so start is also before end
561+ int myStart = p->start;
562+ int myEnd = p->end;
563+ if (p->flip < 0)
564+ {
565+ myStart = p->end;
566+ myEnd = p->start;
567+ }
568+
569+ // Get the direction and a reverse flag for some calcs
570+ int dir = p->bnf * p->dir * p->flip;
571+ int rev = 0;
572+ if (dir < 0) rev = 1;
573+
574+ // Get the current integer index and alpha for interpolation
575+ int idx = (int) p->idx;
576+ float alpha = rev + (p->idx - idx) * dir;
577+ idx += rev;
578+
579+ // Get the indexes for interpolation
580+ int i1 = idx-(1*dir);
581+ int i2 = idx;
582+ int i3 = idx+(1*dir);
583+ int i4 = idx+(2*dir);
584+
585+ int length = p->samp->recordedLength;
586+
587+ // Wrap as needed
588+ i1 = (i1 < length*rev) ? i1 + (length * (1-rev)) : i1 - (length * rev);
589+ i2 = (i2 < length*rev) ? i2 + (length * (1-rev)) : i2 - (length * rev);
590+ i3 = (i3 < length*(1-rev)) ? i3 + (length * rev) : i3 - (length * (1-rev));
591+ i4 = (i4 < length*(1-rev)) ? i4 + (length * rev) : i4 - (length * (1-rev));
592+
593+ outputArray[0] = LEAF_interpolate_hermite_x (buff[i1 * p->channels],
594+ buff[i2 * p->channels],
595+ buff[i3 * p->channels],
596+ buff[i4 * p->channels],
597+ alpha);
598+
599+ outputArray[1] = LEAF_interpolate_hermite_x (buff[(i1 * p->channels) + 1],
600+ buff[(i2 * p->channels) + 1],
601+ buff[(i3 * p->channels) + 1],
602+ buff[(i4 * p->channels) + 1],
603+ alpha);
604+
605+ int32_t cfxlen = p->cfxlen;
606+ if (p->len * 0.25f < cfxlen) cfxlen = p->len * 0.25f;
607+
608+ // Determine crossfade points
609+ int32_t fadeLeftStart = 0;
610+ if (myStart >= cfxlen) fadeLeftStart = myStart - cfxlen;
611+ int32_t fadeLeftEnd = fadeLeftStart + cfxlen;
612+
613+ int32_t fadeRightEnd = myEnd;// + (fadeLeftEnd - start);
614+ // if (fadeRightEnd >= length) fadeRightEnd = length - 1;
615+ int32_t fadeRightStart = fadeRightEnd - cfxlen;
616+
617+
618+
619+
620+ if (p->mode == PlayLoop)
621+ {
622+
623+ int offset = 0;
624+ int cdx = 0;
625+ if ((fadeLeftStart <= idx) && (idx <= fadeLeftEnd))
626+ {
627+ offset = fadeLeftEnd - idx;
628+ cdx = fadeRightEnd - offset;
629+ p->inCrossfade = 1;
630+ }
631+ else if ((fadeRightStart <= idx) && (idx <= fadeRightEnd))
632+ {
633+ offset = idx - fadeRightStart;
634+ cdx = fadeLeftStart + offset;
635+ p->inCrossfade = 1;
636+ }
637+ else p->inCrossfade = 0;
638+
639+ if (p->inCrossfade)
640+ {
641+ int c1 = cdx-(1*dir);
642+ int c2 = cdx;
643+ int c3 = cdx+(1*dir);
644+ int c4 = cdx+(2*dir);
645+
646+ // Wrap as needed
647+ c1 = (c1 < length * rev) ? c1 + (length * (1-rev)) : c1 - (length * rev);
648+ c2 = (c2 < length * rev) ? c2 + (length * (1-rev)) : c2 - (length * rev);
649+ c3 = (c3 < length * (1-rev)) ? c3 + (length * rev) : c3 - (length * (1-rev));
650+ c4 = (c4 < length * (1-rev)) ? c4 + (length * rev) : c4 - (length * (1-rev));
651+
652+ cfxsample[0] = LEAF_interpolate_hermite_x (buff[c1 * p->channels],
653+ buff[c2 * p->channels],
654+ buff[c3 * p->channels],
655+ buff[c4 * p->channels],
656+ alpha);
657+
658+ cfxsample[1] = LEAF_interpolate_hermite_x (buff[(c1 * p->channels) + 1],
659+ buff[(c2 * p->channels) + 1],
660+ buff[(c3 * p->channels) + 1],
661+ buff[(c4 * p->channels) + 1],
662+ alpha);
663+
664+ crossfadeMix = (float) offset / (float) cfxlen;
665+ }
666+
667+ float flipLength = fabsf(p->flipIdx - p->flipStart);
668+ if (flipLength > cfxlen)
669+ {
670+ p->flipStart = -1;
671+ p->flipIdx = -1;
672+ }
673+ if (p->flipIdx >= 0)
674+ {
675+ if (p->flipStart == -1)
676+ {
677+ p->flipStart = p->idx;
678+ p->flipIdx = p->idx;
679+ }
680+ flipLength = fabsf(p->flipIdx - p->flipStart);
681+
682+ int fdx = (int) p->flipIdx;
683+ float falpha = (1-rev) - (p->flipIdx - fdx) * dir;
684+ idx += (1-rev);
685+
686+ // Get the indexes for interpolation
687+ int f1 = fdx+(1*dir);
688+ int f2 = fdx;
689+ int f3 = fdx-(1*dir);
690+ int f4 = fdx-(2*dir);
691+
692+ // Wrap as needed
693+ f1 = (f1 < length*(1-rev)) ? f1 + (length * rev) : f1 - (length * (1-rev));
694+ f2 = (f2 < length*(1-rev)) ? f2 + (length * rev) : f2 - (length * (1-rev));
695+ f3 = (f3 < length*rev) ? f3 + (length * (1-rev)) : f3 - (length * rev);
696+ f4 = (f4 < length*rev) ? f4 + (length * (1-rev)) : f4 - (length * rev);
697+
698+ flipsample[0] = LEAF_interpolate_hermite_x (buff[f1 * p->channels],
699+ buff[f2 * p->channels],
700+ buff[f3 * p->channels],
701+ buff[f4 * p->channels],
702+ falpha);
703+
704+ flipsample[1] = LEAF_interpolate_hermite_x (buff[(f1 * p->channels) + 1],
705+ buff[(f2 * p->channels) + 1],
706+ buff[(f3 * p->channels) + 1],
707+ buff[(f4 * p->channels) + 1],
708+ falpha);
709+
710+ flipMix = (float) (cfxlen - flipLength) / (float) cfxlen;
711+ }
712+ }
713+
714+ float inc = fmodf(p->inc, (float)p->len);
715+ p->idx += (dir * inc);
716+ if (p->flipStart >= 0)
717+ {
718+ p->flipIdx += (-dir * inc);
719+ if((int)p->flipIdx < 0)
720+ {
721+ p->idx += (float)length;
722+ }
723+ if((int)p->idx >= length)
724+ {
725+
726+ p->idx -= (float)length;
727+ }
728+ }
729+
730+
731+
732+ attemptStartEndChange(sp);
733+
734+
735+ if (p->mode == PlayLoop)
736+ {
737+ if((int)p->idx < myStart)
738+ {
739+ p->idx += (float)(fadeRightEnd - fadeLeftEnd);
740+ }
741+ if((int)p->idx > myEnd)
742+ {
743+
744+ p->idx -= (float)(fadeRightEnd - fadeLeftEnd);
745+ }
746+ }
747+ else if (p->mode == PlayBackAndForth)
748+ {
749+ if (p->idx < myStart)
750+ {
751+ p->bnf = -p->bnf;
752+ p->idx = myStart + 1;
753+ }
754+ else if (p->idx > myEnd)
755+ {
756+ p->bnf = -p->bnf;
757+ p->idx = myEnd - 1;
758+ }
759+ }
760+
761+
762+ if (p->mode == PlayNormal)
763+ {
764+ if (p->idx < myStart)
765+ {
766+ p->idx = myStart;
767+ }
768+ else if (p->idx > myEnd)
769+ {
770+ p->idx = myEnd;
771+ }
772+ float ticksToEnd = rev ? ((idx - myStart) * p->iinc) : ((myEnd - idx) * p->iinc);
773+ if ((ticksToEnd < p->ticksPerSevenMs) && (p->active == 1))
774+ {
775+ tRamp_setDest(&p->gain, 0.f);
776+ p->active = -1;
777+ }
778+ }
779+
780+ float sampleGain = tRamp_tick(&p->gain);
781+ for (int i = 0; i < p->channels; i++)
782+ {
783+ outputArray[i] = ((outputArray[i] * (1.0f - crossfadeMix)) + (cfxsample[i] * crossfadeMix)) * (1.0f - flipMix) + (flipsample[i] * flipMix);
784+ outputArray[i] = outputArray[i] * sampleGain;
785+ }
786+
787+
788+
789+
790+ if (p->active < 0)
791+ {
792+ //if was fading out and reached silence
793+ if (tRamp_sample(&p->gain) <= 0.0001f)
794+ {
795+ if (p->retrigger == 1)
796+ {
797+ p->active = 1;
798+ p->retrigger = 0;
799+ tRamp_setDest(&p->gain, 1.f);
800+
801+ if (p->dir > 0)
802+ {
803+ if (p->flip > 0) p->idx = p->start;
804+ else p->idx = p->end;
805+ }
806+ else
807+ {
808+ if (p->flip > 0) p->idx = p->end;
809+ else p->idx = p->start;
810+ }
811+ handleStartEndChange(&p);
812+ }
813+ else
814+ {
815+ p->active = 0;
816+ }
817+
818+ }
819+ }
820+
821+
822+
823+ p->last = outputArray[0];
824+
825+
826+ return p->last;
827+}
828+
829+
503830 void tSampler_setMode (tSampler* const sp, PlayMode mode)
504831 {
505832 _tSampler* p = *sp;
@@ -518,14 +845,23 @@ void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length) · 12 unmodified lines
518845 void tSampler_play (tSampler* const sp)
519846 {
520847 _tSampler* p = *sp;
521−
522− if (p->active != 0)
848+
849+ if (p->active > 0)
523850 {
524851 p->active = -1;
525852 p->retrigger = 1;
526853
527854 tRamp_setDest(&p->gain, 0.f);
528855 }
856+
857+ else if (p->active < 0)
858+ {
859+ p->active = -1;
860+ p->retrigger = 1;
861+
862+ //tRamp_setDest(&p->gain, 0.f);
863+ }
864+
529865 else
530866 {
531867 p->active = 1;
@@ -740,6 +1076,7 @@ void tSampler_setRate (tSampler* const sp, float rate) · 208 unmodified lines
7401076 {
7411077 _tSampler* p = *sp;
7421078
1079+ rate = rate * p->rateFactor; //adjust for sampling rate of buffer (may be different from leaf.sampleRate if audio file was loaded form SD card)
7431080 if (rate < 0.f)
7441081 {
7451082 rate = -rate;
@@ -758,17 +1095,17 @@ void tSampler_setRate (tSampler* const sp, float rate) · 12 unmodified lines
7581095
7591096 void tAutoSampler_init (tAutoSampler* const as, tBuffer* const b, LEAF* const leaf)
7601097 {
761− tAutoSampler_initToPool(as, b, &leaf->mempool);
1098+ tAutoSampler_initToPool(as, b, &leaf->mempool, leaf);
7621099 }
7631100
764−void tAutoSampler_initToPool (tAutoSampler* const as, tBuffer* const b, tMempool* const mp)
1101+void tAutoSampler_initToPool (tAutoSampler* const as, tBuffer* const b, tMempool* const mp, LEAF* const leaf)
7651102 {
7661103 _tMempool* m = *mp;
7671104 _tAutoSampler* a = *as = (_tAutoSampler*) mpool_alloc(sizeof(_tAutoSampler), m);
7681105 a->mempool = m;
7691106
7701107 tBuffer_setRecordMode(b, RecordOneShot);
771− tSampler_initToPool(&a->sampler, b, mp);
1108+ tSampler_initToPool(&a->sampler, b, mp, leaf);
7721109 tSampler_setMode(&a->sampler, PlayLoop);
7731110 tEnvelopeFollower_initToPool(&a->ef, 0.05f, 0.9999f, mp);
7741111 }
@@ -939,7 +1276,7 @@ float tMBSampler_tick (tMBSampler* const sp) · 164 unmodified lines
9391276 {
9401277 _tMBSampler* c = *sp;
9411278
942− if (c->gain->curr == 0.0f && !c->active) return 0.0f;
1279+ if ((c->gain->curr == 0.0f) && (!c->active)) return 0.0f;
9431280 if (c->_w == 0.0f)
9441281 {
9451282 c->_last_w = 0.0f;
@@ -1031,8 +1368,10 @@ float tMBSampler_tick (tMBSampler* const sp) · 85 unmodified lines
10311368 float nextSlope = (afterNext - next) / w;
10321369 float lastSlope = (last - beforeLast) / w;
10331370 place_slope_dd(c->_f, j, p - start, w, nextSlope - lastSlope);
1034−
1035− if (c->mode == PlayNormal) c->active = 0;
1371+ if (c->mode == PlayNormal)
1372+ {
1373+ c->active = 0;
1374+ }
10361375 else if (c->mode == PlayBackAndForth) w = -w;
10371376 }
10381377 // else if (p < (float) start) { /* start has been set ahead of the current phase */
@@ -1056,6 +1395,13 @@ float tMBSampler_tick (tMBSampler* const sp) · 17 unmodified lines
10561395 int i = (int) f;
10571396 f -= i;
10581397 next = buff[i] * (1.0f - f) + buff[i+1] * f;
1398+
1399+
1400+ if ((end - p) < 480) // 480 samples should be enough to let the tExpSmooth go from 1 to 0 (10ms at 48k, 5ms at 192k)
1401+ if (c->mode == PlayNormal)
1402+ {
1403+ tExpSmooth_setDest(&c->gain, 0.0f);
1404+ }
10591405 }
10601406
10611407 if (c->_last_w < 0.0f)
@@ -1095,7 +1441,10 @@ float tMBSampler_tick (tMBSampler* const sp) · 33 unmodified lines
10951441 float lastSlope = (last - beforeLast) / w;
10961442 place_slope_dd(c->_f, j, end - p, w, nextSlope - lastSlope);
10971443
1098− if (c->mode == PlayNormal) c->active = 0;
1444+ if (c->mode == PlayNormal)
1445+ {
1446+ c->active = 0;
1447+ }
10991448 else if (c->mode == PlayBackAndForth) w = -w;
11001449 }
11011450 // else if (p > (float) end) {
@@ -1115,6 +1464,11 @@ float tMBSampler_tick (tMBSampler* const sp) · 13 unmodified lines
11151464 // }
11161465 else {
11171466
1467+ if ((p - start) < 480) // 480 samples should be enough to let the tExpSmooth go from 1 to 0 (10ms at 48k, 5ms at 192k)
1468+ if (c->mode == PlayNormal)
1469+ {
1470+ tExpSmooth_setDest(&c->gain, 0.0f);
1471+ }
11181472 float f = p;
11191473 int i = (int) f;
11201474 f -= i;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t