Fisto c6b5fb71e8 Revert VOX preset to the NetTTS approximation
The tuned values (pitch 0, rate 15, head size 34, lowering 50) matched
the reference metrics better but sound far off the game voice, so restore
the published NetTTS approximation: pitch 3, rate 17, prominences 22,
head size 52, lowering 40, volume 70. Also revert the test expectations,
the published default metadata, and the tuning notes in the docs; keep
tools/vox_compare.py for future experiments.
2026-09-22 19:56:22 +02:00

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 approximated Valve VOX profile 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. Values are 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)
S
Description
No description provided
Readme
169 KiB
Languages
Shell 50.4%
Python 30.7%
C 18.9%