ADSR Envelope API
Posted: Sat Jan 29, 2022 3:25 am
I think a good way to go about it might be:
Store a set of 6.2 fixed-point values: volume, delta-volume
Store a set of 6-bit (6 LSB) sustain_level values
Set VERA address = $1F9C2 (volume register of voice 0), stride = 4
Cycle through all 16 voices:
if delta=0: read VERA data (to advance the stride) and loop to next voice
volume += delta
volume >> 2 (we'll call it 'level' now to distinguish from the 6.2 fixed-point value 'volume')
if level = 0, delta = 0
if level = $3F then delta = voice's decay rate
write_vera: (label)
level |= $C0 (to enable L+R bits)
store level to VERA data (note that we do this even if the integer part didn't change - it's faster to just do it than to check first)
next voice
Triggering a note sets delta = voice's attack rate, sets volume = 0
Releasing a note sets delta = voice's release rate
This may need a little touching up to handle overflow in case the rates aren't ones that would evenly result in levels of $3F or $00.....
EDIT:
instead of comparing level to 0 and $3F, sta ZP_tmp (assuming A holds the computed 'level' after >>2) and then BIT ZP_tmp
BMI -> set delta=0, level=0, volume=0
BVC -> set delta=decay_rate, level=$3F, volume=$FC
Then do BIT delta and BPL to write_vera
else cmp level $3f... BCS to write_vera
else level=sustain_level, volume = level<<2, delta=0
write_vera:
... (same as initial code above)