Skip to content

Persistent sounds & threaded OpenAL#548

Draft
Couls wants to merge 2 commits into
themrdemonized:all-in-one-vs2022-wpo-mtfrom
Couls:MT-SOUND
Draft

Persistent sounds & threaded OpenAL#548
Couls wants to merge 2 commits into
themrdemonized:all-in-one-vs2022-wpo-mtfrom
Couls:MT-SOUND

Conversation

@Couls

@Couls Couls commented May 29, 2026

Copy link
Copy Markdown

Summary

This PR adds an engine-level persistent sound capability and moves OpenAL buffer updates onto a dedicated background thread, so 2D streams (music, PDA radio) keep playing seamlessly across level transitions and during the load screen, and remain fully controllable from Lua afterward. mtSound remains a console command and can be set to 0 to disable multithreaded sound implementation

Motivation

In the engine, every emitter is destroyed when a level unloads (_clear), and the main thread is blocked for seconds during loading, so any streamed audio stops dead. Mods that want continuous music (e.g. a PDA radio) have no clean way to keep a stream alive and re-bind to it after the new level spawns. This PR solves both problems at the source.

What's included

1. Persistent emitters (survive level unload)

  • CSound_emitter::set_persistent(bool) / is_persistent() — a persistent emitter is forced to 2D and is not destroyed during _clear.
  • The core keeps a strong reference to the owner data (s_persistent_refs) so the stream survives Lua GC.
  • During _clear, persistent survivors are detached from their render target (enter "simulating" state), kept in s_emitters, and their backing CSound_source is preserved while every non-persistent emitter/source is released as before.

2. Per-emitter "persist in menu" flag

  • set_persistent_in_menu(bool) / is_persistent_in_menu() controls whether a given persistent emitter keeps playing while the game is paused in a menu, replacing the old global toggle. pause_emitters() honors it per-emitter.

3. Owner re-binding after transition

  • After a level load recreates the Lua sound_object (new owner pointer) while the persistent emitter is still playing, the engine reconnects them: reconcile_emitter_feedback() re-links owner_data->feedback, matching by source handle when the owner pointer changed.
  • New helpers: stop_emitters_for_owner(), has_playing_emitter_for_owner(), consolidated through a single find_emitter_for_owner() lookup.
  • ref_sound::stop() / has_playing_emitter() now work even when the cached feedback pointer was lost across a load.

4. Threaded OpenAL update

  • OpenAL buffer refills run on a dedicated SoundRender_UpdateThread; the main thread only publishes a listener snapshot, so audio does not stutter while the main thread is blocked loading a level.
  • All AL access is serialized by a single critical section (sound_api_enter/leave, which also makes the AL context current per thread).

5. Console command

  • snd_stop_persistent — force-stops all persistent emitters (cleanup / safety).

Lua API

The feature is exposed on the existing sound_object:

  local snd = sound_object("music\\my_track")
  -- Mark the stream persistent so it survives level transitions.
  -- arg1: sets to a persistent emitter across level load
  -- arg2 (optional): keep playing while paused in a menu (default true)
  snd:set_persistent(true, true)
  -- Play as a 2D stream on the music bus (s2d + sm_Intro flag = 2)
  snd:play(nil, 0, sound_object.s2d + 2)
  snd.volume = 0.5
  -- Query state (works even after a level change re-binds the emitter)
  if snd:playing() then ... end
  local p  = snd:is_persistent()
  local pm = snd:is_persistent_in_menu()
  -- Stop and release persistence
  snd:stop()
  snd:set_persistent(false)

@themrdemonized

Copy link
Copy Markdown
Owner

Add new lua exports into lua_help_ex please

@themrdemonized

Copy link
Copy Markdown
Owner

I got this crash while testing this PR. It might be related to relation between mtSound and mtSoundPlayer flag that is used for update_sound_player.
изображение

@themrdemonized

themrdemonized commented May 29, 2026

Copy link
Copy Markdown
Owner
изображение another one. Happened when i shot a monster.

I'm marking as draft, too unstable for me

@themrdemonized themrdemonized marked this pull request as draft May 29, 2026 22:22
@Priler

Priler commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Hope this gon fix issue with rain sounds during loading screens when you alt+tab.
and some issues with the radio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants