← Prompts

Sequencer

Read the current prompt
# Task: Build a Step Sequencer / Drum Machine

Build a 16-step drum sequencer (vanilla JS, no external assets, no CDN, no libraries) with fully synthesized instruments. The top priority is **tight, sample-accurate timing** — a sequencer that drifts or stutters is a failed sequencer.

## Core Specification

**Timing Engine (the hard part — get this right)**
- Use the **lookahead scheduling pattern**: a short-interval timer (`setInterval`/`setTimeout`, ~25ms) that schedules notes ahead of time on the Web Audio clock (`AudioContext.currentTime`, ~100ms lookahead)
- All note triggers are scheduled with `oscillator.start(t)` / `source.start(t)` at precise future times — never trigger audio directly from the timer callback or from `requestAnimationFrame`
- Scheduling must be derived from an absolute step counter and tempo — **never accumulate `currentTime += stepDuration` from a drifting origin**, and never drive timing from `setInterval` delay alone
- Consequence: playback must survive background-tab throttling gracefully (timer slows, but scheduled audio stays gapless because of the lookahead)

**Sequencer Grid**
- 16 steps × 6 instrument tracks; click a cell to toggle, drag across cells to paint/erase
- Steps grouped visually in 4s (beat separators); current step highlighted live during playback (playhead driven from the audio clock, not the timer)
- Per-step velocity: click cycles or right-click sets accent (e.g. normal / accented / off), shown visually (cell brightness or size)
- Controls: play/stop, tempo (BPM slider + numeric readout, 60–200), swing/shuffle amount (0–60%), master volume, clear pattern, random pattern

**Instruments (all synthesized with the Web Audio API — no audio files)**
- **Kick:** sine osc with fast pitch envelope (~150Hz → 50Hz) + amplitude envelope
- **Snare:** filtered noise burst + tonal body (~180Hz), snap from a highpass on the noise
- **Hi-hat (closed & open):** highpass-filtered noise, short vs. longer decay
- **Clap:** several short noise bursts in quick succession through a bandpass
- **Tom/synth stab:** pitched osc with decay — tune it musically relative to the kick
- Each instrument gets a per-track volume slider and mute button; solos optional

**Musical Feel**
- Swing delays off-beat 8th notes by the swing fraction of a step — applied in the scheduler's time calculation, not by nudging the playhead
- Velocity affects gain (and subtly, timbre — e.g. accented snare is brighter)
- Ships with one good-sounding default pattern loaded so pressing Play immediately grooves

**Persistence**
- The full pattern (steps, velocities, tempo, swing, track volumes/mutes) serializes to `localStorage` and restores on reload

## Visual Style
- Dark, hardware-drum-machine aesthetic: chunky pads, glowing active cells, an LED-style moving playhead, BPM readout
- Instrument rows labeled with icons or names; muted tracks dimmed
- Everything readable at a glance while the pattern plays

## Technical Requirements
- Vanilla JS + Web Audio API; code organized with clear section comments
- One shared `AudioContext`, created/resumed on first user gesture
- Tunable constants block at the top (BPM range, lookahead interval, schedule-ahead time, instrument patch parameters)
- No clicks/pops: envelopes must start/end at zero gain

## Quality Bar (must hit all)
- Timing is audibly rock-solid at 60 and 200 BPM — no drift, no doubled or swallowed steps
- Swing is audible and continuous from straight (0%) to hard shuffle (60%)
- The visual playhead tracks the audio exactly
- Muted tracks are silent; accents are louder; the pattern persists across reload
- Stop halts immediately; Play after Stop restarts cleanly on step 1

## Self-Check Before Finishing
Verify with the browser tools:
- Instrument the scheduler (e.g. expose scheduled step times on `window`) and probe: the delta between consecutive scheduled step times at a fixed BPM must be uniform within a small tolerance
- Toggle cells mid-playback and confirm the change is heard on the next pass
- Change BPM mid-playback — tempo shifts without glitches
- Reload and confirm the pattern, tempo, and swing are restored