Oscillator streaming speech recogniser (10.4 M parameters, one C file)

A small English speech recogniser that transcribes while you speak, built for a handheld ARM computer (ClockworkPi uConsole). Text appears every 320 ms instead of after you stop, and the whole model runs faster than real time on one slow ARM core, from a single dependency-free C file.

It is a research model with honest limits: accurate enough to dictate with on clean speech, well behind Whisper and production systems on accuracy. The point is the architecture and its cost.

How it works

  • Front end: a bank of 64 damped complex oscillators running at the 16 kHz sample rate, z_t = c z_(t-1) + x_t with c = exp(-dt/tau + 2 pi i f dt). Frequencies and decay times are learned. No FFT, no convolution. Every 20 ms the bank's state (real, imaginary, energy) is the feature vector.
  • Backbone: six recurrent blocks of complex poles at 50 Hz (learned decay times from under one frame to about 8 s), each followed by a gated MLP. No attention: the state is a fixed size, so cost and memory per second of audio are constant, and output is available as the audio arrives.
  • CTC over characters, decoded greedily as you speak, and re-decoded at each pause with a word 3-gram (prefix beam search, also in the C file).

Every experiment that led here, including the failures, is written up with predictions made before each run (https://experiments.blah.dev/EXP-0049).

Results

LibriSpeech, word error rate (lower is better), all 2,620 / 2,939 test utterances. "LM" = beam search (width 64) with LibriSpeech's own pruned 3-gram (OpenSLR 11), its two weights chosen on dev-clean, run by the int8 C program. Greedy columns are the PyTorch model; the int8 C program scores 16.9 % greedy on test-clean.

model params test-clean greedy test-other greedy test-clean + LM
this model 10.4 M 16.8 % 37.9 % 9.1 %
round 3 (previous) 5.8 M 38.6 % 62.1 % 19.4 %

Speed on the uConsole (ClockworkPi A06 core, Rockchip RK3399), one core, real-time factor = compute seconds per second of audio (lower is faster), 87 s of test audio, model and LM loading included:

recogniser streaming A72 1.8 GHz A53 1.4 GHz WER on these 12 utterances
this model, int8 + 3-gram yes, 320 ms 0.16 0.35 7.7 %
sherpa-onnx streaming Zipformer 20M, int8 yes 0.21 0.48 8.6 % (no LM)
whisper.cpp tiny.en no (30 s window) 2.26 (1 thread) 4.49 (1 thread) 5.0 %

Use

cc -O3 -ffast-math -fno-finite-math-only -o zara_stt zara_stt.c -lm
./zara_stt model.bin speech.wav --int8 --lm librispeech-3gram.zlm --alpha 0.7 --beta 1.0   # 16 kHz mono WAV
arecord -q -f S16_LE -r 16000 -c 1 -t raw | ./zara_stt model.bin --stream --int8 --lm librispeech-3gram.zlm --alpha 0.7 --beta 1.0

--stream prints letters live and a cleaned-up line after each pause. On the uConsole headset use dictate.sh (the codec delivers the mic as left minus right).

Training

LibriSpeech 960 h (train-clean-100, -360, -other-500), 16 kHz mu-law, 150,000 updates of 240 s batches (about 11.3 passes), one NVIDIA RTX 3090, about 28 hours, about $7. Shape: osc front (64 poles), 6 blocks of width 448, gated MLP 672. Optimiser: Muon on the blocks' matrices (Nesterov momentum, Newton-Schulz orthogonalised updates), AdamW for everything else, peak learning rate 3e-3, 200 warmup updates, cosine to 10 %. The language-model weights used by default (alpha 0.7, beta 1.0, passed by dictate.sh) were chosen on dev-clean.

Limitations

  • English read speech only; accents and microphones outside LibriSpeech are weaker.
  • No punctuation or capitals.
  • The language model is built from public-domain books: modern and technical words are often misrecognised.
  • Accuracy far below Whisper and production recognisers.

Files

zara_stt.c (inference: oscillator bank, blocks, int8 NEON kernels, beam search, streaming), model.bin, params.pt (PyTorch), librispeech-3gram.zlm (the 3-gram in the C file's format), zara_stt.py and zara_block.py (training: model, block, optimizer), mulaw.py, pack_libri.py, export_c.py, export_lm.py, score_lines.py, dictate.sh, SHA256SUMS.

Credits

Roland Sharp, with Claude (Anthropic). Muon: Jordan et al. (2024); Liu et al. (2025), "Muon is Scalable for LLM Training". Data: LibriSpeech audio (Panayotov et al., 2015), CC BY 4.0 (OpenSLR 12); the 3-gram and vocabulary are from OpenSLR 11 (public domain).

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Dataset used to train rolandnsharp/oscillator-asr