Audio — WavPlayer and FrontendSounds
RagePluginHook 1.124 has no managed sound API (verified absence). Burnsie.Common.Audio
is the supported path for custom audio: WAV files preloaded into memory off the game
thread, played on background CLR threads. A GameFiber never touches disk and never blocks.
For police-scanner voice lines, use ScannerAudio from the LSPDFR
layer instead — that plays through LSPDFR's scanner system.
WavPlayer — custom WAV playback
var wav = new WavPlayer(log);
// At duty start: preload every sound you may play (off-thread, returns immediately).
wav.Preload("plugins/LSPDFR/MyPlugin/audio/alert.wav");
// Anywhere: play asynchronously. Never blocks the caller.
wav.Play("plugins/LSPDFR/MyPlugin/audio/alert.wav");
// Repeats with a gap (e.g. a triple panic tone):
wav.Play("plugins/LSPDFR/MyPlugin/audio/tone.wav", repeats: 3, gapMs: 450);
// Check load state (e.g. before offering an option that needs the sound):
bool ready = wav.IsLoaded(path);
// Teardown / stand-down:
wav.StopAll();
Behavior
- Formats: PCM WAV — what
System.Media.SoundPlayersupports. (No MP3/OGG.) - Paths: absolute, or relative to the GTA V root.
- Files are cached in memory (case-insensitive by path).
Playon an unloaded file loads it on the playback thread — the first play may be slightly delayed but the game never stalls; preloading at duty start avoids even that. - Missing files degrade to silence with a single warning. The path is remembered as unavailable, so a missing file warns once, not per play.
- One background thread runs each logical playback (including all its repeats) over an in-memory stream — bounded work, no unmanaged thread leaks.
StopAll()abandons all pending repeats of every active playback. A buffer that has already started finishes naturally (SoundPlayerhas no safe cross-thread mid-buffer stop); keep your tones short and this is inaudible in practice.
FrontendSounds — named HUD cues
Static, fail-soft wrappers over the game's frontend sound system (via
SafeNatives.PlayFrontendSound). An unknown sound name/set pair is
silence, never an error.
FrontendSounds.RadioSquelchOpen(); // classic mic click before a broadcast
FrontendSounds.RadioSquelchClose(); // squelch off
FrontendSounds.ErrorBeep(); // neutral denied beep (e.g. pressed during cooldown)
FrontendSounds.TimerStop(); // timer-end cue (hold-to-confirm completion)
The sound name/set pairs come from decompiled-script research. Pair
RadioSquelchOpen/Close around scanner or radio moments for cheap immersion:
FrontendSounds.RadioSquelchOpen();
notifier.Show(Palette.Dispatch("copy, units en route"));
Rules
- Never call
WavPlayermethods expecting them to block until playback ends — everything is fire-and-forget. If you need to sequence after a sound,GameFiber.Sleepfor the sound's known duration. FrontendSoundsmust be called from a GameFiber (it goes through a native call).WavPlayer.Play/Preloadare safe from any thread.