mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 17:09:57 -04:00
Do not mix a menu sound past its end when it restarts during the mix.
menu_sound_play restarts a voice in place for a repeated cursor tick. When that happened between the mixer's loads of the voice's position and its sound, the old position was used with the new, shorter sound: the frame count wrapped and the mixer read past the sound's samples. The mixer now checks that the position is still the voice's and inside the sound. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -177,8 +177,11 @@ void menu_sound_mix(float *out, uint32_t frames, int channels, int rate) {
|
||||
for (int v = 0; v < VOICES; v++) {
|
||||
int pos = atomic_load_explicit(&voices[v].pos, memory_order_acquire);
|
||||
if (pos < 0) continue;
|
||||
int which = atomic_load_explicit(&voices[v].sound, memory_order_relaxed);
|
||||
int which = atomic_load_explicit(&voices[v].sound, memory_order_acquire);
|
||||
const Sound *s = &sounds[which];
|
||||
// menu_sound_play may restart the voice between the two loads: pos would then belong to the old sound, past
|
||||
// the end of a shorter new one; such a voice is mixed from the next call on
|
||||
if (atomic_load_explicit(&voices[v].pos, memory_order_acquire) != pos || (uint32_t)pos >= s->frames) continue;
|
||||
if (g < 0) g = volume();
|
||||
float vg = which == MENU_SOUND_CURSOR ? g * CURSOR_GAIN : g;
|
||||
uint32_t n = s->frames - (uint32_t)pos < frames ? s->frames - (uint32_t)pos : frames;
|
||||
|
||||
Reference in New Issue
Block a user