Skip to content

Racks: chains in lanes, macros, rigs (docs/42), and Zig 0.17 - #28

Merged
nooga merged 9 commits into
masterfrom
claude/racks
Oct 21, 2026
Merged

nooga merged 9 commits into
masterfrom
claude/racks

Conversation

@nooga

@nooga nooga commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Finishes docs/42. Racks hold lanes of chains, run eight macros with formula mappings, and ship as rigs. The build also moves to Zig 0.17.

Racks (docs/42 phases 1–6)

  • Chains in lanes. chain.State is extracted. Rack lanes hold an instrument plus up to 16 inserts. The new FX Rack runs lanes of inserts. Racks nest three deep and align per-lane latency. Rack state v2 still reads the first form, and those projects render byte-identical.
  • Macros. rk-m1..8 and rk-chain map to lane controls, level or pan through MIN/MAX and formulas (src/formula.zig), with set_mod host input. The panel adds MAP mode.
  • Panel. KEY/VEL/CHAIN zone tabs, a collapsed face (rigs open folded), MAP outlines, hand moves on a mapped control driving its macro, and drag-reordering inserts.
  • Group / ungroup. Shift-click a run of devices in the bay, then ⌘G moves it into a Rack or FX Rack along with its automation. ⌘⇧G ungroups a one-lane rack that has no mappings. With no devices selected, ⌘G still groups tracks.
  • Automation inside racks. Targets gain a path of up to 3 (lane uid, slot) steps. Files write inst/L.P:id and fx1/2.1:amp-gain.
  • Rigs. Fretwire Clean and Crunch Rig, Bass DI + Amp, Parallel Squash, and the split/layer presets rewritten as lanes. Rigs appear under a RACKS heading in the machine picker.
  • slabkit. Adds rack(), .lane(), .macro() and .map(), loads rig presets by name, and resolves automation paths into racks. slab --describe lists rack and fxrack. Demo: songs/rack_rigs.py.
  • Docs: docs/42 is now the reference. docs/19, 20 and 22 and the CHANGELOG are updated.

Zig 0.17

Testing

  • zig build test: 527/527 passed. cd fy && zig build test passed.
  • zig build bench -- --all --check --no-sheets: every golden is bit-exact. shift2, resonator2, buffer2 and phaser2 have no goldens on master either, so the check still exits 1.
  • songs/rack_rigs.py renders headless with audio on every stem, including an automation lane two racks deep.
  • Screenshots confirmed the zone tabs, collapsed face, MAP outlines and RACKS picker section. Interactive drag and ⌘G grouping are covered by unit tests but haven't been tried by hand in the app.

🤖 Generated with Claude Code

nooga and others added 9 commits October 16, 2026 23:20
…ts (docs/42)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…assets (docs/42 §Build phases 1)

chain.State holds the latest-value handoff, retirement, the audio copy
and dry lines, so rack lanes can share what tracks use. Tracks keep the
editable instrument and effects; songs render byte-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… rack state v2 (docs/42 §Build phases 2)

Each lane owns a chain.State: an instrument and up to 16 inserts in a
Rack, inserts alone in the new FX Rack (an effect, its lanes in parallel
on the input). Lanes align to the slowest one and the rack reports that
latency; tails, wakes and idle skip reach the inserts; racks nest three
deep. State is {"rack":2,...,"lanes":[...]}; the first form's parts
read as lanes, and a project with one renders byte-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nder and --stems

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tle strip (docs/42)

The selected lane's chain draws as the bay draws a track's: preset menu,
ON/BYP, replace and remove on every machine, I/O meters on inserts, + to
add one. Preset actions go through main as the bay's do; lane and insert
edits are undo steps; lane machines keep their preset names in the state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…; macro block and MAP mode (docs/42 §Build phases 3)

Racks get rk-m1..8 and rk-chain controls that automate, save and nest.
A mapping drives a lane machine's control, or the lane's level or pan,
over a range in the target's knob space through an optional formula
(src/formula.zig: postfix ops, a fixed stack, no failure at run time).
Machines take the value through set_mod, which wins over automation and
the knob and follows as a lane does; while a macro moves the rack renders
its lanes in 32-sample chunks, so a macro sweep equals the same sweep
automated on the control. Lane CHAIN zones close lanes outside them.

The panel gets the macro block: eight knobs, NAME, MAP to map a clicked
control or LV/PN, and the picked macro's mappings with MIN, MAX and f(x).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0.17 drops `b.args`, `getInstallPath`, `**` array repetition, `@cImport`,
`bufPrintZ`/`dupeZ`, `std.meta.fields`, `std.enums.values` and extern
struct `@bitCast`, and reshapes `@typeInfo` and `builtin.mode`. Arrays
fill with `@splat`; C headers are translated by the build (src/c_*.h,
fy/src/c.h); `@hasDecl` sees only pub decls, so the tune test's context
makes `tuneAt` pub. Tests (523 + fy's 82) pass, and every bench render
hashes the same under 0.16 and 0.17. Fixes #3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d automation inside racks (docs/42 §Build phases 4, 6)

The rack panel gets KEY/VEL/CHAIN zone tabs, a fold button that shows only
the named macros, MAP outlines on mappable controls, hand moves on a mapped
control that drive its macro, and drag-reordering of a lane's inserts.
Lanes carry stable uids.

Automation targets gain a path of up to three (lane uid, slot) steps under
the rack's own target; Machine.child/inner walk containers, AutoView.into
hands a nested rack its view, and files write `inst/L.P:id` positions.

Shift-click selects a run of devices in the bay; ⌘G groups it into a new
Rack or FX Rack with settings and automation moved one step down, and
⌘⇧G ungroups a one-lane rack with no mappings (src/rack_group.zig).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…scribe lists racks (docs/42 §Build phases 5)

Factory rigs: Fretwire Clean and Crunch Rig, Bass DI + Amp and Parallel
Squash (FX Rack); the first Rack's split and layer presets are rewritten
as lanes. The machine picker lists Rack and FX Rack under a RACKS heading.
`slab --describe` emits both with rk-m1..8 and rk-chain. slabkit gains
rack()/lane()/macro()/map(), rig presets by name, and automation paths
into racks; songs/rack_rigs.py demos it. docs/42 becomes the reference,
with docs/19, 20 and 22 updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nooga
nooga merged commit 68c89d6 into master Oct 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build: Zig 0.17 fails on std.Build.args despite documented 0.16-or-later support

1 participant