A generative instrument you play by moving through a 274-genre vector space. This page walks the whole pipeline: how one point on the star map becomes a song, how the song refuses to loop, and how a machine proves every genre still sounds like itself.
Part one
HOW A SONG IS MADE — seven stages, always in this order, every random draw pulled from seeded streams so the same seed always renders the same music.
app/audio/targeting.js · weightsAt
The star map turns a point into a genre-weight blend: inverse-square distance over the ≤4 nearest anchors, plus a continuous snap-to-anchor pull scaled by how unambiguously nearest the closest star is — on a star ⇒ pure genre; between two ⇒ natural blend. Each genre neighborhood also gets its own key — the dominant genre's name hashed with the seed, mod 12 — so crossing into a new dominant genre is a key change.
engine/genre-kernel.js · resolveMulti(weights, seed)
One mulberry32(seed) stream — mulberry32 is a tiny seeded random-number generator — with a fixed draw order. Scalars (bpm, swing, humanize, fx) blend by weighted lerp (a linear blend) of each parent's [lo,hi] range, then one sample. Pools (progression, kit, form, voicing) draw one parent proportional to weight, then pick inside that parent's pool — blends combine, never smear. Grouped dimensions draw ONE parent for the whole group so a recipe and its source pool always agree.
Energy-preserving pattern inheritance: for bass and lead patterns, a parent whose pattern-pool energy is ≥1.25 rungs above the runner-up and carries weight ≥.35 takes the draw outright — a dancey parent keeps its groove against a wash-heavy neighborhood. DX7 patches sharing an FM algorithm morph by lerping their ~144-dim param vectors. Meters (3/4 waltz, compound 6/8) parent-pick and never lerp — a bar holds an integer beat count, so a blend keeps ONE parent's bar line and a journey crosses an audible meter flip, not a smear. The MUSIC-MIND axes (adventure, color, voicing, reharm, pipes, rhythm complexity) draw dead last on the same stream.
Then constrain() keeps midpoints songs: from 150 bpm up, any kit that is neither a chopped break nor a straight machine kit snaps to jungle — a declared 3/4 or 6/8 is exempt and keeps its bar line; adventure is capped at .75; a ≤2-chord progression forces reharm off; rhythm complexity is capped at .4 above 165 bpm.
engine/genre-kernel.js · toState(choice, opts)
toState applies the 8 macro sliders (acoustic, density, dust, space, bright, feel, energy, vocal — post-resolution, zero-rng, all-neutral = byte-identical no-op), then builds sections: a form graph walked by one generic interpreter, with a duration solver that lands cycle counts within ±10% of the 180 s target. Past 175 s unevolved, the 3-minute rule splits plateaus and evolves at boundaries — a key walk of +2/−3/+5, a kit or lead re-roll, or a one-time form pivot.
Sampled by default: the state ships with the SF2 sample library (108 sampled instruments, plus 114 DX7 patches), while the nine signature models — tb303, acid, reese, wobble, synclead, modeld, vocoder, hammond, hoover — stay pure synth, because a moving filter, a detune beat, a spinning Leslie or a live speech carrier is not a thing a static multisample can hold. The absent-knob law holds: if a feature wasn't chosen, the blueprint simply doesn't carry that knob — and an absent knob cannot change the output (the byte-identity law).
engine/csd-engine.js · buildEvents(state)
One function turns the state into every note. It runs in this exact order, each pass on its own seed stream:
engine/faust/voices/state-engine.js · mapEvents
The event fabric becomes per-note Faust parameter sets: freq, gain and decay everywhere; the NOTE_PARAMS whitelist maps pipe annotations to real DSP sliders only where the module exposes them (cutoffMul ⇒ cutoff/tone, vib ⇒ vibrato) and silently drops the rest. Blue-note bends render only on sampler units; sampled drums emit one-shots with real tom repitch; found sounds get an auto-tune spec and a speech-rate cap for intelligibility.
engine/faust/voices/state-engine.js · voiceUnits
Per-voice modules are picked from the synth fleet, dx7_algN cartridges and native PCM samplers — the SF2 default — with per-voice insert chains, pool-level dry/reverb/delay/ping-pong sends, and an fx bus: zita or a per-genre reverbColor module, plus a 3-band master compressor. The synth fleet and the DX7 cartridges are Faust compiled to WebAssembly; the sampled instruments are native PCM zone playback — everything mixed on one bus, live in your browser.
engine/faust/live/live.js · makeWalk
ONE authoritative walk stands behind both live output paths, and a gate
holds its per-bar output to what buildEvents would produce for
the whole song. Each call builds exactly
one chord bar — it polls the current target (retarget and glide just mutate
what it reads), reseeds seed + serial×7919 per bar while
instrument identity stays on the song seed, fills only on a section's last
cycle, sweeps only on its first and last. Two output paths: the
ring/worklet path (desktop — same voice topology ⇒ glide by
feeding bars into the running stream; a topology change ⇒ bridge stream
and equal-power crossfade) and the WAV-first path (mobile — rolling
rendered WAV segments on a real audio element, pocket-proof).
Part two
HOW A SONG EVOLVES — nothing loops verbatim, and all of it is seeded.
Per-cycle humanity. Hats drop out 9% per hit; drum levels breathe (25% of hits ±15%); a quiet ghost snare lands on an off-slot in 40% of chord bars; later cycles of a section get busier; bass notes octave-pop 5%, push late 6%, rest 5%. With the rhythm knob: per-cycle bass-cell mutation (drop, anticipate, octave-flip — hard cap 2 per cycle) and melody rhythm cells that snap phrases onto one of three rhythm grids (dotted pairs, tresillo, 3-3-2), pitch material untouched. The snare-law guarantees no snare or hat bar three-peats anywhere.
Section form. 13 form graphs — ten generative (dj, drop, wave, pop, aaba, vamp, storm, throughline, duet, suite) and three bespoke, hand-authored node for node (ritual, anthem, transit) — built from six typed nodes: ground, build, peak, release, exposed, cadence, all walked by one interpreter. Past 175 s unevolved the track MUST evolve: modulate (a cumulative +2/−3/+5 semitone key walk — the whole band, samplers included, transposes), re-roll a fresh kit and lead from the anchor's own pools, or form-pivot — which only the four club forms can do, once per track, and never into wave.
Glide and travel. While LIVE, moving the cursor queues a smooth glide — the continuous morph plus discrete voice and section flips — through the same per-bar path; the traveler walks a drawn path leg by leg, retargeting every bar. Blends interpolate every dimension including the mind axes. And arrival is a contract, not a hope: genre-identity flips (form, kit, lead) are queued first, so parked on a new genre its drums are playing within 3 bars and its kit/lead identity lands within 7 — gated by test/browser/blend-arrival.test.js.
Journeys. Waypoints are genre names or drawn points; weight vectors lerp leg by leg. Per track, the key walks the circle of fifths (+7 or +5 semitones mod 12), and a novelty memory remembers the last 2 tracks' kit/progression/bass/lead/found signature — a candidate matching ≥3 of 5 fields is rerolled, up to 6 attempts. Rendered journeys are DJ-mixed at the PCM level, every seam landing on a downbeat: a bpm gap of ≤8 gets a beatmatched 4-bar crossfade (the outgoing tail varisped to the incoming tempo — the pitch nudge a DJ makes on the fader), a gap up to 40 gets a plain 2-bar crossfade, and anything past that — or a genre that opens cold — gets a hard cut.
Part three
THE VERIFIER LOOP — how a machine keeps 274 genres honest.
Every render is measured on 23 symbolic features — bpm, off-grid feel, snare balance, hat and drum density, variation, wash, sub, motion, sevenths, break/chop/bed use, crackle, pump, compression, swing, humanize, acoustic, rubato, lead voices, soft top, interlock — and scored against 274 per-genre target rows of [lo, hi, weight] fences. The matrix renders every anchor at seeds 1, 2, 3 and requires 274/274 diagonal dominance: every genre scores highest as itself. Run after every change.
1 · Determinism. Same seed ⇒ byte-identical events; an absent knob ⇒ byte-identical output (zero rng draws). Every subsystem draws from its own seeded stream, so new dimensions draw dead last and untouched genres press byte-identically.
2 · The matrix. 274/274 diagonal-dominant after every change. If a tweak makes a genre stop sounding most like itself, the change does not land.