Files
MicroslopSam/README.md
T
Fisto de4631fe54 Sync wrapper with Veskslop: streaming/crunch modes, vox/hev voice IDs
The Veskslop integration copy had grown word streaming
(VESKSLOP_TTS_STREAM, stream gain), 1990s crunch filters
(VESKSLOP_TTS_CRUNCH[_BITS|_RATE]), echo timing/level, and first-class
vox/hev voice IDs with preset-aware default metadata. Merge those back
into the standalone repo, keeping the tuned VOX preset (pitch 0, rate 15,
head size 34, lowering 50) in the preset and in the published defaults.

Update the wrapper regression test to the tuned registry values, add
__pycache__ to .gitignore, and document the new variables, voice IDs,
placeholder set and the word-mode-over-VOX precedence in README, NOTES
and TTS-DESIGN.
2026-09-22 13:55:28 +02:00

143 lines
6.9 KiB
Markdown

# MicroslopSam
Run SAPI4 text-to-speech voices on Linux.
Primary approach: a **Winelib host** — a native Linux ELF that uses Wine's
libraries to load the original 32-bit SAPI4 runtime and TTS engine DLLs.
Voice targets:
- Microsoft Sam / Mary / Mike — MSTTS engine (`msttssyn.dll` + `.vce` data)
- AT&T Flextalk 2.1 — "Keith Bell" and "Kerry Watson" (`FlexTalk.dll`)
Long-term: replace Wine-provided pieces with own shims (rehost) for a
pure-native build, and keep a path to a fully portable engine.
## Status (working)
- Winelib host builds and runs: `build/sapi4host.exe` (launcher) +
`build/sapi4host.exe.so` (native 32-bit ELF).
- Voices enumerate and synthesize:
- MSTTS: Sam, Mary, Mike (+ telephone and effect variants)
- AT&T Flextalk: Keith Bell, Kerry Watson
- Test output: `build/test_sam.wav` (22.05 kHz), `build/test_Keith_Bell.wav`,
`build/test_Kerry_Watson.wav` (11.025 kHz).
## Build
Everything in one command (idempotent; sudo only for system packages):
setup/install.sh
Manual steps, if needed:
sudo setup/install-deps.sh # Wine/Winelib/helpers
setup/setup-prefix.sh # prefix + SAPI4 runtime + MSTTS voices
setup/setup-flextalk.sh # Flextalk extraction + registry
# host build:
winegcc -m32 -O2 -o build/sapi4host-winlib host/sapi4host.c -Ithird_party \
-lole32 -luser32 -ladvapi32
i686-w64-mingw32-gcc -O2 -static -o build/sapi4host.exe host/sapi4host.c \
-Ithird_party -lole32 -luser32 -ladvapi32 -luuid
## Configuration
`setup/install.sh` writes `setup/microslopsam.env` (generated, gitignored) with absolute
paths. Environment variables take precedence over the file, so anything can be relocated
without editing scripts:
| Variable | Default | Meaning |
| --- | --- | --- |
| `MICROSLOP_ROOT` | repo root | project root |
| `MICROSLOP_BUILD` | `$MICROSLOP_ROOT/build` | host binaries, samples |
| `MICROSLOP_PREFIX` | `~/.wine-microslopsam` | wine prefix (exported as `WINEPREFIX`) |
| `MICROSLOP_ASSETS` | `third_party/sapi4` | SAPI4/MSTTS payloads (vendored) |
| `MICROSLOP_FLEXTALK_DIR` | `third_party/flextalk` | Flextalk cabinet/extraction (vendored) |
| `MICROSLOP_SPEECH_H_DIR` | `$MICROSLOP_ROOT/third_party` | `speech.h` include dir (vendored) |
| `MICROSLOP_DISPLAY` | `:77` | Xvfb display used for Wine |
| `MICROSLOP_WINE`, `MICROSLOP_XVFB`, `MICROSLOP_PYTHON`, `MICROSLOP_FFMPEG` | tool names | tool overrides |
Refresh the file after moving the tree: `MICROSLOP_UPDATE_ENV=1 setup/install.sh`.
## Usage
setup/run.sh -l
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, `-V` volume
(volume is engine-specific; not used by the Veskslop wrapper).
## Veskslop integration
export VESKSLOP_TTS_CMD="$PWD/setup/veskslop-tts.sh {out} {text_file}"
export VESKSLOP_TTS_VOICES="$(setup/veskslop-tts.sh --voices)"
The wrapper maps voice IDs (`sam`, `mary`, `mike`, `keith-bell`, `kerry-watson`, `vox`,
`hev`, plus the MSTTS variants), reads `VESKSLOP_TTS_VOICE`, `VESKSLOP_TTS_SPEED` (multiplier),
`VESKSLOP_TTS_PITCH` (semitones) and `VESKSLOP_TTS_EXPRESSION` (0-100, Flextalk voices
only), starts Xvfb when `DISPLAY` is unset, and writes a 48 kHz mono s16le WAV trimmed,
faded and normalized to about -16 LUFS (-3 dBFS true peak).
Speed and pitch apply to every voice (Flextalk's numeric settings must be `REG_DWORD`,
which the setup script writes). Expression is a Flextalk profile value applied at voice
load: the wrapper writes it to the Wine registry before synthesis. `--voices` marks those
voices with `expression=NN`, where NN is the registry default. Mapping details are in
`docs/TTS-DESIGN.md`.
**VOX prosody** (NetTTS-style, Flextalk voices): set `VESKSLOP_TTS_VOX=1` in the
command environment (`VESKSLOP_TTS_VOX_CLEAN=1` omits the `\!wH1/\!wH0` stutter
wrapper). Line-leading `/rate N` and `/pitch N` controls are also handled by the
wrapper, so the WebUI does not need to implement them. See `docs/TTS-DESIGN.md`.
A short low-level leading hum (80 ms, 75 Hz, -48 dBFS) primes Discord's audio pipeline
so the first word is not gated; tune with `VESKSLOP_TTS_HUM_MS` (0 = off),
`VESKSLOP_TTS_HUM_HZ`, and `VESKSLOP_TTS_HUM_DB`.
**Half-Life presets** (Keith Bell): `VESKSLOP_TTS_PRESET=vox` applies the Valve VOX
profile (pitch 0, rate 15, head size 34, lowering 50) and enables VOX prosody;
`VESKSLOP_TTS_PRESET=hev` is a starting point for the HEV suit voice. The `vox` and `hev`
voice IDs select these directly. The VOX values were
tuned against the game's word assets with `tools/vox_compare.py`; details in
`docs/TTS-DESIGN.md`.
`VESKSLOP_TTS_CRUNCH` (`hl90`, `hl90hq`, `telephone`, `adpcm`, `crush`) adds 1990s lossy
character to the output; `VESKSLOP_TTS_CRUNCH_BITS`/`_RATE` override its bit depth and
sample rate. `VESKSLOP_TTS_STREAM=1` makes word mode write the WAV as it goes (no
measurement pass; `VESKSLOP_TTS_STREAM_GAIN_DB` sets the gain). Echo timing and level are
`VESKSLOP_TTS_ECHO_DELAY_MS` and `VESKSLOP_TTS_ECHO_LEVEL`.
## Layout
- `host/sapi4host.c` — host: voice select, pitch/speed, text -> WAV
- `setup/install.sh` — one-shot installer (runs all steps below)
- `setup/install-deps.sh` — Wine/Winelib/helpers (root)
- `setup/setup-prefix.sh` — prefix + SAPI4 runtime + MSTTS engine/voices
- `setup/setup-flextalk.sh` — Flextalk files + registry
- `setup/inf2reg.py` — INF AddReg -> `.reg` converter
- `setup/run.sh` — run helper (prefix + Xvfb)
- `setup/veskslop-tts.sh` — Veskslop command-provider wrapper (post-processing included)
- `setup/test-wrapper.sh` — wrapper regression test (stubbed Wine/host, no prefix needed)
- `setup/vox_parser.py` — NetTTS-style VOX prosody encoder (Flextalk voices)
- `tools/vox_compare.py` — reference-vs-synthesis metrics for preset tuning
- `docs/NOTES.md` — registry/CLSID facts, runtime RE notes, gotchas
- `docs/TTS-DESIGN.md` — integration contract with Veskslop plus engine clarifications
## Known issues
- `xvfb-run` is flaky on this host. `setup/run.sh` starts a persistent Xvfb
(`:77`) instead; Wine needs a working X display because the runtime creates
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.
- 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
- `third_party/` — vendored dependencies; see `third_party/README.md`. Everything the
tool needs is in the repo (SAPI4 runtime, MSTTS voices, Flextalk cabinet, `speech.h`,
NetTTS parser source).
- `/mnt/ghidra/decomp/{msttssyn.dll,speech.dll}/` — decompiled corpora (external, optional)