gen~ attack decay logarithmic envelope
Hey fellas,
I have a hard time finding any examples with envelopes in gen~ (besides famous Peter McCulloch adsr), so what would be your take on making Attack/Decay logarithmic curve envelope? Or maybe ASR?
So, essentially, I want an envelope triggered by incoming click~, which goes from 1 to 0 as a logarithmic curve (slowly moves toward 0 first, then rapidly decreases)
I tried building it by using two click~ objects with a delay into the counter object and then feeding it to the slide object, but maybe there's a more elegant solution.
log exists for gen~, not sure about exp, but in case not, you can roll your own using pow.
your click~, if that is really a precondition, can be converted to phase accumulators / line segments to run them through such functions.
the rest is scaling and cutting/gate.
yes, the signal scaling can become difficult and is cpu intensive.
Take a look at Help > Examples > Gen > gen~.slide
:)

Something like this, in a codebox:
ar(trig, attack, release) {
History env(0), stage(0),
atk_rate(0), atk_coeff(0), atk_offset(0),
rel_rate(0), rel_coeff(0), rel_offset(0);
if (trig) {
// rate in seconds
atk_rate = samplerate * attack;
rel_rate = samplerate * release;
// slope 0 = linear, slope -n = log/exp
atk_slope = exp(-1.5);
rel_slope = exp(-8);
// calculate coefficients
atk_coeff = exp(-log((1 + atk_slope) / atk_slope) / atk_rate);
atk_offset = (1 + atk_slope) * (1 - atk_coeff);
rel_coeff = exp(-log((1 + rel_slope) / rel_slope) / rel_rate);
rel_offset = -rel_slope * (1 - rel_coeff);
// reset & trigger envelope
env = 0;
stage = 1;
}
// stage 0 = idle, 1 = attack, 2 = decay
if (stage == 0) {
env = 0;
} else if (stage == 1) {
env = atk_offset + env * atk_coeff;
if (env >= 1 || attack <= 0) {
env = 1;
stage = 2;
}
} else if (stage == 2) {
env = rel_offset + env * rel_coeff;
if (env <= 0 || release <= 0) {
env = 0;
stage = 0;
}
}
return env;
}