live_coding_synth · StrudelVisualizer
Strudel 16-Step Pattern Visualiser (4x4 grid of sample-typed shapes)
A pure-numpy port of Strudel's signature 4×4 (16-step) pattern grid. A Tidal mini-notation pattern is parsed to exactly 16 events per cycle, then each event is drawn as a sample-typed shape in a 4×4 grid: kick/bd → red filled disc + glow ring; snare/sn → yellow square + centre dot; hi-hat/hh → cyan X-mark; clap/cp → violet diamond; bass → green bar (size = note value); pad/chord/lead → coloured bar; rest (~) → empty cell with a thin gridline. A playback cursor (4 ticks per step) sweeps column-by-column on a per-cycle clock — the same playhead you see in a Strudel REPL. The default pattern is bd*4, ~ sn ~ hh*2, cp*4, bd*2 hh*2 — a four-channel drum-machine polyrhythm exactly like the multi-channel patterns Felix Roos writes in Strudel live-coding sets.
Original: https://strudel.cc
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
parse(pattern) -> steps[16] of (sample, variant). For each step s_i in 0..15: (r, c) = (s_i // 4, s_i % 4); cx,cy = margin + c*cs + cs*0.5. shape(sample): bd -> disc(0.30*cs); sn -> square(0.85*0.30*cs); hh -> X-mark(0.30*cs); cp -> diamond(0.30*cs); bass/lead -> bar(0.30*cs, 0.6 + 0.4*v/8); ~ -> dot(0.04*cs). active_step = (tick // 4) % 16; draw cursor rectangle in (250, 220, 140). canvas[y0:y1,x0:x1] = max(canvas, ink).
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 480 | 256–720 | Output side length in pixels (HxW). |
pattern | str | bd*4, ~ sn ~ hh*2, cp*4, bd*2 hh*2 | — | Tidal/Strudel mini-notation pattern. Supports sample names, ~ rest, [ ] group, *N repeat, /N slow, :N variant, , parallel. |
n_steps | int | 16 | 8–32 | Number of events per cycle (default 16 for the canonical Strudel 4x4 grid). |
cell_size | int | 100 | 60–180 | Pixel size of each cell (square). |
bg_color | tuple | 8,10,16 | — | Background colour. |
grid_color | tuple | 40,40,50 | — | Cell gridline colour. |
seed | int | null | 0–999999 | RNG seed (reserved). |
Reference
First 60 lines of reference.py. Full source:
library_external/live_coding_synth/StrudelVisualizer/reference.py
"""StrudelVisualizer — Strudel's 16-step pattern as a 4x4 grid of shapes.
Strudel (https://strudel.cc) is the JavaScript port of TidalCycles
by Felix Roos and the tidalcycles/strudel team — the same
mini-notation (``bd*4, hh*8, ~ sn``) but running live in the
browser. Strudel's signature visualisation is a 4×4 (16-step)
grid of "events" — each cell shows the sample name, an icon
(Drum, Note, Chord, Rest), and a brightness driven by the
event's `gain` / `velocity`.
This module renders the same 4×4 grid in pure numpy:
* parses a Strudel-style mini-notation pattern (full Tidal
subset — `bd`, `~`, `[ ]`, `*N`, `/N`, `:N`, `< >`, `,`);
* flattens it to exactly 16 events per cycle (the canonical
16-step Strudel cycle);
* draws each event as a small shape in a 4×4 grid:
- kick / bd → red filled disc + glow ring
- snare / sn → yellow square + glow ring
- hi-hat / hh → cyan X-mark
- clap / cp → violet diamond
- bass note → green bar (size = note value)
- chord → 3-stacked triangle
- rest (`~`) → empty cell with thin gridline
- other → small white ring
A playback cursor (the active step) sweeps column-by-column on
a per-cycle clock — the same "playhead" you see in a Strudel
REPL. Per-step gain modulates each cell's brightness.
"""
from __future__ import annotations
import re
from dataclasses import dataclass
from typing import ClassVar
import numpy as np
_DRUM_HUE: dict[str, tuple[int, int, int]] = {
"bd": (240, 70, 80),
"sd": (250, 220, 110),
"sn": (250, 220, 110),
"hh": (130, 230, 250),
"cp": (180, 120, 250),
"lt": (180, 250, 180),
"mt": (250, 180, 200),
"ht": (250, 130, 80),
"cb": (250, 130, 80),
"rim": (210, 200, 240),
"arpy": (140, 220, 180),
"arps": (140, 220, 180),
"bass": (160, 250, 200),
"lead": (255, 200, 240),
"pad": (130, 180, 255),
"stab": (255, 220, 130),
"chord": (255, 220, 130),
}
Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/live_coding_synth/StrudelVisualizer/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from live_coding_synth
Hydra Video Synth (numpy port of Olivia Jack's Hydra)
live_coding_synth · HydraVisualSynth
A pure-numpy port of the core Hydra video-synth API: chains of sources (osc, noise, shape, gradient, solid, voronoi) composed with geometry modifiers (rotate, scale, scroll, kaleid, pixelate, repeat) and color/blend modifiers (invert, posterize, thresh, color, brightness, contrast, luma, saturate, hue, add, diff, mult, blend) — including the signature modulate operator a.modulate(b, scale), which uses b's red and green channels to displace a's x and y coordinates (with modulateRotate, modulateScale, modulatePixelate, modulateKaleid variants).
P5Live sin/cos Spirograph Sketch
live_coding_synth · P5LiveSketch
A pure-numpy port of the canonical p5.js sin/cos live-coding sketch: a spirograph-like cloud of points whose polar coordinates are themselves nested sin/cos chains.
TidalCycles Mini-Notation Pattern Visualiser
live_coding_synth · TidalCyclesPattern
A pure-numpy port of TidalCycles' rhythm mini-notation, expanded per cycle into a row of (sample, variant) tuples and visualised as a row of pulsing shapes that scroll horizontally.
Topolectures (Olivia Jack) — 2D cell grid + text snippets + audio-amplitude pulse
live_coding_synth · TopolecturesOliviaJack
A pure-numpy port of Olivia Jack's Topolectures: a 2D grid of cells, each cell holding a 1–2 character text snippet from a topology-mathematics corpus (sheaf, locale, frame, open, closed, cover, limit, point, net, filter, basis, ideal, prime, ring, mod, field, topos, yoneda, etale, sieve, …) and brightness pulsed by a synthetic audio-amplitude signal.