Revert the VOX preset to the NetTTS approximation
This commit is contained in:
@@ -40,6 +40,13 @@ mobile draft at 390px.
|
||||
- [x] C11 preview caching: Discord-hosted image/GIF previews (WebP 320px, hash-addressed, 5 MiB
|
||||
cap, one attempt) run after every walk in both modes. Live run `...-20260916090722`:
|
||||
`previewed: 2`; thumbs served over `/api/media/<scrape>/<item>/thumb` (200).
|
||||
- [x] C84 Revert the VOX preset to the NetTTS approximation. The tuned values matched the
|
||||
reference metrics but sounded far off the game voice, so SAM commit `c6b5fb7` restores pitch 3,
|
||||
rate 17, prominences 22, head size 52, lowering 40, volume 70 and reverts the tests, metadata
|
||||
and docs; `tools/vox_compare.py` stays for future experiments. Merged on Veskslop and
|
||||
`poc/.env`'s `VESKSLOP_TTS_VOICES` regenerated (back to `pitch:3:rate:17:…`). The stored
|
||||
profile stayed cleared, so the auto path now renders the reverted tuning — verified
|
||||
byte-identical to an explicit old-profile render. Wrapper tests pass.
|
||||
- [x] C83 Merge the SAM updates. `~/Projects/Sam/MicroslopSam` moved ahead (VOX preset tuned
|
||||
against the game word assets, `tools/vox_compare.py`, docs, wrapper/test sync). The updates
|
||||
matched our tree except the local `microslopsam.env` paths, so the merge is: the retuned VOX
|
||||
|
||||
@@ -93,11 +93,9 @@ A short low-level leading hum (80 ms, 75 Hz, -48 dBFS) primes Discord's audio pi
|
||||
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
|
||||
**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
|
||||
|
||||
@@ -129,14 +129,10 @@ without them.
|
||||
- VOX mode is Flextalk-only. The wrapper enables it with `VESKSLOP_TTS_VOX=1`
|
||||
(`VESKSLOP_TTS_VOX_CLEAN=1` drops the stutter wrapper); word mode
|
||||
(`VESKSLOP_TTS_WORDS=1`) wins and skips VOX prosody.
|
||||
- Half-Life presets (`VESKSLOP_TTS_PRESET=vox|hev`) target Keith Bell only. VOX starts
|
||||
from NetTTS `nettts_flextalk_vox_profile.reg` (pitch 3, rate 17, head 52, lowering 40)
|
||||
and is tuned against the game's word assets from `suchipi/half-life-vox-console`:
|
||||
shipped values are pitch 0, rate 15, prominences 22, head size 34, lowering 50,
|
||||
volume 70. Measured on 38 words vs the game assets: F0 82.3 vs 82.3 Hz, duration
|
||||
22.99 vs 23.36 s, >2 kHz share 0.0172 vs 0.0186 (old approximation: 87.5 Hz /
|
||||
22.28 s / 0.0137). `tools/vox_compare.py` reproduces the comparison. `hev`
|
||||
(pitch 15, rate 24) remains an unverified starting point - HL1 credits the suit
|
||||
- Half-Life presets (`VESKSLOP_TTS_PRESET=vox|hev`) target Keith Bell only. VOX values
|
||||
come from NetTTS `nettts_flextalk_vox_profile.reg`: pitch 3, rate 17, prominences 22,
|
||||
head size 52, volume 70 (factory: 27/33/17/46/100); `vox` also implies VOX prosody.
|
||||
`hev` (pitch 15, rate 24) is an unverified starting point - HL1 credits the suit
|
||||
sounds to Kelly Bailey with no published settings.
|
||||
- Flextalk rate/pitch are applied as **vendor tags** (`\!R` = duration factor,
|
||||
`\!%` = pitch multiplier), never `-s`/`-p`, because ITTSAttributes override the
|
||||
|
||||
@@ -402,20 +402,16 @@ Kerry Watson at factory values. The wrapper implements it as a preset:
|
||||
VESKSLOP_TTS_PRESET=vox # implies VOX prosody unless VESKSLOP_TTS_VOX is set
|
||||
VESKSLOP_TTS_PRESET=hev # HEV suit starting point (see note below)
|
||||
|
||||
| Profile value | Factory (Keith) | VOX preset (tuned) | HEV preset (approx.) |
|
||||
| Profile value | Factory (Keith) | VOX preset | HEV preset (approx.) |
|
||||
| --- | --- | --- | --- |
|
||||
| Pitch | 27 | 0 | 15 |
|
||||
| Speaking Rate | 33 | 15 | 24 |
|
||||
| Pitch | 27 | 3 | 15 |
|
||||
| Speaking Rate | 33 | 17 | 24 |
|
||||
| Prominences | 17 | 22 | 22 |
|
||||
| Head Size | 46 | 34 | 52 |
|
||||
| Lowering | 40 | 50 | 40 |
|
||||
| Head Size | 46 | 52 | 52 |
|
||||
| Lowering | 40 | 40 | 40 |
|
||||
| Volume | 100 | 70 | 70 |
|
||||
| Expression | 59 | 59 | 59 |
|
||||
|
||||
The VOX column starts from NetTTS's approximation (pitch 3, rate 17, head 52, lowering
|
||||
40) and is refined against the actual game word assets; see
|
||||
"Tuning against the actual game assets" below.
|
||||
|
||||
- Presets apply only to `keith-bell`; every other voice keeps its defaults.
|
||||
- Precedence: preset < `VESKSLOP_TTS_PROFILE` < `VESKSLOP_TTS_EXPRESSION`.
|
||||
- Equivalent explicit override:
|
||||
@@ -473,49 +469,16 @@ Verified matrix (same line, Keith Bell):
|
||||
| Run | Duration | F0 median |
|
||||
| --- | --- | --- |
|
||||
| factory, no adjustments | 3.35 s | 123 Hz |
|
||||
| VOX preset, no adjustments | 6.06 s | 82 Hz |
|
||||
| VOX preset + `speed=1.0 pitch=0` | 6.06 s, byte-identical | 82 Hz |
|
||||
| VOX preset + `speed=1.3` | 4.02 s | - |
|
||||
| VOX preset + `pitch=+3` | 6.06 s | 96 Hz |
|
||||
| VOX preset, no adjustments | 5.83 s | 87 Hz |
|
||||
| VOX preset + `speed=1.0 pitch=0` | 5.83 s, byte-identical | 87 Hz |
|
||||
| VOX preset + `speed=1.3` | 4.02 s | 84 Hz |
|
||||
| VOX preset + `pitch=+3` | 5.83 s | 88 Hz |
|
||||
| HEV preset, no adjustments | 3.79 s | - |
|
||||
|
||||
Registry inspection after a preset run: 26 values in the Keith speaker key in both
|
||||
hives, `Pitch=0x0`, `Speaking Rate=0xf`, `Head Size=0x22`, `Lowering=0x32`,
|
||||
`Gender=0x2`, `Line Mode=0x1`,
|
||||
hives, `Pitch=0x3`, `Speaking Rate=0x11`, `Gender=0x2`, `Line Mode=0x1`,
|
||||
`Default Speaker={11260610-C84A-11CE-AEC4-0000C0E9CB87}`.
|
||||
|
||||
#### Tuning against the actual game assets (2026-09-22)
|
||||
|
||||
Reference: the word WAVs from `suchipi/half-life-vox-console`
|
||||
(`public/vox/*.wav`, Valve assets - used locally for analysis only, never committed).
|
||||
38 words at 11025 Hz 16-bit, the engine's native rate. `tools/vox_compare.py`
|
||||
reproduces the comparison; it reports the cepstrum F0 median, total audible duration,
|
||||
energy-weighted spectral centroid and the >2 kHz energy share per word set.
|
||||
|
||||
| Metric (38 words) | Game assets | NetTTS approximation | Shipped VOX preset |
|
||||
| --- | --- | --- | --- |
|
||||
| F0 median | 82.3 Hz | 87.5 Hz | 82.3 Hz |
|
||||
| Duration | 23.36 s | 22.28 s | 22.99 s |
|
||||
| Spectral centroid | 515 Hz | 479 Hz | 453 Hz |
|
||||
| >2 kHz energy share | 0.0186 | 0.0137 | 0.0172 |
|
||||
|
||||
Findings:
|
||||
|
||||
- Registry `Pitch 0` is the engine minimum and matches the game's F0; the NetTTS
|
||||
approximation (3) was about 5 Hz high.
|
||||
- `Speaking Rate 15` matches the word durations within about 1.6%; NetTTS's 17 was
|
||||
about 4.6% fast on this corpus.
|
||||
- The game voice is brighter than the approximation. Smaller `Head Size` raises
|
||||
brightness (34 is the engine's effective minimum here; 30 gives identical output) and
|
||||
`Lowering 50` adds a little more, together closing most of the >2 kHz gap
|
||||
(0.0137 -> 0.0172 against 0.0186).
|
||||
- The residual centroid difference is mostly the reference's mid/high-band noise floor
|
||||
(game assets), not voice timbre.
|
||||
- HEV stays a starting point: no published settings and no word-level reference exists.
|
||||
|
||||
Re-run recipe: write the profile to both hives, synthesize the reference word list with
|
||||
`build/sapi4host-winlib.exe -v "Keith Bell" -t <word> -o <dir>/<word>.wav`, then
|
||||
`tools/vox_compare.py <game-assets-dir> <synth-dir>`.
|
||||
|
||||
### Inline rate/pitch controls (engine-side)
|
||||
|
||||
The wrapper consumes NetTTS-style, line-leading controls, so Veskslop and the WebUI do
|
||||
|
||||
@@ -94,8 +94,8 @@ check "vox preset implies VOX parser" "1" "$(grep -c 'wH1' "$STUB_LOG")"
|
||||
# The preset writes the full audible profile to both hives.
|
||||
VESKSLOP_TTS_VOICE=keith-bell VESKSLOP_TTS_PRESET=vox run_wrapper
|
||||
check "preset writes both hives" "2" "$(grep -c 'Speakers\\{11260610' "$STUB_REG")"
|
||||
check "preset pitch (both hives)" "2" "$(grep -c '"Pitch"=dword:00000000' "$STUB_REG")"
|
||||
check "preset rate (both hives)" "2" "$(grep -c '"Speaking Rate"=dword:0000000f' "$STUB_REG")"
|
||||
check "preset pitch (both hives)" "2" "$(grep -c '"Pitch"=dword:00000003' "$STUB_REG")"
|
||||
check "preset rate (both hives)" "2" "$(grep -c '"Speaking Rate"=dword:00000011' "$STUB_REG")"
|
||||
check "preset gender and line mode" "4" "$(grep -cE '"Gender"=dword:00000002|"Line Mode"=dword:00000001' "$STUB_REG")"
|
||||
check "preset default speaker" "2" "$(grep -c '"Default Speaker"' "$STUB_REG")"
|
||||
|
||||
@@ -111,7 +111,7 @@ check "word mode with preset synthesizes every word" "3" "$(grep -c '^ARGV:' "$S
|
||||
check "word mode skips the VOX parser" "0" "$(grep -c 'wH1' "$STUB_LOG")"
|
||||
check "word mode tags every word" "3" \
|
||||
"$(sed -n 's/.*\[-t\] \[\(.*\)\] \[-o\].*/\1/p' "$STUB_LOG" | grep -c '^\\!R0.80 ')"
|
||||
check "word mode keeps the preset profile" "2" "$(grep -c '"Pitch"=dword:00000000' "$STUB_REG")"
|
||||
check "word mode keeps the preset profile" "2" "$(grep -c '"Pitch"=dword:00000003' "$STUB_REG")"
|
||||
check "word mode emits no attributes" "0" "$(attr_count)"
|
||||
|
||||
# The vox preset implies VOX when the variable is unset, but word mode still wins.
|
||||
@@ -139,7 +139,7 @@ check "stream has a gap per word break" "2" \
|
||||
|
||||
# The Half-Life voices carry their profile preset.
|
||||
VESKSLOP_TTS_VOICE=vox VESKSLOP_TTS_VOX=1 run_wrapper
|
||||
check "vox voice writes the VOX profile (both hives)" "2" "$(grep -c '"Pitch"=dword:00000000' "$STUB_REG")"
|
||||
check "vox voice writes the VOX profile (both hives)" "2" "$(grep -c '"Pitch"=dword:00000003' "$STUB_REG")"
|
||||
check "vox voice runs VOX prosody" "1" "$(grep -c 'wH1' "$STUB_LOG")"
|
||||
VESKSLOP_TTS_VOICE=hev run_wrapper
|
||||
check "hev voice writes the HEV profile (both hives)" "2" "$(grep -c '"Pitch"=dword:0000000f' "$STUB_REG")"
|
||||
|
||||
@@ -46,7 +46,7 @@ ROOT=$MICROSLOP_ROOT
|
||||
|
||||
# The Keith Bell defaults follow the active preset so the UI's "default" snap points
|
||||
# match the values the preset actually writes.
|
||||
VOX_DEFAULTS="pitch:0:rate:15:prominences:22:head_size:34:lowering:50:expression:59"
|
||||
VOX_DEFAULTS="pitch:3:rate:17:prominences:22:head_size:52:lowering:40:expression:59"
|
||||
HEV_DEFAULTS="pitch:15:rate:24:prominences:22:head_size:52:lowering:40:expression:59"
|
||||
case "${VESKSLOP_TTS_PRESET:-}" in
|
||||
vox) KB_DEFAULTS="$VOX_DEFAULTS" ;;
|
||||
@@ -243,17 +243,15 @@ if [ -n "$SPEAKER_GUID" ]; then
|
||||
P_LOWER=40
|
||||
P_EXPR=""
|
||||
|
||||
# Half-Life presets for Keith Bell (the game's announcement voice). "vox"
|
||||
# starts from the approximated Valve VOX profile published by NetTTS
|
||||
# (scripts/winetricks/nettts_flextalk_vox_profile.reg), then refines pitch,
|
||||
# rate, head size and lowering against the actual game word assets
|
||||
# (see docs/TTS-DESIGN.md). "hev" is a starting point for the HEV suit
|
||||
# voice, which has no published profile.
|
||||
# Half-Life presets for Keith Bell (the game's announcement voice).
|
||||
# "vox" is the approximated Valve VOX profile published by NetTTS
|
||||
# (scripts/winetricks/nettts_flextalk_vox_profile.reg); "hev" is a starting
|
||||
# point for the HEV suit voice, which has no published profile.
|
||||
case "$PRESET" in
|
||||
vox)
|
||||
if [ "$ENGVOICE" = "Keith Bell" ]; then
|
||||
P_PITCH=0; P_RATE=15; P_VOLUME=70
|
||||
P_PROM=22; P_HEAD=34; P_LOWER=50
|
||||
P_PITCH=3; P_RATE=17; P_VOLUME=70
|
||||
P_PROM=22; P_HEAD=52; P_LOWER=40
|
||||
fi
|
||||
;;
|
||||
hev)
|
||||
|
||||
Reference in New Issue
Block a user