ampixa
// speak · sanoTTS

294k≠294k

e12nano, 294,642 parameters, runs real time on a microcontroller that costs about $3. heart-nano, 294,279 parameters, is the voice actually speaking in this browser tab below. Read quickly, that sounds like one small voice doing both. It isn't — and neither checkpoint has ever run on the other's hardware.

Here's an honest baseline for everything else on this page: the Nepali voice sitting in that same browser demo is 1.47M parameters, free to try, and has never been through a listening test — it predates sanoTTS's own scoring harness, so there's a parameter count and nothing else. Say you're a Nepali speaker reading नेपाली back from a machine: that's how early some of this still is.

e12nano · Arduino library only Pixel isometric breadboard with an ESP32-S3 chip and speaker, labeled e12nano 294,642, with a crossed-out 745k corrected to 567,008.

Measured on real silicon

294,642

int8 · 399 KB flash · the only nano checkpoint with an ESP32-S3 board result

heart-nano · browser demo + pip
// demo · type text, hear it spoken, nothing uploaded

The voice talking in this browser tab (heart-nano, 294,279 params) is not the same model as the one that runs real time on a microcontroller that costs about $3 (e12nano, 294,642 params) — two checkpoints from the same training sequence, shrunk and shipped separately, never tested on each other's hardware.

liveHTTP 200, checked 2026-11-06 · 30 voices, 16 languages, WASM in-browser

Never run on a chip

294,279

int8 · 337 KB weights · browser demo + pip package, not the Arduino build

294,642e12nano · Arduino/ESP32-S3 only
294,279heart-nano · browser + pip
0.383e12nano RTF, SIMD, ESP32-S3 · 2.6× real time
30 / 16heart-nano voices / languages · live, WASM
// field · source: field.png · words: e12nano, heart-nano, 294642, 294279, ESP32-S3, WASM, Arduino, pip, RTF, 363, सानो, heart, robot

// the chip · e12nano

The chip result belongs to a model called e12nano, 294,642 parameters, compiled only into the Arduino library — it isn't in the browser demo's 30 voices or the pip package's 27. It shares an architecture and the identical on-device int8 decoder code with the browser's voice; their internal names, e12nano and e13b, are one experiment apart. "Same sequence, one step apart" isn't "the same model." Nobody has put e12nano in a browser.

The number itself holds up well. On an ESP32-S3, the shipped SIMD build gets RTF 0.383 — 2.6 times faster than the audio it's producing — against a scalar build's 1.58, slower than real time. SIMD alone is a measured 4.13× speedup. All four build variants, SIMD or not, dual-core or not, produce bit-identical audio; only the speed changes.

The correctness gate requires both a correlation check and an output-scale check — they once saw a broken integer FFT pass the correlation test while playing audio ~500× too loud. A speed number without both gates "is not a result."

On the same board, same scalar kernel, model differing only: e12nano scores RTF 1.58 / corr 0.9947 / 399 KB flash against the larger shipped robot/R7 voice's RTF 3.69 / corr 0.9890 / 731 KB. Only 3 boards have real Arduino-path measurements; everything else "builds, never measured" or is untested.

// the browser · heart-nano

The browser demo is real too — 30 voices across 16 languages, nothing to install, text goes through an espeak-NG phonemizer compiled to WebAssembly and then that voice's own tiny network, nothing leaving your machine. But the ten languages added this September — German, Turkish, Russian, French, Spanish, Italian, Portuguese, Romanian, Czech, Arabic — are checked only against sixteen held-out sentences each. That tells you the words come out intelligible, not that anyone would want to listen to them.

Vietnamese and Indonesian score far worse on the no-reference quality metric than English does — 1.53 and 1.71, against English amy's 4.13 — even though the words mostly arrive correctly. No non-English voice in the whole catalog has been through a human listening test.

Shrinking heart to heart-nano, 7.7× smaller, held word accuracy almost exactly — 0.083 WER against 0.080 — but the no-reference quality score dropped from 3.48 to 2.29. That tradeoff, not any single RTF number, is the real finding here.

Independent downstream work exists too — a Japanese clean-room reimplementation and M5Stack ports, other authors' work, not Ampixa's. An independent AtomS3 report passed correctness but missed real time on a different model, language and board entirely — not a failed replication of e12nano.

How the four checkpoints actually connect

Every label here is a number from facts.md. The one edge that matters is the one that isn't drawn: nothing connects e12nano to the browser/pip side, and nothing connects heart-nano to a board measurement.

// scroll to see both sides →
e12nano 294,642 · int8 399 KB flash robot / R7 567,008 · int8 voices-v1 blob Arduino library arduino-lib-0.1.0 · ESP32-S3 target MEASURED · e12nano · ESP32-S3 RTF 0.383 SIMD / 1.58 scalar corr 0.994664 · 4.13× SIMD speedup gate: corr > 0.98 AND 0.80<rms<1.25 teacher models Piper / Kokoro checkpoints heart 2,272,145 · float32 · 24kHz mel100 heart-nano 294,279 · int8 · 337 KB browser demo tts.ampixa.com pip package sanotts 0.5.0 MEASURED · BROWSER 30 voices · 16 languages live, WASM, client-side, no upload HTTP 200 checked 2026-11-06 363 apart · same decoder never tested together × no browser build (e12nano) × no board measurement

What's next, what's missing

  • No non-English listening/MOS test exists for any voice — Nepali, Hindi, Chinese, or the ten languages added in September. WER on a tiny held-out set is an intelligibility proxy, not naturalness. Nepali would be the obvious one to start with, given the name.
  • e12nano and heart-nano need naming separately everywhere this project is described — the moment someone writes "the 294k voice," they've decided which one they mean without saying so.
  • The 30-row browser voice table is a README inventory, not independent proof every variant has a current downloadable package or a qualified listening result.
  • Whether excluded Gemini-derived training examples remain in public v0.2 weights is left ambiguous by the README itself.
  • GPL-3.0 covers most of the public repo (training tooling, eSpeak-NG frontend ports); only the runtime code under mcu/ and mobile/ is MIT. Reuse accordingly.
// receipts · every number on this page is in facts.md
  • 294,642 e12nano params; 294,279 heart-nano params; 363 = 294,642−294,279. README.md:16,31-33,70-71; BOARDS.md:28-29,44-50 (pinned commit 87282046baca9db01af80103a981524ae45dcf18, local fetch) · release-provenance/review-sanotts-release.md:21,23.
  • heart 2,272,145 params float32; heart-nano 337 KB int8; e12nano 399 KB flash. README.md:31 (local fetch); review-sanotts-release.md:20-21,23.
  • RTF 0.383 SIMD / 1.58 scalar, corr 0.994664, ESP32-S3, e12nano. 4.13× SIMD speedup. BOARDS.md:44-50 (local fetch, dated 2026-09-04).
  • Correctness gate (corr > 0.98 AND 0.80<rms_ratio<1.25) and the ~500× loud defective-FFT case. BOARDS.md:18-23 (local fetch).
  • robot/R7: 567,008 params, RTF 3.6948, corr 0.989048, 731 KB flash. BOARDS.md:50-56 (local fetch). "745k"/"kristin" filename correction: README.md:92,283-285 (local fetch).
  • 30 voices / 16 languages browser; 27 voices / 13 languages pip. README.md:17-20 (local fetch); Ampixa-Work-Review.md:3691.
  • Ten languages added 2026-09-08, WER 0.038–0.392 on 16-sentence Tatoeba held-out sets. README.md:21-26,213-244 (local fetch).
  • Vietnamese SCOREQ 1.53, Indonesian 1.71, English amy SCOREQ 4.13. README.md:21-26 (local fetch).
  • heart WER 0.080 / SCOREQ 3.48; heart-nano WER 0.083 / SCOREQ 2.29 (Diverse24 English). README.md:185-194,213-220,258-262 (local fetch); review-sanotts-release.md:19,21,32.
  • Nepali voice 1.47M params, no WER/SCOREQ measured. README.md:21-26 (local fetch).
  • Demo HTTP 200, checked by curl 2026-11-06, this session. huggingface.co/ampixa/sanoTTS HTTP 200, checked 2026-11-06.
  • Japanese AtomS3 independent report: correctness passed, real time missed at xRT 1.718, different model/language/board. review-sanotts-release.md:42-44.
  • License split: runtime (mcu/mobile) MIT; rest GPL-3.0-or-later. review-sanotts-release.md:48-53.