dreamstack/examples/step-sequencer.ds
enzotar 62830fa82a fix: for-in parser token mismatch + enhanced step sequencer
- Fix for...in parser: TokenKind::In → TokenKind::InKw (was using wrong token)
- Remove dead In variant from TokenKind enum
- Fix pre-existing test: When pattern match 2→3 fields
- Enhanced step-sequencer.ds: 16 steps, 4 instrument arrays, play/pause,
  BPM controls with limits, presets, dynamic variants, streaming output
- All 118 tests pass
2026-02-26 23:42:29 -08:00

109 lines
4.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- DreamStack Step Sequencer
-- Collaborative beat grid: two tabs, same pads, real-time sync
--
-- Run:
-- Tab 1: cargo run -p ds-stream (relay)
-- Tab 2: dreamstack dev examples/step-sequencer.ds (player 1)
-- Tab 3: dreamstack dev examples/step-sequencer.ds --port 3001 (player 2)
let bpm = 120
let step = 0
let playing = 1
-- 4 instruments × 16 steps = 64 pads
let kick = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
let snare = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
let hihat = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
let bass = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-- Playhead advances every beat (8th note = 60000 / bpm / 2)
every (60000 / bpm / 2) -> step = if playing then (step + 1) % 16 else step
-- Stream for multiplayer collaboration
stream beats on "ws://localhost:9100/peer/beats" {
mode: signal,
output: bpm, step, playing, kick, snare, hihat, bass
}
view beats =
column [
text "🎹 DreamStack Beats" { variant: "title" }
text "Collaborative step sequencer — synced via bitstream relay" { variant: "subtitle" }
-- Transport controls
row [
button (if playing then "⏸ Pause" else "▶ Play") {
click: playing = if playing then 0 else 1,
variant: "primary"
}
button "⏮ Reset" {
click: step = 0,
variant: "ghost"
}
text "BPM: {bpm}" { variant: "caption" }
button "" { click: bpm = if bpm > 40 then bpm - 10 else bpm, variant: "secondary" }
button "+" { click: bpm = if bpm < 300 then bpm + 10 else bpm, variant: "secondary" }
]
-- Playhead indicator
row [
text " " { variant: "muted" }
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ->
text (if i == step then "▼" else "·") { variant: "muted" }
]
-- Kick row
row [
text "KICK " { variant: "caption" }
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ->
button (if kick[i] then "●" else "○") {
click: kick[i] = if kick[i] then 0 else 1,
variant: (if kick[i] then "primary" else "secondary")
}
]
-- Snare row
row [
text "SNRE " { variant: "caption" }
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ->
button (if snare[i] then "●" else "○") {
click: snare[i] = if snare[i] then 0 else 1,
variant: (if snare[i] then "primary" else "secondary")
}
]
-- HiHat row
row [
text "HHAT " { variant: "caption" }
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ->
button (if hihat[i] then "●" else "○") {
click: hihat[i] = if hihat[i] then 0 else 1,
variant: (if hihat[i] then "primary" else "secondary")
}
]
-- Bass row
row [
text "BASS " { variant: "caption" }
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ->
button (if bass[i] then "●" else "○") {
click: bass[i] = if bass[i] then 0 else 1,
variant: (if bass[i] then "primary" else "secondary")
}
]
-- Presets
text "Presets" { variant: "caption" }
row [
button "Four on the Floor" {
click: kick[0] = 1; kick[4] = 1; kick[8] = 1; kick[12] = 1; snare[4] = 1; snare[12] = 1; hihat[0] = 1; hihat[2] = 1; hihat[4] = 1; hihat[6] = 1; hihat[8] = 1; hihat[10] = 1; hihat[12] = 1; hihat[14] = 1,
variant: "ghost"
}
button "Clear All" {
click: kick[0] = 0; kick[1] = 0; kick[2] = 0; kick[3] = 0; kick[4] = 0; kick[5] = 0; kick[6] = 0; kick[7] = 0; kick[8] = 0; kick[9] = 0; kick[10] = 0; kick[11] = 0; kick[12] = 0; kick[13] = 0; kick[14] = 0; kick[15] = 0; snare[0] = 0; snare[1] = 0; snare[2] = 0; snare[3] = 0; snare[4] = 0; snare[5] = 0; snare[6] = 0; snare[7] = 0; snare[8] = 0; snare[9] = 0; snare[10] = 0; snare[11] = 0; snare[12] = 0; snare[13] = 0; snare[14] = 0; snare[15] = 0; hihat[0] = 0; hihat[1] = 0; hihat[2] = 0; hihat[3] = 0; hihat[4] = 0; hihat[5] = 0; hihat[6] = 0; hihat[7] = 0; hihat[8] = 0; hihat[9] = 0; hihat[10] = 0; hihat[11] = 0; hihat[12] = 0; hihat[13] = 0; hihat[14] = 0; hihat[15] = 0; bass[0] = 0; bass[1] = 0; bass[2] = 0; bass[3] = 0; bass[4] = 0; bass[5] = 0; bass[6] = 0; bass[7] = 0; bass[8] = 0; bass[9] = 0; bass[10] = 0; bass[11] = 0; bass[12] = 0; bass[13] = 0; bass[14] = 0; bass[15] = 0,
variant: "destructive"
}
]
text "🔴 Streaming via ws://localhost:9100 — open another tab to collab!" { variant: "muted" }
]