From 8293bc91d4e2e4b57914f18efa29a27ffb7e5abf Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 18 Feb 2023 03:37:20 +0300 Subject: [PATCH] engine: client: sound: fix PickDynamicChannel to correctly find channel with minimum time left --- engine/client/s_main.c | 65 ++++++++++++++++++++++++++++++++++++++---- engine/client/sound.h | 1 + 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 5a77e24f..3ba4ea13 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -197,6 +197,65 @@ qboolean SND_FStreamIsPlaying( sfx_t *sfx ) return false; } +/* +================= +SND_GetChannelTimeLeft + +TODO: this function needs to be removed after whole sound subsystem rewrite +================= +*/ +static int SND_GetChannelTimeLeft( const channel_t *ch ) +{ + int remaining; + + if( ch->pMixer.finished || !ch->sfx || !ch->sfx->cache ) + return 0; + + if( ch->isSentence ) // sentences are special, count all remaining words + { + int i; + + if( !ch->currentWord ) + return 0; + + // current word + remaining = ch->currentWord->forcedEndSample - ch->currentWord->sample; + + // here we count all remaining words, stopping if no sfx or sound file is available + // see VOX_LoadWord + for( i = ch->wordIndex + 1; i < ARRAYSIZE( ch->words ); i++ ) + { + wavdata_t *sc; + int end; + + // don't continue with broken sentences + if( !ch->words[i].sfx ) + break; + + if( !( sc = S_LoadSound( ch->words[i].sfx ))) + break; + + end = ch->words[i].end; + + if( end ) + remaining += sc->samples * 0.01f * end; + else remaining += sc->samples; + } + } + else + { + int curpos; + int samples; + + // handle position looping + samples = ch->sfx->cache->samples; + curpos = S_ConvertLoopedPosition( ch->sfx->cache, ch->pMixer.sample, ch->use_loop ); + remaining = bound( 0, samples - curpos, samples ); + } + + return remaining; +} + /* ================= SND_PickDynamicChannel @@ -246,11 +305,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean continue; // try to pick the sound with the least amount of data left to play - timeleft = 0; - if( ch->sfx ) - { - timeleft = 1; // ch->end - paintedtime - } + timeleft = SND_GetChannelTimeLeft( ch ); if( timeleft < life_left ) { diff --git a/engine/client/sound.h b/engine/client/sound.h index 19f9eead..d55ee533 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -306,6 +306,7 @@ void S_FadeMusicVolume( float fadePercent ); // int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample ); int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample ); +int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean use_loop ); int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int sampleCount, qboolean use_loop ); void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition ); void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition );