Skip to content

fix(kokoro): COLA-normalize iSTFT deconv weights (FluidAudio #852) - #83

Open
Alex-Wengg wants to merge 1 commit into
mainfrom
fix/kokoro-istft-cola
Open

fix(kokoro): COLA-normalize iSTFT deconv weights (FluidAudio #852)#83
Alex-Wengg wants to merge 1 commit into
mainfrom
fix/kokoro-istft-cola

Conversation

@Alex-Wengg

Copy link
Copy Markdown
Member

Summary

FluidInference/FluidAudio#852 reports that the COLA-corrected KokoroTail described in FluidAudio PR #699 never made it into the published bundles — and it turns out the script fix never made it into mobius either. Only the built artifact survived locally (build/tail-fix/, Jun 13). This PR reconstructs and commits that fix.

CoreMLCustomSTFT replaces torch.istft with a ConvTranspose1d overlap-add but omitted the summed-squared-window (COLA) normalization torch.istft applies. Analysis and synthesis each apply the periodic Hann window once, so the overlap-added output carries a sum(w^2) envelope — a constant 1.5 in the interior for win 20 / hop 5 (edge taps are sliced off by the center pad). Result: raw output exactly 1.5× the PyTorch reference, pure scalar, no spectral change.

The fix folds the envelope into the synthesis deconv weights, in both the laishere (en/ja) and v1.1-zh conversion scripts, with an assert that the interior envelope is actually constant.

Also commits convert-voices.py (laishere voice-pack extraction used to build ANE-ja/voices, referenced by FluidAudio #699 but likewise never committed).

Validation

  • Reconstructed weights match the surviving build/tail-fix/ artifact (the one #699 measured at 1.02× PyTorch, jf_alpha peak 0.306 vs 0.299) to within 1 ulp: max abs diff 7.5e-9, pure fp32 rounding order.
  • CoreML A/B (CPU_ONLY, fixed input) of original vs corrected tails: interior per-sample ratio 1.500000 (std 7e-6), correlation 1.000000000 — for both the en/ja tail and the zh tail (whose iSTFT deconv constants are byte-identical to en's; they are deterministic DFT×window kernels, not trained).

Published artifacts

Corrected tails are live as KokoroTail_v2.mlmodelc alongside the originals in ANE/, ANE-ja/, ANE-zh/ of FluidInference/kokoro-82m-coreml (commit acac8811); originals kept so existing consumers are unaffected until they opt in. Swift-side adoption is tracked in FluidInference/FluidAudio#852.

🤖 Generated with Claude Code

CoreMLCustomSTFT replaces torch.istft with ConvTranspose1d overlap-add
but omitted the summed-squared-window (COLA) normalization torch.istft
applies, leaving output exactly 1.5x too loud (periodic Hann, win 20,
hop 5 -> interior envelope sum(w^2) = 1.5, a pure scalar; edge taps are
sliced off by the center pad). Fold the envelope into the synthesis
weights in both the laishere (en/ja) and v1.1-zh conversion scripts.

This reconstructs the fix described in FluidAudio PR #699, which was
built and measured (1.02x PyTorch raw level, jf_alpha peak 0.306 vs
0.299) but never committed; only the built artifact survived in
build/tail-fix/. The reconstruction reproduces that artifact's deconv
weights to within 1 ulp (max abs diff 7.5e-9, fp32 rounding order).

Also commit convert-voices.py (laishere voice-pack extraction used for
ANE-ja/, referenced by #699 but likewise never committed).

Corrected tails are published as KokoroTail_v2.mlmodelc alongside the
originals in ANE/, ANE-ja/, ANE-zh/ of FluidInference/kokoro-82m-coreml
(commit acac8811); consumer adoption is tracked in FluidAudio #852.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant