6.3 KiB
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+.vcedata) - 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, 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 values were
tuned against the game's word assets with tools/vox_compare.py; details in
docs/TTS-DESIGN.md.
Layout
host/sapi4host.c— host: voice select, pitch/speed, text -> WAVsetup/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/voicessetup/setup-flextalk.sh— Flextalk files + registrysetup/inf2reg.py— INF AddReg ->.regconvertersetup/run.sh— run helper (prefix + Xvfb)setup/veskslop-tts.sh— Veskslop command-provider wrapper (post-processing included)setup/vox_parser.py— NetTTS-style VOX prosody encoder (Flextalk voices)tools/vox_compare.py— reference-vs-synthesis metrics for preset tuningdocs/NOTES.md— registry/CLSID facts, runtime RE notes, gotchasdocs/TTS-DESIGN.md— integration contract with Veskslop plus engine clarifications
Known issues
xvfb-runis flaky on this host.setup/run.shstarts 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_SZvalues 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 phantomdata2.cab, but-Oextracts all 450 entries with exact sizes and valid PE files (the original 1997 upload log listsdata1.cabonly).
Reference material
third_party/— vendored dependencies; seethird_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)