Summary
Add a small modulation matrix: 2–3 assignable LFOs that can be routed to part parameters and ridden automatically. The README already wishes for "a really slow LFO on a Part's position" — this generalises that into a first-class, seed-deterministic modulation layer.
Why it fits
Modular Riffs already has the intensity envelope (a per-bar energy curve), but no free, cyclic modulators. Slow LFOs on octave, gate length, density, or arp position are what make a patch breathe over minutes — the difference between a loop and a living jam — and they're idiomatic to the gear the app is driving.
Proposed scope
New module js/modmatrix.js
- 2–3 LFO sources, each with: shape (sine / ramp / saw / square / random / sample-&-hold), rate (tempo-synced in beats, or free in seconds), depth, and probability (a % chance the modulation applies on each evaluation — controlled chaos).
- Fully driven by the existing seeded PRNG so a seed reproduces the ride exactly.
Destinations (read points in js/generator.js / js/intensity.js)
- Per part: octave, gate length, density / Activity, arp position / register.
- Global (optional): Energy, Swing.
- Evaluate modulators once per step/bar in the generation path; clamp to each destination's valid range.
UI (js/app.js, maybe js/timeline.js)
- A compact matrix: rows = LFOs, columns = shape / rate / depth / probability + a destination picker. Optionally draw the active LFOs as faint moving lines on the timeline so the modulation is visible.
- Persist in
state (rides presets / export).
Where
New js/modmatrix.js; hooks in js/generator.js (apply at read points), js/app.js (UI + state), optional js/timeline.js (viz).
Done when
Open questions
- Bipolar vs unipolar per destination (octave wants bipolar, gate wants unipolar)?
- Should a modulator be allowed to target Evolve, or keep mutation separate from modulation?
Summary
Add a small modulation matrix: 2–3 assignable LFOs that can be routed to part parameters and ridden automatically. The README already wishes for "a really slow LFO on a Part's position" — this generalises that into a first-class, seed-deterministic modulation layer.
Why it fits
Modular Riffs already has the intensity envelope (a per-bar energy curve), but no free, cyclic modulators. Slow LFOs on octave, gate length, density, or arp position are what make a patch breathe over minutes — the difference between a loop and a living jam — and they're idiomatic to the gear the app is driving.
Proposed scope
New module
js/modmatrix.jsDestinations (read points in
js/generator.js/js/intensity.js)UI (
js/app.js, maybejs/timeline.js)state(rides presets / export).Where
New
js/modmatrix.js; hooks injs/generator.js(apply at read points),js/app.js(UI + state), optionaljs/timeline.js(viz).Done when
Open questions