From 0b920be381c69eeeaa34fc1a04399139974fd6c8 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 2 Apr 2026 23:51:37 +0500 Subject: [PATCH] engine: client: delay freeing up the sound channel when it becomes inaudible --- engine/client/s_main.c | 2 +- engine/client/s_mix.c | 11 +++++++++-- engine/client/sound.h | 25 +++++++++++++++---------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 1162b12a..b2f0888c 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -521,7 +521,7 @@ static int S_AlterChannel( int entnum, int channel, const sfx_t *sfx, int vol, i S_SpatializeChannel ================= */ -static void S_SpatializeChannel( int *left_vol, int *right_vol, int master_vol, float dot, float dist ) +static void S_SpatializeChannel( short *left_vol, short *right_vol, int master_vol, float dot, float dist ) { float scale; diff --git a/engine/client/s_mix.c b/engine/client/s_mix.c index ceb21fe2..c58c77f3 100644 --- a/engine/client/s_mix.c +++ b/engine/client/s_mix.c @@ -284,13 +284,20 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate ) // if the sound is unaudible, skip it // if it's also not looping, free it if( ch->leftvol < 8 && ch->rightvol < 8 ) - { + { if( !FBitSet( sc->flags, SOUND_LOOPED ) || !ch->use_loop ) - S_FreeChannel( ch ); + { + if( ch->inauduble_free_time == 0.0f ) + ch->inauduble_free_time = host.realtime + MAX_CHANNEL_INAUDIBLE_TIME; + else if( ch->inauduble_free_time > host.realtime ) + S_FreeChannel( ch ); + } continue; } + ch->inauduble_free_time = 0.0f; + if( rate != sc->rate ) continue; diff --git a/engine/client/sound.h b/engine/client/sound.h index a0b0bbf1..47962b13 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -85,9 +85,9 @@ typedef struct typedef struct rawchan_s { int entnum; - int master_vol; - int leftvol; // 0-255 left volume - int rightvol; // 0-255 right volume + short master_vol; + short leftvol; // 0-255 left volume + short rightvol; // 0-255 right volume float dist_mult; // distance multiplier (attenuation/clipK) vec3_t origin; // only use if fixed_origin is set volatile uint s_rawend; @@ -101,14 +101,15 @@ typedef struct channel_s char name[16]; // keep sentence name sfx_t *sfx; // sfx number - int leftvol; // 0-255 left volume - int rightvol; // 0-255 right volume + vec3_t origin; // only use if fixed_origin is set + float dist_mult; // distance multiplier (attenuation/clipK) int entnum; // entity soundsource int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.) - vec3_t origin; // only use if fixed_origin is set - float dist_mult; // distance multiplier (attenuation/clipK) - int master_vol; // 0-255 master volume + short master_vol; // 0-255 master volume + short leftvol; // 0-255 left volume + short rightvol; // 0-255 right volume + short basePitch; // base pitch percent (100% is normal pitch playback) byte use_loop : 1; // don't loop default and local sounds byte staticsound : 1; // use origin instead of fetching entnum's origin byte localsound : 1; // it's a local menu sound (not looped, not paused) @@ -116,11 +117,15 @@ typedef struct channel_s byte sentence_finished : 1; // if set, finished playing sentence byte finished : 1; // if set, finished playing single word byte word_index; - short basePitch; // base pitch percent (100% is normal pitch playback) - voxword_t words[CVOXWORDMAX]; + // HACKHACK: count when this channel became inaudible + // to not free it when it could be respatialized soon +#define MAX_CHANNEL_INAUDIBLE_TIME 0.1f + float inauduble_free_time; + double sample; double forced_end; wavdata_t *data; + voxword_t words[CVOXWORDMAX]; } channel_t; typedef struct