History

updated ADSR envelopes and removed zeroing when creating mpool object

spiricom committed 6 years ago

Commit 71e82bd1 parent 45cc4384 files · +110 −211Browse files

Unified · Split

4 files
  1. .DS_Store +0 −0
  2. LEAF/Inc/leaf-envelopes.h +27 −16
  3. LEAF/Src/leaf-envelopes.c +81 −196
  4. LEAF/Src/leaf-mempool.c +3 −0
.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-envelopes.h+27−16
@@ -95,25 +95,35 @@ extern "C" { · 94 unmodified lines
9595 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
9696
9797
98+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
99+ enum envState {
100+ env_idle = 0,
101+ env_attack,
102+ env_decay,
103+ env_sustain,
104+ env_release
105+ };
106+
98107 /* ADSR */
99108 typedef struct _tADSR
100109 {
101− const float *exp_buff;
102− const float *inc_buff;
103− uint32_t buff_size;
104−
105− float next;
106−
107− float attackInc, decayInc, releaseInc, rampInc;
108−
109− oBool inAttack, inDecay, inSustain, inRelease, inRamp;
110−
111− float sustain, gain, rampPeak, releasePeak;
112−
113− float attackPhase, decayPhase, releasePhase, rampPhase;
114−
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;
115125 float leakFactor;
116−
126+ float gain;
117127
118128 } _tADSR;
119129
@@ -129,10 +139,11 @@ extern "C" { · 9 unmodified lines
129139 void tADSR_setDecay (tADSR* const, float decay);
130140 void tADSR_setSustain (tADSR* const, float sustain);
131141 void tADSR_setRelease (tADSR* const, float release);
132− void tADSR_setLeakFactor (tADSR* const, float leakFactor);
142+ void tADSR_setLeakFactor (tADSR* const, float leakFactor);
133143 void tADSR_on (tADSR* const, float velocity);
134144 void tADSR_off (tADSR* const);
135145
146+
136147 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
137148
138149 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
LEAF/Src/leaf-envelopes.c+81−196
@@ -253,7 +253,19 @@ float tEnvelope_tick(tEnvelope* const envlp) · 252 unmodified lines
253253 return env->next;
254254 }
255255
256+
256257 /* 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+//-JS
260+
261+
262+
263+float calcADSRCoef(double rate, double targetRatio)
264+{
265+ return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate);
266+}
267+
268+
257269 void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release)
258270 {
259271 tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);
@@ -268,60 +280,27 @@ void tADSR_initToPool (tADSR* const adsrenv, float attack, float decay, fl · 8 unmodified lines
268280 {
269281 _tMempool* m = *mp;
270282 _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m);
271−
272− adsr->exp_buff = __leaf_table_exp_decay;
273− adsr->inc_buff = __leaf_table_attack_decay_inc;
274− adsr->buff_size = sizeof(__leaf_table_exp_decay);
275−
276− if (attack > 8192.0f)
277− attack = 8192.0f;
278− if (attack < 0.0f)
279− attack = 0.0f;
280−
281− if (decay > 8192.0f)
282− decay = 8192.0f;
283− if (decay < 0.0f)
284− decay = 0.0f;
285−
286− if (sustain > 1.0f)
287− sustain = 1.0f;
288− if (sustain < 0.0f)
289− sustain = 0.0f;
290−
291− if (release > 8192.0f)
292− release = 8192.0f;
293− if (release < 0.0f)
294− release = 0.0f;
295−
296− int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
297− int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
298− int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
299− int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
300−
301− if (attackIndex < 0)
302− attackIndex = 0;
303− if (decayIndex < 0)
304− decayIndex = 0;
305− if (releaseIndex < 0)
306− releaseIndex = 0;
307− if (rampIndex < 0)
308− rampIndex = 0;
309−
310− adsr->next = 0.0f;
311−
312− adsr->inRamp = OFALSE;
313− adsr->inAttack = OFALSE;
314− adsr->inDecay = OFALSE;
315− adsr->inSustain = OFALSE;
316− adsr->inRelease = OFALSE;
317−
318− adsr->sustain = sustain;
319−
320− adsr->attackInc = adsr->inc_buff[attackIndex];
321− adsr->decayInc = adsr->inc_buff[decayIndex];
322− adsr->releaseInc = adsr->inc_buff[releaseIndex];
323− adsr->rampInc = adsr->inc_buff[rampIndex];
324−
283+ adsr->sampleRateInMs = leaf.sampleRate * 0.001f;
284+ adsr->targetRatioA = 0.3f;
285+ adsr->targetRatioDR = 0.0001f;
286+ adsr->attackRate = attack * adsr->sampleRateInMs;
287+ adsr->attackCoef = calcADSRCoef(attack * adsr->sampleRateInMs, adsr->targetRatioA);
288+ adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
289+
290+ adsr->decayRate = decay * adsr->sampleRateInMs;
291+ adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR);
292+ adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
293+
294+ adsr->sustainLevel = sustain;
295+ adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
296+
297+ adsr->releaseRate = release * adsr->sampleRateInMs;
298+ adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR);
299+ adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
300+
301+ adsr->state = env_idle;
302+ adsr->gain = 1.0f;
303+ adsr->output = 0.0f;
325304 adsr->leakFactor = 1.0f;
326305 }
327306
@@ -335,61 +314,36 @@ void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp) · 7 unmodified lines
335314 void tADSR_setAttack(tADSR* const adsrenv, float attack)
336315 {
337316 _tADSR* adsr = *adsrenv;
338−
339− int32_t attackIndex;
340−
341− if (attack < 0.0f) {
342− attackIndex = 0.0f;
343− } else if (attack < 8192.0f) {
344− attackIndex = ((int32_t)(attack * 8.0f))-1;
345− } else {
346− attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
347− }
348−
349− adsr->attackInc = adsr->inc_buff[attackIndex];
317+
318+ adsr->attackRate = attack * adsr->sampleRateInMs;
319+ adsr->attackCoef = calcADSRCoef(adsr->attackRate, adsr->targetRatioA);
320+ adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
350321 }
351322
352323 void tADSR_setDecay(tADSR* const adsrenv, float decay)
353324 {
354325 _tADSR* adsr = *adsrenv;
355326
356− int32_t decayIndex;
357−
358− if (decay < 0.0f) {
359− decayIndex = 0.0f;
360− } else if (decay < 8192.0f) {
361− decayIndex = ((int32_t)(decay * 8.0f)) - 1;
362− } else {
363− decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
364− }
365−
366− adsr->decayInc = adsr->inc_buff[decayIndex];
327+ adsr->decayRate = decay * adsr->sampleRateInMs;
328+ adsr->decayCoef = calcADSRCoef(adsr->decayRate,adsr-> targetRatioDR);
329+ adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
367330 }
368331
369332 void tADSR_setSustain(tADSR* const adsrenv, float sustain)
370333 {
371334 _tADSR* adsr = *adsrenv;
372335
373− if (sustain > 1.0f) adsr->sustain = 1.0f;
374− else if (sustain < 0.0f) adsr->sustain = 0.0f;
375− else adsr->sustain = sustain;
336+ adsr->sustainLevel = sustain;
337+ adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
376338 }
377339
378340 void tADSR_setRelease(tADSR* const adsrenv, float release)
379341 {
380342 _tADSR* adsr = *adsrenv;
381343
382− int32_t releaseIndex;
383−
384− if (release < 0.0f) {
385− releaseIndex = 0.0f;
386− } else if (release < 8192.0f) {
387− releaseIndex = ((int32_t)(release * 8.0f)) - 1;
388− } else {
389− releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
390− }
391−
392− adsr->releaseInc = adsr->inc_buff[releaseIndex];
344+ adsr->releaseRate = release * adsr->sampleRateInMs;
345+ adsr->releaseCoef = calcADSRCoef(adsr->releaseRate, adsr->targetRatioDR);
346+ adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
393347 }
394348
395349 // 0.999999 is slow leak, 0.9 is fast leak
@@ -397,46 +351,24 @@ void tADSR_setLeakFactor(tADSR* const adsrenv, float leakFactor) · 1 unmodified line
397351 {
398352 _tADSR* adsr = *adsrenv;
399353
400−
401354 adsr->leakFactor = leakFactor;
402355 }
403356
404357 void tADSR_on(tADSR* const adsrenv, float velocity)
405358 {
406359 _tADSR* adsr = *adsrenv;
407−
408− if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.
409− {
410− adsr->rampPhase = 0;
411− adsr->inRamp = OTRUE;
412− adsr->rampPeak = adsr->next;
413− }
414− else // Normal start.
415− {
416− adsr->inAttack = OTRUE;
417− }
418−
419− adsr->attackPhase = 0;
420− adsr->decayPhase = 0;
421− adsr->releasePhase = 0;
422− adsr->inDecay = OFALSE;
423− adsr->inSustain = OFALSE;
424− adsr->inRelease = OFALSE;
360+ adsr->state = env_attack;
425361 adsr->gain = velocity;
426362 }
427363
428364 void tADSR_off(tADSR* const adsrenv)
429365 {
430366 _tADSR* adsr = *adsrenv;
431−
432− if (adsr->inRelease) return;
433−
434− adsr->inAttack = OFALSE;
435− adsr->inDecay = OFALSE;
436− adsr->inSustain = OFALSE;
437− adsr->inRelease = OTRUE;
438−
439− adsr->releasePeak = adsr->next;
367+
368+ if (adsr->state != env_idle)
369+ {
370+ adsr->state = env_release;
371+ }
440372 }
441373
442374 float tADSR_tick(tADSR* const adsrenv)
@@ -444,89 +376,42 @@ float tADSR_tick(tADSR* const adsrenv) · 1 unmodified line
444376 _tADSR* adsr = *adsrenv;
445377
446378
447− if (adsr->inRamp)
448− {
449− if (adsr->rampPhase > UINT16_MAX)
450− {
451− adsr->inRamp = OFALSE;
452− adsr->inAttack = OTRUE;
453− adsr->next = 0.0f;
454− }
455− else
456− {
457− adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
458− }
459−
460− adsr->rampPhase += adsr->rampInc;
461− }
462−
463− if (adsr->inAttack)
464− {
465−
466− // If attack done, time to turn around.
467− if (adsr->attackPhase > UINT16_MAX)
468− {
469− adsr->inDecay = OTRUE;
470− adsr->inAttack = OFALSE;
471− adsr->next = adsr->gain * 1.0f;
472− }
473− else
474− {
475− // do interpolation !
476− adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
477− }
478−
479− // Increment ADSR attack.
480− adsr->attackPhase += adsr->attackInc;
481−
482− }
483−
484− if (adsr->inDecay)
485− {
486−
487− // If decay done, sustain.
488− if (adsr->decayPhase >= UINT16_MAX)
489− {
490− adsr->inDecay = OFALSE;
491− adsr->inSustain = OTRUE;
492− adsr->next = adsr->gain * adsr->sustain;
493− }
494−
495− else
496− {
497− adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation !
498− }
499−
500− // Increment ADSR decay.
501− adsr->decayPhase += adsr->decayInc;
379+ switch (adsr->state) {
380+ case env_idle:
381+ break;
382+ case env_attack:
383+ adsr->output = adsr->attackBase + adsr->output * adsr->attackCoef;
384+ if (adsr->output >= 1.0f) {
385+ adsr->output = 1.0f;
386+ adsr->state = env_decay;
387+ }
388+ break;
389+ case env_decay:
390+ adsr->output = adsr->decayBase + adsr->output * adsr->decayCoef * adsr->leakFactor;
391+ if (adsr->output <= adsr->sustainLevel) {
392+ adsr->output = adsr->sustainLevel;
393+ adsr->state = env_sustain;
394+ }
395+ break;
396+ case env_sustain:
397+ adsr->output = adsr->output * adsr->leakFactor;
398+ break;
399+ case env_release:
400+ adsr->output = adsr->releaseBase + adsr->output * adsr->releaseCoef;
401+ if (adsr->output <= 0.0f) {
402+ adsr->output = 0.0f;
403+ adsr->state = env_idle;
404+ }
502405 }
406+ return adsr->output * adsr->gain;
407+}
408+
503409
504− if (adsr->inSustain)
505− {
506− adsr->next = adsr->next * adsr->leakFactor;
507− }
508410
509− if (adsr->inRelease)
510− {
511− // If release done, finish.
512− if (adsr->releasePhase >= UINT16_MAX)
513− {
514− adsr->inRelease = OFALSE;
515− adsr->next = 0.0f;
516− }
517− else {
518−
519− adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation !
520− }
521−
522− // Increment envelope release;
523− adsr->releasePhase += adsr->releaseInc;
524− }
525411
526412
527− return adsr->next;
528−}
529413
414+/////-----------------
530415 /* Ramp */
531416 void tRamp_init(tRamp* const r, float time, int samples_per_tick)
532417 {
LEAF/Src/leaf-mempool.c+3−0
@@ -68,10 +68,13 @@ void mpool_create (char* memory, size_t size, _tMempool* pool) · 67 unmodified lines
6868
6969 pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-leaf.header_size);
7070
71+ /*
7172 for (int i = 0; i < pool->head->size; i++)
7273 {
7374 memory[i+leaf.header_size]=0;
7475 }
76+ */
77+ //is zeroing out the memory necessary? This takes a long time on large pools - JS
7578 }
7679
7780 void leaf_pool_init(char* memory, size_t size)

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