diff --git a/docs/NOTES.md b/docs/NOTES.md index 173bb61..da659c2 100644 --- a/docs/NOTES.md +++ b/docs/NOTES.md @@ -42,6 +42,8 @@ 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`. diff --git a/docs/TTS-DESIGN.md b/docs/TTS-DESIGN.md index 45f6ed9..e4f403f 100644 --- a/docs/TTS-DESIGN.md +++ b/docs/TTS-DESIGN.md @@ -53,10 +53,12 @@ these placeholders, splits the string on whitespace, and runs the result directl | `{voice}` | The selected voice ID, or an empty string. | | `{speed}` | The rate multiplier, or an empty string when unset. | | `{pitch}` | The pitch offset in semitones, or an empty string when unset. | +| `{expression}` | The Flextalk Expression profile value, or an empty string when unset. | -The process also receives `VESKSLOP_TTS_VOICE`, and `VESKSLOP_TTS_SPEED` / `VESKSLOP_TTS_PITCH` -when those are set. Write the audio to `{out}` and exit 0. Non-zero exits are errors; stderr is -captured into the log message, so keep it short. +The process also receives `VESKSLOP_TTS_VOICE`, `VESKSLOP_TTS_SPEED`, +`VESKSLOP_TTS_PITCH`, and `VESKSLOP_TTS_EXPRESSION` when those are set. Write the audio to +`{out}` and exit 0. Non-zero exits are errors; stderr is captured into the log message, so keep it +short. Command mode is best for fast, stateless engines. It has no shell quoting: paths with spaces and shell tricks cannot work. Use a small wrapper script if you need options. @@ -133,17 +135,19 @@ Implemented on the Veskslop side (2026-09-15): - `tts` preferences carry `speed` (0.5–2.0) and `pitch` (-12–+12, semitones), both nullable. - `/api/audio/speak` and the MCP `speak` tool accept optional `speed` and `pitch` that override the preferences for that line. -- The command provider substitutes `{speed}`/`{pitch}` and exports `VESKSLOP_TTS_SPEED` / - `VESKSLOP_TTS_PITCH` only when the value is set. -- The HTTP provider adds `speed` and `pitch` to the request body only when set. -- The TTS panel has speed and pitch sliders; changes are saved to the daemon preferences. +- The command provider substitutes `{speed}`/`{pitch}`/`{expression}` and exports + `VESKSLOP_TTS_SPEED` / `VESKSLOP_TTS_PITCH` / `VESKSLOP_TTS_EXPRESSION` only when the value is set. +- The HTTP provider adds `speed`, `pitch`, and `expression` to the request body only when set. +- The TTS panel has speed presets, speed/pitch sliders, and an Expression slider that appears only + for voices that declare it (`expression` / `expression=NN` flags). Changes save to preferences. - Command mode advertises voices through `VESKSLOP_TTS_VOICES`. Entries are separated by commas or newlines and use `id`, `id|Name`, `id|Name|gender`, `id|Name|gender|language`, or - `id|Name|gender|language|flags`, where flags are `+`-separated. The `no-pitch` flag marks a voice - that ignores pitch; `/api/audio/tts/voices` then reports `supportsPitch: false` and the TTS panel - disables the pitch slider. While a custom command is set, the engine's declared voices replace - the espeak list, so no misleading espeak entries appear. Reading `/voices` for the HTTP provider - is still future work. + `id|Name|gender|language|flags`, where flags are `+`-separated. Flags: `no-pitch` (engine ignores + pitch) and `expression` / `expression=NN` (Flextalk profile parameter with its registry default). + `/api/audio/tts/voices` reports `supportsPitch` and `supportsExpression` / + `expressionDefault`; the TTS panel hides controls the voice does not support. While a custom + command is set, the engine's declared voices replace the espeak list. Reading `/voices` for the + HTTP provider is still future work. Do not encode settings into the voice string (for example `anna+speed1.2`). It breaks voice lists and is hard to validate. @@ -290,6 +294,47 @@ host as `sapi4host -V ` and is not sent by Veskslop. - Not exposed by this integration: SSML, prosody/style tags, or SAPI4 attribute extensions beyond pitch/speed/volume. +### Flextalk profile parameters (how to implement) + +Each Flextalk speaker has a profile the engine reads when the voice is loaded. It lives in +the registry; **every numeric value must be `REG_DWORD`**: + + HKLM\Software\AT&T\Watson\2.0\FlexTalk\2.0\Speakers\{11260610-C84A-11ce-AEC4-0000C0E9CB87} # Keith Bell + HKLM\Software\AT&T\Watson\2.0\FlexTalk\2.0\Speakers\{000031CB-3699-551F-AED0-6B4893382D57} # Kerry Watson + +| Value (REG_DWORD unless noted) | Keith Bell | Kerry Watson | Measured effect | +| --- | --- | --- | --- | +| Pitch | 27 | 65 | Natural pitch (F0); the same scale `ITTSAttributes` shifts at runtime | +| Speaking Rate | 33 | 32 | Natural speech rate (about 150 wpm equivalent) | +| Volume | 100 | 100 | Output gain; 0 = silence | +| Expression | 59 | 100 | Audible; changes the waveform at equal duration | +| Prominences | 17 | 17 | Audible; strong prosody/emphasis effect (F0 median 122 -> 197 Hz at 100) | +| Head Size | 46 | 45 | Audible; brightness/level (peak 20001 -> 32205 at 100) | +| Lowering | 40 | 40 | Audible but subtle | +| Age | 30 | 30 | No measured effect on synthesis (informational) | +| Gender (REG_SZ) | "" | "" | No measured effect on synthesis (informational) | +| Mode Name / Speaker Name (REG_SZ) | "Keith Bell" | "Kerry Watson" | Mode name SAPI4 shows for the voice | + +How to apply a change: + +1. `setup/setup-flextalk.sh` writes these defaults, so re-running it restores them. +2. Profiles are read at voice load. The host loads the engine per request, so the next + synthesis after a registry change uses the new profile; no engine restart is needed. +3. Example (lower and slow Keith Bell), with `WINEPREFIX` pointing at the project prefix: + + wine reg add 'HKLM\Software\AT&T\Watson\2.0\FlexTalk\2.0\Speakers\{11260610-C84A-11ce-AEC4-0000C0E9CB87}' \ + /v Pitch /t REG_DWORD /d 20 /f + wine reg add '...' /v "Speaking Rate" /t REG_DWORD /d 28 /f + + Never use `REG_SZ` for numeric values: the engine reads garbage and synthesizes a + monotone buzz at maximum pitch. +4. Not exposed by the Veskslop contract (which sends only text/voice/speed/pitch). If + profile control is wanted later, the clean place is the wrapper: read an env var such + as `VESKSLOP_TTS_PROFILE` (`key=value` list or JSON), write the registry values before + synthesis, then restore. That keeps the Veskslop interface unchanged. +5. Runtime `ITTSAttributes` pitch/speed/volume layer on top of the profile: the profile + defines the natural values, the attributes shift them per request. + ### Transport and latency - Installation is one command: `setup/install.sh` (system dependencies with sudo, wine @@ -363,13 +408,14 @@ _Added 2026-09-15._ 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 - UI to grey out the pitch slider for that voice. -- **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._ + not a fallback. The list accepts commas or newlines. Optional flags: `no-pitch` (hide the pitch + control) and `expression` / `expression=NN` (show the Expression slider and use NN as its + default). +- **Flextalk pitch**: works now that the speaker registry values are `REG_DWORD`; no flag is + needed and Veskslop shows pitch for Keith Bell and Kerry Watson. +- **Expression profile**: implemented for the Flextalk voices. Veskslop stores `tts.expression` + (0-100, nullable), sends it per line (`{expression}` / `VESKSLOP_TTS_EXPRESSION` / the HTTP body), + and shows the slider only for voices flagged `expression=NN`. A null value leaves the registry + 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.