gguf/README.md
| 1 | # sanoTTS GGUF |
| 2 | |
| 3 | Single-file GGUF packaging of the sanoTTS nano voices, for |
| 4 | [audio.cpp](https://github.com/0xShug0/audio.cpp). |
| 5 | |
| 6 | | File | Voice | Params | Rate | Weights | Size | |
| 7 | |---|---|---:|---:|---|---:| |
| 8 | | `gguf/heart-nano.gguf` | heart-nano | 294,279 | 24 kHz | int8 | 357 KB | |
| 9 | | `gguf/heart.gguf` | heart | 2,272,145 | 24 kHz | f32 | 9.1 MB | |
| 10 | |
| 11 | ## What is inside |
| 12 | |
| 13 | Tensors are named after the PyTorch state dict — `duration.blocks.N.net.0.weight`, |
| 14 | `acoustic.frame_blocks.N.net.2.scale`, `decoder.blocks.N.pwconv1.weight` — and |
| 15 | every shape constant travels in the GGUF key/value header under `sanotts.*`, so |
| 16 | a consumer needs no generated C header to rebuild the layout. |
| 17 | |
| 18 | Quantised regions keep their int8 rows alongside f32 `scale` and `bias` as three |
| 19 | separate tensors rather than being dequantised, so the arithmetic a consumer |
| 20 | performs is exactly the arithmetic these were exported for. Row padding |
| 21 | (`n16 = ceil16(in_flat)`, so SIMD kernels can read whole 16-byte groups) is |
| 22 | preserved: those are shipped bytes, not parameters, and dropping them would move |
| 23 | every byte offset. |
| 24 | |
| 25 | ## Provenance and verification |
| 26 | |
| 27 | Converted from the blobs in the |
| 28 | [voices-v2](https://github.com/Ampixa/sanoTTS/releases/tag/voices-v2) release by |
| 29 | [`tools/export_nano_gguf.py`](https://github.com/Ampixa/sanoTTS/blob/master/tools/export_nano_gguf.py). |
| 30 | |
| 31 | Conversion is lossless and checked both ways: |
| 32 | |
| 33 | * Rebuilding both blobs from the GGUF reproduces the originals **byte for byte**. |
| 34 | * Re-running the golden gate on the rebuilt weights gives the same correlation |
| 35 | against the float PyTorch references as the originals: **0.989703** for |
| 36 | heart-nano and **1.000000** for heart, against a 0.98 threshold. |
| 37 | |
| 38 | ## Architecture |
| 39 | |
| 40 | Duration student → contextual acoustic student → mel-100 → ConvNeXt-1D decoder |
| 41 | → iSTFT. The decoder is noise-fed, so a rendering is reproducible only with the |
| 42 | same seed; the reference implementations derive it as `sha256(text)[:8]`. |
| 43 | |
| 44 | Text input needs a 62-symbol misaki-normalised eSpeak-ng IPA front end. eSpeak-ng |
| 45 | is GPL-3.0 and is not included here. |
| 46 | |
| 47 | ## Licence |
| 48 | |
| 49 | Weights are distilled from Apache-2.0 (Kokoro) and MIT (piper) teachers. |
| 50 | The sanoTTS inference runtime is MIT; the wider project is GPL-3.0 because its |
| 51 | grapheme-to-phoneme layer embeds eSpeak-ng. See |
| 52 | [LICENSE.MIT](https://github.com/Ampixa/sanoTTS/blob/master/LICENSE.MIT). |
| 53 | |