File size: 7,158 Bytes
b0cbdfc e26cecf b0cbdfc e26cecf b0cbdfc e26cecf b0cbdfc e26cecf b0cbdfc e26cecf b0cbdfc e26cecf b0cbdfc bb38cf3 b0cbdfc e26cecf b0cbdfc bb38cf3 b0cbdfc e26cecf b0cbdfc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | ---
base_model:
- sahilmahendrakar/Paradee-8M-v1.2
- sahilmahendrakar/Paradee-8M-v1.0
language:
- en
library_name: coreml
license: apache-2.0
pipeline_tag: text-to-speech
tags:
- text-to-speech
- tts
- coreml
- kokoro
- distillation
- apple-silicon
---
# Paradee-8M Core ML
Core ML conversions of [Paradee-8M](https://huggingface.co/sahilmahendrakar/Paradee-8M-v1.2) by Sahil Mahendrakar:
Kokoro-82M distilled into ~8M parameters, English TTS, 24 kHz. Paper: [arXiv 2610.06817](https://arxiv.org/abs/2610.06817).
| Release | Voices | Folder |
|---|---|---|
| [v1.2](https://huggingface.co/sahilmahendrakar/Paradee-8M-v1.2) | `af_heart`, `bf_isabella`, `am_puck`, `bm_fable` (British: `bf_`, `bm_`) | `v1.2/int8/` (11 MB, default), `v1.2/fp32/` |
| [v1.0](https://huggingface.co/sahilmahendrakar/Paradee-8M-v1.0) | `af_heart` | `int8/` (12 MB), `fp32/` |
Used by [FluidAudio](https://github.com/FluidInference/FluidAudio) (`ParadeeManager`, v1.2 by default). Conversion
code: [mobius `models/tts/paradee/coreml`](https://github.com/FluidInference/mobius/tree/main/models/tts/paradee/coreml).
## v1.2
Same two-model layout as v1.0 (below), plus a `voice` input on both models:
```
ParadeeText input_ids [1,T] int32, voice [1] int32 -> duration [1,T], d [1,224,T], asr_tok [1,512,T]
ParadeeAcoustic en [1,224,F], asr [1,512,F], noise [1,1,600F], voice [1] int32 -> audio [1,600F], 24 kHz
```
- `voice`: 0 `af_heart`, 1 `bf_isabella`, 2 `am_puck`, 3 `bm_fable` (`v1.2/config.json`).
- Phonemes are misaki's, American for `af_`/`am_` and **British for `bf_`/`bm_`** (`en.G2P(british=True)`), as
upstream. FluidAudio reads the British voices through `gb_lexicon_cache.json` in
[kokoro-82m-coreml](https://huggingface.co/FluidInference/kokoro-82m-coreml).
- The decoder end is v1.1's frame-rate source-filter head, rewritten for Core ML (GEMM STFT/iSTFT, int32 fixed-point
harmonic phase, closed-form sine bank). The noise is an input, so the graphs are deterministic.
- `CPU_ONLY` or `CPU_AND_NE` only; `ALL` / `CPU_AND_GPU` abort on the LSTMs.
Results (M5 Pro, macOS 27; 10 inputs × 4 voices):
- 0 duration differences vs PyTorch with the same noise; log-mel L1 to the released fp32 ONNX ≤ 0.012.
- Whisper large-v3-turbo WER: Core ML fp32 3.39 % = upstream ONNX fp32; Core ML int8 3.28 % = upstream int8 ONNX.
- ~200× real time on the CPU for text side + acoustic side (v1.0: 150×).
- FluidAudio `tts-benchmark --corpus minimax-english` (Parakeet round trip, includes G2P), int8: WER 0.93 %
(`af_heart`), 0.71 % (`bf_isabella`), 1.00 % (`am_puck`), 0.84 % (`bm_fable`), ~100× real time.
`samples/v1.2/`: upstream's five sample sentences in each voice, rendered by `v1.2/int8/`.
## Files (v1.0)
| Path | What |
|---|---|
| `int8/` | Default. `ParadeeText.mlmodelc` (3.1 MB) + `ParadeeAcoustic.mlmodelc` (9.1 MB), int8 per-channel weights; the phase-lock filter's DFT bases stay fp32 |
| `fp32/` | Same graphs in fp32 (12 + 22 MB). Matches PyTorch to rounding |
| `*/vocab.json` | Phoneme → id map (identical to Kokoro's) |
| `mlpackage/` | Source `.mlpackage`s for both variants |
| `config.json` | Vocab, sample rate, shape limits |
| `samples/` | The model card's five held-out sentences, rendered by `int8/` |
## Pipeline (v1.0)
```
text -> misaki-style en-US phonemes -> ids = [0, ...vocab ids..., 0] (<= 512 total)
ParadeeText input_ids [1,T] int32 -> duration [1,T], d [1,224,T], asr_tok [1,512,T]
host n_i = max(1, round(duration_i / speed)); F = sum(n)
en = d with column i repeated n_i times [1,224,F]
asr = asr_tok with column i repeated n_i times [1,512,F]
noise ~ N(0,1) [1,1,600F]
ParadeeAcoustic en, asr, noise -> audio [1,600F] float32, 24 kHz
```
- `F` may be 1…4000 (100 s at speed 1). Split longer input into chunks of ≤ 510 phonemes.
- `noise` is the harmonic source's Gaussian noise, passed in so the graph is deterministic. It is equivalent to the
upstream in-graph noise (9 per-harmonic channels mixed by a linear layer = one scaled channel).
- Phonemes must be written the way [misaki](https://github.com/hexgrad/misaki) writes them (Kokoro's G2P); that is
all Paradee saw in training. That includes misaki's last step, flap `ɾ` → `T` and glottal stop `ʔ` → `t`:
lexicon-only frontends that skip it garble words like "kittens" and "satellite".
- Use `CPU_ONLY` or `CPU_AND_NE`. **Do not use `ALL` / `CPU_AND_GPU`**: the LSTMs abort in MPSGraph
(`GPURNNOps … JIT not supported`), the same failure Kokoro's prosody stage has.
## Accuracy (v1.0, M5 Pro, macOS 27)
10 inputs: the README quick-start line, the five held-out sentences, a numbers/abbreviation sentence, a 28.6 s
paragraph, and one sentence at speed 0.8 and 1.3.
- fp32 vs PyTorch with the same noise: 0 duration rounding differences, identical lengths. Log-mel L1 against the
upstream ONNX equals the ONNX's own run-to-run difference in every case (e.g. 0.123 vs 0.123).
- Whisper large-v3-turbo transcripts of Core ML fp32 and upstream ONNX fp32 are identical (WER 3.81 %; every miss is
text normalization: "Ia", "favourite", "Zzyzx").
- int8: log-mel L1 to fp32 ONNX 0.18–0.20 vs 0.21–0.31 for upstream `paradee_int8.onnx`; WER 3.81 % vs 2.97 %
(one word of ~236).
FluidAudio `tts-benchmark --corpus minimax-english` (100 phrases, Parakeet TDT round trip, Swift, CPU, includes the
English G2P frontend): WER 1.20 % / CER 0.14 % for both int8 and fp32, RTFx ~100, 77 ms median per phrase.
Conversion notes: the 1024-point phase-lock STFT is a gather + matmul + overlap-add instead of strided convolutions
(the conv form ran ~40× slower on the Core ML CPU), and kokoro's random harmonic start phases are omitted because the
upstream graph never reads them.
## Changelog
| Date | Files | Change | Issue | mobius PR | FluidAudio PR | HF commit |
|---|---|---|---|---|---|---|
| 2026-10-28 | `v1.2/int8/`, `v1.2/fp32/`, `v1.2/mlpackage/`, `v1.2/config.json` | Paradee-8M v1.2, four voices, `voice` input | [FluidAudio #1072](https://github.com/FluidInference/FluidAudio/issues/1072) | [#114](https://github.com/FluidInference/mobius/pull/114) | [#1073](https://github.com/FluidInference/FluidAudio/pull/1073) | [`25644d3e`](https://huggingface.co/FluidInference/paradee-8m-coreml/commit/25644d3ec44eb0d964eb7cab13aef10531c476cb) |
| 2026-10-28 | `samples/v1.2/` | v1.2 samples, five sentences per voice | [FluidAudio #1072](https://github.com/FluidInference/FluidAudio/issues/1072) | [#114](https://github.com/FluidInference/mobius/pull/114) | [#1073](https://github.com/FluidInference/FluidAudio/pull/1073) | [`8afbeb2d`](https://huggingface.co/FluidInference/paradee-8m-coreml/commit/8afbeb2d58fd8cee7ca58c813ecca86dea25c3bc) |
## License
Apache-2.0, same as Paradee and Kokoro-82M. Paradee © Sahil Mahendrakar.
```bibtex
@misc{mahendrakar2026paradee,
title = {Paradee: Distilling Kokoro-82M into an 8M-Parameter Single-Voice Text-to-Speech Model},
author = {Mahendrakar, Sahil},
year = {2026},
url = {https://huggingface.co/sahilmahendrakar/Paradee-8M-v1.0}
}
```
|