History

updated ADSR

spiricom committed 6 years ago

Commit 32b90cf1 parent 1bea5d74 files · +609 −76Browse files

Unified · Split

4 files
  1. .DS_Store +0 −0
  2. LEAF/.DS_Store +0 −0
  3. LEAF/Inc/leaf-envelopes.h +134 −37
  4. LEAF/Src/leaf-envelopes.c +477 −41
.DS_Store+0−0

Binary file not shown.

LEAF/.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-envelopes.h+134−37
@@ -105,47 +105,144 @@ extern "C" { · 104 unmodified lines
105105 };
106106
107107 /* ADSR */
108− typedef struct _tADSR
109− {
110− float sampleRateInMs;
111− int state;
112− float output;
113− float attackRate;
114− float decayRate;
115− float releaseRate;
116− float attackCoef;
117− float decayCoef;
118− float releaseCoef;
119− float sustainLevel;
120− float targetRatioA;
121− float targetRatioDR;
122− float attackBase;
123− float decayBase;
124− float releaseBase;
125− float leakFactor;
126− float gain;
127−
128− } _tADSR;
129−
130− typedef _tADSR* tADSR;
131−
132− void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
133− void tADSR_free (tADSR* const);
134− void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const);
135− void tADSR_freeFromPool (tADSR* const, tMempool* const);
136−
137− float tADSR_tick (tADSR* const);
138− void tADSR_setAttack (tADSR* const, float attack);
139− void tADSR_setDecay (tADSR* const, float decay);
140− void tADSR_setSustain (tADSR* const, float sustain);
141− void tADSR_setRelease (tADSR* const, float release);
142− void tADSR_setLeakFactor (tADSR* const, float leakFactor);
143− void tADSR_on (tADSR* const, float velocity);
144− void tADSR_off (tADSR* const);
108+ typedef struct _tADSR
109+ {
110+ const float *exp_buff;
111+ const float *inc_buff;
112+ uint32_t buff_size;
113+
114+ float next;
115+
116+ float attackInc, decayInc, releaseInc, rampInc;
117+
118+ oBool inAttack, inDecay, inSustain, inRelease, inRamp;
119+
120+ float sustain, gain, rampPeak, releasePeak;
121+
122+ float attackPhase, decayPhase, releasePhase, rampPhase;
123+
124+ float leakFactor;
125+
126+
127+ } _tADSR;
128+
129+ typedef _tADSR* tADSR;
130+
131+ void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
132+ void tADSR_free (tADSR* const);
133+ void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const);
134+ void tADSR_freeFromPool (tADSR* const, tMempool* const);
135+
136+ float tADSR_tick (tADSR* const);
137+ void tADSR_setAttack (tADSR* const, float attack);
138+ void tADSR_setDecay (tADSR* const, float decay);
139+ void tADSR_setSustain (tADSR* const, float sustain);
140+ void tADSR_setRelease (tADSR* const, float release);
141+ void tADSR_setLeakFactor (tADSR* const, float leakFactor);
142+ void tADSR_on (tADSR* const, float velocity);
143+ void tADSR_off (tADSR* const);
144+
145+
145146
146147
147148 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
148149
150+
151+
152+ /* ADSR2 */
153+ typedef struct _tADSR2
154+ {
155+ float sampleRateInMs;
156+ float attack;
157+ float decay;
158+ float release;
159+ float attackLambda;
160+ float decayLambda;
161+ float releaseLambda;
162+ float sustain;
163+ float leakGain;
164+ float leakFactor;
165+ float targetGainSquared;
166+ float factor;
167+ float oneMinusFactor;
168+ float gain;
169+ uint8_t attacking;
170+ uint8_t gate;
171+ float env;
172+ float envTarget;
173+ } _tADSR2;
174+
175+ typedef _tADSR2* tADSR2;
176+
177+ void tADSR2_init (tADSR2* const, float attack, float decay, float sustain, float release);
178+ void tADSR2_free (tADSR2* const);
179+ void tADSR2_initToPool (tADSR2* const, float attack, float decay, float sustain, float release, tMempool* const);
180+ void tADSR2_freeFromPool (tADSR2* const, tMempool* const);
181+
182+ float tADSR2_tick (tADSR2* const);
183+ void tADSR2_setAttack (tADSR2* const, float attack);
184+ void tADSR2_setDecay (tADSR2* const, float decay);
185+ void tADSR2_setSustain (tADSR2* const, float sustain);
186+ void tADSR2_setRelease (tADSR2* const, float release);
187+ void tADSR2_setLeakFactor (tADSR2* const, float leakFactor);
188+ void tADSR2_on (tADSR2* const, float velocity);
189+ void tADSR2_off (tADSR2* const);
190+
191+
192+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
193+
194+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
195+ enum envState {
196+ env_idle = 0,
197+ env_attack,
198+ env_decay,
199+ env_sustain,
200+ env_release
201+ };
202+
203+ /* ADSR3 */
204+ typedef struct _tADSR3
205+ {
206+ float sampleRateInMs;
207+ int state;
208+ float output;
209+ float attackRate;
210+ float decayRate;
211+ float releaseRate;
212+ float attackCoef;
213+ float decayCoef;
214+ float releaseCoef;
215+ float sustainLevel;
216+ float targetRatioA;
217+ float targetRatioDR;
218+ float attackBase;
219+ float decayBase;
220+ float releaseBase;
221+ float leakFactor;
222+ float targetGainSquared;
223+ float factor;
224+ float oneMinusFactor;
225+ float gain;
226+
227+ } _tADSR3;
228+
229+ typedef _tADSR3* tADSR3;
230+
231+ void tADSR3_init (tADSR3* const, float attack, float decay, float sustain, float release);
232+ void tADSR3_free (tADSR3* const);
233+ void tADSR3_initToPool (tADSR3* const, float attack, float decay, float sustain, float release, tMempool* const);
234+ void tADSR3_freeFromPool (tADSR3* const, tMempool* const);
235+
236+ float tADSR3_tick (tADSR3* const);
237+ void tADSR3_setAttack (tADSR3* const, float attack);
238+ void tADSR3_setDecay (tADSR3* const, float decay);
239+ void tADSR3_setSustain (tADSR3* const, float sustain);
240+ void tADSR3_setRelease (tADSR3* const, float release);
241+ void tADSR3_setLeakFactor (tADSR3* const, float leakFactor);
242+ void tADSR3_on (tADSR3* const, float velocity);
243+ void tADSR3_off (tADSR3* const);
244+
245+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
149246 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
150247
151248 /* Ramp */
LEAF/Src/leaf-envelopes.c+477−41
@@ -254,116 +254,553 @@ float tEnvelope_tick(tEnvelope* const envlp) · 253 unmodified lines
254254 }
255255
256256
257+
257258 /* ADSR */
258−//replaced our older ADSR that relied on a large lookup table with this one by Nigel Redmon from his blog. Thanks, Nigel!
259+void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release)
260+{
261+ tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);
262+}
263+
264+void tADSR_free(tADSR* const adsrenv)
265+{
266+ tADSR_freeFromPool(adsrenv, &leaf.mempool);
267+}
268+
269+void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)
270+{
271+ _tMempool* m = *mp;
272+ _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m);
273+
274+ adsr->exp_buff = __leaf_table_exp_decay;
275+ adsr->inc_buff = __leaf_table_attack_decay_inc;
276+ adsr->buff_size = sizeof(__leaf_table_exp_decay);
277+
278+ if (attack > 8192.0f)
279+ attack = 8192.0f;
280+ if (attack < 0.0f)
281+ attack = 0.0f;
282+
283+ if (decay > 8192.0f)
284+ decay = 8192.0f;
285+ if (decay < 0.0f)
286+ decay = 0.0f;
287+
288+ if (sustain > 1.0f)
289+ sustain = 1.0f;
290+ if (sustain < 0.0f)
291+ sustain = 0.0f;
292+
293+ if (release > 8192.0f)
294+ release = 8192.0f;
295+ if (release < 0.0f)
296+ release = 0.0f;
297+
298+ int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
299+ int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
300+ int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
301+ int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
302+
303+ if (attackIndex < 0)
304+ attackIndex = 0;
305+ if (decayIndex < 0)
306+ decayIndex = 0;
307+ if (releaseIndex < 0)
308+ releaseIndex = 0;
309+ if (rampIndex < 0)
310+ rampIndex = 0;
311+
312+ adsr->next = 0.0f;
313+
314+ adsr->inRamp = OFALSE;
315+ adsr->inAttack = OFALSE;
316+ adsr->inDecay = OFALSE;
317+ adsr->inSustain = OFALSE;
318+ adsr->inRelease = OFALSE;
319+
320+ adsr->sustain = sustain;
321+
322+ adsr->attackInc = adsr->inc_buff[attackIndex];
323+ adsr->decayInc = adsr->inc_buff[decayIndex];
324+ adsr->releaseInc = adsr->inc_buff[releaseIndex];
325+ adsr->rampInc = adsr->inc_buff[rampIndex];
326+
327+ adsr->leakFactor = 1.0f;
328+}
329+
330+void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp)
331+{
332+ _tMempool* m = *mp;
333+ _tADSR* adsr = *adsrenv;
334+ mpool_free(adsr, m);
335+}
336+
337+void tADSR_setAttack(tADSR* const adsrenv, float attack)
338+{
339+ _tADSR* adsr = *adsrenv;
340+
341+ int32_t attackIndex;
342+
343+ if (attack < 0.0f) {
344+ attackIndex = 0.0f;
345+ } else if (attack < 8192.0f) {
346+ attackIndex = ((int32_t)(attack * 8.0f))-1;
347+ } else {
348+ attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
349+ }
350+
351+ adsr->attackInc = adsr->inc_buff[attackIndex];
352+}
353+
354+void tADSR_setDecay(tADSR* const adsrenv, float decay)
355+{
356+ _tADSR* adsr = *adsrenv;
357+
358+ int32_t decayIndex;
359+
360+ if (decay < 0.0f) {
361+ decayIndex = 0.0f;
362+ } else if (decay < 8192.0f) {
363+ decayIndex = ((int32_t)(decay * 8.0f)) - 1;
364+ } else {
365+ decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
366+ }
367+
368+ adsr->decayInc = adsr->inc_buff[decayIndex];
369+}
370+
371+void tADSR_setSustain(tADSR* const adsrenv, float sustain)
372+{
373+ _tADSR* adsr = *adsrenv;
374+
375+ if (sustain > 1.0f) adsr->sustain = 1.0f;
376+ else if (sustain < 0.0f) adsr->sustain = 0.0f;
377+ else adsr->sustain = sustain;
378+}
379+
380+void tADSR_setRelease(tADSR* const adsrenv, float release)
381+{
382+ _tADSR* adsr = *adsrenv;
383+
384+ int32_t releaseIndex;
385+
386+ if (release < 0.0f) {
387+ releaseIndex = 0.0f;
388+ } else if (release < 8192.0f) {
389+ releaseIndex = ((int32_t)(release * 8.0f)) - 1;
390+ } else {
391+ releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
392+ }
393+
394+ adsr->releaseInc = adsr->inc_buff[releaseIndex];
395+}
396+
397+// 0.999999 is slow leak, 0.9 is fast leak
398+void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor)
399+{
400+ _tADSR* adsr = *adsrenv;
401+
402+
403+ adsr->leakFactor = leakFactor;
404+}
405+
406+void tADSR_on(tADSR* const adsrenv, float velocity)
407+{
408+ _tADSR* adsr = *adsrenv;
409+
410+ if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.
411+ {
412+ adsr->rampPhase = 0;
413+ adsr->inRamp = OTRUE;
414+ adsr->rampPeak = adsr->next;
415+ }
416+ else // Normal start.
417+ {
418+ adsr->inAttack = OTRUE;
419+ }
420+
421+ adsr->attackPhase = 0;
422+ adsr->decayPhase = 0;
423+ adsr->releasePhase = 0;
424+ adsr->inDecay = OFALSE;
425+ adsr->inSustain = OFALSE;
426+ adsr->inRelease = OFALSE;
427+ adsr->gain = velocity;
428+}
429+
430+void tADSR_off(tADSR* const adsrenv)
431+{
432+ _tADSR* adsr = *adsrenv;
433+
434+ if (adsr->inRelease) return;
435+
436+ adsr->inAttack = OFALSE;
437+ adsr->inDecay = OFALSE;
438+ adsr->inSustain = OFALSE;
439+ adsr->inRelease = OTRUE;
440+
441+ adsr->releasePeak = adsr->next;
442+}
443+
444+float tADSR_tick(tADSR* const adsrenv)
445+{
446+ _tADSR* adsr = *adsrenv;
447+
448+
449+ if (adsr->inRamp)
450+ {
451+ if (adsr->rampPhase > UINT16_MAX)
452+ {
453+ adsr->inRamp = OFALSE;
454+ adsr->inAttack = OTRUE;
455+ adsr->next = 0.0f;
456+ }
457+ else
458+ {
459+ adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
460+ }
461+
462+ adsr->rampPhase += adsr->rampInc;
463+ }
464+
465+ if (adsr->inAttack)
466+ {
467+
468+ // If attack done, time to turn around.
469+ if (adsr->attackPhase > UINT16_MAX)
470+ {
471+ adsr->inDecay = OTRUE;
472+ adsr->inAttack = OFALSE;
473+ adsr->next = adsr->gain * 1.0f;
474+ }
475+ else
476+ {
477+ // do interpolation !
478+ adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
479+ }
480+
481+ // Increment ADSR attack.
482+ adsr->attackPhase += adsr->attackInc;
483+
484+ }
485+
486+ if (adsr->inDecay)
487+ {
488+
489+ // If decay done, sustain.
490+ if (adsr->decayPhase >= UINT16_MAX)
491+ {
492+ adsr->inDecay = OFALSE;
493+ adsr->inSustain = OTRUE;
494+ adsr->next = adsr->gain * adsr->sustain;
495+ }
496+
497+ else
498+ {
499+ adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation !
500+ }
501+
502+ // Increment ADSR decay.
503+ adsr->decayPhase += adsr->decayInc;
504+ }
505+
506+ if (adsr->inSustain)
507+ {
508+ adsr->next = adsr->next * adsr->leakFactor;
509+ }
510+
511+ if (adsr->inRelease)
512+ {
513+ // If release done, finish.
514+ if (adsr->releasePhase >= UINT16_MAX)
515+ {
516+ adsr->inRelease = OFALSE;
517+ adsr->next = 0.0f;
518+ }
519+ else {
520+
521+ adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation !
522+ }
523+
524+ // Increment envelope release;
525+ adsr->releasePhase += adsr->releaseInc;
526+ }
527+
528+
529+ return adsr->next;
530+}
531+
532+
533+
534+
535+/* ADSR 2*/
536+//This one is adapted from the VCV Rack code
259537 //-JS
260538
261539
262540
263−float calcADSRCoef(double rate, double targetRatio)
541+const float ADSR2_MIN_TIME = 1e-3f;
542+const float ADSR2_INV_MIN_TIME = 1000.0f;
543+const float ADSR2_MAX_TIME = 10.f;
544+const float ADSR2_LAMBDA_BASE = 10000.0f;
545+
546+
547+void tADSR2_init(tADSR2* const adsrenv, float attack, float decay, float sustain, float release)
548+{
549+ tADSR2_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);
550+}
551+
552+void tADSR2_free(tADSR2* const adsrenv)
553+{
554+ tADSR2_freeFromPool(adsrenv, &leaf.mempool);
555+}
556+
557+void tADSR2_initToPool (tADSR2* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)
558+{
559+ _tMempool* m = *mp;
560+ _tADSR2* adsr = *adsrenv = (_tADSR2*) mpool_alloc(sizeof(_tADSR2), m);
561+ adsr->sampleRateInMs = leaf.sampleRate * 0.001f;
562+ adsr->attack = LEAF_clip(0.0f, attack * 0.001f, 1.0f);
563+ adsr->attackLambda = powf(ADSR2_LAMBDA_BASE, -adsr->attack) * ADSR2_INV_MIN_TIME;
564+
565+
566+ adsr->decay = LEAF_clip(0.0f, decay * 0.001f, 1.0f);
567+ adsr->decayLambda = powf(ADSR2_LAMBDA_BASE, -adsr->decay) * ADSR2_INV_MIN_TIME;
568+
569+
570+ adsr->sustain= sustain;
571+
572+
573+ adsr->release = LEAF_clip(0.0f, release * 0.001f, 1.0f);
574+ adsr->releaseLambda = powf(ADSR2_LAMBDA_BASE, -adsr->release) * ADSR2_INV_MIN_TIME;
575+
576+ adsr->attacking = 0;
577+ adsr->gate = 0;
578+ adsr->gain = 1.0f;
579+ adsr->targetGainSquared = 1.0f;
580+ adsr->factor = 0.01f;
581+ adsr->oneMinusFactor = 0.99f;
582+ adsr->env = 0.0f;
583+ adsr->leakFactor = 1.0f;
584+}
585+
586+void tADSR2_freeFromPool (tADSR2* const adsrenv, tMempool* const mp)
587+{
588+ _tMempool* m = *mp;
589+ _tADSR2* adsr = *adsrenv;
590+ mpool_free(adsr, m);
591+}
592+
593+void tADSR2_setAttack(tADSR2* const adsrenv, float attack)
594+{
595+ _tADSR2* adsr = *adsrenv;
596+ adsr->attack = LEAF_clip(0.0f, attack * 0.001f, 1.0f);
597+ adsr->attackLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->attack) * ADSR2_INV_MIN_TIME;
598+
599+}
600+
601+void tADSR2_setDecay(tADSR2* const adsrenv, float decay)
602+{
603+ _tADSR2* adsr = *adsrenv;
604+ adsr->decay = LEAF_clip(0.0f, decay * 0.001f, 1.0f);
605+ adsr->decayLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->decay) * ADSR2_INV_MIN_TIME;
606+
607+}
608+
609+void tADSR2_setSustain(tADSR2* const adsrenv, float sustain)
610+{
611+ _tADSR2* adsr = *adsrenv;
612+ adsr->sustain = sustain;
613+
614+ if (adsr->gate)
615+ {
616+ if (adsr->attacking == 0)
617+ {
618+ adsr->envTarget = sustain;
619+ }
620+ }
621+}
622+
623+void tADSR2_setRelease(tADSR2* const adsrenv, float release)
624+{
625+ _tADSR2* adsr = *adsrenv;
626+ adsr->release = LEAF_clip(0.0f, release * 0.001f, 1.0f);
627+ adsr->releaseLambda = fastPow(ADSR2_LAMBDA_BASE, -adsr->release) * ADSR2_INV_MIN_TIME;
628+}
629+
630+// 0.999999 is slow leak, 0.9 is fast leak
631+void tADSR2_setLeakFactor(tADSR2* const adsrenv, float leakFactor)
632+{
633+ _tADSR2* adsr = *adsrenv;
634+
635+ adsr->leakFactor = leakFactor;
636+}
637+
638+void tADSR2_on(tADSR2* const adsrenv, float velocity)
639+{
640+ _tADSR2* adsr = *adsrenv;
641+ adsr->targetGainSquared = velocity * velocity;
642+ adsr->envTarget = 1.2f;
643+ adsr->leakGain = 1.0f;
644+ adsr->gate = 1;
645+ adsr->attacking = 1;
646+}
647+
648+void tADSR2_off(tADSR2* const adsrenv)
649+{
650+ _tADSR2* adsr = *adsrenv;
651+ adsr->gate = 0;
652+ adsr->envTarget = 0.0f;
653+}
654+
655+float tADSR2_tick(tADSR2* const adsrenv)
656+{
657+ _tADSR2* adsr = *adsrenv;
658+ float lambda;
659+
660+ if (adsr->gate)
661+ {
662+ if (adsr->attacking)
663+ {
664+ lambda = adsr->attackLambda;
665+ }
666+ else
667+ {
668+ lambda = adsr->decayLambda;
669+ }
670+ }
671+ else
672+ {
673+ lambda = adsr->releaseLambda;
674+ }
675+
676+
677+ // Adjust env
678+ adsr->env += (adsr->envTarget - adsr->env) * lambda * leaf.invSampleRate;
679+
680+ // Turn off attacking state if envelope is HIGH
681+ if (adsr->env >= 1.0f)
682+ {
683+ adsr->attacking = 0;
684+ adsr->envTarget = adsr->sustain;
685+ }
686+
687+ //smooth the gain value -- this is not ideal, a retrigger while the envelope is still going with a new gain will cause a jump, although it will be smoothed quickly. Maybe doing the math so the range is computed based on the gain rather than 0.->1. is preferable? But that's harder to get the exponential curve right without a lookup.
688+ adsr->gain = ((adsr->factor*adsr->targetGainSquared)+(adsr->oneMinusFactor*adsr->gain));
689+ adsr->leakGain *= adsr->leakFactor;
690+ return adsr->env * adsr->gain * adsr->leakGain;
691+}
692+
693+/* ADSR 3*/
694+//This one doesn't use any lookup table - by Nigel Redmon from his blog. Thanks, Nigel!
695+//-JS
696+
697+float calcADSR3Coef(double rate, double targetRatio)
264698 {
265699 return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate);
266700 }
267701
268702
269−void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release)
703+void tADSR3_init(tADSR3* const adsrenv, float attack, float decay, float sustain, float release)
270704 {
271− tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);
705+ tADSR3_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);
272706 }
273707
274−void tADSR_free(tADSR* const adsrenv)
708+void tADSR3_free(tADSR3* const adsrenv)
275709 {
276− tADSR_freeFromPool(adsrenv, &leaf.mempool);
710+ tADSR3_freeFromPool(adsrenv, &leaf.mempool);
277711 }
278712
279−void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)
713+void tADSR3_initToPool (tADSR3* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)
280714 {
281715 _tMempool* m = *mp;
282− _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m);
716+ _tADSR3* adsr = *adsrenv = (_tADSR3*) mpool_alloc(sizeof(_tADSR3), m);
283717 adsr->sampleRateInMs = leaf.sampleRate * 0.001f;
284718 adsr->targetRatioA = 0.3f;
285719 adsr->targetRatioDR = 0.0001f;
286720 adsr->attackRate = attack * adsr->sampleRateInMs;
287− adsr->attackCoef = calcADSRCoef(attack * adsr->sampleRateInMs, adsr->targetRatioA);
721+ adsr->attackCoef = calcADSR3Coef(attack * adsr->sampleRateInMs, adsr->targetRatioA);
288722 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
289−
723+
290724 adsr->decayRate = decay * adsr->sampleRateInMs;
291725 adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR);
292726 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
293−
727+
294728 adsr->sustainLevel = sustain;
295729 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
296−
730+
297731 adsr->releaseRate = release * adsr->sampleRateInMs;
298732 adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR);
299733 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
300734
301735 adsr->state = env_idle;
302736 adsr->gain = 1.0f;
737+ adsr->targetGainSquared = 1.0f;
738+ adsr->factor = 0.01f;
739+ adsr->oneMinusFactor = 0.99f;
303740 adsr->output = 0.0f;
304741 adsr->leakFactor = 1.0f;
305742 }
306743
307−void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp)
744+void tADSR3_freeFromPool (tADSR3* const adsrenv, tMempool* const mp)
308745 {
309746 _tMempool* m = *mp;
310− _tADSR* adsr = *adsrenv;
747+ _tADSR3* adsr = *adsrenv;
311748 mpool_free(adsr, m);
312749 }
313750
314−void tADSR_setAttack(tADSR* const adsrenv, float attack)
751+void tADSR3_setAttack(tADSR3* const adsrenv, float attack)
315752 {
316− _tADSR* adsr = *adsrenv;
753+ _tADSR3* adsr = *adsrenv;
317754
318755 adsr->attackRate = attack * adsr->sampleRateInMs;
319− adsr->attackCoef = calcADSRCoef(adsr->attackRate, adsr->targetRatioA);
756+ adsr->attackCoef = calcADSR3Coef(adsr->attackRate, adsr->targetRatioA);
320757 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
321758 }
322759
323−void tADSR_setDecay(tADSR* const adsrenv, float decay)
760+void tADSR3_setDecay(tADSR3* const adsrenv, float decay)
324761 {
325− _tADSR* adsr = *adsrenv;
326−
762+ _tADSR3* adsr = *adsrenv;
763+
327764 adsr->decayRate = decay * adsr->sampleRateInMs;
328− adsr->decayCoef = calcADSRCoef(adsr->decayRate,adsr-> targetRatioDR);
765+ adsr->decayCoef = calcADSR3Coef(adsr->decayRate,adsr-> targetRatioDR);
329766 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
330767 }
331768
332−void tADSR_setSustain(tADSR* const adsrenv, float sustain)
769+void tADSR3_setSustain(tADSR3* const adsrenv, float sustain)
333770 {
334− _tADSR* adsr = *adsrenv;
335−
771+ _tADSR3* adsr = *adsrenv;
772+
336773 adsr->sustainLevel = sustain;
337774 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
338775 }
339776
340−void tADSR_setRelease(tADSR* const adsrenv, float release)
777+void tADSR3_setRelease(tADSR3* const adsrenv, float release)
341778 {
342− _tADSR* adsr = *adsrenv;
343−
779+ _tADSR3* adsr = *adsrenv;
780+
344781 adsr->releaseRate = release * adsr->sampleRateInMs;
345− adsr->releaseCoef = calcADSRCoef(adsr->releaseRate, adsr->targetRatioDR);
782+ adsr->releaseCoef = calcADSR3Coef(adsr->releaseRate, adsr->targetRatioDR);
346783 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
347784 }
348785
349786 // 0.999999 is slow leak, 0.9 is fast leak
350−void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor)
787+void tADSR3_setLeakFactor(tADSR3* const adsrenv, float leakFactor)
351788 {
352− _tADSR* adsr = *adsrenv;
789+ _tADSR3* adsr = *adsrenv;
353790
354791 adsr->leakFactor = leakFactor;
355792 }
356793
357−void tADSR_on(tADSR* const adsrenv, float velocity)
794+void tADSR3_on(tADSR3* const adsrenv, float velocity)
358795 {
359− _tADSR* adsr = *adsrenv;
796+ _tADSR3* adsr = *adsrenv;
360797 adsr->state = env_attack;
361− adsr->gain = velocity;
798+ adsr->targetGainSquared = velocity * velocity;
362799 }
363800
364−void tADSR_off(tADSR* const adsrenv)
801+void tADSR3_off(tADSR3* const adsrenv)
365802 {
366− _tADSR* adsr = *adsrenv;
803+ _tADSR3* adsr = *adsrenv;
367804
368805 if (adsr->state != env_idle)
369806 {
@@ -371,10 +808,10 @@ void tADSR_off(tADSR* const adsrenv) · 1 unmodified line
371808 }
372809 }
373810
374−float tADSR_tick(tADSR* const adsrenv)
811+float tADSR3_tick(tADSR3* const adsrenv)
375812 {
376− _tADSR* adsr = *adsrenv;
377−
813+ _tADSR3* adsr = *adsrenv;
814+
378815
379816 switch (adsr->state) {
380817 case env_idle:
@@ -403,14 +840,13 @@ float tADSR_tick(tADSR* const adsrenv) · 22 unmodified lines
403840 adsr->state = env_idle;
404841 }
405842 }
843+ //smooth the gain value -- this is not ideal, a retrigger while the envelope is still going with a new gain will cause a jump, although it will be smoothed quickly. Maybe doing the math so the range is computed based on the gain rather than 0.->1. is preferable? But that's harder to get the exponential curve right without a lookup.
844+ adsr->gain = (adsr->factor*adsr->targetGainSquared)+(adsr->oneMinusFactor*adsr->gain);
406845 return adsr->output * adsr->gain;
407846 }
408847
409848
410849
411−
412−
413−
414850 /////-----------------
415851 /* Ramp */
416852 void tRamp_init(tRamp* const r, float time, int samples_per_tick)

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