Sync with Veskslop integration: Flextalk profile support, words/echo/highpass, wrapper rename

This commit is contained in:
Fisto
2026-09-15 15:04:46 +02:00
parent 57cf5485ce
commit 643cdc38bf
6 changed files with 382 additions and 170 deletions
+4 -2
View File
@@ -42,8 +42,6 @@ From `msttsl/mstts.inf` (`[TTSReg]`):
- `{000031CB-3699-551F-AED0-6B4893382D57}`: "Kerry Watson", Pitch 65,
Speaking Rate 32, Head Size 45, Expression 100, Lowering 40,
Prominences 17, Age 30, Volume 100.
Measured effects per value and the change procedure are in
`docs/TTS-DESIGN.md` ("Flextalk profile parameters").
- Voice data: `EngineData\AE1M08LC.*`, `AE1M11LC.*` (male, 8/11 kHz) and
`AE2F08LC.*`, `AE2F11LC.*` (female); `.INV` inventory, `.NDX` index,
`.COD` codebook, plus shared `DICT_CI.*`, `phondef`, `AMPRULES`, `ENDINGS`.
@@ -72,6 +70,10 @@ final file `WatsonUNInstall.dll` is incomplete).
- Wine reports `err:ole:apartment_add_dll couldn't load in-process dll` when
the `InprocServer32` path does not exist. Check the file copy first
(this bit us: a bad `unshield` run created empty directories).
- Generate registry `.reg` files with `printf`, never `echo`: dash's `echo`
interprets `\2` in `...\Watson\2.0\...` as 0x02, corrupting the key so that
`wine reg import` is a silent no-op (it still returns 0). The wrapper rejects
a generated profile containing control characters.
- 32-bit engines require a 32-bit prefix (`WINEARCH=win32`).
- `sudo` on this machine requires a password; installs are manual.
+56
View File
@@ -419,3 +419,59 @@ _Added 2026-09-15._
untouched, so the voice keeps its engine default.
- **Licensing**: keep the engine DLLs and voice data local and out of any repository; Veskslop
never bundles or redistributes them.
## Current integration path (Veskslop side, 2026-09-15)
Everything below is implemented. The engine stays unchanged; the wrapper and the daemon do the work.
### Voice metadata
`VESKSLOP_TTS_VOICES` entries may carry flags after the language field:
id|Name|gender|language|flags
Flags are `+`-separated:
- `no-pitch` - hide the pitch control for this voice.
- `expression=NN` - Flextalk profile voice; NN is the default Expression value.
- `defaults=pitch:27:rate:33:prominences:17:head_size:46:lowering:40:expression:59` -
per-voice engine defaults. The UI shows "default" at these values and snaps to them
within +/-2 units.
### Wrapper contract (`microslopsam/setup/veskslop-tts.sh`)
Inputs: `{out}`, `{text_file}`, optional positional voice/speed/pitch/expression, and:
| Env | Meaning |
| --- | --- |
| `VESKSLOP_TTS_PROFILE` | `pitch:27:...`/`key=value,...` overrides; the wrapper writes the full profile (defaults + overrides) to the Wine registry with `wine reg import` before every synthesis. |
| `VESKSLOP_TTS_HIGHPASS` | High-pass Hz, 40-400 (default 40). |
| `VESKSLOP_TTS_ECHO` | Mono echo 0-100 (`aecho`), default 0. |
| `VESKSLOP_TTS_WORDS` / `VESKSLOP_TTS_WORD_GAP_MS` | Word-by-word synthesis with silence gaps (Flextalk only). |
Placeholders `{profile}`, `{highpass}`, `{echo}`, `{words}`, `{word_gap_ms}` mirror the env vars.
`wine regedit` fails headlessly but returns 0: use `wine reg import`. A missing profile value
must always write the engine default so no stale registry state survives.
### Daemon and UI path
1. Preferences (`tts`): `profile` (changed keys only), `profilePresets` (5 named slots),
`highpass`, `echo`, `words`, `wordGapMs`, plus `speed`, `pitch`, `expression`, `voice`.
2. `/api/audio/speak` and MCP `speak` accept all of them per line; the request overrides the
preferences and empty fields are omitted so the engine default applies.
3. The TTS panel opens the **Flextalk voice profile** window (movable, recentered on open) with
profile sliders, named presets, radio-kit controls, and test lines (Attention, Laboratory,
Critical, Health, Radiation, plus two persisted custom lines). Test buttons post the same
options as `speak`, so they audition the current profile.
### Known pitfalls
- The daemon runs from `tsx`: restart it after protocol, preference, or metadata changes.
- Static web files can be cached; hard-reload the browser after UI changes.
- `Number(null)` is 0: preference normalizers must treat null/undefined/"" as unset.
- The renderer log spam on a dead client is throttled in the bridge; background polls fail with
`CORE_UNAVAILABLE` and retry.
- Generate the Flextalk profile `.reg` with `printf`, never `echo`: dash's `echo` interprets
`\2` in `...\Watson\2.0\...` as an escape (0x02), so the key is corrupted and
`wine reg import` becomes a silent no-op (it still returns 0). The wrapper now rejects a
generated profile that contains control characters. This was the 2026-09-15 profile bug.