How to turn a slow, offline, bidirectional audio diffusion model into a real-time musical instrument you can jam with on a gaming laptop — by routing clean context so KV-caching finally works for diffusion.
Imagine standing on stage with a synthesizer that doesn't play notes — it plays music. You whisper "drum-n-bass," and a fresh groove streams out of the speakers. You bend a slider, and the texture morphs in real time. You play a guitar lick, and the machine improvises an accompaniment around you, right now, with no perceptible delay.
That is the promise of interactive streaming music generation: a generative model you can play with, like an instrument, not a render farm you wait on.
Why isn't diffusion streamable? Because a diffusion (or flow-matching) model generates a whole chunk of audio by iterating over noise levels, not over time. It attends bidirectionally across the entire chunk at every denoising step. There is no natural "left-to-right, one frame at a time" structure to exploit — so the cheap trick that makes language models fast, KV-caching, simply doesn't apply.
Let's make the inefficiency painfully concrete. To generate one block of audio, you need K denoising steps (say K=50). Naive block-wise diffusion runs a full forward pass over all T frames — both the clean context you already have AND the noisy frames you're generating — on every one of those 50 steps.
| System | Per-block forward passes | What gets recomputed |
|---|---|---|
| Discrete-AR LMM (encoder-decoder) | 1 encode + o decodes | Context encoded once, cached |
| Naive block diffusion | K full passes over s+o frames | Context re-encoded every step |
The diffusion model re-encodes its own fixed, unchanging history 50 times per block. That is the bottleneck. The paper's blunt finding: out of the box, block-wise diffusion is strictly worse than the discrete-AR systems it hoped to replace.
Here is the whole paper in one sentence: the clean context and the noisy target are two different kinds of thing, so stop mixing them together at the input.
In a naive setup, the model concatenates the clean history frames and the noisy frames-being-generated along the channel dimension and feeds them through one shared input projection with full bidirectional attention. Because the noisy frames change at every denoising step, and because attention lets everything see everything, the representation of the clean history also changes at every step. So you can never cache it.
K denoising steps. KV-caching for diffusion, unlocked.Once you've made diffusion stream efficiently, two things fall out that the discrete-AR giants cannot do:
B). Everything else is the pre-trained checkpoint. Total training: under 8 GPU-hours.Before we can stream it, we need to understand what these models actually do. LMDMs are built on flow matching with an optimal-transport path (also called Rectified Flow). It's diffusion's cleaner cousin, and it's the dominant paradigm in modern audio generation.
You never operate on raw waveforms — they're too long. A stereo clip a ∈ R2×L·fs (2 channels, length × sample-rate samples) is first compressed by a VAE into a compact latent x ∈ RC×T: C channels, T latent time frames. Each xt is one frame of music — think of it as a fraction of a second of sound, encoded as a vector.
T ≈ tens of frames instead of hundreds of thousands of samples. Streaming a frame at a time is now tractable.Flow matching defines a dead-simple corruption: linearly interpolate your clean data with Gaussian noise, parameterized by a noise level k ∈ [0,1]:
Read it like a slider. At k=0 you have pure clean music x. At k=1 you have pure noise ε. In between, a straight-line blend. Generation is just running this slider backwards, from k=1 (noise) to k=0 (music).
Differentiate the forward path with respect to k and you get the constant velocity that points from data toward noise:
That's the entire target. We train a network vθ(x(k), k) to predict this velocity at any noise level, by regressing against the true v:
Where vθ is the learned velocity field (a DiT — diffusion transformer), x(k) is the noised input, k is the current noise level, and ε−x is the ground-truth direction. At sampling time we just solve the ODE dx/dk = vθ in reverse using Euler, Heun, or a "ping-pong" sampler, taking K steps from noise to music.
Say a single latent value is x = 0.8 and we drew noise ε = −0.2. At noise level k = 0.5:
x(0.5) = 0.5·0.8 + 0.5·(−0.2) = 0.40 − 0.10 = 0.30v = ε − x = −0.2 − 0.8 = −1.0k: 0.5 → 0.4, step Δk = −0.1): x(0.4) = x(0.5) + v·Δk = 0.30 + (−1.0)(−0.1) = 0.40The estimate moved from 0.30 back toward the clean 0.80. Repeat for all K steps and you arrive at the music. The interactive below lets you watch this slider in both directions.
k, completely independent of the time axis t. That decoupling is exactly why naive diffusion uses bidirectional time attention — and exactly the property the paper exploits to cache the time-dimension context.vθ learn to predict?To stream, you don't generate the whole song at once. You generate it in blocks. Given s frames of past audio context, generate the next o frames, then slide the window forward and repeat — forgetting the oldest history, encoding your fresh output as new context.
Where x1:s is the s-frame clean history, xs:s+o is the next o-frame block we're generating, and c is conditioning (text prompt, sketch, another instrument's audio). This is exactly how the discrete-AR LMMs work too — the difference is purely how each block gets generated.
Standard diffusion outpainting hands the model its clean history by concatenating it as extra channels. You build a fixed conditioning tensor that holds the clean frames where they exist and zeros everywhere else:
i.e. the first s frame-slots carry the clean context; the remaining o = T−s target slots are zero. The model's actual input each step is this stacked alongside the current noisy latent x(k). Training is almost vanilla flow matching: sample a noise level, append xclean, predict the velocity.
At inference, after every denoising step the model resets the first s frames of its iterate back to the clean context (at the appropriate noise level), so the history never drifts. Algorithm 1 in the paper does exactly this in a double loop: for each block, for each of K noise steps, run a full DiT pass over s+o frames.
xclean are fixed for the entire block. Yet because attention is bidirectional and the input is channel-concatenated, their internal representation is recomputed on all K steps. The paper's complexity for naive diffusion is O((E + D)1:T · K) — encoding and decoding fused into one operation over all frames, run every step. The discrete-AR LMM is O(E1:s + Σ Dt) — context encoded once.Here's the precise mechanism. Write the DiT's input projection as Winit = [A, B], where A handles the noisy latent and B handles the concatenated condition. The initial hidden state before any attention block is:
Now split by region. Because xconcat is zero past the first s frames:
That second line is the whole problem. The part of the hidden state that's supposed to "encode the past" is contaminated by the noisy latent A·x(k)1:s — which is different at every noise level k. So the encoder's input changes every step. Chapter 4 fixes exactly this term.
This is the heart of the paper, and it's two small surgical edits to the leaky equation from Chapter 3. Watch the noise contamination disappear.
We already know a priori which frames are context and which are target. So define a binary routing mask r := [01:s, 1s:s+o] — zero on context, one on target — and apply it to the noisy latent before projecting. The input becomes:
Because r zeros out the noisy latent on the first s frames, the leaky A·x(k)1:s term vanishes:
The context's initial hidden state is now the same for every noise level. One leak sealed.
But there's a second leak. Even with a clean initial state, bidirectional attention lets the context frames attend forward to the (noisy) target — so after the first attention block, the context encoding starts changing again as a function of the target. The fix is an asymmetric mask:
Now the context's representation is fully decoupled from the target at every layer. It is an "encoding" of the past that the target "decodes" against — exactly the encoder/decoder split of an LMM, but implemented implicitly inside one DiT via a mask.
K denoising steps for the target attending against the frozen cache — zero recomputation of the context. Complexity drops to O(E1:s + Ds:T·K): one encode, then iterate the decode. Identical complexity class to the LMM, achieved by a finetune.Below is the paper's Figure 2 made interactive. Toggle the routing mask and the attention mask on/off and watch what happens to the context's hidden state across noise levels. With both ON, the green "context encoding" stays flat as you sweep noise — that flat line is the cacheable representation. With either OFF, it wobbles, and the cache is invalid.
The attention mask is a dial, not a switch. The paper offers two settings, trading off how much you can cache against how fast the model adapts to new context.
The Chapter-4 mask (context attends bidirectionally within itself; target sees all). This caches K/V across the K denoising steps of a block. But the full s-frame window uses bidirectional self-attention, so when you slide forward and add a new block to the context, the whole window's encoding changes. You must re-encode all s context frames for every new block. Complexity: O(E1:s + Ds:T·K) — same class as the LMM.
Push the mask further: make the context block-causal — each o-sized block of context can attend only to past blocks (or within itself), never forward. Now adding a freshly generated block doesn't disturb the encodings of earlier blocks (nothing attended forward to them). So after a one-time warmup encoding each block, you cache over both noise and time, only ever encoding the single newest block. Complexity: O(Es−o:s + Ds:T·K) — strictly faster than the LMM, which must re-encode its whole context per block.
One more engineering nicety: at inference, the custom attention masks aren't needed at all. The context encode happens in a fully-bidirectional region (the whole context for Enc-Dec, each block for Block-Causal), and the target decode attends against a clean cache — so both can use highly-optimized flash-attention kernels with no custom-mask overhead. Combined with torch.compile, round-trip latency lands at 110–170 ms on a workstation GPU, with KV-caching giving a 20–25% per-pass speedup.
We can stream efficiently now. But there's a deeper sickness in any autoregressive generator: error accumulation. Training supervises the model one block at a time, on ground-truth context. At inference, the model conditions on its own outputs — small errors compound, and after a minute the music drifts into mush.
The standard cures in AR music generation are ugly: brittle RL pipelines, or explicitly-trained reward models. ARC-Forcing avoids both, by fusing two recent ideas.
Because diffusion sampling is differentiable (no discrete codebook draw), you can generate a full B-block rollout from the model and backprop through the whole thing. The model trains on its own rollouts — exactly matching the inference scenario. To make this affordable: pick a random number of steps k ~ U[2, Kmax] per block and only propagate gradients on the final step (the rest run no-grad). KV-caching keeps the rollout cheap.
Instead of a hand-built reward model, learn the reward as a discriminator Dψ that you co-train. Give it a generated rollout and a real-music clip (same controls, same starting context), noise both to the same level, and have it score which is real via the relativistic loss:
The word "relativistic" is the trick: Dψ never judges a clip in isolation, only relative to a real one. This sidesteps the degenerate collapses that plague ordinary GAN objectives, and — crucially — it provides supervision on the full multi-block rollout, not single blocks. That's what fights long-horizon drift.
To stop the discriminator from fixating on high-frequency texture and ignoring the prompt, add an auxiliary contrastive loss on real music with correct-vs-wrong captions:
where P is a random batch permutation pairing each clip with someone else's prompt. The discriminator is trained on LR + λLC (with λ=1), so it rewards both realism and prompt adherence.
Dψ directly from the finetuned LMDM gave a weak discriminator that destabilized training — because Dψ needs a much larger context window (≈30 s) than the generator (≈10 s). The fix: warm-start the discriminator's backbone on longer audio segments (plain flow-matching, a few thousand iters) before adversarial training. A detail you'd only discover by hitting the wall.After ARC-Forcing the model becomes a few-step generator — it can sample in 1 to 8 steps without classifier-free guidance (using a distilled "ping-pong" sampler), dropping total latency to ~30 ms. And error accumulation is crushed: metrics that steadily degraded over 2 minutes without ARC-Forcing stay flat with it.
Because LMDMs model pθ(xs:s+o | x1:s, c) with no restriction on what c is, a single architecture unifies tasks that prior work built bespoke systems for. The paper organizes the space along two axes.
| Global (c ∈ R) | Local (c ∈ RT) | |
|---|---|---|
| Instrument-like describes the target output; latency = synth speed | Text prompt + prompt transitions | Sketch controls (top-k CQT pitch, loudness curve) |
| Accompaniment-like external context on its own clock; must balance reactivity vs latency | — | Live jamming / accompanying stem |
c is a single text prompt with no temporal axis. Interaction comes from prompt transitions — cross-fading "driving EDM" into "sad country" in real time. Classified as instrument-like because you actively modulate it.c ∈ RT gives the model time-aligned hints about what the future block should contain — e.g. top-k CQT bins (a pitch sketch) plus a loudness envelope. You "draw" the music's contour and the model fills in timbre.tf < 0: it only sees the partner's stream up to some cutoff before the target block, to leave room for compute latency.tf ≥ 0, the model can see the partner's audio that corresponds to the very block it's generating — perfectly synced, but impossible to stream (you'd have to wait for audio from the future). If tf < 0, you reclaim that time for inference, but the model must predict what the partner will play. The paper sweeps tf from ≈−2 s to +2 s and measures inter-stem alignment with CoCoLA score: tighter visibility hurts alignment, looser visibility kills real-time interaction. Live jamming lives in that trade-off.tf < 0 (negative future visibility) necessary?The headline numbers, all from a model with half the parameters and trained on ~100× less data than the discrete-AR LMMs.
Metrics: FD/KD (lower = better audio quality vs real distribution), CLAP (higher = better text adherence), TTFF (time-to-first-frame, seconds). With audio priming:
| Method | D-NFE | Sampler | TTFF↓ | FD↓ | CLAP↑ |
|---|---|---|---|---|---|
| Magenta RealTime | 800 | DPM++ | ≈4 | 72.1 | 0.35 |
| Stable Audio Open | 100 | — | 10.35 | 96.5 | 0.41 |
| MusicGen-Large | 2.4K | — | 10.81 | 190.5 | 0.31 |
| LMDM (ED) | 50 | Euler | 0.11 | 35.4 | 0.23 |
| LMDM (ED) + ARC-Forcing | 8 | Ping-Pong | 0.03 | 29.0 | 0.32 |
Read the bottom rows: ARC-Forcing takes the Enc-Dec LMDM from 50 denoising steps down to 8, cuts TTFF from 0.11 s to 0.03 s (vs 4–11 s for the baselines), and improves both quality (FD 35→29) and text adherence (CLAP 0.23→0.32). Faster and better — the post-training isn't a trade-off, it's a free lunch.
Generating up to 2 minutes and computing metrics on sliding windows: without ARC-Forcing, nearly every metric (FD-OpenL3, KL-PaSST, CLAP) degrades monotonically as the rollout grows. With ARC-Forcing, the curves stay flat. This is the clearest demonstration of error-accumulation control — and it holds for both Enc-Dec and Block-Causal (with one unexplained exception: Block-Causal FD on non-primed generation).
tf traces the predicted trade-off: more visibility = tighter sync, but you need tf<0 to actually stream. The model interpolates gracefully between the ground-truth-pair ceiling and the random-pair floor.The paper doesn't stop at benchmarks. It ships a real instrument: a sketch-conditioned LMDM deployed as a "generative delay" on a consumer gaming laptop, put in front of real musicians, and used in a live performance.
A classic delay pedal repeats your playing after a fixed time. A generative delay takes the musician's improvisation as the conditioning sketch, and instead of echoing it, regenerates it with new timbre and texture — a hallucinated reflection of what you just played. The musician plays, and a transformed version comes back, in time, as a new musical voice to react against.
LMDMs sit at the intersection of three fast-moving lineages — efficient streaming, autoregressive diffusion, and adversarial post-training. Here's how the pieces relate.
The deep lesson transcends music: any generative process with a fixed conditioning context and an iterative refinement loop can be sped up by separating the context's representation so it becomes loop-invariant and cacheable. The same "route it separately, mask it, cache it" recipe could apply to image inpainting, video extension, or any conditional diffusion where part of the input never changes during sampling.
| Symbol / term | Meaning |
|---|---|
x ∈ RC×T | VAE latent: C channels, T time frames of compressed audio |
k ∈ [0,1] | Noise level. k=0 clean music, k=1 pure noise |
v = ε − x | Flow-matching velocity: direction along the noise↔data path |
vθ | Learned DiT velocity network (the generator) |
s / o | Context length / output (target) block length, in frames |
r = [01:s, 1s:s+o] | Routing mask: 0 on context, 1 on target |
A, B | Input-projection sub-matrices for noisy latent / clean context. B is the only new param |
D-NFE | Diffusion network function evals (denoising steps) per block |
TTFF | Time-to-first-frame — the latency metric that decides "playable" |
tf | Future visibility in jamming. tf<0 = predict ahead to leave compute time |
LR / LC | ARC relativistic loss / contrastive (right-vs-wrong-prompt) loss |