fix(local-inference): real Kokoro StyleTTS-2/iSTFTNet decoder — Kokoro TTS actually speaks (#9588) - #9738
Conversation
…ma.cpp bump (#9588) Bumps the native llama.cpp pin to ship the actual Kokoro TTS forward pass. Kokoro previously synthesized a placeholder buzz (the fused kokoro_synthesize was a stub, and the scalar predictor read F16/quantized GGUF tensors as raw F32 -> constant BERT). The submodule now: dequantizes tensors to F32 at load, implements the full iSTFTNet decoder/generator + Snake resblocks + harmonic source, drives espeak-ng G2P, and wires predictor->decoder into kokoro_synthesize. Verified intelligible (whisper) end-to-end on the SHIPPED bundles/2b Q4_K_M GGUF — no GGUF republish needed; the runtime dequant + real decoder make the existing published artifact speak. Per-component ports validated corr=1.0/0.99 vs the PyTorch reference. Submodule pin 3d3133b7f -> 2f6a9e8f (off-main, both reachable via fork branch + tag eliza-pin-9588-kokoro-decoder).
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
Summary
Kokoro TTS never actually produced speech. This makes it work — end-to-end, verified intelligible on the already-shipped
bundles/2bQ4_K_M GGUF (no model republish needed). Nativellama.cppsubmodule bump (82925c0e9 → ba598f562, branch elizaOS/llama.cpp#feat/9588-kokoro-real-decoder, tageliza-pin-9588-kokoro-decoder).Two root causes
kokoro_synthesizewas a placeholder. It ran a hand-rolledsynth_spectrogram(envelope × 1/f timbre × random phase → iSTFT) and discarded the model — the real text-encoder → predictor → decoder graph was stubbed as "J2 follow-up."float*, but the GGUF ships F16 + Q5_0/Q4_K/Q6_K. Reading quantized block bytes as F32 produced garbage → BERT collapsed every position to one vector → a constant-pitch buzz. (This is why the earlier "regenerate the GGUF" instinct was wrong: F16 == Q4 == identical beep; the bug was in the runtime, not the artifact.)What landed (in the submodule)
kokoro_load_modelbuilds a parallel all-F32 context (ggmlto_floattraits handle F16 + every quant type); predictor/decoder read F32 only. This alone un-breaks the already-correct prosody predictor (BERT now matches the PyTorch reference to 3 decimals).kokoro-decoder-front.h(F0/N conv, encode, asr_res, 4 AdainResBlk1d decode blocks) +kokoro-generator.{h,cpp}(SineGen/SourceModuleHnNSF harmonic source from F0, center=True STFT, 2 ConvTranspose upsamples, 6 Snake AdaINResBlock1, noise convs/res, conv_post, center=True iSTFT) +kokoro-decoder.{h,cpp}(binds the F32 tensors, runs front→generator). Wired intokokoro_synthesize(predictor → transpose asr → decoder), variable-length.kokoro-phonemesdrives libespeak-ng (en-us IPA → Kokoro vocab ids, reproducing the reference token sequence); ASCII fallback only when espeak is absent. CMake auto-detectslibespeak-ng.Verification (Apple M-series)
kokoro-tts(text → speech) on the published Q4_K_M GGUF, whisper-transcribed across phrases:test-kokoro-g2p-espeak(exact reference-id match);kokoro_libbuilds clean; existing kokoro tests pass.Notes
main(consistent with the existing eliza pin lineage);ba598f562is reachable via the fork branch + theeliza-pin-9588-kokoro-decodertag. The decoder also lands on the fork'smainseparately so future pin bumps don't regress it.🤖 Generated with Claude Code