Commit graph

3 commits

Author SHA1 Message Date
Me Here
9701f49913 Firmware: parse euclid, GM note-numbers, and unknown-sound fallback
Close three real parser divergences the conformance suite flagged on the device
side (pico-cp + pico-explorer) — cases where the firmware produced a different
groove/sound than the web for the same patch:

- Euclidean (k,n,rot) shorthand (e.g. kick:4(3,8)) — was silently dropped to a
  plain bar; now expands to the same hits as engine.js (added _euclid + parsing).
- GM note-number lane sounds (e.g. 36:4) — now resolve to the voice name (GM_NUM).
- Unknown sound names fall back to beep, matching the web.

vol/cd are NOT carried by the firmware by design: they are web-authoring fields
(the device has a hardware volume knob and no count-in). Documented as an
intentional, permanent host difference rather than a bug; the vol-and-countin
vector stays as expectFail[py] to mark the boundary.

tests/adapters/py_adapter.py: extract the new SOUND_GM/GM_NUM/_euclid nodes.
fixtures: euclid/unknown-sound/gm-note-number now pass on both engines.
docs §6 updated. node tests/run.mjs: 33 pass / 9 known, round-trips stable.
pico-explorer parser spot-checked identical to pico-cp.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 00:15:25 -05:00
Me Here
bf74c860e5 Track format: unify default (no-pattern) groove across web + firmware
A lane with no =pattern produced different defaults on web vs device — a real,
shipped divergence the new conformance suite caught (e.g. hatClosed:4/2 in
"Four-on-the-floor" played steady 8ths in the browser but quarter-notes on the
device). Adopt one rule everywhere: every subdivision sounds at normal level,
accents fall ONLY on group starts (the grouping is the accent map).

- pico-cp/app.py, pico-explorer/app.py: off-beat subdivisions sound at normal (1)
  instead of resting (0); group-start accenting was already correct.
- src/engine.js: default beatsOn accents group starts only (was: every beat);
  laneCfgToStr isDefault check updated to match so round-trips stay idempotent.
- docs + fixtures: document the rule; default-pattern vectors now pass on both.

Audible effect (intended): device subdivided hat/ride lanes gain their off-beat
strokes (now match the web); web stops over-accenting every beat. Lanes with an
explicit =pattern are unchanged. Verified green via node tests/run.mjs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 00:03:34 -05:00
Me Here
754ed1c22d Formalize track format: spec + golden-vector conformance suite
Single source of truth for the track ("program"/"patch") grammar, which was
implemented by hand in src/engine.js and pico-cp/app.py with no cross-check and
had quietly drifted.

- docs/track-format.md: formal grammar, container (programs.json) schema with a
  version field, the new per-track playback-flow model (rep/end + relative goto;
  default = loop forever), normalization rules, and a list of known divergences.
- tests/: golden vectors + a runner that loads the REAL engine.js and app.py
  grammar (no copies; app.py via ast extraction) and compares both against the
  spec. Exit non-zero on unexpected mismatch or round-trip break -> usable as CI.

Surfaces real divergences for follow-up: default accent pattern (no =pattern)
differs web vs device and affects shipped presets; euclid not parsed on device;
vol/cd dropped on device; unknown-sound fallback; tempo clamp; empty patch.
The rep/end playback-flow vectors are the acceptance test for building that.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 23:54:20 -05:00