Novack, Brade, et al. (UCSD / MIT / Adobe), 2026

Live Music Diffusion Models

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.

Prerequisites: Flow Matching / Diffusion intuition + Attention & KV cache basics
11
Chapters
5+
Simulations

Chapter 0: The Problem

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.

The core tension: The models good enough to do this (Google's Live Music Models, MusicGen-Large) are discrete autoregressive giants — over 40 GB of VRAM, billions of parameters. You cannot run them on a laptop. The small, controllable, open-source models that could run on a laptop are diffusion models — and diffusion is fundamentally not streamable.

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.

A concrete latency wall

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.

SystemPer-block forward passesWhat gets recomputed
Discrete-AR LMM (encoder-decoder)1 encode + o decodesContext encoded once, cached
Naive block diffusionK full passes over s+o framesContext 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.

The challenge this paper sets itself: Can we keep diffusion's gifts — small size, data efficiency, fine-grained controllability, an open-source ecosystem — while recovering (and then beating) the inference efficiency of the discrete-AR giants? And can we do it with a finetune, not a from-scratch retrain?
Why can't standard audio diffusion models stream like a discrete-AR language model?

Chapter 1: The Key Insight

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.

The insight: Route the clean context through its own projection, and use an attention mask so the context can never attend to the noisy target. Now the context's hidden states are identical for every noise level — a fixed function of the history alone. That means you can encode it once, cache its keys and values, and reuse them across all K denoising steps. KV-caching for diffusion, unlocked.

The three moves

1. ROUTE
A binary routing mask splits each input frame into "clean context" vs "noisy target" and sends each through a separate input projection (matrix A for noisy, B for clean).
2. MASK
A custom attention mask forbids context frames from attending to target frames. The context's encoding is now decoupled — independent of the noise level.
3. CACHE
Encode the context once, cache its K/V at every transformer layer, and run all denoising steps for the target using the cache. No recomputation.

Two extra superpowers diffusion gets for free

Once you've made diffusion stream efficiently, two things fall out that the discrete-AR giants cannot do:

What single architectural change unlocks KV-caching for diffusion?

Chapter 2: Flow Matching Background

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.

The data: audio becomes a latent

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.

Why a latent, not the waveform? A few seconds of 44.1 kHz stereo is hundreds of thousands of samples. The VAE crushes that by ~1000× into a handful of frames, so the diffusion transformer attends over T ≈ tens of frames instead of hundreds of thousands of samples. Streaming a frame at a time is now tractable.

The forward process: straight-line noising

Flow matching defines a dead-simple corruption: linearly interpolate your clean data with Gaussian noise, parameterized by a noise level k ∈ [0,1]:

x(k) = (1 − k) · x + k · ε,    ε ~ N(0, I)

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).

The velocity: what direction is "toward music"?

Differentiate the forward path with respect to k and you get the constant velocity that points from data toward noise:

dx(k)/dk = ε − x := v

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:

L = Ex, k, ε ∥ vθ(x(k), k) − (ε − x) ∥2

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.

Worked example: one denoising step by hand

Say a single latent value is x = 0.8 and we drew noise ε = −0.2. At noise level k = 0.5:

The 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.

Flow Matching: drag the noise level, watch the velocity
noise k
k = 0.50 — halfway between music and noise
Why this matters for streaming: Generation iterates over the noise axis 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.
In flow matching, what does the network vθ learn to predict?

Chapter 3: Block-AR Outpainting (the baseline that's too slow)

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.

model: pθ(xs:s+o | x1:s, c)

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.

How naive diffusion conditions on history: channel-concat

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:

xconcat := [xclean, 0s:T]C

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.

The inference trick — and why it's wasteful

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.

The buried cost: The context 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.

Pinpointing the leak: the initial hidden state

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:

hinit,k = Winit[x(k), xconcat]C = A·x(k) + B·xconcat

Now split by region. Because xconcat is zero past the first s frames:

hinit,ks:T = A·x(k)s:T   (target: depends on noise ✓)
hinit,k1:s = A·x(k)1:s + B·xclean   (context: ALSO depends on noise ✗)

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.

In naive channel-concat diffusion, why does the clean context's hidden state change at every noise level?

Chapter 4: Routing + Attention Masks (the SHOWCASE)

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.

Move 1 — the routing mask

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:

hinit,k = Winit[r ⊙ x(k), xconcat]C

Because r zeros out the noisy latent on the first s frames, the leaky A·x(k)1:s term vanishes:

hinit,ks:T = A·x(k)s:T   (target, unchanged)
hinit,k1:s = B·xclean   (context: pure function of history ✓)

The context's initial hidden state is now the same for every noise level. One leak sealed.

Move 2 — the attention mask

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.

The payoff: Pass the clean context through the DiT once, cache the Key/Value states at every transformer layer, then run all 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.

SHOWCASE: build the routing pipeline yourself

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 LMDM routing surgery — flip the masks, watch the cache become valid
Both masks ON — context encoding is noise-independent → KV-cacheable ✓

The core insight in runnable code

# LMDM forward: separate projections + routing mask + asymmetric attention def lmdm_initial_state(x_k, x_clean, s): # x_k: [B, C, T] noisy latent over all T = s+o frames # x_clean: [B, C, s] the clean history T = x_k.shape[-1]; o = T - s r = torch.cat([torch.zeros(s), torch.ones(o)]) # routing mask # Route: noisy term killed on context, clean term injected via B h = A(r[None,None] * x_k) # A * (r ⊙ x_k) h[..., :s] = h[..., :s] + B(x_clean) # + B * x_clean return h # h[:s] depends ONLY on x_clean -> same for every k def attn_mask(s, o): # Enc-Dec variant T = s + o; m = torch.zeros(T, T, dtype=torch.bool) m[:s, :s] = True # context attends only to context m[s:, :] = True # target attends to everything return m # Inference: encode context once, cache K/V, reuse for all K denoise steps KV = vtheta_encode(x_clean, c, k=0) # ONE pass, cached for j in range(K, 0, -1): # target only, no context recompute v = vtheta(x_k, c, k_j, kv_cache=KV) x_k = solver_step(v, x_k, k_j, k_{j-1})
Why are BOTH the routing mask and the attention mask needed for KV-caching?

Chapter 5: Enc-Dec vs Block-Causal

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.

Encoder-Decoder LMDM: cache over noise

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.

Block-Causal LMDM: cache over noise AND time

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.

Attention masks side-by-side — what each frame can see
Naive: every frame attends to every frame — nothing is cacheable.
The empirical surprise: Block-Causal is theoretically faster, yet Enc-Dec wins on quality. The reason: Enc-Dec re-reads the full context each block, so it can keep re-interpreting the whole musical history as new audio arrives. Block-Causal freezes old encodings. The paper concludes that the ability to adapt the contextual encoding — even at the cost of more compute and slightly faster drift — is worth it, and focuses on Enc-Dec for the rest of the work.

The inference-time speedup, concretely

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.

Why does the paper ultimately prefer Enc-Dec over the theoretically-faster Block-Causal variant?

Chapter 6: ARC-Forcing (RL-free rollout post-training)

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.

Ingredient 1 — Self-Forcing

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.

Ingredient 2 — ARC (Adversarial Relativistic Contrastive)

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:

LR = E[ f( Dψ(noised generated) − Dψ(noised real) ) ],   f(x)=softplus(x)

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.

Ingredient 3 — a contrastive term for text-following

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:

LC = E[ f( Dψ(real, wrong prompt P(c)) − Dψ(real, right prompt c) ) ]

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.

The non-obvious gotcha they had to fix: Initializing 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.

The payoff: fewer steps, no CFG, stable for minutes

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.

Error accumulation over time — toggle ARC-Forcing
drift over 2 min of generation
How does ARC-Forcing avoid needing a hand-trained reward model?

Chapter 7: The Live Music Design Space

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 transitionsSketch controls (top-k CQT pitch, loudness curve)
Accompaniment-like
external context on its own clock; must balance reactivity vs latency
Live jamming / accompanying stem

The three concrete modalities

Why future visibility is the whole jamming problem: If 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.
In the live-jamming (accompaniment) setting, why is tf < 0 (negative future visibility) necessary?

Chapter 8: Experiments

The headline numbers, all from a model with half the parameters and trained on ~100× less data than the discrete-AR LMMs.

Time-to-first-frame (lower = more interactive)

Text-conditioned global metrics (Table 1)

Metrics: FD/KD (lower = better audio quality vs real distribution), CLAP (higher = better text adherence), TTFF (time-to-first-frame, seconds). With audio priming:

MethodD-NFESamplerTTFF↓FD↓CLAP↑
Magenta RealTime800DPM++≈472.10.35
Stable Audio Open10010.3596.50.41
MusicGen-Large2.4K10.81190.50.31
LMDM (ED)50Euler0.1135.40.23
LMDM (ED) + ARC-Forcing8Ping-Pong0.0329.00.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.

Per-window: ARC-Forcing kills drift over time

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).

Prompt transitions and accompaniment

The takeaway result: A small, open-source-derived diffusion model, finetuned in <8 GPU-hours and post-trained without any RL, matches a 40 GB+ discrete-AR system on quality and text-following while being two orders of magnitude faster to first sound.
What does the per-window evaluation over 2 minutes primarily demonstrate?

Chapter 9: Real-Time Deployment — the generative delay

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.

What "generative delay" means

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.

The deployment stack

Train
PyTorch flow model → LMDM finetune (<8 GPU-hr) → ARC-Forcing (few-step, no CFG)
Export
ONNX export of the few-step generator + VAE; flash-attention paths, no custom masks at inference
Host
C++ / JUCE audio plugin runs the ONNX graph in the real-time audio thread on a consumer laptop GPU
Play
~30 ms round trip → musician improvises, generative delay responds in time

Why each piece is non-negotiable for "playable"

The arc of the whole paper, in one line: Efficiency (KV-cache) buys you real-time; stability (ARC-Forcing) buys you long-form; controllability (sketch/jam) buys you playability. All three together turn a research checkpoint into something a musician can hold and perform with on hardware they already own.

Honest limitations

Why is the model exported to ONNX and hosted in a C++/JUCE plugin rather than run in Python?

Chapter 10: Connections

LMDMs sit at the intersection of three fast-moving lineages — efficient streaming, autoregressive diffusion, and adversarial post-training. Here's how the pieces relate.

2020
DDPM — iterative denoising diffusion (the noise-axis generator)
2022
Rectified Flow / Flow Matching — straight-line ODE paths, the LMDM backbone
2024
Diffusion Forcing → causal video diffusion — per-frame noise schedules, history conditioning
2025
Self-Forcing (video) + ARC (offline audio) — rollout post-training + relativistic adversarial reward
2026
LMDM — routed-context KV-caching + ARC-Forcing → playable streaming music diffusion

The KV-cache idea, generalized

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.

Cheat sheet

Symbol / termMeaning
x ∈ RC×TVAE latent: C channels, T time frames of compressed audio
k ∈ [0,1]Noise level. k=0 clean music, k=1 pure noise
v = ε − xFlow-matching velocity: direction along the noise↔data path
vθLearned DiT velocity network (the generator)
s / oContext length / output (target) block length, in frames
r = [01:s, 1s:s+o]Routing mask: 0 on context, 1 on target
A, BInput-projection sub-matrices for noisy latent / clean context. B is the only new param
D-NFEDiffusion network function evals (denoising steps) per block
TTFFTime-to-first-frame — the latency metric that decides "playable"
tfFuture visibility in jamming. tf<0 = predict ahead to leave compute time
LR / LCARC relativistic loss / contrastive (right-vs-wrong-prompt) loss
"Treat the model as an instrument to be played with, not a render farm to wait on."
— the LMDM thesis, paraphrased