I've written an ADSR class that uses a linear approach instead of an exponential one, i.e. the values rise and fall linearly. One thing that I've noticed when I use the ADSR to modulate the amplitude of an oscillator is that when I set the sustain to zero and the decay to some value, e.g. 1.5 seconds, the sound fades out as expected. But at the tail end, the sound seems to drop off too quickly. I've not had a chance to try an exponential ADSR as I'm still exploring ways of implementing one, but could this drop off be related to the ADSR being linear?
I've searched through past posts here for implementing an exponential ADSR. I've come across some very clever solutions. One that I like is using a first order lowpass IIR filter. This solution has been mentioned a few times, at least once by JCJR and a few times by braindoc. It's attractive because of the low computational costs and, from what I understand, it's the way analog synths implement envelopes (with "RC" circuits, I think?).
In examining this approach I noticed that "attack" portion is logarithmic rather than exponential. To see what I mean, check out an excerpt from Steven W. Smith's excellent book, The Scientist and Engineer's Guide to Digital Signal Processing. This shows the attack as logarithmic. However, the decay curve looks exponential. This graphic shows what I'm talking about.
Apparently, this is the way an analog synth's ADSR behaves. For an example, look here.
Now, to calculate how long a segment should last, you use the following equation:
Code: Select all
x = e^(-1/d)
From what I understand, the amplitude of the envelope will be in the neighborhood of 0.63 at the end of the attack. If you set up your algorithm thinking that at the end of the attack you'll have an amplitude close to 1, you'll be disappointed. Same goes for targetting the sustain level. I found in testing out some code that if I divide "d" by some value larger than one, it causes the filter to run faster thus getting it closer to the target amplitude. This feels a little kludgey, but seems to be a simple enough solution.



