Novack, Saito, Zhong, Shibuya, Cui, McAuley, Berg-Kirkpatrick, Simon, Takahashi, Mitsufuji (UC San Diego / Sony), 2026 · ICASSP 2026

FlashFoley: Fast Interactive
Sketch2Audio Generation

Hum a sound and hear it become realistic Foley in 75 ms — fine-grained pitch/volume/brightness control AND real-time streaming, in one open-source model, by fusing sketch conditioning with adversarial post-training and a block-autoregressive chunker.

Prerequisites: Diffusion / Rectified Flow + GANs + basic audio (spectra)
11
Chapters
6
Simulations

Chapter 0: The Problem

You are a sound designer scoring a film. A character slams a door, and you need the thud. You could dig through a sample library for an hour — or you could just make the sound with your mouth: "duh-DHUMP." That vocal imitation is a sketch. It has roughly the right loudness shape, the right pitch contour, the right brightness. It's wrong in every detail and right in every gesture.

Generative Text-to-Audio (TTA) models can turn "a heavy wooden door slamming" into audio. But text is a blunt instrument. It cannot say "loud here, soft there, pitch rising then a sharp transient at 0.4 seconds." For creative work — Foley, sound design, live jamming — you want to steer the sound continuously through time, the way your voice does when you hum it.

The core tension this paper attacks: Two things you desperately want for interactive audio creation have, until now, been mutually exclusive. (1) Fine-grained control — drive generation with time-varying signals like a vocal sketch. (2) Speed — generate fast enough (sub-half-second) to feel like a live instrument. Existing systems give you one or the other. Controllable models are slow; fast models are uncontrollable.

Why the two goals fight each other

Modern TTA models are flow / diffusion models. They start from pure noise and iteratively denoise toward audio. "Iteratively" is the problem: high quality needs many denoising steps (say 50), and each step is a full forward pass through a large transformer. That is inherently slow — seconds per clip.

The two research communities then pulled in opposite directions:

And even "fast + controllable" isn't enough

Suppose you somehow get a fast, controllable model. You still can't jam with it in real time. Why? Because these models are non-autoregressive: they generate the whole 12-second clip at once, using bidirectional context (the sound at second 2 depends on the sketch at second 10). So you must capture the entire sketch before generation can even start. There is no "play a note, hear it instantly" — the model needs to see the future first.

What you wantWhy it's hardWho had it before
Sketch control (pitch/vol/bright over time)Needs finetuning + conditioning machinerySketch2Sound (slow, closed)
Fast inference (<0.5 s)Diffusion needs many stepsDistilled TTA (text-only)
Real-time streaming (jam live)Non-AR models need the whole futureNobody, for flow models

FlashFoley's claim is that you can have all three at once, in one open-source model. The rest of this lesson builds, piece by piece, exactly how.

Why have fine-grained control and fast inference historically been mutually exclusive in TTA models?

Chapter 1: The Key Insight

FlashFoley is not one idea — it's three ideas stacked in a specific order, and the order is the cleverness. Each one removes exactly one of the three blockers from Chapter 0.

1. Add control first
Finetune a pretrained TTA flow model to accept time-varying sketch controls (volume, pitch, brightness) via a tiny Pre-Transformer Projection (~0.1% new params).
2. Then distill for speed
Apply ARC adversarial post-training to collapse 50 steps down to a handful, while keeping the controls. 11.88 s of stereo 44.1 kHz audio in 75 ms.
3. Then make it streamable
Train with inpainting/outpainting conditions and use a block-autoregressive chunking algorithm so the first audio plays while the user is still sketching.
The load-bearing decision — "control first, then distill": Why not distill the fast model first and add controls after? Or do both at once? Prior work (CoDi, Presto) found that adding controls after distillation, or jointly, is unstable and degrades quality. The authors take the opposite, empirically-grounded order: finetune controls into a clean, slow, high-quality model, then distill that controllable model. The controls actually help the distillation — local supervision gives the few-step generator a clean target to aim at (we'll see this surprise in the ablations).

The whole pipeline in one breath

Start with Stable Audio Open Small (a 340M-parameter rectified-flow DiT). Stage 1: finetune it on the velocity loss with sketch controls + inpainting masks injected via Pre-Transformer Projection. Stage 2: ARC post-training replaces the velocity loss with a relativistic adversarial loss plus a contrastive loss, turning the 50-step model into a 1–8 step generator. Inference: for offline use, run the few-step sampler once; for live use, run the block-autoregressive chunker that generates audio in overlapping blocks as the sketch streams in.

We will build each stage from zero. By the end you could re-draw the training diagram on a whiteboard and explain why every arrow is there.

What is the deliberate ordering decision at the heart of FlashFoley?

Chapter 2: Rectified Flow — the engine

Before controls or speed, we need the base generative model. FlashFoley is a rectified flow (RF) model operating in a VAE latent space. Let's earn that sentence.

From audio to latent

Raw stereo audio is huge: x0 ∈ ℝ2×S·fs — 2 channels, S seconds at fs=44,100 samples/sec. About 1 million numbers for an 11 s clip. We never model that directly. A pretrained VAE encoder compresses it: z0 = ℰ(x0) ∈ ℝM×N. In the paper's model the compression is 2048× in time, leaving 64 channels × 256 latent frames at ~21.5 Hz. All generation happens on these 256 frames; a VAE decoder turns the result back into audio.

Why a latent space at all? Generating 256×64 numbers is tractable; generating a million raw samples is not. The VAE is frozen — it already knows how to turn compact latents into clean audio. FlashFoley only ever learns to produce good latents; the decoder handles the waveform. Keep this shape in your head: [batch, 64, 256] is "one clip" everywhere below.

What "flow" means — the straight-line bet

We want to sample new latents from the data distribution p0. Rectified flow defines a dead-simple bridge between a Gaussian p1 (pure noise) and data p0: a straight line. Given a clean latent z0 and a noise sample ε ∼ 𝒩(0,I), the corrupted point at time t∈[0,1] is just a linear blend:

zt = (1 − t) z0 + t ε

Symbol by symbol: t=0 is clean data, t=1 is pure noise, and in between you slide linearly. The velocity — the direction you'd move to go from data toward noise — is the derivative of that line:

v = d zt / dt = ε − z0

To generate, you run the line backwards: start at noise z1 and integrate dzt = −v\,dt down to t=0. The only thing the network must learn is to predict that velocity at any point and time, given the text prompt:

arg minθ  𝔼z0,c,ε,t [ ‖ v − vθ(zt, t, ctxt) ‖22 ]

This is a simulation-free objective: you don't run the ODE during training, you just pick a random t, blend, and regress the velocity. vθ is the DiT; ctxt is the text embedding; the squared error is the same MSE you've seen a hundred times.

Rectified Flow — the straight-line corruption & the velocity to undo it

The teal dot is data z0; the gray dot is a noise sample ε. Drag t to slide along the straight line to the current zt (orange). The orange arrow is the velocity v=ε−z0 the network learns to predict. Hit Integrate to walk from noise back to data — that's generation.

RF vs diffusion in one line: Rectified flow is mathematically equivalent to diffusion but uses straight paths instead of curved ones, which empirically trains better and samples in fewer steps. That "fewer steps" head start is exactly what makes the later distillation feasible.
In rectified flow with zt = (1−t)z0 + tε, what is the velocity the network learns to predict?

Chapter 3: Sketch Controls — turning a hum into numbers

A vocal sketch is a sound. To condition the model on it, we don't feed the raw waveform — we extract three interpretable, time-varying signals that capture the gesture without the timbre. These come from Sketch2Sound, and choosing them well is what lets a hum control a door slam.

ControlWhat it measuresExtracted byShape
VolumeLoudness over time: RMS in dB of the A-weighted magnitude spectrumsignal processing[1, N]
PitchFundamental frequency over time (a probability matrix over pitches)PESTO (a neural pitch estimator)[Kpitch, N]
BrightnessSpectral centroid — the "center of mass" of the spectrum, i.e. how trebly vs muffledsignal processing[1, N]

Each feature fi ∈ ℝKi×N is a time series of length N (resampled to match the 256 latent frames). The full control set is F = {fi}i=1..l. These are local controls: one value (or vector) per frame, unlike a single global text embedding.

Two engineering choices worth pausing on. (1) Pitch is a probability matrix, not a single number. PESTO outputs a distribution over pitch classes per frame; probabilities below 0.1 are zeroed to "prevent spectral leakage." Why a distribution? Voiced sounds have a clear pitch; unvoiced sounds (a "shhh") have none — a soft distribution gracefully represents "no confident pitch." (2) Brightness is log-rescaled to 0–127, then to 0–1. Because brightness, like pitch, is perceived logarithmically — equal musical intervals, not equal Hz.

The median filter — the dial between "render" and "sketch"

Here is the most beautiful trick in the control design. If you feed the model the exact extracted features, it tries to reproduce them precisely — great for style transfer, but it overfits to the spectral quirks of your voice. If you blur them, the model treats them as loose suggestions — a true sketch. FlashFoley convolves the controls with a median filter of random width during training, so at inference the filter width becomes a continuous knob:

small filter (w≈1)
Render the controls exactly — precise audio-to-audio style transfer.
large filter (w≈5+)
Treat the input as a broad "sketch" — the model fills in realistic detail.
Sketch Feature Extraction — hum → volume / pitch / brightness, with median filtering

The faint line is the raw extracted control from a noisy "vocal sketch"; the bold line is after a median filter of width w. Drag w up and watch the jittery sketch smooth into a clean gesture — that's the "render ↔ sketch" dial. Switch the control to see volume (loudness), pitch (a contour through the probability matrix), and brightness (spectral centroid).

Why does FlashFoley train with a random-width median filter on the sketch controls?

Chapter 4: Pre-Transformer Projection — injecting control cheaply

We have three time-varying controls. How do we feed them into a 340M-parameter DiT without retraining everything or adding bulky adapters? The naive options each add 6–50% new parameters. FlashFoley uses Pre-Transformer Projection (PTP), which adds ~0.1%.

Where the controls go in

A DiT first turns the noisy latent zt into an initial hidden state via an input projector (a small MLP) before any transformer blocks:

hinit = ProjInθ(zt) ∈ ℝH×N

where H is the hidden dimension and N=256 frames. PTP learns one tiny linear operator Wi ∈ ℝKi×H per control, projects each control up to hidden dimension, and simply adds it to that initial hidden state:

h'init = hinit + Σi Wi fi

That's it. Each Wi fi maps a [Ki, N] control to [H, N] and lands as a per-frame additive bias on the hidden state. Then the whole model finetunes on the velocity loss (Eq. of Ch 2). The DiT blocks themselves never change shape.

Why "add to the hidden state before the blocks" is the right place: Three reasons. (1) Minimal graph change — you don't touch the transformer at all, so it's trivial to bolt onto any DiT without breaking the pretrained weights. (2) Independent parameters per control — each control gets its own Wi with no weight sharing with the latent input. (3) That independence turns out to be critical: alternatives like channel-wise concatenation or projecting into the VAE space share weights between controls and the latent, which (with a complex multi-layer ProjIn) caused training instability and degraded audio.

The subtle point: when concat ≡ PTP, and when it breaks

The authors prove a small, illuminating fact. If ProjInθ were a single linear layer, then PTP and channel-wise concatenation are exactly equivalent — concatenating ΣKi extra channels and learning a wider weight matrix is the same as learning a separate Wi per control. But their ProjIn is a 2-layer residual MLP. With that nonlinearity, concatenation forces implicit weight sharing in the projection matrices, and in short finetuning runs the module can't adapt to each control's distribution separately. PTP sidesteps this by construction.

Pre-Transformer Projection — click a control to trace it into the hidden state
Click any node to see the tensor shape flowing through it.

The latent and the three controls each get projected, then summed into h'init — which is the only place the controls enter. Everything downstream is the untouched pretrained DiT. Click the nodes to read the shapes.

python
# Pre-Transformer Projection: ~0.1% new params, no DiT changes
import torch, torch.nn as nn

class PTP(nn.Module):
    def __init__(self, ctrl_dims, H):
        # one independent linear per control: K_i -> H, no bias, no sharing
        self.W = nn.ModuleList([nn.Linear(k, H, bias=False) for k in ctrl_dims])

    def forward(self, h_init, controls):
        # h_init: [B, H, N]   controls[i]: [B, K_i, N]
        for Wi, f in zip(self.W, controls):
            # project K_i -> H along channel dim, add as per-frame bias
            h_init = h_init + Wi(f.transpose(1,2)).transpose(1,2)
        return h_init        # [B, H, N] -> straight into the DiT blocks
Why does PTP learn an independent linear projection per control instead of concatenating channels?

Chapter 5: ARC Post-Training (the showcase)

We now have a slow but controllable model: 50 denoising steps, beautiful sketch control. Stage 2 makes it fast. The goal is a generator Gφ that produces good latents in 1–8 steps instead of 50. The method is ARC — Adversarial Relativistic-Contrastive post-training.

Why not just "use fewer steps"?

If you take the 50-step model and run it for 4 steps, the output is blurry garbage — the velocity field assumes small steps. Classic distillation fixes this by training a student to match a strong teacher, but teachers are expensive and limit quality. ARC instead replaces the regression target entirely with an adversarial one: a discriminator Dψ judges realism at any noise level, so the generator learns to make realistic audio in very few steps with no teacher.

The relativistic twist (and why it kills mode collapse): A vanilla GAN asks "is this sample real or fake?" — an absolute judgement that is easy to game and collapses to a few safe outputs. A relativistic discriminator instead scores the difference between a paired real and generated sample: "is this real one more real than that generated one?" Because the pairs share the same conditioning (ctxt, F), this draws a decision boundary around each individual real sample, forcing the generator to match that specific target rather than retreating to an average. The sketch controls make the pairing even tighter.

The relativistic loss, decoded

Take a real latent z0 and conditioning C={ctxt, F}. Noise it to zt, generate &zcirc;0=Gφ(zt,t,C). Re-noise both to a common level s and let Dψ score them. The min-max objective on the relative scores is:

𝔼[ f( Dψ(&zcirc;s, s, C) − Dψ(zs, s, C) ) ],   f(x) = −log(1 + e−x)

Read it: Dψ(&zcirc;s) − Dψ(zs) is "how much higher the fake scores than the real." Gφ wants this difference large (fool the judge); Dψ wants it small (catch the fake). f is the softplus that turns the score gap into a smooth loss. Everything is relative to the paired real sample — that is the whole anti-collapse mechanism.

A clever initialization, free of charge: The discriminator Dψ isn't built from scratch. It's initialized from the first half of the layers of the sketch TTA model, plus a small Conv1D head at 8× downsampling. So Dψ already understands noisy latents at any level and already accepts all the trained controls. It's a judge that grew up inside the generator.

Inference: ping-pong sampling

Once trained, Gφ generates by "ping-pong": denoise toward data, re-noise to a slightly lower level, denoise again — a handful of times. The result: 11.88 s of stereo 44.1 kHz audio in 75 ms, ~10× faster than existing controllable TTA, with no quality loss (and, surprisingly, slightly better control accuracy).

ARC Few-Step Generation — hum a sketch, watch it denoise in N steps

The orange sketch control (a loudness/pitch gesture) is fixed. Press Generate: the noisy mel-like field (left) ping-pongs into structured audio (right) in T steps, snapping to the sketch's contour. Drag T to fewer steps and watch quality degrade gracefully — even 1 step stays usable because the sketch supervises the generator. Toggle Relativistic D off to simulate a vanilla GAN collapsing to a flat, generic output.

What does the "relativistic" discriminator in ARC do that a standard GAN discriminator does not?

Chapter 6: The Contrastive Loss — making the judge read the words

The relativistic loss makes audio realistic. But realistic-and-ignoring-the-prompt is a known GAN failure: the generator makes great sound that doesn't match the text. ARC adds a second, auxiliary loss to force the discriminator to care about the conditioning.

The contrastive objective

Same relativistic form, but now both samples are real — they differ only in their conditioning. One gets the correct condition C; the other gets a batch-shuffled, wrong condition P[C] (some random permutation of the batch's conditions):

𝔼[ f( Dψ(zs, s, P[C]) − Dψ(zs, s, C) ) ]

The discriminator is trained to maximize this — to score a real sample with its correct caption higher than the same real sample with a mismatched caption. To do that, Dψ must actually read the condition and judge semantic agreement, not just sniff for high-frequency GAN artifacts. The combined objective is:

minφ maxψ  ℒARC = ℒR(φ,ψ) + λ·ℒC(ψ),   λ=1

The design question only sketch2audio raises

Standard ARC (text-only) shuffles the text. But FlashFoley has two kinds of conditioning with very different granularity: a single global text caption, and dense time-varying local controls F. So: which condition should we shuffle in the contrastive loss? The original ARC paper would say "shuffle everything." The authors test this and find it is a trap.

The failure mode — shuffle the sketch and the model breaks: If you also shuffle the local controls, the discriminator's contrastive job becomes trivially easy — local controls are so tightly coupled to the audio that detecting a mismatched sketch needs no real understanding. So Dψ overfits to the sketch controls and stops caring about anything else. The generator then largely ignores the text and loses high-frequency timbral detail. Figure 3 of the paper shows it vividly: "birds chirping" and "train horn" prompts come out wrong when the sketch is contrasted. The fix: compute the contrastive loss with randomized text only, leaving the local controls correct.
Contrastive Loss — what should the discriminator be forced to read?

Two simulated spectrograms for the same prompt. Shuffle text only: the discriminator must read the caption, so generations keep rich text-driven timbre (full frequency content). Shuffle all: the discriminator latches onto the sketch and ignores text — watch the high-frequency content collapse and the prompt get ignored, exactly as in Figure 3.

Why does FlashFoley shuffle ONLY the text (not the local controls) in the contrastive loss?

Chapter 7: Block-Autoregressive Streaming

We now have fast, controllable, high-quality offline generation. But it's still non-autoregressive: it needs the whole sketch first. For live jamming, that's a dealbreaker. Stage 3 makes generation streamable without ever training a causal model.

Step one: teach the model to outpaint

During Stage 1 finetuning, the authors add inpainting/outpainting conditions through the same PTP machinery. They feed the model a masked clean latent (plus the mask itself) where the mask always hides some future context. This trains the model to outpaint — to continue audio given a few conditioning frames. These conditions are kept through ARC post-training too, so both Gφ and Dψ understand "given this much, generate the next."

Step two: the chunking algorithm (Figure 2)

Pick a block size B < N and a stride k. The model generates the next chunk of B frames by inpainting the last B−k frames of the previous chunk. The trick that makes this run on an unchanged non-causal model: it always generates a full N frames, but only fills the first B sketch-control slots (the rest padded with zeros), and uses a "seconds total" embedding to say how much is real. After each pass, the overlap region is forced to equal the previous chunk for seamless transitions; then the new frames stream out.

Why this is the whole ballgame for latency: Normal non-AR sampling has latency ≈ S seconds — you wait for the entire clip. Block-AR has latency dominated by B·S/N — you only wait for one block. With B=128 of N=256 frames, that halves the streaming latency (to ~6 s for capturing controls), so the first chunk plays while the user is still humming the rest. And remarkably, the ablations show stride barely matters — the model needs surprisingly little preceding context.
Block-AR Streaming — drag block size B and stride k, watch the chunks march

The timeline is N=256 latent frames. Each Next chunk generates B frames; the overlap (the last B−k frames of the previous chunk, shown striped) is forced to match for a seamless join, and the fresh k frames (solid) stream out. Smaller B → lower latency but the speed–quality tradeoff worsens; k has little effect on quality.

How does block-autoregressive sampling reduce streaming latency?

Chapter 8: Experiments & Results

The setup: base model is Stable Audio Open Small (340M DiT, stereo 44.1 kHz, 256 latent frames ≈ 11.88 s). Trained on WavCaps (~400K audio samples), 40K control-finetuning steps + 70K ARC steps, batch 256 across 4 H100s. Evaluated on VimSketch — ~10K real human vocal imitations of 500 audio classes.

What the metrics mean (don't skip this)

MetricMeasuresDirection
Control L1 (RMS / centroid / pitch / chroma)How well the generation follows the sketch (L1 on each control)lower better ↓
FD (Fréchet Distance, openl3)Audio quality / realism vs real audio distributionlower better ↓
CLAPText adherence (cosine sim of audio & caption embeddings)higher better ↑
MOSHuman-rated subjective quality (0–100, 95% CI)higher better ↑
OL / SLOffline latency / Streaming latency (seconds)lower better ↓

The main table, read like a story

ModelStepsFD ↓CLAP ↑MOS ↑OL ↓SL ↓
SAOS (base, no controls)5041.870.3250.80.6312.52
+ sketch controls5056.380.2664.20.6312.52
FlashFoley (ARC)554.320.2363.70.0811.96
+ BAR (streaming)556.870.2261.90.086.02
+ sketch LC (the trap)565.100.1354.40.0811.96
Three findings that matter: (1) ARC is nearly free. Going from 50 steps to 5 (FlashFoley) collapsed offline latency 0.63 s → 0.08 s (~8×) with no significant quality loss — it even improved control accuracy. (2) BAR halves streaming latency (11.96 → 6.02 s) with only a small FD/MOS dip. (3) The sketch-LC trap is real — contrasting all controls wrecks FD (65.10) and CLAP (0.13), confirming Chapter 6's analysis quantitatively.

Note the expected tradeoff in the first two rows: adding sketch controls raises FD and lowers CLAP (controls are a harder target than text alone) — but raises MOS sharply, because humans find controllable, sketch-following audio far more useful. The whole point is that ARC then makes this controllable model ~10× faster without giving that back.

Latency Collapse — FlashFoley's headline result
What did ARC post-training achieve relative to the 50-step controllable model?

Chapter 9: Ablations — the surprising tradeoffs

The ablations plot FD against average relative error (control error relative to the baseline SAOS error, averaged over controls). Two knobs are swept; each reveals something non-obvious.

Ablation 1: filter width & sampling steps (non-AR)

As expected from Sketch2Sound, there's a tradeoff: a small median filter (w=1) gives low control error but worse FD; a large filter (w=5) gives better FD but looser control. The surprise is on sampling steps: dropping from 8 steps to 1 degrades quality only slightly.

The counterintuitive gem: Even 1-step sampling beats the sketch-LC variant. Normally 1-step generation is a quality disaster. Here it isn't, because the local sketch controls supervise the generator densely in time — they hand the few-step generator a clean per-frame target, overcoming the quality collapse you'd expect at 1–2 steps. Control isn't just a feature; it's a regularizer that makes extreme distillation viable.

Ablation 2: block size & stride (BAR)

Block size B is anti-correlated with both FD and error — a clean speed–quality tradeoff (smaller blocks = lower latency but worse quality). Stride k, however, has little relationship to performance. That means FlashFoley needs surprisingly little preceding context to stay coherent — you can use a large stride (stream more fresh audio per chunk) almost for free.

Ablation Explorer — the FD vs control-error frontier

Each dot is a configuration; lower-left is better (low FD, low control error). Hover/tap points to read the config. Filter & steps: see steps barely move FD, while filter width trades control for quality. Block & stride: see block size B drive the frontier while stride k barely matters.

What surprising result did the sampling-steps ablation reveal?

Chapter 10: Connections & Cheat Sheet

FlashFoley is a synthesis paper: it stands on three prior lines and welds them into the first open-source, fast, controllable, streamable sketch2audio system.

control
Sketch2Sound — time-varying volume/pitch/brightness controls via PTP (slow, closed-source)
speed
ARC Post-Training — relativistic+contrastive adversarial distillation for fast TTA (text-only)
streaming
Live Music Models — chunk-based fixed-window autoregression for real-time generation
2026
FlashFoley — control + ARC + block-AR, all on a rectified-flow DiT (Stable Audio Open Small). 75 ms offline, 6 s streaming.

The cheat sheet — every key equation

IdeaEquation / RuleWhat each symbol means
RF corruptionzt = (1−t)z0 + tεz0=clean latent, ε=noise, t∈[0,1]
RF velocity / lossv=ε−z0; min ‖v−vθ2vθ=DiT velocity prediction
PTP injectionh'init = hinit + Σi Wi fiWi=per-control linear (Ki→H), fi=control
Relativistic lossf(D(&zcirc;s)−D(zs)), f=−log(1+e−x)paired real/fake, same C; boundary per real sample
Contrastive lossf(D(zs,P[C])−D(zs,C))P[C]=shuffled text only; forces D to read prompt
ARC objectiveminφmaxψR + λℒC, λ=1G=generator, D=discriminator
Streaming latency≈ B·S/NB=block size, S=clip seconds, N=latent frames

The one-paragraph summary you could give on a whiteboard

FlashFoley starts from a rectified-flow text-to-audio DiT (Stable Audio Open Small). Stage 1: finetune on the velocity loss while injecting three time-varying sketch controls (volume, pitch, brightness) — plus inpainting masks — through Pre-Transformer Projection, a per-control linear added to the hidden state for ~0.1% new params; a random-width median filter becomes the inference dial between "render exactly" and "loose sketch." Stage 2: ARC post-training distills 50 steps down to a few via a relativistic adversarial loss (score the difference between paired real/fake to kill mode collapse) plus a contrastive loss that shuffles text only (shuffling the sketch makes the discriminator ignore text and lose timbre). Result: 11.88 s stereo 44.1 kHz in 75 ms, ~10× faster, no quality loss. Inference: a block-autoregressive chunker generates overlapping B-frame blocks with forced overlap, cutting streaming latency to ~B·S/N so you hear the first chunk while still sketching.

"We address this unnecessary tradeoff between speed and control... generating 11s samples from audio sketches in 75ms."
— Novack et al., FlashFoley (ICASSP 2026)