From eb7b540346ab2a6374ebcdb37030acb1bd61bd39 Mon Sep 17 00:00:00 2001 From: Misa Date: Mon, 28 Dec 2020 12:33:54 -0800 Subject: [PATCH] Fix no-draw frames when exiting a level with custom assets When exiting a level, music.init() gets called again, and every time it gets called after the first time it gets called, it will free all music tracks. To do so, it calls Mix_FreeMusic(). Unfortunately, if there is music fading, Mix_FreeMusic() will call SDL_Delay(), which will result in annoying no-draw frames. Meaning, the screen freezes and doesn't draw anything, and has to wait a bit before continuing. Here's the relevant piece of code from SDL2_mixer's music.c: if (music == music_playing) { /* Wait for any fade out to finish */ while (music->fading == MIX_FADING_OUT) { Mix_UnlockAudio(); SDL_Delay(100); Mix_LockAudio(); } if (music == music_playing) { music_internal_halt(); } } This is especially annoying if you're a TASer, because no-draw frames in a libTAS movie aren't guaranteed to last for a consistent number of frames when you change your inputs around. After this patch, as long as your computer can unmount and re-mount assets fast enough (it doesn't seem like mine can, unfortunately), then you won't get any freezes when exiting a level that has custom assets. (This freeze didn't happen when loading a level because the title screen music fadeout upon pressing ACTION had enough time to fully complete before the level got loaded.) --- desktop_version/src/Music.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/desktop_version/src/Music.cpp b/desktop_version/src/Music.cpp index 3cf427ff..47436c48 100644 --- a/desktop_version/src/Music.cpp +++ b/desktop_version/src/Music.cpp @@ -33,11 +33,18 @@ musicclass::musicclass() void musicclass::init() { - for (size_t i = 0; i < soundTracks.size(); ++i) { + for (size_t i = 0; i < soundTracks.size(); ++i) + { Mix_FreeChunk(soundTracks[i].sound); } soundTracks.clear(); - for (size_t i = 0; i < musicTracks.size(); ++i) { + + // Before we free all the music: stop playing music, else SDL2_mixer + // will call SDL_Delay() if we are fading, resulting in no-draw frames + Mix_HaltMusic(); + + for (size_t i = 0; i < musicTracks.size(); ++i) + { Mix_FreeMusic(musicTracks[i].m_music); } musicTracks.clear();