Always clamp 'frames_needed' to the allowed mix/max range in the mixer
This fixes tripping the check_casts at the start of `MIXER_MixData` when putting your laptop to sleep on macOS when audio playback is active. Probably it fixes all sorts of other weird edge cases. This is a medium-term solution to ensure safety until the mixer code is thorougly refactored. Triggering and/or understanding all the special cases when the 'frames_needed' under/overshoot can happen is rather tricky with the current code.
This commit is contained in:
parent
dfc3d0a5a3
commit
a25af54d53
1 changed files with 22 additions and 5 deletions
|
@ -221,6 +221,16 @@ static struct mixer_t mixer = {};
|
|||
|
||||
alignas(sizeof(float)) uint8_t MixTemp[MixerBufferLength] = {};
|
||||
|
||||
// TODO Once the mixer code is thorougly refactored, revisit whether this is
|
||||
// still necessary (i.e., we might be able to be more precise with our
|
||||
// 'frames_needed' calculation so we never under or overshoot).
|
||||
static int clamp_frames_needed(const int frames_needed)
|
||||
{
|
||||
return clamp(frames_needed,
|
||||
mixer.min_frames_needed.load(),
|
||||
mixer.max_frames_needed.load());
|
||||
}
|
||||
|
||||
uint16_t MIXER_GetPreBufferMs()
|
||||
{
|
||||
assert(mixer.prebuffer_ms > 0);
|
||||
|
@ -897,7 +907,8 @@ void MixerChannel::Mix(const uint16_t frames_requested)
|
|||
return;
|
||||
}
|
||||
|
||||
frames_needed = frames_requested;
|
||||
frames_needed = clamp_frames_needed(frames_requested);
|
||||
|
||||
while (frames_needed > frames_done) {
|
||||
auto frames_remaining = frames_needed - frames_done;
|
||||
frames_remaining *= freq_add;
|
||||
|
@ -2105,7 +2116,11 @@ static void MIXER_Mix()
|
|||
|
||||
MIXER_MixData(mixer.frames_needed);
|
||||
mixer.tick_counter += mixer.tick_add;
|
||||
mixer.frames_needed += mixer.tick_counter >> TickShift;
|
||||
|
||||
const auto frames_needed = mixer.frames_needed +
|
||||
(mixer.tick_counter >> TickShift);
|
||||
mixer.frames_needed = clamp_frames_needed(frames_needed);
|
||||
|
||||
mixer.tick_counter &= TickMask;
|
||||
|
||||
MIXER_UnlockAudioDevice();
|
||||
|
@ -2137,7 +2152,7 @@ static void MIXER_Mix_NoSound()
|
|||
|
||||
/* Set values for next tick */
|
||||
mixer.tick_counter += mixer.tick_add;
|
||||
mixer.frames_needed = (mixer.tick_counter >> TickShift);
|
||||
mixer.frames_needed = clamp_frames_needed(mixer.tick_counter >> TickShift);
|
||||
mixer.tick_counter &= TickMask;
|
||||
mixer.frames_done = 0;
|
||||
|
||||
|
@ -2267,7 +2282,9 @@ static void SDLCALL MIXER_CallBack([[maybe_unused]] void* userdata,
|
|||
}
|
||||
|
||||
mixer.frames_done -= reduce_frames;
|
||||
mixer.frames_needed -= reduce_frames;
|
||||
|
||||
const auto frames_needed = mixer.frames_needed - reduce_frames;
|
||||
mixer.frames_needed = clamp_frames_needed(frames_needed);
|
||||
|
||||
pos = mixer.pos;
|
||||
mixer.pos = check_cast<work_index_t>((mixer.pos + reduce_frames) &
|
||||
|
@ -2888,7 +2905,7 @@ void MIXER_Init(Section* sec)
|
|||
|
||||
mixer.pos = 0;
|
||||
mixer.frames_done = 0;
|
||||
mixer.frames_needed = mixer.min_frames_needed + 1;
|
||||
mixer.frames_needed = clamp_frames_needed(mixer.min_frames_needed + 1);
|
||||
mixer.min_frames_needed = 0;
|
||||
mixer.max_frames_needed = mixer.blocksize * 2 + 2 * prebuffer_frames;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue