blob: 439d7b1e697fa0c5ffc106745656a2f15853ed1c (
plain) (
tree)
|
|
#include "adsr.h"
#include "synth_engine.h"
#include "synth_math.h"
float
adsr_amplitude(adsr_t *adsr, float noteOn, float noteOff, unsigned long long elapsed)
{
float mod = 0.0;
float release_amplitude = 0.0;
float lifetime = elapsed / (float)SAMPLE_RATE;
//float time_active = (noteOn + lifetime) - noteOff;
float time_active = noteOn - noteOff + lifetime;
if (noteOn != 0 && noteOff == 0) {
if (lifetime < adsr->a)
mod = (lifetime / adsr->a)*(lifetime / adsr->a) * adsr->peak;
if (lifetime >= adsr->a && lifetime <= ( adsr->a + adsr->d))
mod = ((lifetime - adsr->a) / adsr->d) * (adsr->s - adsr->peak) + adsr->peak;
if (lifetime > (adsr->a + adsr->d))
mod = adsr->s;
}
else { // Note is off
if (lifetime < adsr->a)
release_amplitude = (lifetime / adsr->a)*(lifetime / adsr->a) * adsr->peak;
if (lifetime >= adsr->a && lifetime <= (adsr->a + adsr->d))
release_amplitude = ((lifetime - adsr->a) / adsr->d) * (adsr->s - adsr->peak) + adsr->peak;
if (lifetime > (adsr->a + adsr->d))
release_amplitude = adsr->s;
mod = (time_active / adsr->r) * (0.0 - release_amplitude) + release_amplitude;
if (adsr->r < 0) {
mod = adsr->s;
}
}
// Amplitude should not be negative
if (mod <= 0.000)
mod = 0.0;
return clamp(mod, -1, 1);
}
float
fix_adsr(adsr_t *adsr, float noteOn, float noteOff, unsigned long long elapsed, unsigned long long noteOffSample)
{
// convert to samples
unsigned long long attack = adsr->a * SAMPLE_RATE + 1;
unsigned long long decay = adsr->d * SAMPLE_RATE + 1;
unsigned long long sustain = adsr->s * SAMPLE_RATE + 1;
unsigned long long release = adsr->r * SAMPLE_RATE + 1;
float mod = 0.0f;
// if note is pressed
if (noteOn != 0 && noteOff == 0) {
if (elapsed < attack) {
// we are in the attack phase
mod = ((float)elapsed / attack) * adsr->peak;
}
else if (/* elapsed >= attack && */ elapsed < attack + decay) {
// we are in the decay phase
mod = ((float)(elapsed - attack) / decay) * (adsr->s - adsr->peak) + adsr->peak;
}
else {// sustain
mod = adsr->s;
}
}
else { // note is not pressed
if (elapsed < noteOffSample + release) {
// we are on the release
// reuse previous block to find starting value
if (noteOffSample < attack) {
mod = ((float)noteOffSample / attack) * adsr->peak;
}
else if (/* elapsed >= attack && */ noteOffSample < attack + decay) {
mod = ((float)(noteOffSample - attack) / decay) * (adsr->s - adsr->peak) + adsr->peak;
}
else {
mod = adsr->s;
}
mod = (0 - mod) / (float)release * (elapsed - noteOffSample) + mod;
}
//printf("el: %ld, att: %ld MOD: %f, on %f, off %f\n", elapsed, attack, mod, noteOn, noteOff);
}
return mod;
}
|