|
From: Paul K. <pau...@ma...> - 2002-11-15 14:15:44
|
Steve Harris <S.W...@ec...> wrote:
>
> Benno and I were discussing envelope generation last night, I think that
> the right way to generate an exponential envelope (I checked some synths
> outputs too and it looks like this is that way its done) is to feed a
> constant value into a LP filter with different parameters for each stage.
Yes, so the envelope level tends exponentially to a target level.
Where this gets complicated is the attack, which should have a target level
maybe 1.5 times it's end level, otherwise you spend a long time at nearly full
volume waiting for the decay to start. DLS specifies the attack should be
linear not exponental, and I tend to agree with that - for short attacks it
doesn't sound any different, but for long attacks an exponential curve gets
too loud too soon.
Some softsynths now have much more complicated envelopes, with a time,
target level and curve (variable between exp/lin/log) for each stage, but
it's important to let the user set up a simple ADSR if that is all that's
needed.
> I suspect that, in general you need to calculate the amplitude of the
> envelope for each sample, to avoid stairstepping (zipper noise).
Yes, or use short linear segments, and update the envelope every 32 samples
for
example (64 samples is too long, and people will complain about the
resolution).
> Example code:
>
> env = env_input * ai + env * a;
May be faster with one multiplication: env += ai * (env_input - env);
If you allow real-time control of envelope times/rates, counting down the
time to the next stage can get complicated, so it might be better to
trigger the next stage when you reach a certain level. Here is some
nasty code that does it that way, so env_rate could be modulated in
real-time (but to be able to modulate the sustain_level, you would have
to make env_target a pointer).
//initialize:
env = 0.0f;
env_rate = ATTACK_RATE;
env_thresh = 1.0f;
env_target = 1.5f; //else we will never reach threshold
//per sample:
env += env_rate * (env_target - env);
if(env > env_thresh) //end of attack
{
env_rate = DECAY_RATE;
env_thresh = env; //move threshold out of the way
env_target = SUSTAIN_LEVEL;
//could set a flag so this block is skipped in future
}
//note off:
env_rate = RELEASE_RATE;
env_target = 0.0f; //kill the voice before this de-normals!
Paul.
_____________________________
m a x i m | digital audio
http://mda-vst.com
_____________________________
|