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.
143 lines
6.9 KiB
Markdown
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)
|