Files
seedbox/firmware/engine/engine.h
Gee 2196633ed5
Some checks failed
check / check (push) Has been cancelled
Seedbox v0.1 + firmware, generic kit/synth, ROOT/SCALE pages
First commit of the repo. Contents beyond the v0.1 simulator and layout:

- Full Pico 2 W firmware (firmware/app, drivers, engine port, host test).
- BANK page and 404 mode A/B removed; learned pads play exactly what was learned.
- 404/MiniFreak renamed to KIT/SYNTH throughout (jacks, code, sim, docs,
  layout labels; wiring rebuilt).
- ROLL returns to page select after a re-roll; a freshly learned track turns on.
- LCD contrast 66.
- ROOT and SCALE pages: 21 scales, AUTO = the seed picks; global and sticky.

Intended music change: the scale table grew from 8 to 21 and AUTO picks from
all of them, so every seed's scale changed. Vectors regenerated with
npm run vectors, plus new key-override cases. Flash record is now version 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:39:36 +03:00

68 lines
2.7 KiB
C

/* Seedbox engine: C port of sim/engine.js. Portable C99, no SDK, no allocation, integer-only.
sim/engine.js is the reference; this file must reproduce test/vectors bit for bit.
Not reentrant: render from one core only (scratch buffers are static). */
#ifndef SEEDBOX_ENGINE_H
#define SEEDBOX_ENGINE_H
#include <stdint.h>
#define SB_TPB 840 /* ticks per quarter */
#define SB_TPS 210 /* ticks per 16th */
#define SB_CLOCK_TICKS 35 /* MIDI clock every 35 ticks */
#define SB_PHRASE_BARS 4
#define SB_NT 11 /* tracks */
#define SB_NSCALES 21
#define SB_MAX_EVENTS 128 /* per bar and per scratch list; the vectors peak at 54 */
enum { SB_T_KICK, SB_T_KICK2, SB_T_SNARE, SB_T_GHOST, SB_T_HAT, SB_T_HAT16, SB_T_PERC,
SB_T_BASS, SB_T_MELA, SB_T_MELB, SB_T_PAD };
enum { SB_GEN_EUCLID, SB_GEN_SKELETON, SB_GEN_SUBDIV, SB_GEN_AUTOMATA, SB_GEN_AMENIZER, SB_NGEN };
/* hash and RNG */
uint32_t sb_mix(uint32_t a, uint32_t b);
typedef struct { uint32_t s; } sb_rng;
void sb_rng_init(sb_rng *r, uint32_t seed);
uint32_t sb_rng_next(sb_rng *r);
int sb_rng_below(sb_rng *r, int n);
int sb_rng_chance(sb_rng *r, int p);
/* genome: field names follow engine.js */
typedef struct {
int steps;
int form_idx; /* index into FORMS; form[] is a copy */
int form[4];
int scale, root;
int dens[2];
int fillP, monoLen, monoRange, rot, hocket, bassDeg;
int prog_idx; /* index into PROGS; prog[] is a copy */
int prog[4];
int swing, arc, motifLen, accentCycle, layback, frame, freeK, freeRot;
} sb_genome;
void sb_genome_make(uint32_t seed, sb_genome *g);
const char *sb_form_name(int form_idx);
typedef struct { uint32_t seed; uint32_t salts[2]; } sb_state;
typedef struct { int gen, energy, drift, fill, scale, root; } sb_params; /* scale, root: -1 = AUTO (the seed picks) */
/* one output row: [t, lane, v, vel, len, tr] */
typedef struct { int16_t t, len; uint8_t lane, v, vel, tr; } sb_event;
typedef struct {
int bar, pos, phrase, sec, fill, variants[2], barTicks, steps;
int overflow; /* nonzero if any list hit SB_MAX_EVENTS (should never happen) */
int n;
sb_event ev[SB_MAX_EVENTS];
} sb_bar;
/* ROOT / SCALE pages: overrides the genome's scale and root when they're >= 0 (app.js applyKey). */
void sb_apply_key(sb_genome *g, const sb_params *p);
const char *sb_scale_name(int scale); /* screen name, at most 10 characters */
void sb_render_bar(const sb_state *st, const sb_params *p, int bar, sb_bar *out);
/* FNV-1a over rows, each field & 0xFFFF. Feed a whole case's events in order, starting from SB_FNV_INIT. */
#define SB_FNV_INIT 0x811C9DC5u
uint32_t sb_checksum_event(uint32_t h, const sb_event *e);
#endif