[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,
-Richie,
More information about the Synth-diy
mailing list