Sounds editor — keyboard reference
The Sounds tab is a tracker-style pattern editor. Click any cell in the 32×5 pattern grid to place the cursor, then use the keymap below to write notes, instruments, volumes, and stops. The cursor's sub-column (Note / Inst / Vol) determines which keys are active.
Notes — FT2 two-octave keymap
Two rows on the keyboard map to two consecutive octaves, anchored on the editor's current octave (default 4). The lower row (Z–M plus ", L .") covers C through D# of the next octave; the upper row (Q–U plus 2-7) covers C through B of the next octave; I–P plus 9 0 reach the third octave's C through E.
| Key | Note | Octave offset |
|---|---|---|
Z | C | +0 |
S | C# | +0 |
X | D | +0 |
D | D# | +0 |
C | E | +0 |
V | F | +0 |
G | F# | +0 |
B | G | +0 |
H | G# | +0 |
N | A | +0 |
J | A# | +0 |
M | B | +0 |
, | C | +1 |
L | C# | +1 |
. | D | +1 |
Q | C | +1 |
2 | C# | +1 |
W | D | +1 |
3 | D# | +1 |
E | E | +1 |
R | F | +1 |
5 | F# | +1 |
T | G | +1 |
6 | G# | +1 |
Y | A | +1 |
7 | A# | +1 |
U | B | +1 |
I | C | +2 |
9 | C# | +2 |
O | D | +2 |
0 | D# | +2 |
P | E | +2 |
Pressing a note key writes the note at the cursor, advances the cursor down one row, and live-previews the note via the cell's instrument.
Stop / clear
| Key | Effect |
|---|---|
= | Note-off — triggers ADSR release; voice rings through release phase, then silences. |
- | Note-cut — immediate silence, no release ramp. |
Backspace / Delete | Clear the active sub-column at the cursor (Note / Inst / Vol). |
Octave shift
| Key | Effect |
|---|---|
< | Lower the editor's base octave (clamped to 0). |
> | Raise the editor's base octave (clamped to 8). |
The current octave is shown in the transport bar at the bottom of the Sounds tab. Default is 4 (so Z = C4).
Hex digits — Inst and Vol sub-columns
When the cursor is on the Inst or Vol sub-column, 0–9 and A–F write hex values.
| Sub-column | Behavior |
|---|---|
| Inst (2 hex digits) | Shift-register: each keypress shifts the existing value left and appends the new digit. Type 0 then 5 to enter 05. Cursor does NOT auto-advance, so you can build a 2-digit instrument id without losing the row. |
| Vol (1 hex digit) | Replace: each keypress overwrites the current value. Cursor does NOT auto-advance. |
Navigation
| Key | Effect |
|---|---|
↑ / ↓ | Move cursor up / down one row. |
← / → | Move cursor left / right one sub-column (wraps across channel boundaries). |
Tab | Move cursor right (same as →). |
Shift+Tab | Move cursor left (same as ←). |
Home | Jump to row 0, channel 0, Note sub-column. |
End | Jump to last row of the current channel + sub-column. |
PageUp / PageDown | Jump 8 rows up / down. |
Undo / redo
| Key | Effect |
|---|---|
Ctrl+Z / ⌘+Z | Undo. |
Ctrl+Shift+Z / ⌘+Shift+Z | Redo. |
Ctrl+Y | Redo (alternate). |
Undo snapshots the entire SOND data on each meaningful change. Typing bursts are debounced with a 250 ms window so a sequence of note keypresses collapses into one undo step. The undo stack is capped at 50 snapshots; older snapshots drop FIFO.
Transport buttons
Below the pattern grid the transport bar shows the current pattern, row, and BPM. Buttons:
| Button | Effect |
|---|---|
▶ Play | Start the host engine on the active pattern (loops; same as cart-Forth's play-pattern). |
■ Stop | Halt the engine and all SFX slots (panic button). Equivalent to stop-music followed by -1 stop-sfx. |
⊙ Follow | Toggle whether the cursor tracks the playhead row while the engine is running. |
Music and SFX buses
As of P5.2 the host tracker engine has two parallel buses: a music slot that loops your background track, and four SFX slots that overlay one-shot or looping sound effects on top. Each slot reads patterns from the same SOND pool — the distinction is entirely about which cart-Forth word you call, not how you author the pattern.
Music bus: ( pattern -- ) play-music starts a looping
pattern; ( -- ) stop-music halts it. play-pattern is an alias retained from pre-P5.2 — both names produce identical bytecode.
SFX bus: ( pattern slot -- ) play-sfx fires a one-shot
pattern on slot 0–3 (or -1 to auto-allocate the first
idle slot, evicting the oldest if all four are busy). loop-sfx ( pattern slot -- ) is the looping variant. ( slot -- ) stop-sfx stops one slot; -1 stop-sfx stops all SFX without touching music.
When two slots write to the same voice on the same tick, the engine dispatches in fixed order — music first, then SFX 0, 1, 2, 3 — and the last write wins. Authors who want non-conflicting layering can author SFX patterns to use voices the music doesn't touch (typically the sawtooth + noise channels).
play-once (pre-P5.2 single-pattern player) is retained
as a shorthand: it's equivalent to passing your pattern number followed by -1 to play-sfx. For example, 2 play-once and 2 -1 play-sfx compile to
equivalent behavior — both fire pattern 2 on an auto-allocated SFX slot.
The semantic shift is intentional — pre-P5.2 it cut music; post-P5.2 it
overlays.
On GameTank carts the same music and SFX also play in native ROM builds
(the studio's Export .gtr) — the ROM embeds a tracker
sequencer driving the audio coprocessor's fixed-function mixer firmware,
and tempo stays locked to 60 Hz wall-time even when a frame runs over
budget. Two voice counts are easy to conflate here: the GameTank machine
profile itself reports 4 voices — a conservative,
browser-side software-mix cap the studio and cost model use for
portability warnings — while the native ACP mixer firmware implements 5 hardware voice slots, one per SOND channel role
(sq0, sq1, triangle, sawtooth, noise). A cart's browser playback and its
native .gtr playback both draw on the same SOND patterns
either way; the 4-vs-5 split is a browser-estimate-vs-hardware-reality
distinction, not a feature you author around.
Dynamic tempo
A cart can change the music slot's tempo at any time by calling ( frames-per-row -- ) set-bpm. The new tempo (clamped to 2..=64) takes effect at the next row boundary. SFX slots are
never affected.
Call set-bpm every frame to drive smooth tempo ramps —
useful for Space-Invaders-style march acceleration or any rhythm-based
gameplay that responds to game state.
\ Halve the music tempo from frame ~60 onward.
variable frame
: update
frame @ 1 + frame !
frame @ 60 = if 4 set-bpm then
;
set-bpm is a no-op when no music is playing — it does not
pre-stage a tempo for a future play-music; that call
always re-reads the cart's SOND header tempo.
Sample instruments (GameTank)
GameTank carts can back an instrument with an imported PCM sample instead
of a synth voice. The instrument editor's Kind select
— Synth / Sample — only appears on
GameTank carts; SC8 has no PCM samples, so its instruments stay synth-only.
Switching Kind keeps the instrument's channel hint and resets everything
else to a fresh preset for the new kind.
Sample-kind instruments replace the ADSR + volume sliders above with three controls:
| Control | Effect |
|---|---|
| Smp | Slot picker over the cart's Samples-tab table (up to 16 slots), each option labeled with its duration. An empty table shows a hint pointing at the Samples tab; a stale reference (e.g. after a slot delete) shows a disabled placeholder plus a warning line. |
| Pitch | Base pitch, 0–127, read and written as a MIDI note number
with a live name readout next to the slider (e.g. 69 · A4). Cart-Forth triggers the sample
repitched relative to this note. |
| CH | The same channel-hint select synth instruments use, reused unchanged. |
Sample instruments are audible in-studio the same two ways as synth
instruments: the ▶ test button previews MIDI note A4
on the instrument's channel, and the transport bar's ▶ Play button plays back any pattern that references
the instrument — exactly as it will sound on /play.
Import rate (rate_code)
A sample instrument's pitch and slot live here in the Sounds tab, but the rate the underlying audio was captured at is chosen back in the Samples tab, at import time. Every import is decoded, downmixed to mono, and resampled to one of four fixed rates:
rate_code | Rate |
|---|---|
| 0 | 22050 Hz (default) |
| 1 | 11025 Hz |
| 2 | 5513 Hz |
| 3 | 44100 Hz |
A lower rate costs proportionally fewer bytes per second of audio — Samples & sample instruments covers the import pipeline, the waveform editor, and loop markers in full. The number that matters from the Sounds tab's side: all of a cart's samples must together fit in 2,048 bytes of audio-coprocessor RAM — the budget left over on native hardware after the ACP mixer firmware and its zero-page / stack pages — or a native ROM export (Export .gtr) will reject the cart. Browser playback is unaffected either way; the Samples tab surfaces this as a non-blocking warning once the total is exceeded.