Web64 IDE SID Tracker User Guide
Version: 2026-09-06
The SID Tracker is Web64 IDE's browser-local music editor for Commodore 64 SID compositions. The editable source of truth is a .w64sid file. Saving it generates one playable .sid and one assembly .inc; it does not generate a duplicate .bin.
The v3 tracker uses the modular web64-modular-v3 compiler and an adaptive player. It measures event-stream and compact-interpreter representations, emits the smaller valid backend, links only required command families, and publishes exact per-voice position through a stable status block.
For general project and emulator workflows, see the Web64 IDE User Manual.
Contents
- Tracker files
- Workspace
- Toolbar keyboard shortcuts
- Pattern editing
- Selection and clipboard
- Instruments
- Graphical ADSR editor
- Instrument tables
- Effects
- Song and order editor
- Subtunes
- Preview and audition
- Playback position
- Saving and generated files
- Generated include reference
- C project integration
- GoatTracker interchange
- Driver limits and compatibility
- Troubleshooting
- Implementation modules
Tracker Files
The tracker recognizes these related project records:
| File | Purpose |
|---|---|
.w64sid | Editable composition, instruments, tables, patterns, orders, subtunes, metadata, and export settings |
.sid | Generated PSID v2 binary containing the Web64 player and rendered music data |
.inc | Generated assembly constants for loading and calling the .sid payload |
Use Export W64SID to download the editable source for transfer to another project. A downloaded .w64sid can be added through the IDE project-file import workflow.
Saving a tracker removes an obsolete same-stem .bin only when that file was generated from the same .w64sid. Manually authored binary files are preserved.
Version 1 and 2 .w64sid files are migrated in memory to schema version 3. Existing musical data and native playback behavior remain available. Version 3 adds typed order commands, the raw GoatTracker speed table, exact instrument gate/first-frame fields, and a playback-backend preference.
Workspace
The tracker is split into three responsive areas.
Song Rail
The left rail lists the project's .w64sid assets, validation diagnostics, driver version, and resource counts. Collapse it when the pattern needs more width.
Pattern Surface
The center contains:
- Compact icon buttons for play, stop, undo, and redo.
- FastSID or reSID realtime selection and the concrete SID 6581/8580 preview chip.
- Audio enable, mute, and a fixed-width toolbar volume control.
- Pattern selection and naming, New Pattern, Duplicate, and row add/remove.
- Entry octave, playback follow, and selected-pattern loop controls.
- Per-voice Mute and Solo buttons embedded in each sticky voice heading.
- The three-voice pattern grid.
The Name field beside the pattern selector renames the selected pattern. Press Enter or leave the field to commit the name; pattern renames participate in Undo and Redo. Blank names are rejected.
New Pattern creates an empty pattern without modifying an order list. Duplicate copies the pattern and appends the new pattern to the existing orders for backward compatibility.
Inspector
The right inspector uses tabs for Instrument, Tables, Song, and Info. It can be collapsed to a narrow strip that keeps the selected instrument visible.
Instrument topics are independently collapsible. Controls use compact typography and visual editors where a graph or gesture communicates the setting better than a numeric field. Raw numeric entry remains available.
Every editable field and compact control has a descriptive browser tooltip. Hover a field to see its range and command-specific meaning without opening the manual.
The toolbar SID chip and the Info tab's SID model/Clock selections apply to song, pattern, and instrument/note previews. Restart preview after changing them. Concrete choices also update export metadata and are undoable with the song. Compatibility values 6581/8580 and PAL/NTSC retain the current concrete preview chip/clock; they do not emulate two machines at once. Loading a song preserves its explicitly saved playback profile.
Toolbar Keyboard Shortcuts
Toolbar tooltips include their shortcuts. Tracker commands use modifiers so they do not collide with keyboard note entry. Ctrl shortcuts also accept Command on macOS.
| Shortcut | Command |
|---|---|
Ctrl+P, Ctrl+Shift+P | Play the selected subtune or stop preview |
Ctrl+Z, Ctrl+Shift+Z | Undo or redo |
Alt+E | Switch between reSID realtime and FastSID |
Alt+Page Up, Alt+Page Down | Previous or next subtune |
Alt+A, Alt+M | Toggle audio or mute |
Ctrl+Alt+Down, Ctrl+Alt+Up | Decrease or increase preview volume |
Ctrl+Page Up, Ctrl+Page Down | Previous or next pattern |
F2 | Focus pattern rename |
Alt+P | Play the selected native pattern or the displayed GoatTracker voice patterns |
Ctrl+N, Ctrl+D | Create or duplicate a pattern |
Alt+Insert, Alt+Delete | Add or remove the final pattern row |
Alt+Down, Alt+Up | Decrease or increase entry octave |
Alt+F, Alt+L | Toggle playback follow or pattern looping |
Ctrl+[, Ctrl+] | Transpose the note or selection |
Ctrl+Alt+M, Ctrl+Alt+S | Mute or solo the current voice |
Pattern Editing
GoatTracker songs show three independent voice panes, each with its own pattern selector. On opening a subtune these come from its per-voice start orders: for example, voice 1 can display pattern 00 while voices 2 and 3 display 01 and 02. GoatTracker patterns are single-voice parts, not three-voice song sections. The old view showed one part in every column even though song playback used the correct independent orders. Existing imported .w64sid assets work in this view without reimporting or rewriting their musical data.
Selecting a pane's pattern only changes the view, not the song arrangement. The focused voice's pattern is the target of the top Name, Duplicate and Row controls. Edits, selection, transpose, cut/paste and undo operate on that pane's actual voice and pattern. Tab moves to the next voice. Copy/paste may transfer a single-voice selection between panes; multi-voice clipboard blocks are rejected here rather than editing hidden cells. Native Web64 songs retain the combined three-voice pattern editor.
Each voice column has Note, Instrument, Effect, Parameter, and Volume fields on every row.
The one-digit Volume field is a per-note sustain-level override from $0 to $f. Leave it blank to inherit the instrument's Note volume. A volume value may also appear without a note to change the active voice's sustain level. This is separate from SID master volume: the pattern VOL effect and instrument/subtune Master values affect the shared $d418 volume nibble and therefore all three voices.
Notes use tracker notation such as C-4, C#4, and A-5. Special note values are:
| Value | Meaning |
|---|---|
Blank or ... | Hold the current voice state |
~~~ | Tie; keep the current note and gate |
=== | Release; clear the gate and let SID release run |
^^^ | Cut; clear the gate |
The editor wraps from the final row to row zero while entering notes or moving vertically.
Keyboard Note Entry
| Keys | Notes |
|---|---|
z s x d c v g b h n j m | C through B around octave 3 |
q 2 w 3 e r 5 t 6 y 7 u | C through B around octave 4 |
i 9 o 0 p | C through E around octave 5 |
. | Hold marker |
The Octave field shifts this keyboard layout. Entering a playable note immediately auditions the selected instrument at the entered pitch and advances to the next row.
Navigation and editing:
| Key | Action |
|---|---|
| Arrow keys | Move by row or field |
| Tab / Shift+Tab | Move to the next or previous voice |
| Enter | Move to the next row |
| Enter in Effect | Open the searchable command list |
| Home / End | First or last pattern row |
| Delete / Backspace | Clear the selected field or region |
| Ctrl/Cmd+A | Select the full pattern |
| Ctrl/Cmd+C | Copy selection |
| Ctrl/Cmd+X | Cut selection |
| Ctrl/Cmd+V | Paste at the cursor |
| Ctrl/Cmd+Z | Undo |
| Ctrl/Cmd+Y or Ctrl/Cmd+Shift+Z | Redo |
The Effect command popup lists every implemented command, its meaning, parameter format, and range. It opens upward inside the visible pattern area, scrolls long command lists internally, and keeps the active command visible during keyboard navigation. Search by command or description, then press Enter to apply it.
Selection and Clipboard
Drag across rows, voices, and individual fields to create a rectangular selection. Shift navigation extends the selection.
Selections are column-precise. Copying only Effect and Parameter does not overwrite Note or Instrument when pasted. Paste clips safely at the pattern and voice boundaries.
The Transpose - and Transpose + controls move playable notes down or up one semitone. They affect the highlighted block when a selection exists, or the note under the current cursor otherwise. Each transpose is one undoable transaction and clamps notes to the tracker's supported octave range.
The tracker writes a tab-and-line based text form to the browser clipboard and retains an internal clipboard if browser permission is unavailable. Empty note and effect placeholders round-trip as empty cells instead of commands. Cut and Clear use one undoable transaction.
Instruments
The v3 instrument model supports:
- Triangle, saw, pulse, and noise waveforms.
- Gate, test, oscillator sync, and ring modulation flags.
- Attack, decay, sustain, and release.
- Pulse width from
$000to$fff. - Arpeggio and vibrato, including vibrato delay.
- Default tone-portamento speed.
- Hard restart, first-frame control byte, and gate timer.
- A prominent default Note volume/ADSR sustain level from 0 to 15.
- Default SID master volume from 0 to 15.
- Complete SID filter cutoff, resonance, routing, modes, and voice 3 disable.
- Independent pointers into wave, pulse, filter, speed, arpeggio, and vibrato tables.
The pulse-width editor shows the duty cycle with a transparent-to-slate-green fill and provides a slider plus raw hexadecimal entry. Vibrato and arpeggio have visual previews with raw-byte access. Click an editable arpeggio step to increment it, right-click to decrement it, or drag vertically for faster changes. Each arpeggio pole maps values 0 through 15 across the complete available lane height, excluding only the handle itself, so the handle follows the grabbed pointer without leaving an unused upper region. The editable poles expose cyan and purple gradient levels as they rise. Portamento has a continuous control and numeric entry on the same compact row as the arpeggio raw value.
Note volume and the ADSR graph's S point edit the same SID sustain nibble; SID hardware does not provide a separate per-voice volume register. The pattern Volume field can override that nibble per row. Master writes the SID's global volume nibble and is intentionally distinct; changing it can affect every active voice. Both volume controls are kept in the main Sound section rather than hidden under Advanced.
Every continuous slider, graph, and pole gesture uses component-local preview state while the pointer is moving. The tracker commits the final ADSR, pulse, filter, modulation, portamento, or volume value to project state once when the pointer is released. Keyboard changes still commit immediately. This keeps pointer feedback independent of project history, serialization, diagnostics, and the main IDE render tree.
The compact filter and advanced layouts keep related modes, routing, restart, volume, timing, and first-frame controls together while wrapping on narrow inspector widths. Hard restart emits a gate-off/test first-frame sequence before the normal control value. Gate Timer automatically releases the note after the configured tick count. A zero gate timer leaves the gate active until a pattern command or note event changes it.
Filter
Enable Route this voice through filter to make a triggered instrument claim the global SID filter. The instrument can set:
- 11-bit cutoff.
- 4-bit resonance.
- Low-pass, band-pass, and high-pass modes in any combination.
- Voice 1, 2, and 3 routing mask.
- Voice 3 output disable.
- Optional filter-table pointer.
The filter graph is draggable on both axes and keyboard accessible, with a light-blue response gradient below the curve. Horizontal movement changes cutoff and upward movement increases resonance. Arrow Left/Right adjust cutoff; Arrow Up/Down adjust resonance. The latest instrument or filter command that claims the filter supplies the active global settings.
Graphical ADSR Editor
The envelope editor displays attack, decay, sustain, and release as an interactive curve.
- Drag the four curve points to change values.
- Use arrow keys on a focused point for one-step changes.
- Enter values from 0 to 15 in the numeric fields.
- Read the corresponding SID attack/decay/release timing beside the graph.
The graph and numeric controls update the same quantized SID values. Each horizontal point uses the same segment for rendering and pointer conversion, so the point stays under the pointer throughout its valid range even when the SVG is responsively scaled. A yellow-orange gradient below the envelope makes its current shape easier to read. Similar modulation concepts use the same visual-first approach while retaining raw numeric entry.
Attack value 0 is drawn vertically at the left edge to represent the SID's effectively instant attack. Dragging the attack point to the right increases the attack value and displayed time.
Instrument Tables
Each instrument can point at a row in one or more global tables. Tables execute once per player tick and support duration, secondary value, jump target, and loop behavior.
| Table | Commands |
|---|---|
| Wave | WAV, GATE, ARP, NOP, CMD, DLY, JMP, END |
| Pulse | PUL, SET, SLD, DLY, JMP, END |
| Filter | FCO, SET, FRE, MOD, SLD, DLY, JMP, END |
| Speed | SPD (raw high/low bytes) |
| Arpeggio | ARP, DLY, JMP, END |
| Vibrato | VIB, DLY, JMP, END |
Table row fields:
| Field | Meaning |
|---|---|
| Command | Operation for this table |
| Value | Primary byte, word, or signed delta |
| Secondary | Routing, depth, or another command-specific value |
| Duration | Ticks to wait after executing the row, or the slide duration for SLD |
| Target | Row used by JMP or looping END |
| Loop | Makes END jump to Target instead of stopping the table |
The table tab shows a visual value plot above the raw row editor. Unknown commands remain in migrated source long enough for validation to report them; they are not silently converted.
Table Command Reference
| Command | Tables | Operation |
|---|---|---|
WAV | Wave | Set the voice waveform/control byte; gate state is still controlled by the note and GATE logic |
GATE | Wave | Set or clear the voice gate from Value bit 0 |
ARP | Wave, Arpeggio | Apply Value as a signed semitone offset to the current note |
NOP | Wave | Advance without changing waveform or pitch |
CMD | Wave | Execute the GoatTracker command in Value with Secondary as its parameter |
PUL | Pulse | Set the 12-bit pulse width from Value |
SET | Pulse, Filter | Set pulse width or 11-bit filter cutoff directly |
FCO | Filter | Set the 11-bit filter cutoff directly |
FRE | Filter | Set resonance from Value's low nibble and voice routing from Secondary's low three bits |
MOD | Filter | Set low-pass, band-pass, high-pass, and voice-3-off mode bits from Value's high nibble |
VIB | Vibrato | Set speed from Value's high nibble and depth from its low nibble; nonzero Secondary overrides depth |
SPD | Speed | Preserve the two-byte GoatTracker speed value used by portamento, vibrato, and funk tempo |
SLD | Pulse, Filter | Add signed Value on each tick for Duration ticks |
DLY | All tables | Wait Value ticks before processing the following row |
JMP | All tables | Continue at the zero-based Target row on a later tick |
END | All tables | Stop the table, or jump to Target when Loop is enabled |
An instrument table pointer and every pattern table-pointer effect use a zero-based row. Row 0 is valid; a blank instrument pointer disables that table. Wave, pulse, arpeggio, and vibrato tables are per voice. The filter table controls the SID's one shared filter and is owned by the latest instrument or filter effect that claims it.
Table rows execute once per player tick. A finite table stops when it reaches its last row or a non-looping END. Use a looping END for continuous PWM, vibrato, arpeggio, or filter movement. Use DLY and Duration to control timing without repeating identical rows.
Effects
All commands in the v3 effect contract are compiled for preview and export.
| Code | Parameter | Operation and usage |
|---|---|---|
SPD | $01-$1f | Set ticks per row immediately. Lower values advance rows faster. |
ARP | $00-$ff | Three-step arpeggio: root, high-nibble semitone offset, low-nibble semitone offset. Static forms use the compact adaptive runtime command. |
PU+ | $00-$ff | Raise frequency by the parameter amount on every tick. Zero uses the minimum step of one. |
PU- | $00-$ff | Lower frequency by the parameter amount on every tick. Zero uses the minimum step of one. |
TPO | $00-$ff | Slide the existing voice toward this row's note without retriggering its envelope. Zero uses the instrument Portamento value, then the minimum step. |
VIB | $00-$ff | Set vibrato speed in the high nibble and depth in the low nibble. For example, $24 is speed 2 and depth 4. |
PWM | $00-$ff | Start the pulse table at this zero-based row. PTB is the explicit equivalent. |
FCO | $00-$ff | Set filter cutoff to Parameter multiplied by 8, covering the SID's 11-bit range in coarse steps. |
FRE | $00-$ff | Set resonance from the high nibble and route voices from the low three bits. |
WAV | $00-$ff | Set the voice waveform/control byte; the current gate state supplies bit 0 during playback. |
VOL | $0-$f | Set the SID master-volume nibble. This is global and affects all three voices. |
INS | $00-$3f | Select an instrument by zero-based index, with or without a note on the same row. |
BRK | $00-$3f | Finish the current pattern and continue at this row in the next order position. |
JMP | $00-$ff | Jump to this zero-based order position. It can be combined with BRK on another voice to choose a start row. |
DLY | $0-$f | Delay this row's note trigger by the low-nibble tick count. |
CUT | $0-$f | Clear this voice's gate after the low-nibble tick count. |
AD | $00-$ff | Write attack in the high nibble and decay in the low nibble for this voice. |
SR | $00-$ff | Write sustain in the high nibble and release in the low nibble for this voice. |
WTB | $00-$ff | Start the wave table at this zero-based row. |
PTB | $00-$ff | Start the pulse table at this zero-based row. |
FTB | $00-$ff | Claim the shared filter and start the filter table at this zero-based row. |
ATB | $00-$ff | Start the arpeggio table at this zero-based row. |
VTB | $00-$ff | Start the vibrato table at this zero-based row. |
Unknown commands and out-of-range parameters produce diagnostics and block preview/export instead of generating incorrect data.
Filter effects on the same row as a filtered note take precedence over that instrument's default filter values. This lets FCO, FRE, or FTB establish the intended first filter frame instead of being overwritten by note initialization.
Song and Order Editor
The Song tab edits:
- The selected subtune and all of its playback settings.
- One independent pattern-order lane for each SID voice.
- Order-step append and removal.
- Global speed and tempo defaults.
Each order position chooses one pattern for each of the three voices. + Step appends a position to all voices, and - Step removes the final position. Start, Loop, and End in the selected subtune determine which range of that order is compiled.
Tempo is rendered relative to the 125 baseline used by the 50 Hz player. Higher values reduce rendered ticks per row; lower values increase them within the driver limits. Subtunes can inherit these global defaults or override them.
Subtunes
A subtune is an independently initialized and playable entry within one SID file. Subtunes are the normal way to package related audio that shares a player and sound resources:
- Title music and in-game music.
- Level, boss, or ambient themes.
- Game-over and completion jingles.
- One-shot sound effects such as pickups, alarms, or menu confirmations.
All subtunes share the composition's patterns, instruments, and five global tables. Each subtune owns an independent order list and playback settings, so the same patterns can be arranged differently without duplicating instrument/table data.
Creating and Managing Subtunes
Use the Song tab controls:
| Control | Result |
|---|---|
| + New | Create a new subtune with a new one-step order list that starts with pattern 0 |
| Duplicate | Copy the selected subtune settings and clone its complete order list |
| Delete | Remove the selected subtune and its private order list; at least one subtune always remains |
| Play | Compile and preview the selected subtune |
| Default | Make the selected subtune the PSID start song and default Web64 preview |
The compact Sub selector in the main tracker toolbar selects the subtune used by the icon Play button. Selecting a nonzero subtune passes its exact zero-based index to the generated driver's init routine. Play remains available and restarts the selected subtune; Stop ends preview.
Subtune Settings
| Setting | Meaning |
|---|---|
| Name | Human-readable name shown in selectors and generated include comments |
| Purpose | Music, Title music, Game music, Ambient, Jingle, Sound effect, or Custom classification |
| Description | Project notes describing where and how the subtune is used |
| Default | Initial song in PSID metadata and the default selection when opening the asset |
| Loop checkbox | On: return to Loop order after End. Off: emit STOP after End for one-shot playback |
| Start | First zero-based order position played after init |
| Loop order | Zero-based order position used when a looping subtune reaches End |
| End | Final zero-based order position included in this subtune |
| Speed | Optional ticks-per-row override; blank inherits Global speed |
| Tempo | Optional timing-scale override; blank inherits Global tempo |
| Master | Optional SID master-volume override from 0 to 15 |
| Transpose | Shift all playable notes from -24 to +24 semitones without modifying patterns |
For a sound effect, set Purpose to Sound effect, disable Loop, and keep Start/End around only the required order positions. When music is already playing, initializing such a subtune starts it as an overlay: the background stream continues advancing and the effect uses only its owned SID voices. A one-shot jingle remains a primary subtune unless its Purpose is Sound effect. For title/game music, leave Loop enabled and set Loop to the first order position that should repeat; an intro can remain before that point.
Subtune Master overrides instrument master values during that subtune. Per-note pattern Volume and instrument Note volume/ADSR sustain still control each voice's sustain level. Transpose is applied during compilation and leaves shared source patterns unchanged, which allows one pattern to serve several pitched effects.
Sound-Effect Voice Inheritance
A Sound effect can keep the current music on voices 1 and 2 and use a short pattern on voice 3. Assign the same background pattern/order sequence to the inherited voices and assign the effect pattern to its owned voice. The compiler compares each SFX channel with the music subtunes:
- A matching channel sequence is inherited and is not duplicated into the SFX stream.
- A different channel containing notes, commands, or volume changes is owned by the SFX.
- The SFX duration and encoded stream use only owned patterns. A 4-row voice-3 effect therefore remains four rows even if inherited voices point at a 64-row game pattern.
- Overlay streams preserve the shared SID master/filter registers. Pattern Volume and the instrument ADSR sustain value continue to control the owned voice.
Effects should own voices that the background arrangement leaves available. Starting another SFX while one is active replaces the current overlay. When an effect reaches STOP, its owned voice gates are cleared and the primary music remains selected and playing.
Runtime Numbering
The Web64 driver uses zero-based subtune indexes:
lda #song_sid_subtune_2 ; generated value 1
jsr song_sid_init_address
frame:
jsr song_sid_play_address
; wait for the next video frame
jmp frame
Call init once whenever switching primary subtunes, with the required index in A. Call play once per video frame while the status Playing byte is nonzero. A primary one-shot clears Playing when it reaches STOP; a looping subtune continues from its Loop position. Initializing a non-looping Sound effect while a primary subtune is playing starts the overlay without changing the primary status Subtune or Playing bytes.
Calling play again after a primary one-shot has stopped is safe: the driver checks Playing and returns without reading beyond the stream. An overlay STOP ends only the effect and does not require the game to initialize its music again.
The PSID header follows the SID file convention: song count and start song are one-based. The generated assembly constants and the driver's A register remain zero-based. Therefore song_sid_subtune_1 is 0, song_sid_subtune_2 is 1, and so on.
Saving compiles one event stream for every subtune. The adaptive player is shared once, so adding a subtune adds its music stream and order behavior rather than another complete driver. Sound-effect streams omit inherited music voices and shared global-register traffic. Stream encoding v3 also removes ordinary sequential row-status writes; the player advances those row counters itself and the stream emits a correction only at pattern, order, jump, or loop boundaries.
Keep one-shot sound effects limited to the rows and order positions they actually require. Eventless tails compress efficiently, but an intentionally short pattern also reduces render work and makes the generated per-subtune size constant easier to interpret.
Preview and Audition
Use the main Play icon for the selected subtune and its saved order lists. For native songs, Pattern Play auditions the displayed three-voice pattern. For GoatTracker songs the button is Patterns: it auditions the three independently displayed voice patterns together, without advancing through the song order. With Loop pattern enabled each voice repeats its selected pattern; otherwise each runs once and playback stops when all voices finish. The accepted instrument, table and SID timing behavior is unchanged.
With Follow enabled each GoatTracker pane follows its own playing pattern and rows. Turn Follow off to browse different patterns without playback forcing the selections back. This changes only navigation, not the playing song.
Preview compiles the current draft, resets the Web64 runtime, applies its PAL/NTSC and 6581/8580 profile, writes the generated player and streams, and initializes the selected subtune. Ordinary playback uses video timing (50 Hz PAL, 60 Hz NTSC). GoatTracker half-speed and multispeed profiles use a matching CIA timer; PSID exports advertise CIA timing too.
While an editable SID preview owns the shared C64, project Live Patch is suspended. Preview startup invalidates queued project patches and waits for any in-flight write before loading its player. Editing or compiling the project cannot overwrite the audition driver or interrupt its audio. Explicitly starting the project returns ownership to normal project playback and restores live patching; the Live Patch preference itself is unchanged.
Instrument Preview plays C/E/G on adjacent pattern rows at the song's speed. At speed 6 and ordinary PAL timing, successive phrase notes are 120 ms apart. Full table support does not slow the player clock or add blank rows between notes. Single-note entry audition keeps a four-row hold to expose sustained modulation. GoatTracker's own startup/hard-restart lead time still applies; the preview does not replace its articulation with native Web64 behavior.
Preview-only controls:
- FastSID for lower CPU cost and approximate playback.
- reSID realtime for the fidelity-reference realtime engine, including accurate portamento playback.
- Voice mute and solo.
- Pattern Play and Loop pattern for isolated pattern preview.
- Audio enable, mute, and volume.
Preview-only mute, solo, and pattern looping do not change the .w64sid or generated .sid.
Preview Instrument compiles a short C-E-G audition with the selected instrument and the current song tables. Note entry uses a disposable single-note sequence through that same compiled player: ADSR, waveform/control, gate flags, wave/pulse/filter/speed tables and their modulation continue over successive ticks, followed by release. The source composition is unchanged. CPU execution writes live SID I/O; monitor memory writes are not used for SID registers because they address underlying RAM rather than live I/O.
The C-E-G phrase uses the keyboard-entry octave, not the notes used by that instrument in the song. Pitch-relative percussion can therefore sound quite different: GoatTracker includes silent frequency entries above B-7, so large positive table offsets at octave 4 may silence part of a noise sound that plays normally at octave 3. To compare timbre, audition the same note at the song's octave. Imported instruments retain GoatTracker's pitch rules and SID register-write order; the older native-dialect preview is not a fidelity reference.
The tracker applies the chosen FastSID/reSID resources before song, instrument, and note preview.
Song Play and Pattern Play change the toolbar to an active preview state before runtime boot or compilation begins, so Stop is enabled on the next browser paint. Both remain available and restart their requested preview even while a note or instrument audition owns the preview runtime. Stop cancels an in-progress startup and updates the toolbar before waiting for emulator reset or destruction. Audio priming continues asynchronously after the player starts.
SID emulation and audio production run in the emulator Web Worker, while browser output runs in an AudioWorklet. On cross-origin-isolated deployments they exchange samples through a shared ring buffer. The non-isolated fallback uses a direct transferable MessageChannel from the emulator worker to the worklet, so tracker rendering and other main-thread work cannot delay audio block delivery. The worker preview path targets about 80 ms of queued audio instead of the older 240 ms target.
Playback Position
The v3 player publishes exact playback state in a 13-byte status block:
| Offset | Value |
|---|---|
| 0 | Playing |
| 1 | Subtune |
| 2 | Tick |
| 3 | Speed |
| 4-6 | Order position for voices 1-3 |
| 7-9 | Pattern index for voices 1-3 |
| 10-12 | Row index for voices 1-3 |
The emulator worker watches this block at its video cadence and pushes a message only when the bytes change. This removes repeated main-thread memory requests and their worker queue. The IDE does not estimate the row with a browser timer. The active row is highlighted for each voice.
Playback snapshots are published through a tracker-scoped external store rather than Web64Ide state. Follow playback changes pages only when the active row leaves the visible page, and it does not scroll the grid on every note. Only actual row/state changes render the tracker surface; playback no longer renders the complete IDE tree.
Saving and Generated Files
Save validates and writes the .w64sid, then regenerates:
<name>.sid<name>.inc
The PSID contains:
- One compact 6502 frame-event decoder shared by every subtune.
- Rendered register-event streams for all subtunes.
- Stable playback status block.
- Audition mailbox storage reserved by the stable audition ABI.
Most pattern density affects rendered music data rather than decoder code. Stream encoding v3 selects direct-register writes, contiguous SID runs, voice masks, short delays, signed frequency deltas, signed pulse-width deltas, and repeated-delta runs only when the complete composition saves more bytes than the required decoder branch costs. Adaptively linked runtime features and their song-specific preset tables can also change driver size. Compile fails if the selected driver/music addresses would exceed C64 memory.
The generated include is replaced only when it is a generated sibling of the current .w64sid. Older tracker-generated includes are recognized by the Generated by Web64 IDE marker even when an older project format lacks generatedFrom metadata. A genuinely manual .inc at the same path is preserved.
Saving music for a multi-load disk
The .w64sid source stays editable. The generated .sid is a PSID container, not a raw load-address PRG: its 124-byte header makes it 122 bytes larger than the equivalent two-byte-prefixed PRG. Changing its filename extension is not a conversion.
Inside Web64, create a data-only assembly Build Target that includes the generated .inc and uses .incbin with *_c64_data_offset and *_c64_data_size to select the payload. Set the target origin to the generated load address. In Disk/Media, add the target with Add Logical Output, select PRG mode > Raw data, and Place File on the disk. Keep Runnable (SYS) for the executable boot file.
After editing, use Tracker Save -> Build Dependencies -> Run Disk. Download File exports that logical file as the exact mastered PRG; the disk's Download exports the D64. Rebuild resident code if it references generated song sizes or entry addresses. No external converter, local repository, manual project-JSON edit, or separate stale PRG source is needed. See Disk mastering and project media for the complete browser workflow, RAM planning, loading, errors and persistence.
Generated Include Reference
With the normal filename-derived prefix for song.w64sid, the include exposes:
song_sid_load_addresssong_sid_init_addresssong_sid_play_addresssong_sid_driver_addresssong_sid_music_data_addresssong_sid_driver_sizesong_sid_music_data_sizesong_sid_status_addresssong_sid_status_sizesong_sid_status_versionsong_sid_status_playing,song_sid_status_subtune,song_sid_status_tick,song_sid_status_speedsong_sid_status_order_1throughsong_sid_status_order_3song_sid_status_pattern_1throughsong_sid_status_pattern_3song_sid_status_row_1throughsong_sid_status_row_3song_sid_audition_address,song_sid_audition_sizesong_sid_audition_command,song_sid_audition_note,song_sid_audition_instrument,song_sid_audition_voicesong_sid_size,song_sid_endsong_sid_subtune_count,song_sid_default_subtunesong_sid_subtune_1throughsong_sid_subtune_<count>as zero-based init valuessong_sid_subtune_1_stream_sizethroughsong_sid_subtune_<count>_stream_sizesong_sid_subtune_1_voice_maskthroughsong_sid_subtune_<count>_voice_masksong_sid_subtune_1_overlaythroughsong_sid_subtune_<count>_overlaysong_sid_driver_version,song_sid_stream_encoding_versionsong_sid_linked_compact_arpeggio,song_sid_linked_arpeggio_preset_countsong_sid_linked_short_delay,song_sid_linked_direct_sid,song_sid_linked_sid_run,song_sid_linked_voice_masksong_sid_linked_frequency_delta,song_sid_linked_frequency_delta_runsong_sid_linked_pulse_delta,song_sid_linked_pulse_delta_runsong_sid_linked_sfx_overlaysong_sid_driver_hash,song_sid_music_data_hash,song_sid_payload_hashsong_sid_file_sizesong_sid_data_offset,song_sid_c64_data_offset,song_sid_c64_data_sizesong_sid_payload_address,song_sid_payload_end
Assembly should import only the C64 payload from the PSID container:
.include "assets/music/song.inc"
* = song_sid_load_address
.incbin song_sid, "assets/music/song.sid", song_sid_c64_data_offset, song_sid_c64_data_size
Call song_sid_init_address with the zero-based subtune in A, then call song_sid_play_address once per video frame.
C Project Integration
For C builds, assets/generated.h exposes the generated .sid as one Web64SidAsset. The .w64sid source and .inc do not create duplicate C asset declarations.
Generated constants include the file size, C64 data offset and size, payload pointer, load/init/play addresses, song count, one-based PSID start song, and SID metadata flags. This lets C or mixed C/assembly code load the same payload described by the assembly include. Use the generated assembly subtune constants in a small assembly wrapper when C code needs to initialize a specific zero-based driver subtune in A.
Older projects that still contain only a generated .bin remain readable. Saving the composition with the current tracker creates the .sid/.inc pair and removes only the obsolete generated .bin.
GoatTracker Interchange
Import GT opens the guided importer for standard single-SID GoatTracker 2 songs (GTS3, GTS4, and GTS5) and instruments (GTI3, GTI4, and GTI5; .ins and .gti). Project-tree import uses the same dialog. Song import asks for the W64SID destination, PAL/NTSC timing, 6581/8580 preference, speed multiplier, and adaptive/event-stream/interpreter backend. Instrument import can append or replace the selected instrument and relocates its table pointers into the current song.
SNG files do not store the SID chip model. The import dialog's 6581 default is a choice, not detected author intent. Select the intended model explicitly; 6581 and 8580 combined waveforms and filters can sound substantially different. The toolbar chip selector lets you compare without reimporting the song.
W64SID becomes authoritative immediately after import. Web64 does not keep a hidden source file and does not restore stale GoatTracker bytes during export. Export SNG and GTI rebuild GTS5 or GTI5 from the current editable patterns, orders, instruments, and tables. Export reflects edits, not stale raw effect metadata. Byte-identical round-trip is not promised: unused blank slots may be omitted, indices relocated and legacy data upgraded to version 5. Nonempty unused patterns retain distinct editable identities, even if their bytes match another pattern.
Each unique source pattern appears once in the editor. Repeated/transposed occurrences stay order references, and each subtune keeps three independent order lists. Import diagnostics distinguish stored pattern slots from materialized editable patterns; the 208-pattern limit does not count repeated occurrences. A zero instrument byte means inheritance, including across pattern boundaries; an explicit instrument on a REST row still changes the current instrument.
The importer preserves:
- all three order lists per subtune, including transpose, repeat, restart, and independent channel positions;
- notes, REST/KEYOFF/KEYON commands, the zero instrument byte meaning "keep current instrument," and pattern commands
0throughF; - AD/SR, wave/pulse/filter/speed pointers, vibrato delay, gate timer flags, first-frame control, and instrument names;
- wave, pulse, filter, and speed table bytes, jumps, delays, modulation, and command rows;
- per-channel GoatTracker tempo changes and funk tempo during preview/export rendering.
GoatTracker pattern commands map as follows:
| GT | W64SID | Meaning |
|---|---|---|
0 | none | No command |
1 / 2 | PU+ / PU- | Portamento up/down using the speed table |
3 | TPO | Tone portamento |
4 | VIB | Vibrato using the speed table |
5 / 6 | AD / SR | Set envelope register |
7 | WAV | Set waveform/control |
8 / 9 / A | WTB / PTB / FTB | Set table pointer |
B / C | FRE / FCO | Set filter resonance/routing or cutoff |
D | VOL or MRK | Master volume 0-F; larger values remain timing markers |
E | FUN | Select funk-tempo speed-table pair |
F | TMP | Global or voice-local tempo |
Imported rows show a blank instrument field when GoatTracker encoded instrument 00; the currently playing instrument is retained. Entering a hexadecimal instrument explicitly enables an instrument change. The instrument editor exposes gate-off, hard restart, raw gate timer, and first-frame special values (00 unchanged, FE gate off, FF gate on). Raw GoatTracker table rows remain visible and become ordinary W64SID rows when edited.
Legacy GTS3/GTS4 and GTI3/GTI4 data is accepted with a normalization warning and exports as version 5. Standard three-voice, single-SID GoatTracker 2 is the compatibility target. Stereo GoatTracker variants, RSID, and multi-SID export are explicitly deferred and are not silently flattened.
Playback retains the GoatTracker dialect in the editable asset. The gate timer is a hard-restart lead time, not a note duration. Table execution preserves delayed waves, absolute/relative pitch, pulse accumulator wrap/phase, filter routing/mode/cutoff, speed-table effects and independent voice tempo. Native Web64 and GoatTracker table semantics are not interchangeable: a GTI can adopt the dialect in an empty song, but importing it into a nonempty native song is refused. Edited native-only effects/table commands without a GoatTracker representation produce an explicit compile/export diagnostic.
The compiled player never reads write-only SID registers for arithmetic: it maintains RAM shadows. GoatTracker pulse operations run at playback time so a musical loop does not reset PWM phase. A dictionary shares repeated frame bodies. Pathological nonrepeating streams, malformed table execution and payloads that exceed C64 RAM or cross SID I/O are rejected rather than truncated. The standard compatibility target is tick-level SID state and relative hardware-write order, not cycle-identical write timing or analog-filter identity across SID chips/emulators.
Reusable Cloud Music Library
The optional Cloud tab inside SID Tracker owns private Instruments, Patterns and Subtunes libraries. Local editing, playback and project saving remain available without Cloud. These are not new project file/editor types and never become implicit live-linked dependencies.
Save the currently selected item under a Cloud display name; saving does not edit the song. Browse/filter your own items, inspect their dependency counts, then choose Preview import. Instruments and patterns can be added or explicitly replace a selected slot; subtunes are always added. Confirm the allocation preview to import one undoable local copy. Profile differences require explicit adoption in an empty song. Network/auth/quota/validation errors and stale previews leave the local song unchanged.
- Instrument copies include their complete referenced table graph, ADSR/control and playback profile.
- Pattern copies include referenced instruments and tables with repaired indices. A pattern whose first sounding note inherits an unknown incoming instrument must have that instrument made explicit before independent saving.
- Subtune copies include their own editable order (including intro/restart references), referenced patterns/instruments/tables, channel enables, timing and initial per-voice instruments. Other subtunes and unrelated patterns are excluded. Shared definitions are reused only when their complete named content matches; equal display names alone never merge sounds.
| Category | Free items | Paid items | Maximum JSON payload |
|---|---|---|---|
| Instruments | 10 | 200 | 256 KiB |
| Patterns | 10 | 100 | 384 KiB |
| Subtunes | 10 | 50 | 4 MiB |
Limits are enforced by the server using the current subscription-backed entitlement, alongside total Cloud storage limits. Deleted items immediately free their category slot, but retained payload bytes continue counting toward storage until purged after 30 days on a subsequent save. Rename and delete affect only the Cloud copy. Duplicate names are allowed; stable IDs identify items. Version 1 payloads use explicit type/version/content/dependency manifests; unknown versions or incomplete closures are rejected. After import the local .w64sid is authoritative and does not need Cloud to play.
Driver Limits and Compatibility
web64-modular-v3 supports:
- 3 SID voices.
- 208 patterns.
- 128 rows per pattern.
- 64 instruments.
- 255 rows per table.
- 32 subtunes.
- PSID v2 export.
- Single SID at
$d400.
RSID, stereo GoatTracker, and multi-SID export remain intentionally unsupported and produce diagnostics. The runtime/player is browser-local and does not require native VICE tools, cc65, Electron, Tauri, or host filesystem paths.
Adaptive Linking and Stream Compression
The exported player is linked from the rendered song rather than emitted as one fixed feature-complete binary:
- A song without a compact instrument arpeggio contains no arpeggio interpreter, preset tables, or arpeggio state.
- Static three-step arpeggios link only the exact base/high/low frequency presets used by the composition. A note change selects one preset and the player cycles it at runtime instead of storing two frequency-register writes on every tick.
- Vibrato, pulse modulation, slides, and table-driven modulation retain deterministic rendered values. Repeated signed frequency or pulse-width deltas are collapsed into one delta-run command and expanded by the player once per frame.
- A one-register frame can use a two-byte direct write. Consecutive SID registers and sparse registers within one voice use compact run or mask records when their shared decoder is profitable.
- Consecutive frames without stream events use a delay run. Frequently occurring delays up to 32 frames use one-byte short-delay tokens.
- Native tick and ordinary row progression are maintained by the player. GoatTracker streams publish explicit per-voice row changes to retain pre-roll and independent tempo semantics. Equal order, pattern, or row values for all three voices use one grouped status command.
- Hard restart is prepared once on the final frame before the new note with the next instrument's First frame value; the note row does not store a redundant second gate-off write.
- Decoder branches and state for each v3 bytecode family are omitted unless aggregate savings across all subtunes exceed their player cost.
- Non-looping Sound effect subtunes link one secondary stream context. The primary pointer, delay, delta-run state, position, portamento, and sustain writes continue once per frame while the effect context decodes its owned voice.
- The hot stream pointer and frame counters use self-modifying operands. The player does not claim a fixed zero-page range, avoiding collisions with the host program's own zero-page allocation.
Existing .w64sid v2 projects remain source-compatible. Save the composition again to regenerate a .sid with stream encoding v3 and the adaptively linked player.
When copying a generated PSID payload at runtime, the generated <prefix>_c64_data_offset and <prefix>_c64_data_size constants provide the exact range. A fixed page count is also valid when its capacity has been checked against the current C64 payload size; for example, a 6 KB copy fully covers a 5.6 KB payload. Recheck that bound when the composition grows.
Troubleshooting
Nothing plays
Click Play or enter a note directly so the browser can grant audio permission. Check Audio, Mute, volume, and the selected FastSID/reSID engine. Validation errors are shown in the song rail and block compile.
Only the first subtune plays
Select the required subtune in the toolbar's Sub selector or the Song tab before pressing Play. At runtime, call init again with the zero-based subtune index in A; calling play without reinitializing continues the previously selected stream. PSID players show song numbers as one-based, while Web64 generated subtune constants are zero-based.
A sound-effect subtune never finishes
Disable the subtune Loop checkbox. Confirm End covers the final required order position. A non-looping subtune emits STOP and clears the generated status Playing byte after the last rendered frame.
Note volume changes every voice
Use the pattern Volume column or instrument Note volume for per-voice sustain level. Instrument Master, subtune Master, and the VOL effect write the shared SID master-volume register and can affect all voices.
Instrument tables do not affect note or instrument preview
Recompile/resave the .w64sid to replace an older generated player. Current note-entry and instrument previews execute the active composition's complete tables using its playback dialect. For GoatTracker imports select the original SID model/timing and prefer reSID for fidelity checks; FastSID is approximate.
The same song sounds different in an older Web64 build
Compare the same chip, clock and preview engine first. Earlier Web64 preview setup selected 8580 through the emulator engine setting, even for imports labeled 6581. Current preview applies the song's concrete playback profile. Select SID 8580 beside the engine and restart Play to compare with that older setup. Info edits now update the actual profile, rather than only changing metadata labels. A chip match does not establish that browser buffering, register-write timing, or every musical feature is identical; report remaining clicks or timing differences separately.
Web64 2.3.1 retains GoatTracker's programmed wavetable pitch/delay steps, pulse modulation and gate/hard-restart behavior. Older previews could omit some of those changes and therefore sound smoother while differing from the source instrument. The corrected playback was accepted after comparison with GoatTracker's own exported player; it is not smoothed to reproduce the older preview. Register/tick checks and that listening comparison do not imply cycle-identical writes or identical analog sound on every SID model.
After upgrading, save/recompile the editable .w64sid to regenerate its player. If an older import already discarded pattern/order structure, re-import the original .sng into a separate asset before transferring any later edits. Existing .sid exports and Cloud copies do not change automatically.
Playhead is on the wrong row
Current versions read the generated status block. Confirm the current .w64sid draft was compiled and that the main project has not replaced the preview in emulator memory.
Main program does not start after tracker preview
The IDE Start command leaves tracker preview mode, stops status polling, power-resets the runtime, loads the current build, and starts it. Pause/Resume does not reset. If Start is blocked, inspect project compile diagnostics rather than tracker playback state.
Export is too large
Static instrument arpeggios and empty frame runs are compacted automatically. Long songs with continuously changing vibrato, pulse, filter, slide, or table modulation still require pre-rendered register events. Shorten unused order ranges, remove redundant table changes, or move the music-data address if the payload overlaps other C64 memory.
A manual include was not replaced
This is intentional. Web64 only overwrites .inc records marked as generated from the current .w64sid.
Implementation Modules
The tracker is no longer embedded in the main IDE component.
Core compiler modules:
web64-ide/sid-assets.mjs: schema, migration, transactions, validation, exports, preview payloads, and generated include.web64-ide/sid-tracker-contract.mjs: v3 commands, capabilities, ABIs, normalization, and ADSR math.web64-ide/sid-tracker-renderer.mjs: song/effect/table renderer and compact 6502 event player.web64-ide/goattracker-sng.mjs: standard GoatTracker song/instrument inspection, import, semantic mapping, and export.
React workspace modules:
sid-tracker/SidTrackerWorkspace.jsxsid-tracker/PatternEditor.jsxsid-tracker/InstrumentEditor.jsxsid-tracker/AdsrCurveEditor.jsxsid-tracker/VisualParameterEditors.jsxsid-tracker/InstantRange.jsxsid-tracker/note-audition.mjssid-tracker/pointer-geometry.mjssid-tracker/playback-store.mjssid-tracker/TableEditors.jsxsid-tracker/SongEditor.jsxsid-tracker/GoatTrackerImportDialog.jsx
Web64Ide.jsx retains only the project-file, runtime, audio, save/export, and preview bridge.