Replace the pitch*127 encoding hack with a dedicated midiNote field on
pattern steps. IntervalLock now writes integer MIDI notes to step.midiNote
while preserving the original [0,1] pitch for other consumers. The clock
and sequencer bridge pass midiNote through the event pipeline.
Also reworks mergePatterns to be trigger-aware: when only one generator
fires at a step, use its values directly instead of averaging with the
other generator's defaults.
Four modules that build on the Layer 0 foundation:
- primitive.js: base class with category system (generator/processor/
timing/converter), param schema validation, boundary enforcement
(clamp/wrap/scaled), symbolic process() interface, state management
for freeze, and applyBoundary() utility for delta control
- clock.js: AudioContext lookahead scheduling (25ms interval, 100ms
window) replacing setTimeout arpeggiator. Reads pattern descriptions
for per-step swing (timeOffset) and ratchet (subdivisions). Emits
seq.noteOn/noteOff/step/loopStart via event bus.
- projection.js: composable transform chain with 5 transforms
(VelocityCurve, GateThreshold, RangeMap, OctaveFolder, StutterMap)
and 3 presets (expressive, percussive, fullRange). Pitch quantization
deliberately excluded (handled by Interval Lock primitive).
- step-viz.js: Canvas2D circular step visualizer with even angular
spacing for any step count. Pitch→radius, velocity→node size,
accent→color. 60fps-friendly with pre-allocated coordinate buffers.
Tap interaction for step toggling.