The MIDI engine & voices
Music, and any sound the game chooses to play as notes, goes through a General-MIDI-like engine: 8 ports of 16 MIDI channels each, sharing 48 hardware voices. Instruments come from tone banks whose samples carry complete AICA register settings.
Ports, channels and voices
Tone banks: programs, layers and splits
An instrument bank (tagged SMPB) is a tree:
Everything inside a bank is position-independent: the driver adds the bank's address when it follows offsets, including sample addresses, so the SH-4 can place a bank anywhere in sound RAM. This driver also carries two tiny built-in banks: a default instrument bank (a square and a sawtooth wave) that every channel points at after boot, and a default drum kit built on the noise generator.
What happens on note-on
- Find the instrumentThe event names a port, channel, note and velocity. The channel's current program gives up to four layers; muted layers are skipped.
- Pick a split per layerThe first split whose key range and velocity range both contain the note wins.
- Get a voiceThe allocator returns a free voice or steals one (see below). The voice records who owns it: port, channel, note, velocity and the port's priority.
- Program the AICA channelThe split's register image is copied into the channel, with adjustments: sample address relocated by the bank address; envelope and filter-envelope rates offset by the channel's controllers; filter levels offset by the channel's cutoff; LFO depth scaled by the modulation wheel; send bus and send level from the tone, channel and port; pan from the tone or channel plus the port pan; resonance and filter on/off from controllers.
- LoudnessThe velocity passes through the bank's velocity curve and is multiplied by the channel level (volume × expression) and the tone's own level; the port volume is added as an offset, and the result becomes the channel's total level.
- PitchThe note's distance from the split's root key, the port pitch, the channel's pitch bend and the split's fine tune give a pitch in 1/256 semitones, converted into octave and fraction with two lookup tables.
- Key onUnless the layer asks for a delay, the channel is keyed on at once. A delayed layer is keyed on by the 4 ms update when its counter expires, unless a note-off arrives first.
Voice allocation and stealing
With 48 voices shared by eight ports and up to four voices per note, running out is normal. The allocator walks all 48 voices once:
If every one of the 48 voices has a higher priority than the new note, the allocator is supposed to fail. Instead, because of a pointer that is only reset inside the loop, it reads two of its own instruction words as "the chosen voice" and reports success, and note-on then writes to garbage addresses. It only happens when all voices are busy with higher-priority sounds. Details on the quirks page.
Note off and the sustain pedal
Note-off releases every voice playing that port, channel and note (duplicates included) by clearing its key-on, so the AICA moves the voice into its release phase. If the sustain pedal (CC 64) was down, the voice is only marked as released and keeps sounding; lifting the pedal releases all such voices on the channel. The voice's "age" restarts and its level is reset, so the allocator will prefer it once it is quiet.
Controllers
Standard MIDI controllers behave as expected, and Sega added a set of controllers that edit the AICA parameters of the tone in real time. Controllers that change something audible also update voices already sounding on that channel.
| Group | Controllers | Effect |
|---|---|---|
| Level & pan | 7 volume, 11 expression, 10 pan | channel level (a curve of volume × expression) and pan; live voices updated |
| Expression | 1 modulation | scales the tone's vibrato/tremolo depth |
| Pedal | 64 damper | hold released notes until the pedal is lifted |
| Parameters | 6 data entry, 96/97 increment/decrement, 98-101 NRPN/RPN select | RPN sets the pitch-bend range |
| Bank | 32 bank select | which downloaded tone bank the next program change uses (CC 0 is ignored) |
| Filter | 74 cutoff, 75 cutoff range, 110-117 cutoff at fixed ranges, 71/85 resonance, 70 filter on/off | brighter or darker, more or less resonant |
| Filter levels | 20-24 (coarse) / 52-56 (fine) | offset each of the five filter-envelope levels |
| Filter envelope | 25-28 | filter attack / decay 1 / decay 2 / release rates |
| Amplitude envelope | 73/87 attack, 88 decay level, 89 decay rate, 72/86 release | offset the tone's envelope |
| Effects | 91 reverb send, 76 DSP input bus | how much of the voice goes to the DSP, and on which bus |
| DSP (port 7) | 77 / 78 output pan / level, 79 effect program, 80 positional pan | control the DSP from MIDI (see DSP) |
| Misc | 48 timing counter, 121 reset all controllers | a counter the game can read; reset a whole port's channels |
| Ignored | 0, 120, 123, poly and channel pressure | no effect in this build |
Pitch bend and program change
Pitch bend is scaled by the bend range (from the layer, or an RPN override) and applied at once to every sounding voice of the channel. Program change looks up the current bank (falling back to the built-in bank), and switches only if the program exists; notes already playing are unaffected. For drums, a host command marks a MIDI channel as a drum channel, whose bank select chooses between two drum-kit bank slots.
What happens every 4 ms
- Delayed key-ons count down and fire.
- Port changes (volume, pan and pitch fades driven by host commands) are applied to every voice of the port, so a fade-out of the music affects notes already sounding.
- Envelope monitoring continues in the background every millisecond, keeping each voice's "how loud am I" value fresh for the allocator.