Music Generation and Audio-Language Models
Codec tokens, MusicGen, audio encoders and projectors, Thinker and Talker, TTFAB budgets and audio pitfalls.
- Concepts and terms
- Tasks and commands
- Annotated code
- Diagrams
- Defaults and numbers
- Troubleshooting
- Questions and tips
Audio becomes codec tokens#
From Lesson 08.11
Numbers that matter#
- Codec rate
- 8 RVQ codebooks at 75 Hz give 600 tokens/sec.
- Stream floor
- at 75 tokens/second, generate ≥75 tokens/sec per user.
- Talker floor
- 50 Hz speech tokens need ≥50 tok/s from the Talker.
- Codebook
- 1024 or 2048 entries is typical.
- MusicGen codec
- EnCodec at 32 kHz with 4 codebooks.
- Log-Mel shape
- 30 s at 100 Hz frame rate gives (3000, 80).
- Round trip
- below 500ms, the user stops noticing the lag.
Two generator families#
- Token-autoregressive
- a decoder-only transformer over flattened RVQ tokens.
- Delayed parallel
- MusicGen emits K codebook streams with per-stream offsets.
- VALL-E
- speech tokens from a text prompt and a 3-second voice sample.
- Latent diffusion
- Stable Audio Open works on compressed audio. Good for loops.
- Flow matching
- Stable Audio 2.5 uses it on continuous audio latents.
- Trend
- flow matching wins for music. Token-AR dominates speech.
From Lesson 08.11, Lesson 06.09
MusicGen, melody and FAD#
from audiocraft.models import MusicGenmodel = MusicGen.get_pretrained("facebook/musicgen-small")300M, fastmodel.set_generation_params(duration=10)seconds of audiowav = model.generate(["upbeat synthwave with driving drums, 128 BPM"])torchaudio.save("out.wav", wav[0].cpu(), 32000)32 kHz outputmelody, sr = torchaudio.load("humming.wav")wav = model.generate_with_chroma(keeps the tune, swaps timbre ["jazz piano cover"], melody.squeeze(), sr)from frechet_audio_distance import FrechetAudioDistancefad = FrechetAudioDistance()VGGish embedding distancefad.get_fad_score("generated_folder/", "reference_folder/")lower is betterFrom Lesson 06.09
Audio-language model template#
From Lesson 06.10
Projector and audio Q-former#
class AudioProjector(nn.Module): def __init__(self, audio_dim=1280, llm_dim=4096): super().__init__() self.down = nn.Linear(audio_dim, llm_dim)audio to LLM width self.act = nn.GELU() self.up = nn.Linear(llm_dim, llm_dim) def forward(self, audio_features): return self.up(self.act(self.down(audio_features)))qf = QFormer(n_queries=8, hidden=20)N=8 queriestokens = qf.forward(frames)99 frames in, 8 tokens outQ&A#
- When is a cascade enough?
- Transcription is the goal, with no music and no emotion.
- When do I need end-to-end?
- Music, emotion, multi-speaker or complex audio reasoning.
- What does a cascade lose?
- Mood, speaker identity, timing and deepfake cues.
- Why a small Talker?
- A 7B Talker falls behind the 50 tok/s floor.
- Why TMRoPE?
- It gives each token an absolute timestamp. Vision, audio and text align.
- Half or full duplex?
- Qwen2.5-Omni is half-duplex by default. Moshi supports full-duplex.
From Lesson 12.19, Lesson 12.20
Log-Mel and encoder settings#
| Setting | Default | Note |
|---|---|---|
| Sample rate | 16 kHz | Resample first |
| Window | 25ms | win_ms: int = |
| Hop | 10ms | hop_ms: int = |
| Mel filters | 80 | 0-8000 Hz |
| Log compress | math.log(1 + x) | Dynamic range |
| Q-former queries | 32 or 64 | AF3 uses 64 |
| Whisper encoder | 12-layer | Frozen in the ALM pattern |
Thinker and Talker#
From Lesson 12.20
TTFAB budget at 7B#
| Setting | Default | Note |
|---|---|---|
| Mic to audio tokens | 40-80ms | Streams |
| Prefill | 100-200ms | Much more at 70B |
| First Thinker text token | 40ms | |
| Talker on first text token | 20ms | |
| First speech tokens commit | 40ms | |
| Residual-VQ decode | 30ms | rvq_decode = |
| Speech waveform decode | 50-80ms | wave_decode = |
| Total TTFAB | 320-510ms | 600-900ms at 70B |
Troubleshooting#
| Symptom | Cause | Fix |
|---|---|---|
| Music loops past 30 s | AR models loop | Crossfade, or use ACE-Step |
| Tempo leaves the BPM | Models wander | BPM tags, librosa beat_track |
| Mushy sung words | Open models are weak on lyrics | Commercial API or fine-tune |
| Hallucinations on silence | Whisper encoder issue | VAD-gate |
| Speakers mixed past 10 minutes | Long-audio degradation | Diarize first, then summarize |
| Multi-audio near 25% | Random-chance level | Do not trust "which clip" tasks |
| Errors from RVQ layer 1 spread | RVQ error accumulation | Temperature 0 on higher layers |
| Artifacts at clip joins | Crossfade boundaries | Careful overlap-add |
From Lesson 06.09, Lesson 06.10, Lesson 08.11
Tasks in code#
| Task | Code |
|---|---|
| Load the ALM processor | AutoProcessor.from_pretrained("Qwen/ |
| Generate an answer | model.generate(**inputs, |
| Load MMAU-Pro | load_dataset("gamma-lab-umd/ |
| Score MMAU-Pro officially | evaluate_mmau_pro_comprehensive.py |
| Cut audio into frames | window_frames(wave, |
| List TTFAB parts | ttfab(cfg) |
| Sample codec tokens | generate(counts, |
From Lesson 06.10, 06.10 code/main.py, 12.19 code/main.py, 12.20 code/main.py, 08.11 code/main.py, Lesson 08.11
Tips#
- To ship safely, generate instrumental only.
- Tag each generation with watermarks and metadata.
- Report each MMAU-Pro
categoryseparately. - Check the codec first. It caps output quality. DAC is the current open best.
- For voice cloning, add abuse detection and opt-out lists.
From Lesson 06.09, Lesson 06.10, Lesson 08.11