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

live_coding_synth · HydraVisualSynth

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

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). The chain string is parsed into a small AST and evaluated on a low-trail canvas; set_chain() lets a viewer 'live-code' by swapping the chain and calling step() again — the same edit-and-rerun loop that defines a Hydra session.

Original: https://hydra.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
synth
Render
live_video_synth
Complexity
high
Agents
102400
Year
2023
Author
Olivia Jack (hydra.ojack.xyz)

Math essence

chain := source (mod)* ; source in {solid, gradient, osc, noise, shape, voronoi} ; mod in {rotate, scale, scroll, kaleid, pixelate, repeat, invert, posterize, thresh, color, brightness, contrast, luma, saturate, hue, add, diff, mult, blend, modulate, modulateRotate, modulateScale, modulatePixelate, modulateKaleid}. modulate(b, k): resample a at uv + k * (b.r, b.g). canvas <- trail*canvas + (1-trail)*bg + eval(chain).

Parameters

Name Type Default Range Description
dim int 320 128–640 Output side length in pixels (HxW).
chain str osc(20, 0.1, 0.8).rotate(0.05).modulate(noise(3, 0.1).rotate(0.1), 0.5).modulate(osc(8).kaleid(4), 0.3) — Hydra-style chain string (sources composed with .modifiers).
trail float 0.88 0–0.99 Per-step canvas persistence (1.0 = no trail, 0.0 = full clear).
bg_color tuple 8,6,14 — Background colour mixed in at (1-trail) per step.
seed int null 0–999999 RNG seed (reserved for stochastic sources).

Reference

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

"""HydraVisualSynth — Olivia Jack's Hydra video synth in pure numpy.

A small, faithful subset of the Hydra API
(`https://hydra.ojack.xyz`) ported to numpy arrays so the same
chained-function live-coding aesthetics can be rendered from a
deterministic seed:

    osc(freq, sync, offset)        # source: visual oscillator (sin-based)
    noise(scale, offset)           # source: hash-based pseudo-Perlin
    shape(sides, radius, smooth)   # source: regular polygon SDF
    gradient(speed)                # source: 3-channel horizontal gradient
    solid(r, g, b)                 # source: solid colour
    voronoi(scale, speed, blend)   # source: Voronoi cells

    .rotate(theta)                 # geometry: rotate uv around centre
    .scale(s)                      # geometry: scale uv around centre
    .scroll(x, y)                  # geometry: pan uv
    .kaleid(n)                     # geometry: kaleidoscope fold
    .pixelate(p, smooth)           # geometry: posterise uv
    .repeat(x, y)                  # geometry: tile

    .modulate(src, amount)         # modulate: src.r → x warp,
                                   #            src.g → y warp
    .modulateRotate(src, amount)   # modulate: src.r,g → θ(x,y)
    .modulateScale(src, amount)    # modulate: src.r → scale warp
    .modulatePixelate(src, range_) # modulate: src.r → pixelate amount
    .modulateKaleid(src, range_)   # modulate: src.r → kaleid fold count
    .add(src), .diff(src), .mult(src), .blend(src)
                                   # blend: arithmetic on RGB

The composition `osc(40).modulate(noise().rotate(0.1), 0.5).out()`
becomes ``hydra.evaluate("osc(40).modulate(noise().rotate(0.1), 0.5)")``.

A built-in operator chain can be edited at run-time with
``set_chain("osc(10, 0.1).rotate(0.1).kaleid(4).modulate(noise(3), 0.5)")``
so a viewer can "live-code" by swapping the chain string and calling
``step()`` again. The chain is parsed into an AST, evaluated against
the source dictionary, and composited onto a low-trail canvas so the
visual keeps an evolving ghost of past frames.
"""

from __future__ import annotations

import re
from dataclasses import dataclass, field
from typing import Any, Callable, ClassVar

import numpy as np


# ---------------------------------------------------------------------------
# Sources
# ---------------------------------------------------------------------------

def src_solid(canvas: np.ndarray, r: float, g: float, b: float) -> np.ndarray:
    h, w, _ = canvas.shape
    out = np.zeros((h, w, 3), dtype=np.float32)
    out[..., 0] = np.float32(r)
    out[..., 1] = np.float32(g)
    out[..., 2] = np.float32(b)

Try running it locally

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

python library_external/live_coding_synth/HydraVisualSynth/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 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 →
Sample of Topolectures (Olivia Jack) — 2D cell grid + text snippets + audio-amplitude pulse

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.

View →

See all live_coding_synth artworks →