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
105 };105 };
106 106
107 /* ADSR */107 /* ADSR */
108 typedef struct _tADSR108 typedef struct _tADSR
109 {109 {
110 float sampleRateInMs;110 const float *exp_buff;
111 int state;111 const float *inc_buff;
112 float output;112 uint32_t buff_size;
113 float attackRate;113
114 float decayRate;114 float next;
115 float releaseRate;115
116 float attackCoef;116 float attackInc, decayInc, releaseInc, rampInc;
117 float decayCoef;117
118 float releaseCoef;118 oBool inAttack, inDecay, inSustain, inRelease, inRamp;
119 float sustainLevel;119
120 float targetRatioA;120 float sustain, gain, rampPeak, releasePeak;
121 float targetRatioDR;121
122 float attackBase;122 float attackPhase, decayPhase, releasePhase, rampPhase;
123 float decayBase;123
124 float releaseBase;124 float leakFactor;
125 float leakFactor;125
126 float gain;126
127 127 } _tADSR;
128 } _tADSR;128
129 129 typedef _tADSR* tADSR;
130 typedef _tADSR* tADSR;130
131 131 void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);
132 void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release);132 void tADSR_free (tADSR* const);
133 void tADSR_free (tADSR* const);133 void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const);
134 void tADSR_initToPool (tADSR* const, float attack, float decay, float sustain, float release, tMempool* const);134 void tADSR_freeFromPool (tADSR* const, tMempool* const);
135 void tADSR_freeFromPool (tADSR* const, tMempool* const);135
136 136 float tADSR_tick (tADSR* const);
137 float tADSR_tick (tADSR* const);137 void tADSR_setAttack (tADSR* const, float attack);
138 void tADSR_setAttack (tADSR* const, float attack);138 void tADSR_setDecay (tADSR* const, float decay);
139 void tADSR_setDecay (tADSR* const, float decay);139 void tADSR_setSustain (tADSR* const, float sustain);
140 void tADSR_setSustain (tADSR* const, float sustain);140 void tADSR_setRelease (tADSR* const, float release);
141 void tADSR_setRelease (tADSR* const, float release);141 void tADSR_setLeakFactor (tADSR* const, float leakFactor);
142 void tADSR_setLeakFactor (tADSR* const, float leakFactor);142 void tADSR_on (tADSR* const, float velocity);
143 void tADSR_on (tADSR* const, float velocity);143 void tADSR_off (tADSR* const);
144 void tADSR_off (tADSR* const);144
145
145 146
146 147
147 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~148 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
148 149
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 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
149 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~246 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
150 247
151 /* Ramp */248 /* Ramp */
LEAF/Src/leaf-envelopes.c+477−41
@@ -254,116 +254,553 @@ float tEnvelope_tick(tEnvelope* const envlp) · 253 unmodified lines
254}254}
255 255
256 256
257
257/* ADSR */258/* ADSR */
258//replaced our older ADSR that relied on a large lookup table with this one by Nigel Redmon from his blog. Thanks, Nigel!259void 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
264void tADSR_free(tADSR* const adsrenv)
265{
266 tADSR_freeFromPool(adsrenv, &leaf.mempool);
267}
268
269void 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
330void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp)
331{
332 _tMempool* m = *mp;
333 _tADSR* adsr = *adsrenv;
334 mpool_free(adsr, m);
335}
336
337void 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
354void 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
371void 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
380void 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
398void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor)
399{
400 _tADSR* adsr = *adsrenv;
401
402
403 adsr->leakFactor = leakFactor;
404}
405
406void 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
430void 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
444float 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
259//-JS537//-JS
260 538
261 539
262 540
263float calcADSRCoef(double rate, double targetRatio)541const float ADSR2_MIN_TIME = 1e-3f;
542const float ADSR2_INV_MIN_TIME = 1000.0f;
543const float ADSR2_MAX_TIME = 10.f;
544const float ADSR2_LAMBDA_BASE = 10000.0f;
545
546
547void 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
552void tADSR2_free(tADSR2* const adsrenv)
553{
554 tADSR2_freeFromPool(adsrenv, &leaf.mempool);
555}
556
557void 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
586void tADSR2_freeFromPool (tADSR2* const adsrenv, tMempool* const mp)
587{
588 _tMempool* m = *mp;
589 _tADSR2* adsr = *adsrenv;
590 mpool_free(adsr, m);
591}
592
593void 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
601void 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
609void 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
623void 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
631void tADSR2_setLeakFactor(tADSR2* const adsrenv, float leakFactor)
632{
633 _tADSR2* adsr = *adsrenv;
634
635 adsr->leakFactor = leakFactor;
636}
637
638void 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
648void tADSR2_off(tADSR2* const adsrenv)
649{
650 _tADSR2* adsr = *adsrenv;
651 adsr->gate = 0;
652 adsr->envTarget = 0.0f;
653}
654
655float 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
697float calcADSR3Coef(double rate, double targetRatio)
264{698{
265 return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate);699 return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate);
266}700}
267 701
268 702
269void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release)703void tADSR3_init(tADSR3* const adsrenv, float attack, float decay, float sustain, float release)
270{704{
271 tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);705 tADSR3_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);
272}706}
273 707
274void tADSR_free(tADSR* const adsrenv)708void tADSR3_free(tADSR3* const adsrenv)
275{709{
276 tADSR_freeFromPool(adsrenv, &leaf.mempool);710 tADSR3_freeFromPool(adsrenv, &leaf.mempool);
277}711}
278 712
279void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)713void tADSR3_initToPool (tADSR3* const adsrenv, float attack, float decay, float sustain, float release, tMempool* const mp)
280{714{
281 _tMempool* m = *mp;715 _tMempool* m = *mp;
282 _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m);716 _tADSR3* adsr = *adsrenv = (_tADSR3*) mpool_alloc(sizeof(_tADSR3), m);
283 adsr->sampleRateInMs = leaf.sampleRate * 0.001f;717 adsr->sampleRateInMs = leaf.sampleRate * 0.001f;
284 adsr->targetRatioA = 0.3f;718 adsr->targetRatioA = 0.3f;
285 adsr->targetRatioDR = 0.0001f;719 adsr->targetRatioDR = 0.0001f;
286 adsr->attackRate = attack * adsr->sampleRateInMs;720 adsr->attackRate = attack * adsr->sampleRateInMs;
287 adsr->attackCoef = calcADSRCoef(attack * adsr->sampleRateInMs, adsr->targetRatioA);721 adsr->attackCoef = calcADSR3Coef(attack * adsr->sampleRateInMs, adsr->targetRatioA);
288 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);722 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
289 723
290 adsr->decayRate = decay * adsr->sampleRateInMs;724 adsr->decayRate = decay * adsr->sampleRateInMs;
291 adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR);725 adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR);
292 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);726 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
293 727
294 adsr->sustainLevel = sustain;728 adsr->sustainLevel = sustain;
295 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);729 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
296 730
297 adsr->releaseRate = release * adsr->sampleRateInMs;731 adsr->releaseRate = release * adsr->sampleRateInMs;
298 adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR);732 adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR);
299 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);733 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
300 734
301 adsr->state = env_idle;735 adsr->state = env_idle;
302 adsr->gain = 1.0f;736 adsr->gain = 1.0f;
737 adsr->targetGainSquared = 1.0f;
738 adsr->factor = 0.01f;
739 adsr->oneMinusFactor = 0.99f;
303 adsr->output = 0.0f;740 adsr->output = 0.0f;
304 adsr->leakFactor = 1.0f;741 adsr->leakFactor = 1.0f;
305}742}
306 743
307void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp)744void tADSR3_freeFromPool (tADSR3* const adsrenv, tMempool* const mp)
308{745{
309 _tMempool* m = *mp;746 _tMempool* m = *mp;
310 _tADSR* adsr = *adsrenv;747 _tADSR3* adsr = *adsrenv;
311 mpool_free(adsr, m);748 mpool_free(adsr, m);
312}749}
313 750
314void tADSR_setAttack(tADSR* const adsrenv, float attack)751void tADSR3_setAttack(tADSR3* const adsrenv, float attack)
315{752{
316 _tADSR* adsr = *adsrenv;753 _tADSR3* adsr = *adsrenv;
317 754
318 adsr->attackRate = attack * adsr->sampleRateInMs;755 adsr->attackRate = attack * adsr->sampleRateInMs;
319 adsr->attackCoef = calcADSRCoef(adsr->attackRate, adsr->targetRatioA);756 adsr->attackCoef = calcADSR3Coef(adsr->attackRate, adsr->targetRatioA);
320 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);757 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
321}758}
322 759
323void tADSR_setDecay(tADSR* const adsrenv, float decay)760void tADSR3_setDecay(tADSR3* const adsrenv, float decay)
324{761{
325 _tADSR* adsr = *adsrenv;762 _tADSR3* adsr = *adsrenv;
326 763
327 adsr->decayRate = decay * adsr->sampleRateInMs;764 adsr->decayRate = decay * adsr->sampleRateInMs;
328 adsr->decayCoef = calcADSRCoef(adsr->decayRate,adsr-> targetRatioDR);765 adsr->decayCoef = calcADSR3Coef(adsr->decayRate,adsr-> targetRatioDR);
329 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);766 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
330}767}
331 768
332void tADSR_setSustain(tADSR* const adsrenv, float sustain)769void tADSR3_setSustain(tADSR3* const adsrenv, float sustain)
333{770{
334 _tADSR* adsr = *adsrenv;771 _tADSR3* adsr = *adsrenv;
335 772
336 adsr->sustainLevel = sustain;773 adsr->sustainLevel = sustain;
337 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);774 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
338}775}
339 776
340void tADSR_setRelease(tADSR* const adsrenv, float release)777void tADSR3_setRelease(tADSR3* const adsrenv, float release)
341{778{
342 _tADSR* adsr = *adsrenv;779 _tADSR3* adsr = *adsrenv;
343 780
344 adsr->releaseRate = release * adsr->sampleRateInMs;781 adsr->releaseRate = release * adsr->sampleRateInMs;
345 adsr->releaseCoef = calcADSRCoef(adsr->releaseRate, adsr->targetRatioDR);782 adsr->releaseCoef = calcADSR3Coef(adsr->releaseRate, adsr->targetRatioDR);
346 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);783 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
347}784}
348 785
349// 0.999999 is slow leak, 0.9 is fast leak786// 0.999999 is slow leak, 0.9 is fast leak
350void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor)787void tADSR3_setLeakFactor(tADSR3* const adsrenv, float leakFactor)
351{788{
352 _tADSR* adsr = *adsrenv;789 _tADSR3* adsr = *adsrenv;
353 790
354 adsr->leakFactor = leakFactor;791 adsr->leakFactor = leakFactor;
355}792}
356 793
357void tADSR_on(tADSR* const adsrenv, float velocity)794void tADSR3_on(tADSR3* const adsrenv, float velocity)
358{795{
359 _tADSR* adsr = *adsrenv;796 _tADSR3* adsr = *adsrenv;
360 adsr->state = env_attack;797 adsr->state = env_attack;
361 adsr->gain = velocity;798 adsr->targetGainSquared = velocity * velocity;
362}799}
363 800
364void tADSR_off(tADSR* const adsrenv)801void tADSR3_off(tADSR3* const adsrenv)
365{802{
366 _tADSR* adsr = *adsrenv;803 _tADSR3* adsr = *adsrenv;
367 804
368 if (adsr->state != env_idle)805 if (adsr->state != env_idle)
369 {806 {
@@ -371,10 +808,10 @@ void tADSR_off(tADSR* const adsrenv) · 1 unmodified line
371 }808 }
372}809}
373 810
374float tADSR_tick(tADSR* const adsrenv)811float tADSR3_tick(tADSR3* const adsrenv)
375{812{
376 _tADSR* adsr = *adsrenv;813 _tADSR3* adsr = *adsrenv;
377 814
378 815
379 switch (adsr->state) {816 switch (adsr->state) {
380 case env_idle:817 case env_idle:
@@ -403,14 +840,13 @@ float tADSR_tick(tADSR* const adsrenv) · 22 unmodified lines
403 adsr->state = env_idle;840 adsr->state = env_idle;
404 }841 }
405 }842 }
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);
406 return adsr->output * adsr->gain;845 return adsr->output * adsr->gain;
407}846}
408 847
409 848
410 849
411
412
413
414/////-----------------850/////-----------------
415/* Ramp */851/* Ramp */
416void tRamp_init(tRamp* const r, float time, int samples_per_tick)852void 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