latency: cache profile writes; docs: data2 resolved, latency and fade measurements

This commit is contained in:
Fisto
2026-09-16 12:57:05 +02:00
parent 928218bd9c
commit f9f1c454d5
4 changed files with 60 additions and 15 deletions
+4 -2
View File
@@ -110,8 +110,10 @@ wrapper, so the WebUI does not need to implement them. See `docs/TTS-DESIGN.md`.
windows.
- Flextalk numeric speaker settings must be `REG_DWORD` (the installer script handles
this); `REG_SZ` values cause a monotone buzz. Pitch and speed work on all voices.
- The Flextalk archive lacks `data2.cab`; `unshield -O` extracts `data1.cab`
but one tail file (`WatsonUNInstall.dll`) is incomplete.
- Flextalk extraction needs `unshield -O` (old compression). The installer is
single-volume: the new decompressor reports a phantom `data2.cab`, but `-O` extracts
all 450 entries with exact sizes and valid PE files (the original 1997 upload log lists
`data1.cab` only).
## Reference material
+19 -2
View File
@@ -47,8 +47,25 @@ From `msttsl/mstts.inf` (`[TTSReg]`):
`.COD` codebook, plus shared `DICT_CI.*`, `phondef`, `AMPRULES`, `ENDINGS`.
Extraction: `unshield -O -d extracted x installer/flextalk/data1.cab`
(`-O` = old compression; the archive.org package has no `data2.cab`, so the
final file `WatsonUNInstall.dll` is incomplete).
(`-O` = old compression). The package is single-volume: the original 1997 upload log
(`WS_FTP.LOG`) lists `data1.cab` only, and `-O` extracts all 450 entries with exact
sizes. Without `-O`, unshield's new decompressor reports a phantom "volume 2" and fails
on `MSVCRT.DLL` / `WatsonUNInstall.dll`; with `-O` both are complete, valid PE files.
The `.ENV` files the engine probes (`ae1m11lc.ENV`) were never shipped; synthesis works
without them.
## Latency and output shape (measured 2026-09-16)
- Warm wrapper time: ~410-425 ms per short line (engine call 190-220 ms, ffmpeg measure
~110 ms, apply ~90 ms, profile write ~57 ms when it runs). First (cold) call ~730 ms.
- The Flextalk profile write is cached per voice in the Wine prefix
(`~/.wine-microslopsam/.microslopsam-profile<GUID>.reg`): unchanged profiles skip
`wine reg import`. Recreating the prefix invalidates the cache.
- Fades: the 8 ms fade-in/out is applied to the trimmed file whose 25-30 ms padding
silence is retained, so it shapes silence, not speech. Measured head: first sample
>30 at 22.6 ms, speech (>500) at 29.6 ms, natural ~15 ms attack; tail decays over
~18 ms. No click, no attenuation of the first word.
## SAPI4 runtime engine discovery (`speech.dll`)
+18 -5
View File
@@ -229,6 +229,11 @@ record what the engine needs to interpret, add, or hide._
- Verified: Keith Bell -18.4 LUFS, Kerry Watson -17.9 LUFS, Sam -20.6 LUFS; every file is
48 kHz mono s16le at -3.0 dBFS true peak. The WAV handed to Veskslop is compliant; the
"Veskslop does not normalize" rule holds.
- Fades: the 8 ms fade-in/out is applied to the trimmed file, and the retained 25-30 ms
padding silence sits at the edges, so the fade shapes silence, not the first phoneme.
Measured on a Keith Bell line: first sample >30 at 22.6 ms, speech (>500) at 29.6 ms,
attack rising naturally over about 15 ms, tail decaying over about 18 ms. No click and
no attenuation of the first word; Veskslop's 150 ms playback lead-in sits on top.
### Voice IDs
@@ -451,11 +456,15 @@ This tree is written to survive a copy into the Veskslop repository next to its
text file, transliterates UTF-8 to CP1252, starts or reuses an Xvfb when `DISPLAY` is
unset, calls the engine, then post-processes (trim, fades, measured fixed gain, 48 kHz
mono s16le). A stale private Xvfb is retried once.
- Measured on the dev host: engine-only synthesis is about 290 ms wall for Sam and about
40 ms for Flextalk, including process start; the full wrapper adds the ffmpeg
measure/apply passes, about 630-880 ms per short line. That is above the 500 ms target;
the known optimization is a per-voice static gain (skip the measurement pass), expected
to land around 400-500 ms.
- Measured on the dev host (warm): engine call about 190 ms (Flextalk) to 220 ms (Sam)
including Wine start, ffmpeg measure about 110 ms, ffmpeg apply about 90 ms, profile
registry write about 57 ms when it runs. Full wrapper: about 410-425 ms per short line
warm, about 730 ms for the first (cold) call. The 500 ms target is met warm; Veskslop's
"Start engine" warm-up covers the cold case.
- Latency optimization implemented: the Flextalk profile write is cached per voice inside
the Wine prefix (`.microslopsam-profile<GUID>.reg`); an unchanged profile skips the
`wine reg import` round-trip (about 57 ms warm, 300 ms cold). Recreating the prefix
invalidates the cache automatically.
- Manual checks: `setup/run.sh -l`, `setup/run.sh -v "Keith Bell" -t "Hello." -o out.wav`
(raw engine WAV), and the wrapper above for normalized output.
- HTTP provider (later): a persistent process returning `audio/wav` bytes and `/voices`,
@@ -465,6 +474,10 @@ This tree is written to survive a copy into the Veskslop repository next to its
- Flextalk numeric speaker settings must be `REG_DWORD`; `REG_SZ` values make the engine
synthesize a buzz. `setup/setup-flextalk.sh` writes them correctly.
- Flextalk cabinet is single-volume: `unshield -O` extracts all 450 entries with exact
sizes. Without `-O`, the new decompressor reports a phantom "volume 2" and fails on
`MSVCRT.DLL` / `WatsonUNInstall.dll`; both are complete with `-O` (verified against the
original 1997 upload log, which lists `data1.cab` only).
- The mode list includes TruVoice names with no installed voice data; filter those out of
`/voices` (or mark them `unavailable`).
- Wine needs a working X display; the project helper starts a persistent Xvfb.
+19 -6
View File
@@ -233,13 +233,26 @@ if [ -n "$SPEAKER_GUID" ]; then
exit 1
fi
if ! command -v "$MICROSLOP_WINE" >/dev/null 2>&1; then
echo "wine is required to set the Flextalk profile" >&2
exit 1
# Skip the wine round-trip when this voice's profile was already applied.
# The cache lives inside the prefix, so recreating the prefix invalidates
# it automatically.
PROFILE_CACHE="$WINEPREFIX/.microslopsam-profile$SPEAKER_GUID.reg"
if [ -f "$PROFILE_CACHE" ] && cmp -s "$TMP/profile.reg" "$PROFILE_CACHE"; then
PROFILE_APPLIED=1
else
PROFILE_APPLIED=0
fi
if ! "$MICROSLOP_WINE" reg import "$TMP/profile.reg" >/dev/null 2>&1; then
echo "could not write the Flextalk profile" >&2
exit 1
if [ "$PROFILE_APPLIED" != "1" ]; then
if ! command -v "$MICROSLOP_WINE" >/dev/null 2>&1; then
echo "wine is required to set the Flextalk profile" >&2
exit 1
fi
if ! "$MICROSLOP_WINE" reg import "$TMP/profile.reg" >/dev/null 2>&1; then
echo "could not write the Flextalk profile" >&2
exit 1
fi
cp -f "$TMP/profile.reg" "$PROFILE_CACHE" 2>/dev/null || true
fi
fi