From 58de196cfa843ad052291cd35be3ebd29e57efcc Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Sun, 25 Aug 2024 12:43:30 +1000 Subject: [PATCH] snd_mutewhenidle: add only-when-minimised mode, fix cl_capturevideo compat, cleanup Maybe snd_mutewhenidle 2 should be the default? When inactive/minimised with snd_mutewhenidle enabled, the audio capture was unreliable and sound was sometimes output when it should have been muted. Closes https://gitlab.com/xonotic/darkplaces/-/issues/92 (the video issue was already fixed). Timedemos now share the same mute implementation as snd_mutewhenidle. Signed-off-by: bones_was_here --- cl_screen.c | 3 ++- snd_main.c | 36 +++++++++++------------------------- snd_main.h | 3 +-- snd_mix.c | 12 ------------ snd_null.c | 8 -------- snd_sdl.c | 4 +++- vid_sdl.c | 19 ------------------- 7 files changed, 17 insertions(+), 68 deletions(-) diff --git a/cl_screen.c b/cl_screen.c index bf4c3d19..1ded3749 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -2280,7 +2280,8 @@ void CL_UpdateScreen(void) } #ifdef CONFIG_VIDEO_CAPTURE - if (vid_hidden && !cls.capturevideo.active && !cl_capturevideo.integer) + if (vid_hidden && !cls.capturevideo.active + && !cl_capturevideo.integer) // so we can start capturing while hidden #else if (vid_hidden) #endif diff --git a/snd_main.c b/snd_main.c index 9ac20114..cee8ec58 100644 --- a/snd_main.c +++ b/snd_main.c @@ -152,8 +152,8 @@ qbool simsound = false; static qbool recording_sound = false; #endif -int snd_blocked = 0; -static int current_swapstereo = false; +bool snd_blocked = false; +static bool current_swapstereo = false; static int current_channellayout = SND_CHANNELLAYOUT_AUTO; static int current_channellayout_used = SND_CHANNELLAYOUT_AUTO; @@ -168,7 +168,6 @@ cvar_t snd_initialized = {CF_CLIENT | CF_READONLY, "snd_initialized", "0", "indi // Cvars declared in snd_main.h (shared with other snd_*.c files) cvar_t snd_channellayout = {CF_CLIENT, "snd_channellayout", "0", "channel layout. Can be 0 (auto - snd_restart needed), 1 (standard layout), or 2 (ALSA layout)"}; -cvar_t snd_mutewhenidle = {CF_CLIENT | CF_ARCHIVE, "snd_mutewhenidle", "1", "whether to disable sound output when game window is inactive"}; cvar_t snd_streaming = {CF_CLIENT | CF_ARCHIVE, "snd_streaming", "1", "enables keeping compressed ogg sound files compressed, decompressing them only as needed, otherwise they will be decompressed completely at load (may use a lot of memory); when set to 2, streaming is performed even if this would waste memory"}; cvar_t snd_streaming_length = {CF_CLIENT | CF_ARCHIVE, "snd_streaming_length", "1", "decompress sounds completely if they are less than this play time when snd_streaming is 1"}; cvar_t snd_waterfx = {CF_CLIENT | CF_ARCHIVE, "snd_waterfx", "1", "underwater sound filter strength"}; @@ -191,6 +190,7 @@ cvar_t snd_spatialization_occlusion = {CF_CLIENT | CF_ARCHIVE, "snd_spatializati cvar_t _snd_mixahead = {CF_CLIENT | CF_ARCHIVE, "_snd_mixahead", "0.15", "how much sound to mix ahead of time"}; cvar_t snd_swapstereo = {CF_CLIENT | CF_ARCHIVE, "snd_swapstereo", "0", "swaps left/right speakers for old ISA soundblaster cards"}; cvar_t snd_maxchannelvolume = {CF_CLIENT | CF_ARCHIVE, "snd_maxchannelvolume", "10", "maximum volume of a single sound"}; +cvar_t snd_mutewhenidle = {CF_CLIENT | CF_ARCHIVE, "snd_mutewhenidle", "1", "1 disables sound output when game window is inactive, 2 disables it only when the window is minimised"}; cvar_t snd_softclip = {CF_CLIENT | CF_ARCHIVE, "snd_softclip", "0", "Use soft-clipping. Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. WARNING: This feature creates distortion and should be considered a last resort."}; //cvar_t snd_softclip = {CF_CLIENT | CF_ARCHIVE, "snd_softclip", "0", "Use soft-clipping (when set to 2, use it even if output is floating point). Soft-clipping can make the sound more smooth if very high volume levels are used. Enable this option if the dynamic range of the loudspeakers is very low. WARNING: This feature creates distortion and should be considered a last resort."}; cvar_t snd_entchannel0volume = {CF_CLIENT | CF_ARCHIVE, "snd_entchannel0volume", "1", "volume multiplier of the auto-allocate entity channel of regular entities (DEPRECATED)"}; @@ -1107,27 +1107,6 @@ qbool S_IsSoundPrecached (const sfx_t *sfx) return (sfx != NULL && sfx->fetcher != NULL) || (sfx == &changevolume_sfx); } -/* -================== -S_BlockSound -================== -*/ -void S_BlockSound (void) -{ - snd_blocked++; -} - - -/* -================== -S_UnblockSound -================== -*/ -void S_UnblockSound (void) -{ - snd_blocked--; -} - /* ================= @@ -1974,7 +1953,9 @@ static void S_PaintAndSubmit (void) } soundtimehack = usesoundtimehack; - if (!soundtimehack && snd_blocked > 0) + // mixing is always required here when capturing, even if output is muted + // (capture doesn't use threaded/callback mode) + if (!soundtimehack && snd_blocked && !cls.capturevideo.active) return; if (snd_usethreadedmixing) @@ -2086,6 +2067,11 @@ void S_Update(const matrix4x4_t *listenermatrix) if (snd_renderbuffer == NULL || nosound.integer) return; + // enable/disable sound on focus gain/loss + snd_blocked = (snd_mutewhenidle.integer == 1 && !vid_activewindow) + || (snd_mutewhenidle.integer == 2 && vid_hidden) + || cls.timedemo; + { double mindist_trans, maxdist_trans; diff --git a/snd_main.h b/snd_main.h index 681fc32f..f276f8d5 100644 --- a/snd_main.h +++ b/snd_main.h @@ -127,7 +127,6 @@ extern snd_ringbuffer_t *snd_renderbuffer; extern qbool snd_threaded; ///< enables use of snd_usethreadedmixing, provided that no sound hacks are in effect (like timedemo) extern qbool snd_usethreadedmixing; ///< if true, the main thread does not mix sound, soundtime does not advance, and neither does snd_renderbuffer->endframe, instead the audio thread will call S_MixToBuffer as needed -extern cvar_t snd_mutewhenidle; extern cvar_t snd_waterfx; extern cvar_t snd_streaming; extern cvar_t snd_streaming_length; @@ -137,7 +136,7 @@ extern cvar_t snd_streaming_length; #define SND_CHANNELLAYOUT_ALSA 2 extern cvar_t snd_channellayout; -extern int snd_blocked; // counter. When > 0, we stop submitting sound to the audio device +extern bool snd_blocked; ///< When true, we submit silence to the audio device extern struct mempool_s *snd_mempool; diff --git a/snd_mix.c b/snd_mix.c index d8ea1dbe..41358fee 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -184,10 +184,6 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p *snd_out++ = painted_ptr->sample[0]; } } - - // noise is really really annoying - if (cls.timedemo) - memset(rb_ptr, 0, nbframes * nchannels * width); } else if (width == 2) // 16bit { @@ -243,10 +239,6 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767); } } - - // noise is really really annoying - if (cls.timedemo) - memset(rb_ptr, 0, nbframes * nchannels * width); } else // 8bit { @@ -302,10 +294,6 @@ static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_p val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255); } } - - // noise is really really annoying - if (cls.timedemo) - memset(rb_ptr, 128, nbframes * nchannels); } } diff --git a/snd_null.c b/snd_null.c index 28309c39..5d15bff0 100755 --- a/snd_null.c +++ b/snd_null.c @@ -127,14 +127,6 @@ qbool S_LocalSoundEx (const char *s, int chan, float fvol) return false; } -void S_BlockSound (void) -{ -} - -void S_UnblockSound (void) -{ -} - int S_GetSoundRate(void) { return 0; diff --git a/snd_sdl.c b/snd_sdl.c index e34a46e8..706fa304 100644 --- a/snd_sdl.c +++ b/snd_sdl.c @@ -58,7 +58,9 @@ static void Buffer_Callback (void *userdata, Uint8 *stream, int len) FrameCount = MaxFrames; StartOffset = snd_renderbuffer->startframe % snd_renderbuffer->maxframes; EndOffset = (snd_renderbuffer->startframe + FrameCount) % snd_renderbuffer->maxframes; - if (StartOffset > EndOffset) // if the buffer wraps + if (snd_blocked) + memset(stream, snd_renderbuffer->format.width == 1 ? 0x80 : 0, len); + else if (StartOffset > EndOffset) // if the buffer wraps { unsigned int PartialLength1, PartialLength2; diff --git a/vid_sdl.c b/vid_sdl.c index 631b0da8..ea6fe26e 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -1042,7 +1042,6 @@ static keynum_t buttonremap[] = //#define DEBUGSDLEVENTS void Sys_SDL_HandleEvents(void) { - static qbool sound_active = true; int keycode; int i; const char *chp; @@ -1330,24 +1329,6 @@ void Sys_SDL_HandleEvents(void) vid_activewindow = !vid_hidden && vid_hasfocus; - // enable/disable sound on focus gain/loss - if (vid_activewindow || !snd_mutewhenidle.integer) - { - if (!sound_active) - { - S_UnblockSound (); - sound_active = true; - } - } - else - { - if (sound_active) - { - S_BlockSound (); - sound_active = false; - } - } - if (!vid_activewindow || key_consoleactive || scr_loading) VID_SetMouse(false, false); else if (key_dest == key_menu || key_dest == key_menu_grabbed) -- 2.39.2