Self-contained in-game TTS for Valheim - speaks chat, runes, raven/intro, center-screen messages, dreams and NPC dialogue. Bundled pure-C# Silero neural voices (RU/EN/DE) via TorchSharp. No Python, no extra downloads, no Piper.
Separate RuneStonesVolume channel. Rune stones (TextViewer.ShowText style 0) now route to a dedicated Channel.RuneStones with its own [Channel Volume] RuneStonesVolume (default 1.0, 0.0–3.0), so rune stones can be quieter than the raven. Raven/intro/tutorial (style 1/2) stay on Channel.Runes. Fixes "rune stones too loud" without silencing the raven.
Soft clipping (tanh). Replaced hard clipping at ±1.0 with Math.Tanh saturation in WavPlayer. Higher gain now compresses smoothly instead of distorting; vol=1 stays near-linear, vol>=2 pushes into smooth saturation.
Normalization target lowered to 0.74 so the volume knob keeps headroom.
1.3.2
Sentence chunking. Long narration (raven tutorial, NPC dialogue) is now split into sentence-sized pieces before synthesis (SileroEngine.SplitIntoChunks, max 200 chars/chunk). Each chunk is synthesized as its own utterance and the PCM is concatenated with a 150 ms silence gap. Gives natural pauses between the header and the body and between paragraphs, and keeps each forward pass short so prosody/energy stay strong (long single utterances drifted and went quiet).
LineJoin header/body joiner (SpeechHooks). Ensures the header ends with sentence punctuation so it becomes its own chunk with a pause before the body — fixes headers read "merged" (слитно) into the rest of the text. Applied to LoreTextHook (raven/runes/intro) and NpcDialogueHook.
1.3.1
Peak normalization.WavPlayer.ToClip now peak-normalizes the decoded PCM to a target of 0.74 (above a 0.01 noise floor) before applying the channel/master volume. Silero often synthesizes RU text at a low peak (~0.1); without normalization the volume multiplier just clipped the few loud peaks while the body stayed inaudible. The raven/runes are now clearly audible at RunesVolume = 2.
1.3.0
Voice overlap control — new [Voice] OverlapMode:
Queue (default): wait for the current line to finish, then play the next — no overlap. Fixes the raven/text collision.
Interrupt: cut off the current line, play the new one immediately.
Overlap: let multiple lines mix.
Narration is now serialized through a single queue (one synth + one playback at a time).
Per-channel volume — new [Channel Volume] section: ChatVolume, CenterVolume, RunesVolume, NpcVolume, DreamsVolume, each 0.0–3.0, multiplied on top of the master [Voice] Volume.
Silence trim + first-letters fix — new [Voice] TrimTrailingSilence (default true) cuts the model's long quiet tail so narration is snappy; new [Voice] PreRollMs (default 120) adds a short lead-in so the first phoneme isn't swallowed by the audio source's start-up ramp. This directly fixes "первые буквы проглатываются".
Reworked WavPlayer to take volume/pre-roll/trim as parameters; Play2DClip/Play2DTransient/PlaySpatialClip replace the old PlayOnPlayer/PlayAtPoint.
1.2.1
Volume control — new [Voice]Volume (default 1.0, range 0.0–3.0).
Above 1.0 amplifies the signal (e.g. 1.5 noticeably louder, 2.0 very loud),
hard-clipped to avoid distortion. Below 1.0 = quieter. Independent of the
game's master volume. Applied at PCM level so the boost works on both the
2D narration and spatial NPC sources.
1.2.0
Best male voice by default:Speaker default changed to aidar (the only
male voice in v5_4_ru).
Tone & speed controls — new [Voice] config entries:
Pitch (default 1.0, range 0.5–2.0): < 1.0 lower/rougher/deeper,
> 1.0 higher/brighter. Scales the model's per-token pitch contour.
No model retraining or .pt rebuild required — applied at synthesis time.
Config descriptions updated for v5_4_ru (4 voices) and the new entries.
1.1.0
Russian upgraded to Silero v5_4_ru (newer neural model, 4 voices:
kseniya, aidar, baya, xenia; eugene falls back to xenia).
Rewrote the RU accentor as a pure-C# port of the v5 AccentorNgram
(native-Cyrillic n-gram + stress/ё MLP, 16969 exceptions), verified 1:1 against
the original v5 TorchScript accentor on a wide test set.
The v5 BERT homograph disambiguation (HomoSolver, 1924 words) is not
bundled — homographs use the n-gram-predicted stress. This keeps the package
Python/BERT-free; the only behavioural delta vs full v5 SileroStress is on
those 1924 homographs.