edgefader

edgefader · utilities

EDGEFADER — a two-source video CROSSFADER that fades THROUGH THE EDGES. Both IN A and IN B get the EDGES operator every frame (Rec. 601 luma, 3×3 Sobel, THRESH gate, THICK dilation) at half engine resolution, packed into one atlas with where the two masks COINCIDE and a coarse edge-density similarity (the regions of A and B whose edges sit in the same place — the fade's anchors). The A/B fader (0 = only A, 1 = only B, exact at both ends) drives a CASCADE down the frame: five 20% bands, each fading over its own window of the fader's travel, the next band starting when the one above is half done (so the top band finishes exactly as the second reaches where the first was when the second began), interpolated between band centres so there is no seam. Within a band edged pixels fade first, coincident / similar edges first of all, a pixel just INSIDE an edge (centre-ward of it) leads one just outside, and flat regions follow — the fade ripples down the edges. The operator is a progressive BLUR that peaks mid-fade (edged regions go soft, then the incoming picture's edges sharpen in) or, with MELT engaged (a latching toggle OR'd with a gate jack), a liquid SCREEN MELT: each band slides down column by column (per-column start delay and drip length from an integer-hash value noise, the classic 1993 screen melt made stateless), with rounded droplet heads at the drip fronts, a sinusoidal horizontal wobble, and drips that carry the melting band down into the band below before dissolving. STATELESS — a pure function of (A, B, fader, thresh, thick, melt) with no clock, RNG or history — so a pinned engine renders the same frame every step; at the resting fader (0.5) the top two bands show B, the middle band is mid-fade and the bottom two show A. CV inputs for fader / thresh / thick (port id == param id) and a MELT gate. The cascade, lead and melt laws are a 1:1 CPU mirror unit-tested in $lib/video/modules/edgefader-core.

edgefader is a two-source video crossfader that fades THROUGH the edges of the two pictures instead of dissolving them uniformly. It runs the EDGES operator (Rec. 601 luma, 3x3 Sobel, THRESH gate, THICK dilation) on both IN A and IN B every frame and packs the two masks into one atlas, together with the coarse edge density of each — the regions of A and B that carry edges in the same place are where the fade anchors. The A/B fader (0 = only A, 1 = only B, exact at both ends) drives a cascade down the frame: the picture is cut into five 20% bands and each band fades over its own window of the fader's travel, the next band starting when the one above is half done, so by the time the top band is fully across the second is where the first was when the second began, and so on to the bottom. Inside a band the fade is led by the edges: pixels on an edge go first, pixels where A's and B's edges coincide go first of all, a region whose edges mostly coincide (THICK sets how close two edges must sit to count as the same) leads a flat one, a pixel just inside one of A's edges (closer to the centre of the screen than the edge) leads one just outside it, and flat regions follow — the fade ripples down the edges. The top three quarters of each band start together and the bottom quarter ramps to the next band's start, so the five regions stay visible without a seam. The operator is a blur around the edges that peaks mid-fade (the regions around the strokes go soft, then the incoming picture's edges sharpen in). MELT, a latching toggle OR'd with a gate jack, swaps the blur for a liquid screen melt: each band's content slides down column by column with a per-column start delay and drip length drawn from a smooth value noise (columns with more edges start first), rounded droplet tongues hang from the slid content, a sinusoidal horizontal wobble grows with the slide, and the drips carry the melting band down into the band below before dissolving. The whole law is stateless — a pure function of the two inputs, the fader and the two detector settings, with no clock, random source or history — so it renders identically on every frame for a given input, and turning the fader back runs the same cascade in reverse (bottom band first), and the inside/outside ripple is anchored on A's edges in both directions. At the resting fader (0.5) the top two bands show B (the lowest rows of band 1 still finishing), the middle band's edges are fading first, and the bottom two show A. Patch two sources into IN A / IN B, put the fader at either end to see one picture, sweep it to fade; raise THRESH to anchor the fade on fewer, stronger contours, raise THICK to widen the region each contour leads.

the faceplate

edgefaderin_avideoin_bvideofadercvthresholdcvthicknesscvmelt_gategateoutvideoaudiocvgatepitch
6 inputs · 1 outputs · 5 params

inputs

idcablewhat it does
in_avideoThe A video source — what shows when the A/B fader is at 0, and the picture whose edges are detected as A's edge mask. Left unpatched it reads as opaque black with no edges, so an unpatched A with the fader toward A gives a black frame.
RGB video stream
in_bvideoThe B video source — what shows when the A/B fader is at 1, and the picture whose edges are detected as B's edge mask. Left unpatched it reads as opaque black with no edges.
RGB video stream
fadercvCV modulation of the A/B fade, centred on the manual A/B slider. Effective position = slider + CV x 0.5, clamped to 0..1. With the slider at 0.5 a bipolar -1..+1 signal sweeps fully from A to B. Unplugging restores the manual slider position.
control voltage (CV); modulates fader (additive offset — ±1 CV sweeps the full range, centered on the knob)
thresholdcvCV input that modulates Thresh — raising it via CV keeps only the strongest gradients as edges (fewer anchor regions), lowering it lets faint edges lead the fade. Linear-scaled into the 0..1 control range.
control voltage (CV); modulates threshold (additive offset — ±1 CV sweeps the full range, centered on the knob)
thicknesscvCV input that modulates Thick — drives the dilation of both edge masks in pixels, i.e. how wide a region around each contour leads the fade. Linear-scaled into the 1..8 px control range and clamped so it cannot blow up the dilation loop.
control voltage (CV); modulates thickness (additive offset — ±1 CV sweeps the full range, centered on the knob)
melt_gategateMELT gate. WHILE the gate is HELD HIGH (level >= 0.5) the blur fade is replaced by the liquid melt — a momentary hold that drops back to the blur the instant the gate goes low. OR-combined with the MELT toggle, so either can engage the melt independently.
gate / trigger; modulates meltGate (summed directly (the destination DSP scales it)); gate — acts while the level is high (reacts to both edges)

outputs

idcablewhat it does
outvideoThe crossfaded picture: exactly IN A with the fader at 0, exactly IN B at 1, and between them the edge-led cascade (blur, or melt when MELT is engaged). With nothing patched into either input this is black.
RGB video stream

params

idlabelrangedefaultcurve
faderA/B0..1—linear
thresholdThresh0..1—linear
thicknessThick1..?px—linear
meltMelt0..1—discrete
meltGateMelt Gate0..1—linear

controls

controlwhat it does
A/BThe A<->B crossfade position: 0 shows only IN A, 1 shows only IN B. In between, the fader's travel is split into five overlapping windows, one per 20% band of the picture from the top down (each band starts when the band above is half done), and within each band the edged regions fade first. At the 0.5 default the top two bands show B, the middle band's edges are fading first, and the bottom two show A. Clamped to 0..1.
MeltMELT (0/1, default 0): a toggle you switch on and leave on — it swaps the blur fade for the liquid screen melt, where bands slide down in dripping columns with droplet tongues that fall into the band below. The melt gate additionally forces it while that gate is high. The fader's endpoints stay exact in either mode.
Melt GateMelt Gate (0..1, default 0): hidden synthetic param the melt-gate CV bridge writes each frame with the gate LEVEL; while it is HIGH (>= 0.5) the melt is forced (OR-combined with the MELT toggle, so the per-frame level never stomps the toggle's latched state). Exposed only as the melt gate jack, not as a knob.
ThickThick is the width in pixels (1..8 px, default 2) of the region around each detected contour that counts as edged and leads the fade — both masks are dilated by it (the same radius law as EDGES), so it is also the tolerance within which an edge of A and an edge of B count as coinciding.
ThreshThresh sets the normalised gradient magnitude (in luma-step units) at or above which a pixel counts as an edge in BOTH pictures. 0 = every pixel is an edge, so the whole frame fades as one edged region; 1 = almost nothing is, so the fade degrades to a plain delayed crossfade; default 0.2 catches salient contours without low-contrast texture noise.

source

edgefader.ts on GitHub.

Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo