Add arktts (Audio8-TTS-Preview-0.6b): DualAR TTS with zero-shot voice cloning - #867
Conversation
… cloning Adds the arktts model family: a DualAR transformer (24-layer slow AR emitting one semantic token per frame + 4-layer fast AR emitting 10 codec codebooks), with the bundled 44.1 kHz codec (DAC-style encoder/decoder, split semantic + residual RVQ, windowed transformer pre/post modules) and the reference prompt format for zero-shot voice cloning. Parity vs the PyTorch reference (fp32, CPU stream): unit/block outputs within 1e-4, reference-audio encode 100% code-exact, greedy generation 100% token-exact over a 102-frame validation utterance, decoded waveform max-abs 7.5e-6. Converted weights: mlx-community/Audio8-TTS-Preview-0.6b-bf16. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Formatting only (line wrapping) — the repo's pre-commit style hook reformatted arktts.py, codec.py, and test_arktts.py. No semantic changes: the 7 unit tests still pass and the PyTorch parity harness was re-run to confirm. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| ] | ||
| self.fast_norm = ArkttsRMSNorm(config.fast_dim, config.norm_eps) | ||
| self.fast_output = nn.Linear(config.fast_dim, config.codebook_size, bias=False) | ||
| self._freqs_cis = _precompute_rope( |
There was a problem hiding this comment.
These two cache arrays need to be materialized with e.g. mx.eval((self._freqs_cis, self._fast_freqs_cis)) at init time so the model doesn't crash moving across streams/threads.
lucasnewman
left a comment
There was a problem hiding this comment.
@xocialize Very nice, thank you! Can you fix the cache array issue I mentioned and add a README for the model, and then we can merge?
Review feedback from @lucasnewman: 1. The two rope tables are plain attributes, not module parameters, so nothing else forces them. Left lazy, their graph would first be evaluated inside whichever stream/thread ran the first forward, which crashes when the model is moved across streams. Now mx.eval'd at init. Verified by constructing on the GPU stream and running a forward on the CPU stream. 2. Added mlx_audio/tts/models/arktts/README.md following the house style (Voxtral/confucius4): supported model, Python + CLI usage, languages, options, architecture, conversion notes, parity numbers. The CLI block documents only flags that exist — mlx_audio.tts.generate has no --ref-audio/--ref-text, so cloning is noted as Python-API only rather than showing a command that would fail. 7/7 arktts tests green; black/isort clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for the review! Both addressed: 1. Cache arrays. Good catch — the two rope tables are plain attributes rather than module parameters, so nothing else was forcing them. They're now 2. README added at One small thing worth flagging: I'd initially written the CLI example with |
Adds the
arkttsmodel family — Audio8/Audio8-TTS-Preview-0.6b (Apache-2.0), a 0.6B multilingual TTS model with zero-shot voice cloning and a bundled 44.1 kHz codec. Architecture is DualAR (Fish S2 Pro-style): a 24-layer slow AR transformer emits one semantic token per frame; a 4-layer fast AR emits the frame's 10 codec codebooks conditioned on the slow hidden state.What's included
mlx_audio/tts/models/arktts/— model (arktts.py), codec (codec.py, DAC-style encoder/decoder + split semantic/residual RVQ + windowed transformer pre/post modules), mirroring the upstream remote-code structure file-for-filesanitize()consumes either raw upstream checkpoints (folds both parametrized and legacy weight norm, transposes conv layouts, reshapes Snake alphas) or the pre-converted mlx repo (idempotent)mlx_audio/tts/tests/test_arktts.py— sanitize contract + tiny-model forward/generation tests (no weights needed)Converted weights
mlx-community/Audio8-TTS-Preview-0.6b-bf16 (bf16 LM + fp32 codec), validated by fresh-download →
mlx_audio.tts.utils.load→ voice-clone generation.Parity vs PyTorch reference (fp32, CPU stream)
Usage
🤖 Generated with Claude Code