Split kit and keys; KEYS GEN with MOTIF, 303, TURING, ARP
Some checks failed
check / check (push) Has been cancelled
Some checks failed
check / check (push) Has been cancelled
- genome(seed, salts) now has three parts with their own RNG streams: shared (steps, form, swing, arc, layback, fill odds, phase offset), kit (density, frame, accent cycle, free snare) and keys (scale/root, progression, motif, hocket, bass tone, note lengths, range). ROLL KEYS now renews the harmony too; ROLL KIT leaves the keys alone. - Keys generators share one signature and can fix note lengths: MOTIF (the old line), 303 (acid bass, answers in the rests, drone or silent pad), TURING (8/16-bit shift register, DRIFT flips bits, 16-bar window), ARP (triad/7th arpeggio, roots on kicks). - Pages: KIT GEN, KEYS GEN; ROLL shows KIT / KEYS; slots keep both gens. - Flash record v3 (old settings ignored). Bring-up golden checksums updated. - C port matches; host test and ASan/UBSan pass. Intended music change: every seed sounds different (genome split, new generators). Vectors regenerated with npm run vectors; the case grid now crosses all kit and keys generators, with TURING runs past its window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,14 +5,14 @@
|
||||
#include <string.h>
|
||||
|
||||
#define MAGIC 0x53425831u /* "SBX1" */
|
||||
#define VERSION 2 /* 2: ROOT / SCALE added, BANK gone. Older records are ignored. */
|
||||
#define VERSION 3 /* 3: KEYS GEN. Older records are ignored. */
|
||||
#define OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
|
||||
#define BUFSZ 512
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic, version;
|
||||
uint32_t seed, salts[2];
|
||||
int32_t gen, bpm, scale, root, mono_ch, mono_oct;
|
||||
int32_t gen, keys, bpm, scale, root, mono_ch, mono_oct;
|
||||
uint8_t on[SB_NT];
|
||||
pad_t learn[NKIT];
|
||||
slot_t slots[NSLOTS];
|
||||
@@ -33,7 +33,7 @@ void storage_defaults(live_t *L, slot_t *slots){
|
||||
int t;
|
||||
memset(L, 0, sizeof *L);
|
||||
L->state.seed = 0x5EEDB0C5u;
|
||||
L->gen = 0; L->scale = -1; L->root = -1; L->energy = 64; L->drift = 32; L->bpm = 165;
|
||||
L->gen = 0; L->keys = 0; L->scale = -1; L->root = -1; L->energy = 64; L->drift = 32; L->bpm = 165;
|
||||
for(t = 0; t < SB_NT; t++) L->on[t] = 1;
|
||||
L->mono_ch = 1; L->mono_oct = 0; L->clock = 1;
|
||||
memset(slots, 0, sizeof(slot_t) * NSLOTS);
|
||||
@@ -45,7 +45,7 @@ int storage_load(live_t *L, slot_t *slots){
|
||||
storage_defaults(L, slots);
|
||||
if(r->magic != MAGIC || r->version != VERSION || r->crc != crc(r)) return 0;
|
||||
L->state.seed = r->seed; L->state.salts[0] = r->salts[0]; L->state.salts[1] = r->salts[1];
|
||||
L->gen = r->gen; L->bpm = r->bpm; L->scale = r->scale; L->root = r->root; L->mono_ch = r->mono_ch; L->mono_oct = r->mono_oct;
|
||||
L->gen = r->gen; L->keys = r->keys; L->bpm = r->bpm; L->scale = r->scale; L->root = r->root; L->mono_ch = r->mono_ch; L->mono_oct = r->mono_oct;
|
||||
for(t = 0; t < SB_NT; t++) L->on[t] = r->on[t] ? 1 : 0;
|
||||
memcpy(L->learn, r->learn, sizeof L->learn);
|
||||
memcpy(slots, r->slots, sizeof r->slots);
|
||||
@@ -64,7 +64,7 @@ int storage_save(const live_t *L, const slot_t *slots){
|
||||
memset(r, 0, sizeof *r);
|
||||
r->magic = MAGIC; r->version = VERSION;
|
||||
r->seed = L->state.seed; r->salts[0] = L->state.salts[0]; r->salts[1] = L->state.salts[1];
|
||||
r->gen = L->gen; r->bpm = L->bpm; r->scale = L->scale; r->root = L->root; r->mono_ch = L->mono_ch; r->mono_oct = L->mono_oct;
|
||||
r->gen = L->gen; r->keys = L->keys; r->bpm = L->bpm; r->scale = L->scale; r->root = L->root; r->mono_ch = L->mono_ch; r->mono_oct = L->mono_oct;
|
||||
memcpy(r->on, L->on, sizeof r->on);
|
||||
memcpy(r->learn, L->learn, sizeof r->learn);
|
||||
memcpy(r->slots, slots, sizeof r->slots);
|
||||
|
||||
Reference in New Issue
Block a user