Fix Flextalk buzz: REG_DWORD speaker settings; measured pitch/speed mapping; fixed-gain normalization

This commit is contained in:
Fisto
2026-09-15 13:14:50 +02:00
parent fa4fbaf74b
commit ad81303b6f
5 changed files with 105 additions and 54 deletions
+13 -1
View File
@@ -33,7 +33,9 @@ From `msttsl/mstts.inf` (`[TTSReg]`):
`HomographDictionary="1 ft_hgrap.dll"`, `ProperNameDictionary="3 ft_namsa.dll"`,
`LetterToSoundDictionary="4 ft_l2s.dll"`.
- Options: `...\FlexTalk\2.0\Options` `Gender=Male`, `SampleRate=11025`.
- Speakers (per-voice settings; names come from these values):
- Speakers (per-voice settings; names come from these values). **All numeric
values must be REG_DWORD**: with REG_SZ the engine reads garbage and
synthesizes a monotone buzz (pitch fixed at max, pitch control dead).
- `{11260610-C84A-11ce-AEC4-0000C0E9CB87}`: Mode Name / Speaker Name
"Keith Bell", Pitch 27, Speaking Rate 33, Head Size 46, Expression 59,
Lowering 40, Prominences 17, Age 30, Volume 100.
@@ -71,6 +73,16 @@ final file `WatsonUNInstall.dll` is incomplete).
- 32-bit engines require a 32-bit prefix (`WINEARCH=win32`).
- `sudo` on this machine requires a password; installs are manual.
## Engine units (measured)
- speed: MSTTS range 30-450, Flextalk 50-390; the natural rate is about 150 for every
voice (duration at 100/200/300 fits a natural value near 140-150).
- pitch: engine units, roughly linear in F0 near the natural point (~1.1 Hz per unit).
Natural values: about 100 (MSTTS), 106 (Keith Bell), 186 (Kerry Watson); Flextalk max 250.
Verified with the corrected DWORD registry: Kerry 0 st = 209 Hz, -6 st = 148 Hz,
+6 st = 250 Hz (clamped at max); Keith 0 st = 119 Hz, +6 st = 170 Hz.
- The wrapper maps semitones as `natural * 2^(st/12)` and clamps to the range.
## Decompiled corpora (Ghidra)
- `/mnt/ghidra/decomp/msttssyn.dll/` (786 functions, engine)
+18 -1
View File
@@ -267,7 +267,8 @@ record what the engine needs to interpret, add, or hide._
### Quirks the wrapper must hide
- Flextalk reports default pitch/speed as maximum through `ITTSAttributes`.
- Flextalk numeric speaker settings must be `REG_DWORD`; `REG_SZ` values make the engine
synthesize a buzz. `setup/setup-flextalk.sh` writes them correctly.
- 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.
@@ -301,6 +302,19 @@ _Added 2026-09-15._
- **Display**: the daemon does not export `DISPLAY` to TTS children. The wrapper must start or
find its own Xvfb and set `DISPLAY` itself, as the project helper already does. Do not rely on
the client's display.
- **Engine selection**: the Speech settings and the TTS panel list every configured engine. The
command engine appears under `VESKSLOP_TTS_NAME` (default "custom engine") and is selectable
directly; Auto uses the command engine first. Selecting it hides the language row and shows the
`VESKSLOP_TTS_VOICES` list.
- **Start engine**: the Speech settings have a **Start engine** button (`POST /api/audio/tts/warm`,
MCP `start_tts_engine`) that runs one throwaway synthesis to warm the command engine (Xvfb, Wine,
host). Keep the wrapper able to handle a short sentence; the warm-up uses "The quick brown fox
jumps over the lazy dog." and reports the elapsed milliseconds. Two-pass `loudnorm` must not fail
on that input.
- **Lead-in silence**: Veskslop prepends a short silence at playback time (`VESKSLOP_TTS_LEAD_MS`,
default 150 ms) so Discord's voice pipeline is ready before the first syllable. It is added with
`adelay` in the player, not in the audio file. The engine needs no change and can keep its
5–10 ms edge fades.
- **Voice declarations**: list only usable IDs in `VESKSLOP_TTS_VOICES`. Veskslop hides the
espeak list while a custom command is set, so a missing declaration means an empty voice list,
not a fallback. The list accepts commas or newlines, and the optional `no-pitch` flag tells the
@@ -308,5 +322,8 @@ _Added 2026-09-15._
- **Flextalk pitch**: confirmed that pitch is a no-op for Keith Bell and Kerry Watson. Mark those
entries `no-pitch` so users are not offered a control that does nothing. Speed applies to every
voice and needs no flag.
_Engine correction (2026-09-15): the no-op was caused by the speaker registry values being
`REG_SZ`; with `REG_DWORD` pitch works and the voices are declared without the flag. See the
speed/pitch section._
- **Licensing**: keep the engine DLLs and voice data local and out of any repository; Veskslop
never bundles or redistributes them.