host: volume option; docs: voice adjustments beyond speed (volume, Flextalk profile)
This commit is contained in:
@@ -46,7 +46,8 @@ Manual steps, if needed:
|
||||
setup/run.sh -v Sam -t "Hello." -o sam.wav
|
||||
setup/run.sh -v "Keith Bell" -t "Hello." -o keith.wav -p 100 -s 150
|
||||
|
||||
Options: `-v` voice, `-t` text, `-o` output WAV, `-p` pitch, `-s` speed.
|
||||
Options: `-v` voice, `-t` text, `-o` output WAV, `-p` pitch, `-s` speed, `-V` volume
|
||||
(volume is engine-specific; not used by the Veskslop wrapper).
|
||||
|
||||
## Veskslop integration
|
||||
|
||||
|
||||
@@ -82,6 +82,12 @@ final file `WatsonUNInstall.dll` is incomplete).
|
||||
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.
|
||||
- volume: available through `ITTSAttributes` (host flag `-V`). Flextalk is linear
|
||||
(0-65535, default 65535; half is about -6 dB). MSTTS is non-linear (0 = silence,
|
||||
4096 about -24 dB, 65535+ full scale); treat it as on/off.
|
||||
- Flextalk per-speaker profile values are applied at voice load; `Expression` was
|
||||
verified audible (0/59/100 produce different waveforms at equal duration). Changing
|
||||
them requires a registry edit and re-selecting the voice.
|
||||
|
||||
## Decompiled corpora (Ghidra)
|
||||
|
||||
|
||||
+28
-2
@@ -260,10 +260,36 @@ record what the engine needs to interpret, add, or hide._
|
||||
### Text handling
|
||||
|
||||
- SAPI4 is ANSI/CP1252. The wrapper converts UTF-8 to CP1252 and maps emoji and
|
||||
unmappable characters to spaces. Engine tag parsing is disabled, so input stays plain
|
||||
text (no SSML), matching the contract.
|
||||
unmappable characters to spaces. The host passes `TTSDATAFLAG_TAGGED`, so SAPI4 control
|
||||
tags in the text are enabled at the engine level; tagged input is not part of this
|
||||
contract and is untested. Plain text (no SSML) is the contract.
|
||||
- Lines up to 1000 characters are well within engine limits.
|
||||
|
||||
### Other voice adjustments (beyond speed)
|
||||
|
||||
All voices implement SAPI4 `ITTSAttributes`, so **pitch, speed and volume** exist at the
|
||||
API level. The Veskslop contract exposes only speed and pitch; volume is available in the
|
||||
host as `sapi4host -V <value>` and is not sent by Veskslop.
|
||||
|
||||
- **Volume** (measured 2026-09-15):
|
||||
- Flextalk: linear, range 0-65535, default 65535; half (32767) is about -6 dB, 0 is
|
||||
silence.
|
||||
- MSTTS: default is 0xFFFFFFFF; 0 is silence, but the response is not linear (for
|
||||
example 4096 gives about -24 dB while 65535 and larger are full scale). Treat volume
|
||||
as effectively on/off for MSTTS.
|
||||
- **Flextalk per-speaker profile** (applied at voice load, not runtime-adjustable):
|
||||
values live in `HKLM\Software\AT&T\Watson\2.0\FlexTalk\2.0\Speakers\{GUID}` (see
|
||||
`docs/NOTES.md` for the full list and defaults). `Pitch`/`Speaking Rate` set the natural
|
||||
voice; **Expression** was verified to change the synthesis audibly (Keith Bell at
|
||||
Expression 0 / 59 / 100 yields different waveforms with the same duration). Changing a
|
||||
profile requires a registry edit and re-selecting the voice.
|
||||
- **MSTTS voice character** is fixed by the `.vce`/`.cfg` data; the engine exposes no
|
||||
per-voice profile in the registry. Its effect variants (telephone, in Hall, in Stadium,
|
||||
in Space) are separate voice modes with separate data, exposed as distinct voice IDs
|
||||
(`mike-telephone`, `mary-hall`, ...), not runtime effects.
|
||||
- Not exposed by this integration: SSML, prosody/style tags, or SAPI4 attribute
|
||||
extensions beyond pitch/speed/volume.
|
||||
|
||||
### Transport and latency
|
||||
|
||||
- Installation is one command: `setup/install.sh` (system dependencies with sudo, wine
|
||||
|
||||
+12
-3
@@ -157,7 +157,7 @@ static void usage(void)
|
||||
fprintf(stderr,
|
||||
"usage: sapi4host -l\n"
|
||||
" sapi4host -v <voice> -t <text> -o <out.wav>"
|
||||
" [-p pitch] [-s speed]\n");
|
||||
" [-p pitch] [-s speed] [-V volume]\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -168,6 +168,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
const char *voice = NULL, *text = NULL, *out = NULL;
|
||||
int pitch = -1, speed = -1;
|
||||
long volume = -1;
|
||||
int i;
|
||||
TTSMODEINFO mode;
|
||||
|
||||
@@ -182,6 +183,7 @@ int main(int argc, char **argv)
|
||||
else if (!strcmp(argv[i], "-o")) out = argv[++i];
|
||||
else if (!strcmp(argv[i], "-p")) pitch = atoi(argv[++i]);
|
||||
else if (!strcmp(argv[i], "-s")) speed = atoi(argv[++i]);
|
||||
else if (!strcmp(argv[i], "-V")) volume = strtol(argv[++i], NULL, 0);
|
||||
else { usage(); return 2; }
|
||||
}
|
||||
if (!voice || !text || !out) { usage(); return 2; }
|
||||
@@ -257,9 +259,9 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Pitch and speed are optional: when unset, leave the engine's own
|
||||
/* Pitch, speed and volume are optional: when unset, leave the engine's own
|
||||
voice profile untouched (probing/setting would override it). */
|
||||
if (pitch >= 0 || speed >= 0) {
|
||||
if (pitch >= 0 || speed >= 0 || volume >= 0) {
|
||||
WORD pmin = 0, pmax = 0;
|
||||
DWORD smin = 0, smax = 0;
|
||||
|
||||
@@ -284,6 +286,13 @@ int main(int argc, char **argv)
|
||||
printf("speed: %d (%lu..%lu)\n",
|
||||
speed, (unsigned long)smin, (unsigned long)smax);
|
||||
}
|
||||
if (volume >= 0) {
|
||||
DWORD vdef = 0;
|
||||
attr->lpVtbl->VolumeGet(attr, &vdef);
|
||||
attr->lpVtbl->VolumeSet(attr, (DWORD)volume);
|
||||
printf("volume: %ld (default %lu)\n",
|
||||
volume, (unsigned long)vdef);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user