■ 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

Each pass is independently toggleable. Disabled passes are completely skipped — no bleed-through. GLITCH and SCANLINES are also weighted against each other by the A/B Mix layer-priority slider: the recessive effect's opacity floors at 35% rather than reaching zero, so both remain visible at any position. The ring stores the clean source frame each cycle — passes that sample the ring (GLITCH, TRAILS, FLOW WARP with PULSE) always read previous frames, never the one being assembled.
huff effect pipeline diagram — full per-frame processing order from Source through Trails, Glitch, Luma Key, Scanlines, Global Mix, Feedback, Flow Warp, Symmetry, Solarize, to Output

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