# Split kit and keys, three new keys generators 2026-10-11. Status: draft for review. ## Goal Drums and keys each run their own generator, picked on their own page. One seed still drives both. ROLL KIT and ROLL KEYS re-roll one half. The change ships with three new keys generators: 303, TURING and ARP. Further generators get their own small specs. ## Decisions | Question | Answer | |---|---| | Seeds | One seed, as now. ROLL KIT / ROLL KEYS re-roll one half through its salt. | | What's separate | The generator menu and the seed-driven choices. ENERGY and DRIFT stay shared. | | Coupling | Stays. Keys see the bar's kit (bass can lock to kicks). Bar length, form and swing are shared. | | Naming | "LINE" becomes "KEYS" everywhere the user sees it: ROLL shows KIT / KEYS, NEW KEYS. | | 303 slides | A legato overlap only, no CCs. Audible glide depends on the synth's settings. | | Old data | None kept. The seeds' sound changes, the vectors are regenerated, and the flash record goes to v3. | ## Engine structure (`sim/engine.js`, then `firmware/engine/engine.c`) `genome(seed)` is split into three parts, each with its own RNG stream. | Part | Seeded by | Renewed by | Fields | |---|---|---|---| | shared | seed | SEED | steps, form, swing, layback, arc, fillP, rot | | kit | seed + salt 0 | SEED, ROLL KIT | dens[0], frame, accentCycle, freeK, freeRot | | keys | seed + salt 1 | SEED, ROLL KEYS | scale, root (AUTO), prog, motifLen, hocket, bassDeg, monoLen, monoRange, dens[1] | - `renderBar(st, p, bar)`: 1. builds the shared part; 2. runs the kit generator `p.gen` (unchanged list); 3. runs the keys generator `p.keys`. - The key override (`applyKey`) applies to the keys part. - AMENIZER still forces 16 straight steps on the whole bar. - Every keys generator has one signature. It receives: - the keys seed and phrase variant; - the shared and keys parts; - steps, section and bar position; - the bar's sorted kit events; - the fill flag; - ENERGY / DRIFT; - the absolute bar index. It returns `{bass, mel, pad}` lists of `{t, v, vel, tr}`, each with an optional `len`. Without `len`, today's note-length rules apply. MEL notes carry `tr` MEL A or MEL B. - In the outputs, groove, nudge, swing, the melody shift and the perc phase offset stay as they are and apply to every generator. - In C, `sb_params` gains `keys`. `describe()` names the keys generator. ## Keys generators (KEYS GEN, menu order) The chord is the bar's chord degree from `prog`, in the current scale. | # | Name | BASS | MEL A / B | PAD | |---|---|---|---|---| | 0 | MOTIF | Today's: the chord root on kicks, the colour tone on alternate kicks, an approach note | Today's motif and answer, hocket split | Today's: the bar's triad | | 1 | 303 | Acid line (below) | Short answers in the bass gaps | Silence or a root drone | | 2 | TURING | Roots, gated by the shift register | The register's melody, hocket split | Chord held | | 3 | ARP | The chord root on every kick | Arpeggio, alternating A / B | The arpeggio's chord | ### 303 - **Pattern:** 16 steps, from the keys seed, looped across the bar (wrapped or cut for 12/14/20 steps). Each step has: - a gate; - a degree offset (mostly 0; sometimes the 3rd, 5th or 7th in scale steps); - accent, slide and octave flags. - **Pitch:** the bar's chord root plus the step's offset, in the bass register (36–47). The octave flag adds +12. - **Accent:** velocity ~120. Other notes ~80. - **Slide:** `len` reaches 20 ticks into the next note (an overlap). - **ENERGY:** how many gated steps sound. - **DRIFT:** the chance that a phrase variant flips some gates and flags. - **Melody:** 1–2 note answers on chord tones, only where the bass rests for ≥ 2 steps. Short and alternating A / B. - **Pad:** the keys seed picks silence or a drone on the key's root (C3–B3), held all bar. *Guess: 50/50.* ### TURING - **Register:** 8 or 16 bits (from the keys seed). It rotates one bit per 16th. - **Flips:** at each step the wrapped bit may flip. The chance follows DRIFT: 0 locks the loop. Whether absolute step k flips is decided by a hash of (keys seed, k), so a flip is the same event however we get there. - **Window:** the register at a bar's start is rebuilt from the base register over the last 16 bars of steps. Flips stick for 16 bars and then fall away. The cost per bar is fixed, and any bar can be rendered on its own (start, the Pico's render-ahead). - **Melody:** the register's value scaled to a scale degree over 1–2 octaves (`monoRange`), with the existing hocket split. ENERGY thins notes out (`dens[1]`). - **Bass:** the chord root on steps where bit 0 is set. *Guess: another bit picks the root's octave.* - **Pad:** the bar's triad, held (as MOTIF). ### ARP - **Chord:** a triad or 7th (from the keys seed). The degrees are c, c+2, c+4 (+ c+6). - **Direction (keys seed):** up, down, up-down, or a fixed shuffle. **Range:** 1–2 octaves (`monoRange`). - **Rate:** 8ths at low ENERGY, 16ths at high. Notes alternate MEL A / MEL B. - **Bass:** the chord root on every kick, with no colour tone. - **Pad:** the same chord as the arpeggio (adds the 7th when the arp has it). ## Panel (firmware `app/main.c`, simulator `app.js`) - Pages: SEED · KIT GEN · KEYS GEN · ROOT · SCALE · BPM · SLOT · ROLL · LEARN. - KIT GEN is today's GEN (label `KIT GEN`). KEYS GEN cycles MOTIF, 303, TURING, ARP (label `KEYS GEN`). - ROLL shows KIT / KEYS. The message is NEW KIT / NEW KEYS. - A generator change is heard from the next bar. - Slots store the seed, salts, kit gen and keys gen. ROOT / SCALE stay global (as before). - On AUTO, ROOT / SCALE show the keys part's pick (it changes with ROLL KEYS). ## Storage - `live_t` and the flash record gain `keys`. The record goes to version 3, and old records are ignored. - The simulator stores `keys` in localStorage. Its slots gain `keys`. ## Vectors - Run `npm run vectors`. The commit message says it's an intended music change. - Cases gain `keys`. The main grid crosses the kit gens with all four keys gens, at fewer energy/drift sets so the count stays sane. - Extra cases: - ROLL KEYS (salt 1) changes `prog`, and ROLL KIT doesn't; - TURING at drift 0 repeats exactly; - TURING at bar ≥ 16 (the window); - 303 with 12- and 20-step bars; - ARP with a 7th chord. - `primitives.json` genomes become the three parts. - `firmware/bringup` golden checksums are updated. ## Docs - `docs/controls.md`: the pages table (KIT GEN, KEYS GEN, ROLL KIT/KEYS). - `docs/concept.md`: - the genome split table; - a keys generators section (the table above, in short); - "LINE" becomes "keys". - `docs/decisions.md`: one line each on one seed with per-half ROLL, and on the overlap-only slide. ## Testing 1. `npm test` and `cd firmware/test && make test` pass. 2. Listening in the simulator: each keys generator over two or three kit gens and seeds. 3. Bench: - ROLL KEYS brings new chords and leaves the drums alone; - ROLL KIT leaves the keys alone; - KEYS GEN switches at the next bar; - 303 slides overlap on the synth.