[sdiy] Fast envelope generation

rburnett at richieburnett.co.uk rburnett at richieburnett.co.uk
Tue Dec 18 16:11:02 CET 2012

On 2012-12-18 07:54, Gordon JC Pearce wrote:
> On 18/12/12 01:53, Scott Nordlund wrote:
>>> I await the onslaught of "it's been done" and "it doesn't work"
>>> ;-)
>> It's been done, as early as 1971, in the Allen Digital Computer 
>> Organ
>> (and derivative models like the RMI Keyboard Computer). This 
>> actually
>> included two different tabularized variations, with the attack and
>> decay rates controlled by different foot pedal-controlled clocks.
> Good, so presumably it works then!  That's always a good start...
> I've always said that electronics is 80% Ohm's Law and the rest is
> just guesswork and plagiarism :-)

Hi Gordon,

It's really not that hard to just generate the envelope waveform 
directly with a simple first-order IIR digital filter!  The equation is 
of the form:

y[n] = y[n-1] + r * ( x[n] - y[n-1] )

Where y[n] is the current output, y[n-1] is the previous output, and 
x[n] is the current input (i.e. the destination of where the envelope is 
ramping towards.)

r is a variable that determines the rate (time constant of the 
exponential attack/decay).  If r is 0 it will take forever to get there, 
if r=1 it will get there in one sample.  Values in between 0 and 1 give 
you all the time constants possible for your attack/decay/release.  You 
just substitute the relevant constant in the possition of r in your 
calculation in order to get different attack, decay and release times as 
the envelope progresses.

Essentially you just calculate the difference between the current 
envelope output and where it's ultimately heading too, scale this value, 
and add it to the last envelope output on every iteration of the 
envelope calculation.

I can see why many might think that a lookup-table approach might be 
better suited to a low-end 8-bit micro.  However, if you need to do 
interpolation between entries in a lookup table then that requires more 
than 8-bit data-types and a multiply operation, and if you have the 
ability to handle large data-types and perform hardware or software 
multiply then you might as well just calculate the envelope directly 
with the IIR filter equation above.

Provided you make the word length of y[n] sufficiently large you can 
calculate exponential attack and decay to arbitrary precision and for 
any time constant.  You can also arrange for the multiply operation to 
be done as a combination of binary right shift and add instructions if 
your processor doesn't have hardware multiply.  This is what I have done 
before for Microchip devices like the PIC12 series.

The only advantage I can see that the exponential lookup-table gives 
you is that you can substitute in other attack and decay shapes like 
linear or reverse exponential etc.  The IIR filter equation will always 
give you an output that follows the input with a first order lag so 
behaves like an RC network with variable time constant.

If you choose to go down the exponential lookup-table path, it is worth 
bearing in mind that your lookup table only needs to store one octave's 
worth of the exponential curve (i.e. where the output varies over a 2:1 
ratio.)  (Outside this range the function just repeats with steeper or 
shallower gradient.)  All other output values can be obtained by 
left-shifting or right-shifting the value pulled from the lookup table 
for input values outside of this range.  This significantly reduces the 
size of the exponential lookup table required whilst adding little 
complexity to the calculations.

I hope this helps,


More information about the Synth-diy mailing list