Commit Graph

13 Commits

Author SHA1 Message Date
L'électron rare 144d55a7fa feat(matrix): MD-index pinch slot = breakdown
CI build oscope-of / build-check (push) Has been cancelled
User request live: right-hand index pinch fires breakdown instead of
relanceEvolve — SC default, generator default, web defaults, the 196
presets and the test pins all updated. relanceEvolve stays in the
assignable vocabulary.
2026-07-02 21:44:40 +02:00
L'électron rare 1302ffd87a feat(matrix): deepen hand mod bindings to 0.70
CI build oscope-of / build-check (push) Has been cancelled
User request live: more audible depth on the hand X/Y mods. All 1848
lHand/rHand X/Y bindings across the 84 presets raised from 0.40-0.50
to 0.70 (per-voice editable in the web UI as before).
2026-07-02 18:44:10 +02:00
L'électron rare bcf7ac180e chore(matrix): migrate presets to new mapping
CI build oscope-of / build-check (push) Has been cancelled
Update globalActions in all 84 .matrix preset files from old
default to: [\fill, \doubleTime, \washReverb, \muteDrums,
\relanceEvolve, \halfTime, \next, \muteMelo].
2026-07-02 14:56:50 +02:00
L'électron rare 65c06ed4c6 feat(presets): emit default fist threshold
Context: Task 1 wired fistThresh into the SC matrix engine (default
0.15); the generator was not yet emitting this field, so every
.matrix was missing it and the engine fell back to its hardcoded
default.

Approach: TDD — added a failing check to test_global_actions.py,
then edited to_sc so pinchHoldMs ends with a comma and fistThresh
0.15 follows as the last field before the closing paren.
Regenerated 84 presets twice for determinism.

Changes:
- generate_presets.py: pinchHoldMs now ends with comma; fistThresh
  0.15 emitted as the final key in every preset's SC Event literal
- test_global_actions.py: EXPECT_FTH block checks to_sc output and
  all 84 on-disk .matrix files
- *.matrix (84 files): regenerated with fistThresh field

Impact: all four gates green (GLOBALACT-PY, test_sections,
test_families, GLOBALACT SC); fistThresh is now a first-class
preset field readable at load time by ~matLoadFile.
2026-06-30 16:50:02 +02:00
L'électron rare 2ced4e728f feat(presets): emit default pinch hold ms
Add top-level 'pinchHoldMs': 300 to every generated .matrix so the SC
engine (Task 2) reads it instead of its hardcoded default.

- generate_presets.py: globalSettings ends with ',' and
  'pinchHoldMs': 300 is the last field before the closing ')'
- test_global_actions.py: EXPECT_PHMS check added (TDD red then green)
- 84 .matrix files regenerated (28 morceaux x intro/live/outro)
2026-06-30 16:01:59 +02:00
L'électron rare 9590615069 feat(presets): 8 pinch actions, trim settings
Expand globalActions from 4 to 8 slots:
[\fill, \drop, \breakdown, \evolve,
 \muteDrums, \muteMelo, \washReverb, \next]

Drop openThresh/closeThresh from globalSettings (now
engine-side constants via Task 1). Regenerate all 84
.matrix files deterministically.

All gates: GLOBALACT-PY PASS, TEST PASS x2, GLOBALACT PASS
2026-06-30 14:56:50 +02:00
L'électron rare 8bead14e23 feat(presets): emit default global settings
Context: Phase 2 Task 1 made the SC engine load a globalSettings Event
from .matrix files (openThresh/closeThresh/transientBars/breakdownKeep)
and default it when absent. Generator was not yet writing the field.

Approach: append globalSettings after globalActions in to_sc() return
string; extend test_global_actions.py with EXPECT_SET check against
both the to_sc sample and all 84 .matrix files on disk.

Changes:
- generate_presets.py: to_sc now ends with globalActions (comma) then
  globalSettings Event with default values matching SC defaults
- test_global_actions.py: add EXPECT_SET literal + two check() calls
- *.matrix (84 files): each preset now carries the globalSettings field

Impact: every preset ships with openThresh/closeThresh/transientBars/
breakdownKeep defaults; SC engine reads them on load; no more implicit
fallback needed at runtime for any preset in the library.
2026-06-30 13:36:00 +02:00
L'électron rare 50e9e79a22 feat(presets): emit default global actions mapping
Context: SC engine (Task 2) loads 'globalActions' from .matrix files
and defaults to [\fill, \drop, \evolve, \breakdown] when absent.
Generated presets did not write this field, causing implicit reliance
on the engine default.

Approach: extend to_sc() return string to include the globalActions
key so every preset explicitly carries the default mapping
(LH-open=fill, LH-closed=drop, RH-open=evolve, RH-closed=breakdown).

Changes:
- generate_presets.py: add 'globalActions' line in to_sc() return
- test_global_actions.py: new Python test verifying to_sc() output
  and all 84 on-disk .matrix files carry the field
- 84 .matrix files: regenerated with globalActions field present

Impact: presets are self-documenting; SC engine reads the explicit
value rather than applying a silent default.
2026-06-30 11:50:51 +02:00
L'électron rare 8dde561c34 feat(presets): per-style variation in live loop
CI build oscope-of / build-check (push) Has been cancelled
The live loop tiled the plateau into 4 identical blocks -- full but static.
LIVE_STYLE maps each morceau to a style group; LIVE_VAR holds per-style
profiles; _live_variation recolours active cells in some 16-bar blocks
(rhythmic 2/4, melodic 3 octave) and adds phrase-end fills (colour 6) so the
full loop breathes in a genre-appropriate way -- techno double-time hats +
fills, breaks snare rolls, ambient gentle bell octaves, etc. Active cells
only -> density unchanged, no voice dropped, no intro/breakdown back.

test_sections asserts the live still has no intro/breakdown AND varies (not
4 identical blocks). Regen 84 deterministic, VALIDATE 84/84 + DEFAULTS PASS.
2026-06-30 10:27:05 +02:00
L'électron rare db8d7d465f feat(presets): live = continuous full loop
CI build oscope-of / build-check (push) Has been cancelled
Each morceau's _live section reused the standalone arc, which re-introduced
(near-empty intro -> rebuild -> plateau -> breakdown). Now make_live_continuous
tiles the plateau (P, bars 32-47) across all 64 bars: full groove from bar 0,
no intro ramp, no breakdown -- a clean loop the _intro builds to and the
_outro descends from. Applied post-apply_colors for the live section only via
to_sc(post=); intro/outro unchanged.

test_sections asserts the live is full-from-start + has no breakdown dip.
Regen 84 deterministic, VALIDATE 84/84 + DEFAULTS PASS, test_families PASS.
2026-06-30 10:03:16 +02:00
L'électron rare 5def521587 fix(presets): remove default pose->voice triggers
CI build oscope-of / build-check (push) Has been cancelled
The SP-A default bound danse->gate on the fx and sweep voices, so the
action-head classifying the dancer as "danse" toggled those voices on/off
even with no fx/sweep cells in the grid -- poses triggering FX that the
user never placed. Pose->voice triggers are now opt-in (default_poses
returns []); continuous pose modulation (default_mods) is unchanged.

Updated test_default_mods.py + the validate_presets DEFAULTS assertion
(fx voicePoses now expected empty). Regenerated 84 presets. VALIDATE
84/84 + DEFAULTS PASS; test_families + test_sections PASS.
2026-06-30 09:48:21 +02:00
L'électron rare 4c7d960b45 feat(presets): wire families + live default
Wire the hand-authored families into the 84 presets and make the launcher
boot the live section.

Changes:
- patterns_for: strip the _intro/_live/_outro suffix before the
  PRESET_FAMILY lookup, so all 84 section presets resolve to their
  morceau's family.
- PRESET_FAMILY: retarget mel families to the new banks where they fit -
  house (detroit/rave/trance/melodic/electro), psy (hypnotic/psytrance/
  minimal), dub (dub_techno/melodic_deep), ambient (ambient_intro); drum
  families now style ride/shaker/clap/perc per dfam.
- launch_concert.sh: MATRIX_PRESET default -> techno_drive_live.

Impact: genre presets now use the authored families. test_families PASS,
test_sections PASS, regen deterministic, VALIDATE PASS 84/84.
2026-06-30 00:20:19 +02:00
L'électron rare 1090f2c223 feat(presets): 56 intro/outro arcs
Hand-write the intro and outro arc for each of the 28 morceaux (56 new
independent arc functions). intro = voices enter across the 64 bars
(sparse->full, capped at the plateau with a light O lead-in into live);
outro = voices exit (full early, dropping out toward the break/outro).

Approach:
- one arc_intro_<m> / arc_outro_<m> per morceau, registered in
  INTRO_ARCS/OUTRO_ARCS; composed from the primitive fill/hit grid API
  over the I/B/R/D/P/K/O section codes.
- the 7 breaks morceaux share a _breaks_intro/_breaks_outro shape
  parameterized per morceau (deviation from "fully independent" - flagged
  for review).
- test_sections.py gate: intro builds, outro breaks down, live densest -
  all 28 PASS.

Impact: 84 presets regenerated, VALIDATE PASS 84/84. Section feel is
shape-correct; musical review by ear pending.
2026-06-30 00:17:51 +02:00