From 8747ee63d37499caaed82ec0886d1529f7129d4a Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Thu, 24 Jun 2021 05:22:15 +0200 Subject: [PATCH] Make sure `sampleTime` used in sound updates is multiple of 8 Originally sound updates only happened about every 100ms and `sampleTime` (or `newSoundTime`) was a multiple of 4096 (`MIXBUFFER_SAMPLES`). After I changed this to updates every 16ms and made the calculation of `sampleTime` a lot simpler, it could be any value (as it's current amount of milliseconds multiplied by 44.1). It generally seemed to work, but it seems advisable to make it a multiple of 8 (see also "Fix endless loop when decoding OGGs" commit). So I round it to the nearest multiple of 8 now. Furthermore I increased the accuracy when the game has been running for a long time by using double instead of float, and tried to make sure that `sampleTime` is always positive (or at least as long as `inTime` is positive). --- neo/sound/snd_system.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/neo/sound/snd_system.cpp b/neo/sound/snd_system.cpp index ce37c975..804a0f84 100644 --- a/neo/sound/snd_system.cpp +++ b/neo/sound/snd_system.cpp @@ -793,7 +793,19 @@ int idSoundSystemLocal::AsyncUpdateWrite( int inTime ) { return 0; } - int sampleTime = inTime * 44.1f; + // inTime is in milliseconds and if running for long enough that overflows, + // when multiplying with 44.1 it overflows even sooner, so use int64 at first + // (and double because float doesn't have good precision at bigger numbers) + // and then manually truncate to regular int afterwards - this should at least + // prevent sampleTime becoming negative (as long as inTime is not) + long long int sampleTime64 = double( inTime ) * 44.1; + + // furthermore, sampleTime should be divisible by 8 + // (at least by 4 for handling 11kHz samples) so round to nearest multiple of 8 + sampleTime64 = (sampleTime64 + 4) & ~(long long int)7; + + const int sampleTime = sampleTime64 & INT_MAX; + int numSpeakers = s_numberOfSpeakers.GetInteger(); // enable audio hardware caching