pinobatch/pently

Compress instrument envelopes without arpeggio

Closed this issue · 1 comments

Sound effect data can be compressed by setting a row period greater than one. This serves two purposes. One is data reduction. The other is priority scaling, allowing another effect to interrupt the long tail of a slowly decaying effect.

Instrument attack envelopes are similar to sound effects but cannot be compressed. I can think of a few cases where might want to: a long volume envelope that covers both the attack and decay phases of (say) a piano that sustains at volume 1, or a long duty sequence for a pulse instrument.

Currently, each frame of an envelope is 16 bits big endian:

  • Bits 15-14 store duty.
  • Bits 13-12 are unused.
  • Bits 11-8 store volume.
  • Bits 7-0 store arpeggio as a signed offset from the note's pitch.

Most frames of most instruments have a 0 arpeggio value, making bits 7-0 redundant. So Pently could reserve bits 13-12 for "frame type", where 0 is what we have now (for backward compatibility reasons), 1 omits the arpeggio and assumes its value is 0, and 2 and 3 mean something to be determined later.

Statistics: Among attack phases in instruments in the current musicseq.pently, there are about 97 frames with zero pitch and 52 frames with nonzero pitch, the latter mostly in an orchestra hit and a few effects used in argument. (One of these is argdive, a fake portamento that can probably be optimized out.) This also gives an estimate of how many bytes we have at porta_not_injected to interpret a compressed attack.

pentlyas: Common substring elimination will need to operate on .byte values rather than .dbyt values.

musicseq: As this is an engine and data format change, no changes here are necessary.

The fix took 9 bytes of code. So if the zero-pitch frames in the attack envelopes of a score's instruments total more than 9 frames, it's a net win.