Walleij — A SID player routine (MIDI-driven player design, note tables, hard restart)
Design notes, in pseudo-code, for a MIDI-controlled sid player, written on request from Michael Kleps (the "M.K." of the extended Soundtracker module signature and author of the QuadraSID VST). linus-walleij learned how players work by writing the C64 MIDI program MIDIslave and from the editors he used — SoundMonitor (Chris Hülsbeck), Future Composer (Finnish Gold), Rockmonitor, Pro-Drum and Music Assembler (the Dutch USA-team), the JCH Editor, Soundtracker 64 (Mechanix) and the Soedesoft Editor (Jeroen Soede). Sample playback is left out. In the raw copy a few lines of the note_process loop header (the channel loop and the waveform-macro write) were lost to HTML tag-stripping; the intent is clear from the surrounding comments.
Key claims#
- Hard restart, as he describes it: the JCH player is "a very good one" because it uses hard restart — "the SID provides quite bad accuracy on attack after releasing a note", so the fix is "to write 0x00 to all registers at $d400–$d406 2/50 second (2 frames) before next attack"; "the actual minimum time is 33 ms = 2^15 cycles according to Dag Lem, author of reSID"; "some say setting the test bit … is just as good"; the problem "only affects the 6581 version of the SID chip (or so I am told...) and not the later 8580", so "for some MIDI appliances the 8580 is a lot better choice"; hard restart "only fixes problems with attack, not the ever-present problem with release".
- The MIDI catch-22: hard restart needs to know two frames ahead that a note is coming, which a live MIDI player cannot; the SIDstation either hard-restarts every voice on key press (delaying every note by 1/50 s) or on key release ("kills the voice effectively, and makes all release settings superfluous").
- Player structure:
instrument_onwrites the filter registers ($d415,$d416, and the resonance byte masked& $F0 | $0Finto$d417so all voices are routed) and the filter type into$d418;note_onallocates one of the three channels (stealing the oldest on a FIFO basis if wanted), then writes frequency → pulse width (only if the waveform is pulse,$40) → waveform| $01(gate) → attack/decay → sustain/release, and arms the macro speed and the vibrato / pulse-vibrato delays;note_processruns "at a reasonably high rate, say 400 Hz" — the C64 macro rate is usually 50 Hz, so the default step is 8, and "the highest rate I have seen in a C64 playroutine is 600 Hz";note_offonly clears the gate bit (& $FE). - Macros: waveform table per instrument; an arpeggio table of bytes "which represents the number of halftones to transpose the current note UPWARDS. For example macro 0x00 0x03 0x07 creates a minor chord"; a pulse-width table usually writing only the high byte (
$d403) — "most c64 players don't" write the low byte; a filter table writing the cutoff high byte and a resonance byte (masking the low nybble is "my choice" because that nybble "has dangerous effects like switching filter off or on for current channel"); tables "can loop or end". - Vibrato: a delay before vibrato, then an amplitude and a period (from the instrument or a wheel) added as an LFO over
$d400/$d401, taking the pitch wheel into account; pulse-width vibrato the same over$d402/$d403"but larger amplitude can be used"; the filter can follow a wheel or an LFO ("sinus or sawtooth, or square wave") for "a TB303-like-effect". - Note table: 95 entries of high and low bytes for the 6581, index 0 = C-0, 36 = C-3, 57 = A-4, 95 = A-7 — "last B in octave 8 is not possible to replay with c64"; "the numbers in the C64 hardware reference manual are simply WRONG"; calculating the values "is preferable, especially to modulate the pulsewidth and such".
Practical takeaways#
- A minimal SID player is: per-frame macro steps for waveform, arpeggio (semitone offsets), pulse width and filter, plus delayed LFO vibrato — the same architecture as sid-wizard's and goattracker's instrument-tables.
- Hard restart is incompatible with real-time MIDI unless you accept a one-frame delay or lose the release phase — a design constraint for any live SID instrument.
Notable quotes#
"This problem only affects the 6581 version of the SID chip (or so I am told...) and not the later 8580 version."
"Hard restart only fixes problems with attack, not the ever-present problem with release."
Relevance#
An independent player-author's description of hard-restart (with Dag Lem's 33 ms figure) that contradicts the wiki's other sources on the 8580 — recorded on the page; a compact model of a sid-player-routine; confirmation of the 0 3 7 arpeggio idiom from the player side (chord-arpeggio); and a MIDI-on-C64 data point for sync.
Pages touched#
hard-restart · sid-player-routine · vibrato · pulse-width-modulation · filter-programming · chord-arpeggio · sync · linus-walleij · c64-programmers-reference-guide