Sequencer — live coded
In the spirit of TidalCycles and Sonic Pi: rhythms and melodies are vectors of data in Clojure. Edit the source, the grid and the drum machine update. Companion to the subtractive synth demo.
A 16-step, 4-track step sequencer. Three percussion tracks
(kick / snare / hat) plus a melody line whose pitches come from
the cljrs.music library — try changing the scale
from :minor to :dorian or
:pentatonic and watch the melody re-harmonize on
the next bar. Web Audio handles sample-accurate scheduling; the
cljrs runtime owns the score, and the entire grid below is
rendered by cljrs.ui from the source.
Hold Alt (or Ctrl) and drag any number — try
BPM — to scrub it live. Press
Cmd/Ctrl+Enter to apply
immediately. Click a cell to toggle; click Randomize melody
to regenerate the melody from the current scale.
Click any cell to toggle. Pick a melody preset to re-voice the melody line. Reverb / delay sends live to the right.
What's happening
- The Clojure source defines the score (BPM + four 16-element vectors) and the entire control panel as a
cljrs.uihiccup tree. Editing the file re-evals it, then(boot)re-mounts the panel — Preact diffs against the live DOM. - Click any kick/snare/hat cell to toggle that step; Randomize melody picks fresh notes from the current
(cljrs.music/scale ROOT SCALE)using a deterministic LCG (norandin cljrs yet). The kick/snare/hat randomize buttons each have their own density default. - Web Audio scheduling: a setInterval-driven lookahead walks the next ~100 ms of steps and queues drum hits / oscillator notes with
audioCtx.currentTime, the standard Chris Wilson scheduling pattern. The cljrs interpreter is fast enough for per-frame logic but sample-accurate timing belongs in the audio thread. - The playhead column is just
(reset! STEP n)from JS once per audio step — cljrs.ui re-renders to highlight the current column.