■ huff Home How It Works Install Interface MIDI OSC Output
--:--:--
How It Works
_

huff processes video through a sequential chain of effect passes each frame. Understanding the order helps predict how parameter changes interact.


Effect Pipeline

SOURCE (video / webcam)
[1] SCANLINE BANDS — horizontal displacement from ring
[2] FLOW WARP — noise-field UV distortion
[3] GLITCH / DATAMOSH — tile displacement from ring buffer
[4] FEEDBACK — previous frame zoomed/rotated back
[5] SYMMETRY — axis mirror
[6] SOLARISE — luminance-threshold inversion
[7] TRAILS — ghost frame blend
[8] BASE VIDEO MIX — raw source composited on top
RING BUFFER UPDATE — frame written to ring for next pass
OUTPUT → WebSocket relay → Canvas / Syphon / Spout
Each pass is independently toggleable. Disabled passes are completely skipped — no bleed-through. The ring is updated at the end of each frame — passes always read the previous frame's ring state, never the one being assembled.

UI → Effect Data Flow

All parameter control — sliders, MIDI CC, OSC messages — converges on the same DOM element values. The p5.js draw loop reads these values directly on every frame.

No debounce, no interpolation layer, no intermediate state object. Moving a slider and receiving a MIDI CC produce identical results — both write the same DOM element. There is no latency between a MIDI CC and it affecting the output; the next draw() frame picks it up.

Frame Ring Buffer

The ring buffer stores raw ImageData objects — RGBA pixel arrays at canvas resolution. It is the shared memory between passes.

ParameterEffect on ring
QUALITYControls ring depth: 0 → 4 frames, 1 → 60 frames
DEPTHHow far back effects sample into the ring (0–50% of ring depth)
DEPTH SCATTERPer-tile randomisation of the back index
192 MB capRing depth also capped by pixel budget: at 1080p (~8 MB/frame) max ≈ 23 frames regardless of quality
ResolutionBytes/frameMax frames (quality=1)
720p (1280×720)~3.7 MB51 frames
1080p (1920×1080)~8.3 MB23 frames
1440p (2560×1440)~14.7 MB13 frames
4K (3840×2160)~33.2 MB5 frames
720p or 1080p is the practical sweet spot. At 4K the ring holds only 5 frames — DEPTH and temporal effects lose most of their range.

Frame Output Pipeline

At the end of each draw() call, huff routes the composited output frame to one or more destinations. Syphon and Spout use a magic-byte prefix on the same WebSocket connection as the canvas mirror — Rust inspects the first bytes and routes accordingly.

canvas.getImageData()
→ raw RGBA bytes
→ magic prefix (HUFFSYPH / HUFFSPOUT) + dimensions + pixels
→ binary WebSocket to port 8787
→ Rust relay inspects prefix
HUFFSYPH → syphon::push_frame() → MTLTexture → Syphon clients
HUFFSPOUT → spout::push_frame() → D3D11 texture → Spout receivers
(none) → forwarded to canvas role clients as JPEG frames