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
95 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~95 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
96 96
97 97
98 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
99 enum envState {
100 env_idle = 0,
101 env_attack,
102 env_decay,
103 env_sustain,
104 env_release
105 };
106
98 /* ADSR */107 /* ADSR */
99 typedef struct _tADSR108 typedef struct _tADSR
100 {109 {
101 const float *exp_buff;110 float sampleRateInMs;
102 const float *inc_buff;111 int state;
103 uint32_t buff_size;112 float output;
104 113 float attackRate;
105 float next;114 float decayRate;
106 115 float releaseRate;
107 float attackInc, decayInc, releaseInc, rampInc;116 float attackCoef;
108 117 float decayCoef;
109 oBool inAttack, inDecay, inSustain, inRelease, inRamp;118 float releaseCoef;
110 119 float sustainLevel;
111 float sustain, gain, rampPeak, releasePeak;120 float targetRatioA;
112 121 float targetRatioDR;
113 float attackPhase, decayPhase, releasePhase, rampPhase;122 float attackBase;
114 123 float decayBase;
124 float releaseBase;
115 float leakFactor;125 float leakFactor;
116 126 float gain;
117 127
118 } _tADSR;128 } _tADSR;
119 129
@@ -129,10 +139,11 @@ extern "C" { · 9 unmodified lines
129 void tADSR_setDecay (tADSR* const, float decay);139 void tADSR_setDecay (tADSR* const, float decay);
130 void tADSR_setSustain (tADSR* const, float sustain);140 void tADSR_setSustain (tADSR* const, float sustain);
131 void tADSR_setRelease (tADSR* const, float release);141 void tADSR_setRelease (tADSR* const, float release);
132 void tADSR_setLeakFactor (tADSR* const, float leakFactor);142 void tADSR_setLeakFactor (tADSR* const, float leakFactor);
133 void tADSR_on (tADSR* const, float velocity);143 void tADSR_on (tADSR* const, float velocity);
134 void tADSR_off (tADSR* const);144 void tADSR_off (tADSR* const);
135 145
146
136 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~147 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
137 148
138 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~149 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
LEAF/Src/leaf-envelopes.c+81−196
@@ -253,7 +253,19 @@ float tEnvelope_tick(tEnvelope* const envlp) · 252 unmodified lines
253 return env->next;253 return env->next;
254}254}
255 255
256
256/* ADSR */257/* 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
263float calcADSRCoef(double rate, double targetRatio)
264{
265 return (rate <= 0.0f) ? 0.0f : exp(-log((1.0 + targetRatio) / targetRatio) / rate);
266}
267
268
257void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release)269void tADSR_init(tADSR* const adsrenv, float attack, float decay, float sustain, float release)
258{270{
259 tADSR_initToPool(adsrenv, attack, decay, sustain, release, &leaf.mempool);271 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
268{280{
269 _tMempool* m = *mp;281 _tMempool* m = *mp;
270 _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m);282 _tADSR* adsr = *adsrenv = (_tADSR*) mpool_alloc(sizeof(_tADSR), m);
271 283 adsr->sampleRateInMs = leaf.sampleRate * 0.001f;
272 adsr->exp_buff = __leaf_table_exp_decay;284 adsr->targetRatioA = 0.3f;
273 adsr->inc_buff = __leaf_table_attack_decay_inc;285 adsr->targetRatioDR = 0.0001f;
274 adsr->buff_size = sizeof(__leaf_table_exp_decay);286 adsr->attackRate = attack * adsr->sampleRateInMs;
275 287 adsr->attackCoef = calcADSRCoef(attack * adsr->sampleRateInMs, adsr->targetRatioA);
276 if (attack > 8192.0f)288 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
277 attack = 8192.0f;289
278 if (attack < 0.0f)290 adsr->decayRate = decay * adsr->sampleRateInMs;
279 attack = 0.0f;291 adsr->decayCoef = calcADSRCoef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR);
280 292 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
281 if (decay > 8192.0f)293
282 decay = 8192.0f;294 adsr->sustainLevel = sustain;
283 if (decay < 0.0f)295 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
284 decay = 0.0f;296
285 297 adsr->releaseRate = release * adsr->sampleRateInMs;
286 if (sustain > 1.0f)298 adsr->releaseCoef = calcADSRCoef(release * adsr->sampleRateInMs, adsr->targetRatioDR);
287 sustain = 1.0f;299 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
288 if (sustain < 0.0f)300
289 sustain = 0.0f;301 adsr->state = env_idle;
290 302 adsr->gain = 1.0f;
291 if (release > 8192.0f)303 adsr->output = 0.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
325 adsr->leakFactor = 1.0f;304 adsr->leakFactor = 1.0f;
326}305}
327 306
@@ -335,61 +314,36 @@ void tADSR_freeFromPool (tADSR* const adsrenv, tMempool* const mp) · 7 unmodified lines
335void tADSR_setAttack(tADSR* const adsrenv, float attack)314void tADSR_setAttack(tADSR* const adsrenv, float attack)
336{315{
337 _tADSR* adsr = *adsrenv;316 _tADSR* adsr = *adsrenv;
338 317
339 int32_t attackIndex;318 adsr->attackRate = attack * adsr->sampleRateInMs;
340 319 adsr->attackCoef = calcADSRCoef(adsr->attackRate, adsr->targetRatioA);
341 if (attack < 0.0f) {320 adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
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];
350}321}
351 322
352void tADSR_setDecay(tADSR* const adsrenv, float decay)323void tADSR_setDecay(tADSR* const adsrenv, float decay)
353{324{
354 _tADSR* adsr = *adsrenv;325 _tADSR* adsr = *adsrenv;
355 326
356 int32_t decayIndex;327 adsr->decayRate = decay * adsr->sampleRateInMs;
357 328 adsr->decayCoef = calcADSRCoef(adsr->decayRate,adsr-> targetRatioDR);
358 if (decay < 0.0f) {329 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
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];
367}330}
368 331
369void tADSR_setSustain(tADSR* const adsrenv, float sustain)332void tADSR_setSustain(tADSR* const adsrenv, float sustain)
370{333{
371 _tADSR* adsr = *adsrenv;334 _tADSR* adsr = *adsrenv;
372 335
373 if (sustain > 1.0f) adsr->sustain = 1.0f;336 adsr->sustainLevel = sustain;
374 else if (sustain < 0.0f) adsr->sustain = 0.0f;337 adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
375 else adsr->sustain = sustain;
376}338}
377 339
378void tADSR_setRelease(tADSR* const adsrenv, float release)340void tADSR_setRelease(tADSR* const adsrenv, float release)
379{341{
380 _tADSR* adsr = *adsrenv;342 _tADSR* adsr = *adsrenv;
381 343
382 int32_t releaseIndex;344 adsr->releaseRate = release * adsr->sampleRateInMs;
383 345 adsr->releaseCoef = calcADSRCoef(adsr->releaseRate, adsr->targetRatioDR);
384 if (release < 0.0f) {346 adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
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];
393}347}
394 348
395// 0.999999 is slow leak, 0.9 is fast leak349// 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
397{351{
398 _tADSR* adsr = *adsrenv;352 _tADSR* adsr = *adsrenv;
399 353
400
401 adsr->leakFactor = leakFactor;354 adsr->leakFactor = leakFactor;
402}355}
403 356
404void tADSR_on(tADSR* const adsrenv, float velocity)357void tADSR_on(tADSR* const adsrenv, float velocity)
405{358{
406 _tADSR* adsr = *adsrenv;359 _tADSR* adsr = *adsrenv;
407 360 adsr->state = env_attack;
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;
425 adsr->gain = velocity;361 adsr->gain = velocity;
426}362}
427 363
428void tADSR_off(tADSR* const adsrenv)364void tADSR_off(tADSR* const adsrenv)
429{365{
430 _tADSR* adsr = *adsrenv;366 _tADSR* adsr = *adsrenv;
431 367
432 if (adsr->inRelease) return;368 if (adsr->state != env_idle)
433 369 {
434 adsr->inAttack = OFALSE;370 adsr->state = env_release;
435 adsr->inDecay = OFALSE;371 }
436 adsr->inSustain = OFALSE;
437 adsr->inRelease = OTRUE;
438
439 adsr->releasePeak = adsr->next;
440}372}
441 373
442float tADSR_tick(tADSR* const adsrenv)374float tADSR_tick(tADSR* const adsrenv)
@@ -444,89 +376,42 @@ float tADSR_tick(tADSR* const adsrenv) · 1 unmodified line
444 _tADSR* adsr = *adsrenv;376 _tADSR* adsr = *adsrenv;
445 377
446 378
447 if (adsr->inRamp)379 switch (adsr->state) {
448 {380 case env_idle:
449 if (adsr->rampPhase > UINT16_MAX)381 break;
450 {382 case env_attack:
451 adsr->inRamp = OFALSE;383 adsr->output = adsr->attackBase + adsr->output * adsr->attackCoef;
452 adsr->inAttack = OTRUE;384 if (adsr->output >= 1.0f) {
453 adsr->next = 0.0f;385 adsr->output = 1.0f;
454 }386 adsr->state = env_decay;
455 else387 }
456 {388 break;
457 adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];389 case env_decay:
458 }390 adsr->output = adsr->decayBase + adsr->output * adsr->decayCoef * adsr->leakFactor;
459 391 if (adsr->output <= adsr->sustainLevel) {
460 adsr->rampPhase += adsr->rampInc;392 adsr->output = adsr->sustainLevel;
461 }393 adsr->state = env_sustain;
462 394 }
463 if (adsr->inAttack)395 break;
464 {396 case env_sustain:
465 397 adsr->output = adsr->output * adsr->leakFactor;
466 // If attack done, time to turn around.398 break;
467 if (adsr->attackPhase > UINT16_MAX)399 case env_release:
468 {400 adsr->output = adsr->releaseBase + adsr->output * adsr->releaseCoef;
469 adsr->inDecay = OTRUE;401 if (adsr->output <= 0.0f) {
470 adsr->inAttack = OFALSE;402 adsr->output = 0.0f;
471 adsr->next = adsr->gain * 1.0f;403 adsr->state = env_idle;
472 }404 }
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;
502 }405 }
406 return adsr->output * adsr->gain;
407}
408
503 409
504 if (adsr->inSustain)
505 {
506 adsr->next = adsr->next * adsr->leakFactor;
507 }
508 410
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 }
525 411
526 412
527 return adsr->next;
528}
529 413
414/////-----------------
530/* Ramp */415/* Ramp */
531void tRamp_init(tRamp* const r, float time, int samples_per_tick)416void tRamp_init(tRamp* const r, float time, int samples_per_tick)
532{417{
LEAF/Src/leaf-mempool.c+3−0
@@ -68,10 +68,13 @@ void mpool_create (char* memory, size_t size, _tMempool* pool) · 67 unmodified lines
68 68
69 pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-leaf.header_size);69 pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-leaf.header_size);
70 70
71 /*
71 for (int i = 0; i < pool->head->size; i++)72 for (int i = 0; i < pool->head->size; i++)
72 {73 {
73 memory[i+leaf.header_size]=0;74 memory[i+leaf.header_size]=0;
74 }75 }
76 */
77 //is zeroing out the memory necessary? This takes a long time on large pools - JS
75}78}
76 79
77void leaf_pool_init(char* memory, size_t size)80void 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