DSP envelopes

The envelope value (ENVX) of each S-SMP DSP voice is driven by either an ADSR envelope, or a gain control. This gives an additional way to automatically shape the volume of the voice over time, aside from its VOL registers.

The ADSR describes a 4 stage envelope:
 * Attack begins at key-on, rising from 0 to full over a chosen amount of time.
 * Decay lowers from full to a chosen sustain level.
 * Sustain is the volume level reached after the decay concludes.
 * Release begins at key-off, lowering to 0 with an exponential decay.

Internally the envelope is an 11-bit value multiplied by by the voice output. The ENVX value that can be read from the DSP contains only the high 7 bits.

See:
 * ADSR
 * GAIN

ADSR Envelope Timings
See: S-SMP ADSR

At a rate according to the period table the following action is performed, and the envelope is clamped to 0-2047 ($7FF):
 * Attack at period[A*2+1]: adds 32, or if A=$F adds 1024 ($400).
 * Decay at period[D*2+16]: envelope -= 1, then envelope -= envelope >> 8.
 * Release at period[R]: envelope -= 1, then envelope -= envelope >> 8.

This table of timings gives the resulting time taken by the above operations:
 * Attack is the time from 0 to full.
 * Decay is the time from full to sustain level.
 * Release is the time from full to 0.

Gain Timings
See: S-SMP GAIN

At a rate according to the period table the following action is performed, and the envelope is clamped to 0-2047 ($7FF):
 * Linear gain adds or subtracts 32.
 * Bent gain adds 32 if below 1536 ($600), or 8 if above.
 * Exponential is two steps: envelope -= 1, then: envelope -= envelope >> 8.

This table gives times taken between 0 volume and full volume (or the reverse):

Period Table
The rate of DSP envelope events are controlled by a common table of 32 periods. Each entry is how many S-SMP clocks elapse per envelope operation. The table is arranged in groups of 3.

Additionally, each column of periods appears to have a delay offset applied to it, affecting when the operation occurs. If counter is counting down the number of S-SMP clocks elapsed since reset, the envelope operation is applied when the following is true:
 * 0 == (counter + offset[rate]) % period[rate]

The counter begins at 0 after reset, and decrements on each S-SMP clock, wrapping to $77FF (30,720) when it would go below 0. (The first clock after reset will wrap.)

Note that most of the offsets given above are effectively much smaller, given that they are modulo (%) with their associated period, but the modulo-equivalent larger values shown here demonstrate the symmetry between columns.