Skip to content
Sample of Topolectures (Olivia Jack) — 2D cell grid + text snippets + audio-amplitude pulse

live_coding_synth · TopolecturesOliviaJack

Topolectures (Olivia Jack) — 2D cell grid + text snippets + audio-amplitude pulse

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. The pulse combines a per-cell sin chain (cell_freq, phase) with a 1 Hz kick impulse and a low/mid/high band amplitude (the performer's speech amplitude in the live Topolectures piece). The default grid is 16×16 with a 14-px cell, 480×480 canvas. A small 5×7 pixel font is rasterised into a numpy bitmap for each cell and composited onto the canvas at the per-cell brightness.

Original: https://ojack.xyz

▶ 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.

Family
live_coding_synth
Source
live_coding_synth
Evolution
grid
Render
cell_text_grid
Complexity
medium
Agents
256
Year
2019
Author
Olivia Jack

Math essence

Per cell (r, c): phase, cell_freq ∈ rand; amp = audio_low(t) + audio_mid(t) + audio_high(t) + 1Hz_kick(t). bright(r,c,t) = clip(0.5 + 0.4*sin(t * amp_freq * cell_freq + phase * phase_jitter) + 0.5*kick_pulse + 0.25*amp, 0, 1). canvas[y0:y1,x0:x1] = max(canvas[y0:y1,x0:x1], fg_color * bright * glyph_bitmap[word]).

Parameters

Name Type Default Range Description
dim int 480 240–720 Output side length in pixels (HxW).
grid_size int 16 4–32 Side length of the cell grid (N×N).
cell_size int 14 8–32 Pixel size of each cell (square).
n_glyphs int 2 1–4 Max number of glyphs per cell (1 or 2 looks best).
amp_freq float 0.13 0.02–1 Time-frequency of the per-cell brightness sin chain.
phase_jitter float 0.6 0–2 How much the random per-cell phase enters the brightness equation.
low_freq float 0.7 0.1–4 Audio low-band frequency (synthetic).
mid_freq float 1.7 0.1–4 Audio mid-band frequency (synthetic).
high_freq float 2.9 0.1–4 Audio high-band frequency (synthetic).
kick_freq float 1 0.1–4 1-Hz-like speech-rhythm kick frequency (per Olivia Jack's live Topolectures).
kick_strength float 0.7 0–2 Strength of the kick impulse on every cell.
bg_color tuple 10,12,18 — Background colour.
fg_color tuple 220,230,255 — Foreground (text) colour.
seed int null 0–999999 RNG seed (cell text + phase + cell_freq).

Reference

First 60 lines of reference.py. Full source: library_external/live_coding_synth/TopolecturesOliviaJack/reference.py

"""TopolecturesOliviaJack — Olivia Jack's 2D cell-grid + text snippets.

Topolectures (Olivia Jack) is a 2D grid of small cells. Each cell
displays a tiny snippet of text (one or two characters), and the
brightness of each cell pulses with an audio-amplitude signal —
synthetic here, but the structure matches the live-coding
performance: the performer reads aloud, the cell whose text
matches what is being said lights up, the rest stay dim.

The visual is built by rasterising each cell's text glyph into a
small bitmap (numpy), then compositing it onto the canvas with a
per-cell brightness multiplier that tracks a per-cell sin chain
whose phase is randomised at reset. A 1 Hz kick impulse (the
audio amplitude envelope) brightens every cell briefly so the
whole grid breathes in time with the speech rhythm.

Cell-text is sampled from a corpus of words associated with
topology / topolectures ("sheaf", "locale", "frame", "open",
"closed", "cover", "limit", "point", "net", "filter", ...). The
default cell size is 14×14 px and the default grid is 16×16, so
the rendered canvas is 240×240. Two-character cells (e.g. "≤",
"id", "~") are drawn as two 7×14 bitmaps stitched side-by-side.
"""

from __future__ import annotations

from typing import ClassVar

import numpy as np


_CORPUS: tuple[str, ...] = (
    "sheaf", "locale", "frame", "open", "closed", "cover",
    "limit", "point", "net", "filter", "basis", "ideal",
    "prime", "ring", "mod", "field", "topos", "yoneda",
    "etale", "sieve", "germ", "stalk", "space", "chart",
    "atlas", "sheaf", "gluing", "flabby", "injective",
    "kernel", "image", "rank", "trace", "spec", "scheme",
    "stack", "gerbe", "torsor", "lie", "group", "algebra",
    "module", "tensor", "hom", "ext", "tor", "der",
    "diff", "conn", "curv", "tors", "geod", "chart",
    "~", "id", "Δ", "≤", "≥", "→", "↦", "≅", "⊂", "⊃", "∧", "∨", "¬", "∀", "∃",
    "∞", "∑", "∏", "∂", "∇", "∈", "∉", "∋", "∅", "η", "π", "λ", "μ", "σ", "φ",
)


# ---------------------------------------------------------------------------
# 5x7 pixel font for ASCII printable + a few unicode glyphs
# ---------------------------------------------------------------------------

_FONT_5x7: dict[str, tuple[str, ...]] = {
    "A": ("01110", "10001", "10001", "11111", "10001", "10001", "10001"),
    "B": ("11110", "10001", "10001", "11110", "10001", "10001", "11110"),
    "C": ("01110", "10001", "10000", "10000", "10000", "10001", "01110"),
    "D": ("11110", "10001", "10001", "10001", "10001", "10001", "11110"),
    "E": ("11111", "10000", "10000", "11110", "10000", "10000", "11111"),
    "F": ("11111", "10000", "10000", "11110", "10000", "10000", "10000"),
    "G": ("01110", "10001", "10000", "10111", "10001", "10001", "01110"),
    "H": ("10001", "10001", "10001", "11111", "10001", "10001", "10001"),
    "I": ("11111", "00100", "00100", "00100", "00100", "00100", "11111"),

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/live_coding_synth/TopolecturesOliviaJack/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from live_coding_synth

Sample of Hydra Video Synth (numpy port of Olivia Jack's Hydra)

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).

View →
Sample of P5Live sin/cos Spirograph Sketch

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.

View →
Sample of Strudel 16-Step Pattern Visualiser (4x4 grid of sample-typed shapes)

Strudel 16-Step Pattern Visualiser (4x4 grid of sample-typed shapes)

live_coding_synth · StrudelVisualizer

A pure-numpy port of Strudel's signature 4×4 (16-step) pattern grid.

View →
Sample of TidalCycles Mini-Notation Pattern Visualiser

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.

View →

See all live_coding_synth artworks →