Hard restart

aliases HR, hardrestart, ADHR, ADSR bug, envelope bug
sources SID-Wizard 1.8 User Manual (summary) · GoatTracker v2.72 readme (summary) · Lemon64 threads: SID and ADSR re-triggering? (2008) / Hard restart – what's the story? (2015) · Composing in SID Factory II, Part 4 — Instruments (Chordian) · Creating Chiptunes with SID-Wizard, Second Edition (summary) · Walleij — A SID player routine (MIDI-driven player design, note tables, hard restart) · chipmusic.org — C64 Music for Dummies (ant1's SID-Wizard 1.0 tutorial, 2012) · HVSC — SID file format description (PSID v1–v4, RSID) · Furnace tracker — C64 (SID) system and instrument documentation · uCApps MIDIbox SID — Wavetable Sounds Tutorial #1 (Thorsten Klose) · commodore-64.eu — The C64 SID Chip (6581 vs 8580 overview) · The SID Homepage — Interview with Bob Yannes (Andreas Varga, August 1996) · Remix64 — An Interview with Martin Galway (Neil Carr, 2001) · The SID Homepage — Interviews with Jeroen Tel (Commodore Zone 1997, 64'er 3/91) · SIDin #2 — Matt Gray's Driller music routine (Stefano Tognon, 2002) · GitHub realdmx/c64_6581_sid_players — Cybernoid II in Deenen's MUSICFILE, the MoN SFX player, the Driller listing · 64'er 10/1986 — Musik wie noch nie: the Soundmonitor article and manual · The Brief History of SID — Jan Harries (SIDwave), Vandalism News #64 (2015) · realdmx: Charles Deenen's two test tunes — an undated MUSICFILE build and the 'Scoop designs' Maniacs of Noise player · realdmx: Rob Hubbard's driver — McSweeney's Monty on the Run disassembly and the Commando title · realdmx: Martin Galway's Rambo II loader — the macro-language player, reverse-engineered by dmx87 · realdmx: Martin Galway's Arkanoid — Tognon's SIDin #4 reverse-engineering, with the 'sample' synthesis through $D418 · realdmx: Johannes Bjerregaard's own player — the James Bond 3 demo (a Maniacs of Noise commission) and Myth · realdmx: two scene players with their own sources — Francois Prijt's Audial Arts 'zong player' v1/v2 (1991) and Adam Bulka's FAME 'Sound Routine f 4.1.0' (1988) · realdmx: Jonathan Dunn's Daley Thompson '88 and Ocean Loader 5 in Paul Hughes's Ocean music driver · realdmx: three smaller drivers — Fred Gray's Mutants (song as code), Jeroen Kimmel's 'Red's music player' (1989) and David Whittaker's Panther driver · SIDin #6 — Asterion Sid Tracker v1.0 reviewed (Stefano Tognon, 2004) · SIDin #7 — Inside Modules: Ivan Del Duca's music engine (Stefano Tognon, 2005) · SIDin #8 — Tiny Sid Compo, the 512-byte entries (Stefano Tognon, 2005) · SIDin #9 — Tiny Sid Compo, the 256-byte entries (Stefano Tognon, 2006) · SIDin #9 — Catweasel Mk4 follow-up: driver, hardware buffer, two 6581s and the filter (Stefano Tognon, 2006) · SIDin #11 — Tiny Sid 2, part 2: BLOCK ACID DUB and Resolution (Stefano Tognon, 2007) · SIDin #13 — JITT64 Tracker: Tognon's Java Ice Team Tracker from the user's side (2010) · SIDin #13 — Inside JITT64: the player routine (Stefano Tognon, 2010) · SIDin #12 — Tiny Sid 2, part 3: Plaster (512 b) and Back To Basics (256 b) (Stefano Tognon, 2008) · chipmusic.org — the defMON megathread (2014–2026) · defMONing 102: extended field guide (iLKke et al.) · defMON wiki — features, interface overview, seqED key map · My Computer Chronicles — Jens-Christian Huus / JCH (2017) · Old C64/PC Player/Editor Notes — Chordian (2017) · The CheeseCutter Guide — the recovered site manual (Wayback) · DUET research: SID-Wizard player.asm deep dive (summary) · DUET research: SID-Wizard 1.97 formats and player (summary) · DUET docs: DUST and DUSK, the two synths (summary) · defMONing 101: A defMON Operator Field Guide (iLKke, 2013) · realdmx: Reyn Ouwehand's Armada (MUSICFILE, 'Special version for Reyn Ouwehand', 1989) and Dutch Breeze (the 1990 MoN player) · Remix64 — An Interview with Anders Carlsson aka GOTO80 (Neil Carr, 2002) · SIDin #1–15 — Editorials and News digest (Stefano Tognon, 2002–2015) · SIDin #4 — Martin Galway's Arkanoid music routine, the explanation (Stefano Tognon, 2003) · SIDin #14 — Inside Matt Gray's Dominator player (Tognon's commented PLAYER V4.2 and the musician's guide to composing in it, 2015)
created 2026-08-30 · updated 2026-08-31

What it is#

A player-routine trick that gates a sid voice off and loads a special ADSR value one or two frames before the next note, so that every note's attack starts from a known envelope state. It exists because of the SID's envelope bug: "SID provides quite bad accuracy on attack after releasing a note, resetting the ADSR registers before a note is played helps with this problem" (source: s-witchmaster-creating-chiptunes-with-sid-wizard); "Hard restart was invented to defeat this ADSR bug" (source: s-chordian-sf2-instruments). Every C64 tracker in the wiki implements it per instrument or per driver.

Why it works#

  • The failure mode, in lasse-oorni's words: "trying to trigger a sound when the envelope is still at max. volume will result in silence and lockup that lasts until the gatebit gets cleared again"; the cure is "the minimum 2 frame period with gatebit off". The test bit is not the cure — it "will be reset immediately" on the oscillator but "doesn't affect the envelope generator at all" (source: s-lemon64-hard-restart-threads).
  • chordian: in a run of short notes each kept gated until the next, "you would probably hear the ADSR stumble here and there"; some ADSR values alleviate it, "but it's easy to keep running into this problem". The restart "works by gating off and resetting the ADSR values a few ticks before the next note triggers" — two ticks in SID Factory II's drivers; a 15-tick note plays 13 ticks, then the HR ADSR takes over, possibly "a tiny bit staccato", and "the next note always triggers perfectly" (source: s-chordian-sf2-instruments).
  • The bug is deterministic in emulators (reSID's envelope.h, also in VICE) but hard to be deterministic about from 6502 code, because it depends on exact timing (encore, source: s-lemon64-hard-restart-threads); the goattracker readme accordingly warns that packed players with unbuffered writes and "unpredictable timing variation" can still ADSR-bug (source: s-goattracker-readme).
  • The same bug seen from a hardware synthesizer: rebuilding a Hubbard drum on a MIDIbox SID, Thorsten Klose found the first (triangle) frame missing from the real chip's output — "the gate is delayed by up to ca. 30mS", an effect "reverse engineered by Dag Lem, and documented in the source code of reSID"; a release rate of 0 removes the delay entirely (at the price of no fade), which is why most MIDIbox SID presets use no release, and why his wavetables end with a step that "resets the envelope registers in order to avoid 'ADSR hick-ups'" (source: s-ucapps-wavetable-sounds-tutorial-1). Compare Walleij's "33 ms = 2^15 cycles" below — the same figure.
  • What the chip's designer says — and does not say: bob-yannes's 1996 account explains the envelope generator's design (an 8-bit up/down counter, a rate divider with a look-up table, a sustain comparator — see adsr-envelope) but does not describe the re-gating lock-up; the nearest statements are that the sustain comparator stops the envelope clock only "when the counter counted down to the Sustain value" and that the counter "would not count UP if the Sustain level were set higher" (source: s-sidmusic-yannes-interview). Do not cite the interview as the cause of the bug. The same interview does give a silicon reason for the $09 first frame: zero-volume "signal leakage … could be dealt with by stopping the oscillator" (source: s-sidmusic-yannes-interview).
  • The composer's version of all of the above, from goto80 in 2004, is one sentence: the SID's "trigging of the sound, the attack, fucks up now and then (which hardrestarts kinda solves)". Note kinda — the working assumption in the scene is that the technique makes the bug rare, not that it removes it (source: s-remix64-goto80-interview).

How to do it#

SID-Wizard#

Instrument main settings (F7):

settingmeaning
ADHRthe ADSR loaded "1-2 frames before a new note is triggered"; common values 0F00 and F800
HardRestart timer0..2 frames before the note
HardRestart typenormal, or staccato / aggregated: the test bit is also reset at hard restart, "adds 1-2 frames of gap between consequent notes"
Frame-1 waveformwaveform/control byte for the note's first frame (enable with RETURN, on by default); Hermit: its purpose "is the same as in Goattracker, to test / reset the oscillators with waveform $09 (test-bit set) before the sound starts and get a short 'sexy' start of the sound"

In SID-Wizard 1.0 the beginners' tutorial had every instrument set HRTY to 2 (a square symbol appears next to the number) "so that the gate bit is reset between each note, which is important because otherwise notes will not sound if they come after another note rather than a note off" — later versions do this by default (source: s-chipmusic-c64-music-for-dummies). The Medium player drops the HR type and frame-1 setting; the Demo player has no hard-restart/frame-1 settings (sid-player-routine) (sources: s-sid-wizard-manual, s-witchmaster-creating-chiptunes-with-sid-wizard).

What the player actually does (SW 1.97 player.asm)#

The exact schedule behind the HR timer, from m64's duet research (player.asm 1517–1592, 1726–1728, 1820–2054; source: s-duet-research-sidwizard-deep):

  • A row is fetched at tick 0 but its note starts at tick 2 — uniformly 2 frames later. That lookahead is what makes hard restart possible: the control byte's bit 1 fires the HR phase at tick 0, bit 0 at tick 1 (both bits = both ticks), so "HR timer 0..2" is literally which of the two pre-note frames get the treatment.
  • An HR phase sets the ghost ADSR to the instrument's HR values (ADHR), masks the gate off, and clears the gate bit in the waveform ghost. The staccato type (ctrl bit 2) additionally writes waveform $18 (test bit + triangle) and skips the rest of the channel's processing that tick — the audible 1–2 frame gap.
  • During HR ticks the Normal player pauses vibrato, filter and pulse tables but keeps the WF table running (even for HR-timer-0 instruments); the Extra player pauses nothing. Because tick 2 must exist, the Normal player needs tempo ≥ 3 for notes; only Extra's fast-speed binding folds the ticks for tempo 1–2.
  • Hard restart is suppressed when the incoming row is legato ($3F), tone portamento ($03), or follows a $78 portamento flag — glides never restart.
  • The 1st-frame waveform mechanism at tick 2: the player writes the frequency hi byte only (the low byte still holds the previous note) plus the frame-1 waveform — default $09, whose test bit freezes the oscillator so the stale low byte is inaudible; the WF table's row 0 then executes on the next call, releasing the test bit and setting the true 16-bit pitch in the same write-out. ADSR order at note start: SR is written first, then AD.

GoatTracker#

  • Per instrument: HR/Gate timer = how many ticks before the next note the note fetch, gate-off and hard restart happen (at most tempo−1; with tempo 6 and timer 2 they happen on tick 4, "2 ticks before first frame"); bit $80 disables hard restart, $40 disables gate-off. 1stFrame Wave is "usually $09 (gate + testbit)".
  • Global: the HR ADSR value (-Axx, SHIFT+F7), default 0F00 — "0000 is probably too hard to be useful, except perhaps with gateoff timer value 1. 0F00 (default) is a lot softer, and 0F01 adds also a little bit of release to the gateoff phase for even softer sound. 000F makes the note start very pronounced." Attack F enables an alternative playroutine that writes the waveform before ADSR, "more reliable note triggering, especially for very fast releases 0 & 1".
  • Legato without restart: timer bit $40 and 1stFrame $00 (tables and ADSR still re-initialise).
  • Multispeed: multiply the timer with the speed (2 → 4 at 2×). If a packed tune still bugs: make note-init take more cycles (nonzero pulse start position, 1stFrame $09$0B), use buffered writes, or attack F; since v2.68 notes with attack 0 and release 1 are the sensitive case.

(source: s-goattracker-readme)

SID Factory II#

Set bit $80 of the instrument's third flag byte; the second nibble points into the HR table, whose default pair 0F 00 is the ADSR used for the last two ticks — "I have never had to change it" (source: s-chordian-sf2-instruments).

CheeseCutter#

The restart is a per-instrument type nibble (byte C's high nibble, "works mostly as in NP21.G5"), a menu of four flavours (cheesecutter; source: s-cheesecutter-guide):

typebehaviour
0xnote restart: gate off 3 frames before the next note, waveform cleared 1 frame before
4xsoft restart: gate off 2 frames before — "usually works best (least buggy) with big (>= 8) release values"
8xregular hard restart: gate off + HR ADSR 2 frames before; instrument byte D goes to the waveform register 1 frame before
Ax"Laxity restart": like 8x but "the AD part of the volume envelope is not touched"

"Restart types 0x and 8x are the ones to use for most of the time." The HR ADSR value lives in the Command Table's first row (default 0F 00 — the GoatTracker default again); byte D (the HR waveform) is "usually values 0 & 8", the gate bit added automatically.

DUST (DUET)#

  • duet's DUST synth makes hard restart a patch parameter: RESTART OFF / SOFT (gate down for the window) / FULL (gate down and the envelope slammed to zero) over a 1–200 ms window spent before the note; the engine peeks at the next row so the attack, not the restart, lands on the beat (source: s-duet-docs-dust-dusk).

Furnace#

furnace calls it envelope reset: in the chip configuration, Hard reset envelope is the ADSR "used during the short reset before a note" and Envelope reset time the number of ticks — "0 disables reset, which prevents notes from triggering. 1 is short, but may exhibit SID envelope bugs. 2 is a good value." From the pattern, 15xx sets the reset time (00, or more than the song speed, = no reset) and 1Axx disables it for the channel; per instrument, Don't test before new note "disables the one-tick hard reset and test bit before a new note" — so Furnace, like GoatTracker's $09, sets the test bit during the reset (source: s-furnace-c64-docs).

defMON#

The only editor that automates nothing — frantic (2018-02-22): "You can do any kind of hardrestart in defMON, whereas most other editors only feature one type of built in hardrestart and no reasonable way to do it manually." Automated HR would need look-ahead sequence parsing, which costs rastertime; instead every sequence has a −1 step before line 0 (reach it with CTRL+G twice) where the restart rows go, ~2 frames before the note (source: s-chipmusic-defmon-thread). The field guide new users are pointed at says the same thing as a boast: "Most flexible hard restart ever, period. Because you do it all yourself." (source: s-defmon-wiki-defmoning-101).

  • The common idiom (used by goto80 and Amelinium): on the restart line waveform/gate 00 00 with ADSR $0F00, wait 2 ticks (DL), then gate 09 (test + gate) with the instrument's real ADSR, then the waveform — the GoatTracker recipe, typed by hand in the sidTAB (source: s-chipmusic-defmon-thread).
  • iLKke's compendium (2015-08-03) names four HR shapes — old school (one frame gate-off, ADSR $0000), new school (gate-off with ADHR, then $09 + real ADSR, then waveform+gate+note), hybrid, "heatbeat" — and the known ADHR values: $0000 "hardest", $0F00 "most common", $0F18 Drax, $0F20 GRG, $0FF0 Randall/Jammer, $F000 Linus, $FF00 Jeff. Sustain $F "is especially buggy (try E then?)"; a soft restart wants release ≥ $8 (sources: s-chipmusic-defmon-thread, s-defmon-wiki-defmoning-102).
  • How much HR you need: F7sus4 — the full test-bit restart is "obligatory only with drums and snares"; leads, bass and arps are fine soft-restarted. 4mat's minimal recipe: "$08 on the first frame before you set the gate … ($08,$41,$41,$40)". Bonus trick: vary the AD nibble on the HR line ($01–$0F) to scale a drum's volume per hit (source: s-chipmusic-defmon-thread).

In your own player routine#

iAN CooG's retrigger sequence for a sound effect (the thread starts with a game coder who cannot retrigger one — see sound-effects): write $09 (gate + test) to the control register, wait two frames, write $00, then set ADSR and pitch and gate on. encore's three strategies: hard restart; "finding safe ADSR-values in a song where the bug never triggers (and this depends entirely on the situation/arrangement/instrument/bpm)"; or "keep a voice continuously in its sustain mode and simulating new notes with changes in pwm or filter instead" (source: s-lemon64-hard-restart-threads).

linus-walleij's version, from the JCH player he admired: "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 Lemon64 threads above say it is not — the test bit resets the oscillator, not the envelope); and "hard restart only fixes problems with attack, not the ever-present problem with release". For a live MIDI player the technique is "a catch 22": you cannot know a frame ahead that a note is coming, so the SIDstation either hard-restarts every voice on key press, delaying all notes by 1/50 s, or on key release, which "kills the voice effectively, and makes all release settings superfluous" (source: s-walleij-sid-player-routine).

Before hard restart existed#

martin-galway's workaround at Ocean (1984–87) was avoidance: "Certain ADSR settings totally screw up and play too early – as I recalled it was with long attacks and long decays. The key-on/key-off circuitry had a problem, evidently. I called it the school band effect and simply had to stay away from certain ADSR settings, which was a drag sometimes on original works" (source: s-remix64-galway-interview) — the same strategy encore lists above as "finding safe ADSR-values".

Does the 8580 need it? (a contradiction between sources)#

Walleij: the problem "only affects the 6581 version of the SID chip (or so I am told...) and not the later 8580 version, so for some MIDI appliances the 8580 is a lot better choice" (source: s-walleij-sid-player-routine). The wiki's other sources do not make that distinction: the Lemon64 explanations describe the lock-up as a property of the envelope generator without naming a revision (source: s-lemon64-hard-restart-threads); the SID-Wizard book only credits the 8580 with "maybe more predictable ADSR envelope-handling" (source: s-witchmaster-creating-chiptunes-with-sid-wizard); HVSC's format document speaks of "the ADSR bugs in the SID chip" in general (source: s-hvsc-sid-file-format); and every tracker on this page applies hard restart regardless of the model selected. Walleij himself hedges ("or so I am told"). Two later descriptions do not distinguish the chips either: Furnace applies its envelope reset whichever model is selected (source: s-furnace-c64-docs), and commodore-64.eu describes "a well-known bug in the envelope generator" as a property of the SID as such (source: s-commodore-64-eu-sid-chip; secondary). The composer interviews add nothing decisive either: none tests the 8580; Galway's "school band effect" comes from 6581-era work at Ocean (1984–87), and jeroen-tel's remark about chip versions that "varied a lot" concerns the filter, not the envelope (sources: s-remix64-galway-interview, s-sidmusic-jeroen-tel-interviews). Until a source tests both chips, treat hard restart as needed on both and the 8580 as at most less sensitive.

Ancestors in the classic drivers#

  • matt-gray-player (1987): instrument byte 6 is "Control register set at the end of the note, but in the same frame of when setting the new note", and effect bit 2 plays a separate control register "for the first two frames" of a note before the normal one — a gate-off and a different first-frame waveform at note boundaries, done per instrument; a pattern byte $00 re-plays the previous note "with the gate bit set to 0, so the release phase will start" (source: s-sidin02-matt-gray-driller). The Dominator player (V4.2, 1989) shows the finished form: byte 6 is written "with the gate bit forced off when the instrument is selected, and just before the normal control register at each new note" — Tognon calls it "a 'basic' restart of note", and reads byte 6 plus the implex control byte together as a pre-tracker hard restart: gate off on instrument change, a different waveform for the first frames of the note (source: s-sidin14-dominator-player).
  • musicfile (1988): per-instrument starttabel ($81,$81,$81,$81, $41,$11,$11,$81 …) and startlen ($02 … $06) tables — verified in Deenen's own test-tune source: a start waveform applied from the note's second frame (effects skip the first), where $81 also forces the pitch to $faxx for one frame of high noise, and $41/$11 swap the waveform at pitch for four or five frames — the same idea as goattracker's 1st-frame waveform (sources: s-realdmx-sid-players, s-realdmx-deenen-test-tunes).
  • MoN as reyn-ouwehand used it (Armada, 1990): the gate-off point is a per-instrument field, not player policy — filcount's high nibble in the earlier bank ($f0 = "release almost at once", which is what every drum uses), fx0's high nibble in the later one, with fx3 bit 3 a separate "hard cut" (afkappen) flag. The opposite switch is a sequence byte: $fb "connect" is legato, keeping gate, ADSR and pulse programs running across the note boundary (source: s-realdmx-ouwehand-mon-tunes).
  • soundmonitor (1986) separates the waveform at key-on (register 0, gate bit set) from the waveform at key-off (register 8, gate cleared), and lets a note be entered with SHIFT so it is not retriggered — legato versus restart decided per note (source: s-64er-soundmonitor-article).
  • Who invented it — two accounts, kept side by side. SIDwave's memoir: "JCH is the inventor of what we call a hard-restart. It's a little pause-trick code, so that a sound never fails and the oscillator starts from point 0 of the waveform of the SID, not somewhere in middle where it was running before. This has been developed by GRG to also a soft-restart, so that sounds go from very hard start, to softer hit on key, when starting" (source: s-recollection-brief-history-of-sid). But JCH himself, in his 2017 memoir, disclaims the invention: "It was Jesper [JO of Amok] who first made me aware of the technique … It had previously been used by Rob Hubbard and also Laxity had figured it out" — his description being "zero values in the registers during the last two frames of the lifetime of a note", slightly staccato "but the ADSR would be rock solid". His period notes date the implementation to NewPlayer 17.G1 (jch-editor) — likely why the editor's users remember him as the inventor: his was the editor that shipped it (sources: s-chordian-my-computer-chronicles, s-chordian-player-editor-notes).

More ancestors, from the drivers recovered as source in 2026-08-30's realdmx batch (details on the linked tool pages):

  • hubbard-player (1985): no restart at all — but a note-off writes $00 to both AD and SR together with the gate bit, so every note ends with the fastest release; and a Hubbard note has no first-frame waveform, the drum flag supplies the noise frame instead (source: s-realdmx-hubbard-player).
  • galway-player (1986): every note start writes $00 (Rambo) or $08 — the test bit — (Arkanoid) to the voice registers and then the instrument's values; after the gate is released, a per-instrument "hrtime" counts down and the voice's seven registers are zeroed — Tognon's comment on that code is "; hard restart" (sources: s-realdmx-galway-rambo-player, s-realdmx-galway-arkanoid-player). Seen from the data instead of the code, the Arkanoid instrument ends with exactly two timing bytes: $1B "Duration before apply release ($FF means not apply release)" and $1C "Duration before an hard restart (after the end of event of previous 1Bh register)", with $FF meaning no hard restart — release timing and restart timing as two per-instrument counters, the same pair every later tracker exposes. The instrument's test bit is conditional on the first of them: it is "tested if 1Bh table value is below current duration before apply a release", and the value actually written to the SID is the control byte without the test bit (source: s-sidin04-galway-arkanoid).
  • ocean-music-driver (1988): the init writes 8 (test bit) then 0 to every SID register "so there's no grotty clicking"; the DT88 build also pauses every modulator on a note's last frame (MOD_OFF) (source: s-realdmx-ocean-dunn-hughes-driver).
  • FAME's "Sound Routine f 4.1.0" (Adam Bulka, dated 27.07.1988): instruments with bit 7 of their release byte get AD = SR = $00 on the trigger tick and no other SID write that frame; frequency, waveform and ADSR follow on the next frame — a dated hard restart from the scene, used by every drum and bass in the tune (source: s-realdmx-audial-arts-fame-players).
  • bjerregaard-player (1989), two ways: James Bond 3 zeroes ADSR two ticks before every note, writes $F0 to the control register one tick before and $09 (test + gate) on the note frame; Myth zeroes ADSR one tick early only for instruments flagged "shutup notes", never sends the test bit, and starts every wave program with a $01 (gate, no waveform) frame (source: s-realdmx-bjerregaard-player).
  • whittaker-player (1986) does neither: the gate is written off and on in the same call at note starts and never released otherwise, so silence comes from SR = 0; Red's 1989 player likewise (source: s-realdmx-fredgray-kimmel-whittaker). Audial Arts' v2 (1991) zeroes $d404/$d405/$d406 at note-on and rewrites them in the same frame — a retrigger, not a restart (source: s-realdmx-audial-arts-fame-players).
  • asterion-sid-tracker (2004) makes hard restart a per-instrument switch: bit 8 of the sound table's R/T field is "Hardrestart on/off", next to the filter type; 2x bit 1 ties a note without retrigger (source: s-sidin06-asterion-sid-tracker).
  • The modules driver (1988) has no restart; a note-off is the explicit command $83, which writes the instrument's separate control off byte (tbCntOff, the on byte minus the gate), so every instrument row carries both control values like Soundmonitor's key-on/key-off pair (source: s-sidin07-inside-modules).

In 256 and 512 bytes (2005)#

The tiny-sid-compo players each solved the restart in a few bytes, and none skipped it (sources: s-sidin08-tiny-sid-512b, s-sidin09-tiny-sid-256b):

  • Test bit before the note: Frantic's New Kid On The Block writes $08 to the control register when a note's duration expires, before the next note's frequency, AD and waveform; 4mat's Empty starts every note with $09. The cheapest form — one immediate and one store.
  • Zero the envelope early: Laxity's Twone Five writes AD $0f, SR $00 and control $00 two frames before each note ends (speedcnt timing), then the instrument's values on the note frame — his comment: "Hard restart is always enabled".
  • Three-stage (Crue Gurl, gateEnd = 3): gate off ($40) three frames before, test bit ($08) two frames before, one frame of noise $81 at frequency high $ff with SR $e9 one frame before — the source notes "Set to different (non-zero) values to get various restart types".
  • Where it is not optional: Tognon's Random Ninja drum voice needs a $09 write on its ninth tick — "this is needed, otherwise no sound is produced"; Repeat Me simply drops the gate at every note end ("a sort of hardrestart").

And a hardware observation from the same magazine: on a catweasel Mk4 whose driver delivered register writes late, tunes with hard restart played while older ones "without a proper hardrestart" broke up in what Tognon recognised as the ADSR bug — a restart makes a tune robust against timing jitter, not only against the composer's own note lengths (source: s-sidin09-catweasel-6581).

Hard restart in two data bytes (BLOCK ACID DUB, 2006)#

Frantic's 256-byte tiny-sid-compo entry hard-restarts only its drum channel: when that voice's tick counter reaches 2, the instrument pointer is forced to a @hardrestart row — SID_SR | SID_CTRL | STAY followed by $00, $10 — which writes sustain/release $00 and control $10 (gate off) two frames before the next hit and holds there until the new instrument is fetched. It is the GoatTracker recipe (gate off + HR ADSR, two ticks early) with no code of its own: the restart is just another "instrument" in the register-stream table (source: s-sidin11-tiny-sid-2-part-2).

JITT64 (2010): hard restart as five instrument fields#

Tognon's jitt64 makes every part of the restart an explicit per-instrument setting (sources: s-sidin13-jitt64-tracker, s-sidin13-inside-jitt64):

  • Three choices: no action ("all is left to you for preventing ADSR bugs"), Gate off N ticks before the end of the note, or Hard Restart — N ticks before the end the player writes Attack/Decay HR, Sustain/Release HR and First Control HR, and on the last tick before the new note Second Control HR. N is capped by the pattern tempo (timing 3, ticks 4 → 3 effective).
  • A per-instrument write order, Wave–ADSR or ADSR–Wave, "for letting you obtain good hardrestart (some one need accurate write timing to be achieved)" — the choice GoatTracker makes globally with its attack-F playroutine.
  • Two test-bit recipes: (a) HR AD/SR set, first control with the gate released, second control $09 (test + gate), at least 2 ticks, order ADSR–Wave; (b) both HR controls gate-off, one tick, and the instrument table's first row sets ADSR and wave $09 before the real waveform, order ADSR–Wave.
  • In the player the instrument record starts with an HR byte (low nibble = ticks, bit 7 = full HR rather than gate off) and AD, SR, CTRL1, CTRL2; the hard-restart block runs last in the interrupt so that it overrides every other command, and the SID is written from shadow registers at the start of the next interrupt so that all voices — and the HR frame — land together; Tognon restructured the routine because variable block timing "can cause some hard-restart of note problem too". A hard-restart pattern command was still on the to-do list.

And a hard restart in 512 bytes: GRG's Tiny Sid Compo II winner Plaster writes SR $01 and AD $0F when a note's remaining duration reaches 1 — the 0F01 value — and starts every control sequence with $09 then $81 (source: s-sidin12-tiny-sid-2-part-3); the same GRG is credited above with the "soft restart".

What a decade of release notes settled (GoatTracker and NinjaTracker, 2003–2009)#

sidin's news pages reported every version of goattracker and ninjatracker as it appeared, and read end to end they are the clearest record the wiki has of hard restart turning from a trick into a setting (source: s-sidin-news-digest for every item here).

  • It becomes programmable. GoatTracker 1.4b Final (2003-01-09) ships "a programmable (1 or 2 frame) hard restart" — the timer the goattracker page documents. 1.4c (2003-09-20) and 1.4d are "updated for better hardrestart handling (wavetable also executed on hardrestart frame)": the instrument's wave program keeps running through the restart instead of being suspended by it.
  • The test bit becomes the default. 1.5 (2004-01-25): "Playroutine rewritten. Uses testbit hard restart from now on for much sharper sounds" — and in the same release the hard-restart ADSR becomes configurable, "previously only AD". That is the moment 0F00-style HR values became something a musician types rather than something a driver hard-codes; by 2.23–2.24 it has its own editor key (SHIFT+F7).
  • Then it becomes optional again, per instrument. 2.05 adds instrument legato (Hardres and 1stwave both 00) and moves the ADSR writes away from the wave writes — the write-order question jitt64 later exposes as a switch. 2.59 gives the gate-off timer two flag bits: $80 disables hard restart, $40 disables gate-off. 1.53 (May 2005) is a packer fix "for instruments without hard restart/pulse init", i.e. the no-restart case had become common enough to break the packer.
  • One experiment worth knowing about. 2.47 adds /Z, an "experimental random delay to write of reSID register, in order to make potential ADSR-bugging on C64 audible" — the editor deliberately jittering its own register writes so that a tune which only bugs on real hardware bugs in the emulator too. It is the answer to the readme's own warning about unpredictable timing in packed players, and the closest thing in the wiki to a test for "will this restart hold up on a C64?".
  • A special case for the hardest attack. 2.57: "alternative hardrestart method & playroutine that is used when HR attack parameter is at maximum (FF00 or F800 for example) - this can in theory give better reliability". 2.51 had tried starting the wavetable on the init frame via the gatetimer's high bit, and 2.58 removed it again — not everything stuck.
  • ninjatracker converged on the same points. 1.1 (2004-01-25): "Hardrestart is more solid (set both AD,SR to $00)", in both the standard and the gamemusic player. 2.02 (2006) adds a two-frame hard restart and cuts zero-page use to 2 bytes at the cost of being "slightly slower and bigger"; 2.03 adds a "hifi" style hard restart alongside the plain one — the same two-tier choice (cheap versus accurate) that GoatTracker made with its speedtable options and JITT64 with its write order.

Tips & pitfalls#

  • HR shortens the previous note by the timer length; on very fast runs that is audible (commodorejohn's objection to cutting notes "a very audible fraction of a second before"). The HR ADSR trades this: 0F01 softer, 000F harder attacks (sources: s-lemon64-hard-restart-threads, s-goattracker-readme).
  • Leave the HR ADSR at 0F00 unless you hear a reason (Chordian); in SID-Wizard F800 is the other common value.
  • Timer 2 is the norm; timer 1 only with the hardest HR ADSR (0000) (GoatTracker readme).
  • A staccato HR type or the test bit in frame 1 also fixes the noise lock-up and resets oscillator phase — see ring-modulation-and-sync.
  • Drums lose their first frame to the envelope delay unless the release is short: Klose's MIDIbox drums (release 8) played the noise and pulse frames but not the opening triangle frame (source: s-ucapps-wavetable-sounds-tutorial-1).

adsr-envelope · instrument-design · sid-wizard · goattracker · sid-factory-ii · furnace · defmon · sid-player-routine · multispeed · linus-walleij · sync · martin-galway · bob-yannes

Sources#

s-sid-wizard-manual · s-goattracker-readme · s-lemon64-hard-restart-threads · s-chordian-sf2-instruments · s-witchmaster-creating-chiptunes-with-sid-wizard · s-walleij-sid-player-routine · s-chipmusic-c64-music-for-dummies · s-hvsc-sid-file-format · s-furnace-c64-docs · s-ucapps-wavetable-sounds-tutorial-1 · s-commodore-64-eu-sid-chip · s-sidmusic-yannes-interview · s-remix64-galway-interview · s-sidmusic-jeroen-tel-interviews · s-sidin02-matt-gray-driller · s-realdmx-sid-players · s-64er-soundmonitor-article · s-recollection-brief-history-of-sid · s-realdmx-deenen-test-tunes · s-realdmx-hubbard-player · s-realdmx-galway-rambo-player · s-realdmx-galway-arkanoid-player · s-realdmx-bjerregaard-player · s-realdmx-audial-arts-fame-players · s-realdmx-ocean-dunn-hughes-driver · s-realdmx-fredgray-kimmel-whittaker · s-sidin06-asterion-sid-tracker · s-sidin07-inside-modules · s-sidin08-tiny-sid-512b · s-sidin09-tiny-sid-256b · s-sidin09-catweasel-6581 · s-sidin11-tiny-sid-2-part-2 · s-sidin13-jitt64-tracker · s-sidin13-inside-jitt64 · s-sidin12-tiny-sid-2-part-3 · s-chipmusic-defmon-thread · s-defmon-wiki-defmoning-102 · s-defmon-wiki-manual · s-chordian-my-computer-chronicles · s-chordian-player-editor-notes · s-cheesecutter-guide · s-duet-research-sidwizard-deep · s-duet-research-sidwizard · s-duet-docs-dust-dusk · s-defmon-wiki-defmoning-101 · s-realdmx-ouwehand-mon-tunes · s-remix64-goto80-interview · s-sidin-news-digest · s-sidin04-galway-arkanoid · s-sidin14-dominator-player

source file wiki/techniques/hard-restart.md · graph