From 349ab399dcb397a84f318d7a3c72ab55dc57c5f1 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Tue, 23 Jan 2024 18:38:28 +0300 Subject: [PATCH] Load and unload music files as needed When VVVVVV is run on devices (such as the Nintendo Wii) that are memory costrained, it's not possible to load all the music files at startup. Therefore, change the MusicTrack contructor to only save the RWops structure, and load the music data only when Play() gets called. Also, when a song start playing we do unload the previous one. --- desktop_version/src/Music.cpp | 61 +++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/desktop_version/src/Music.cpp b/desktop_version/src/Music.cpp index b725940c..9b4d37a6 100644 --- a/desktop_version/src/Music.cpp +++ b/desktop_version/src/Music.cpp @@ -372,9 +372,20 @@ float SoundTrack::volume = 0.0f; class MusicTrack { public: - MusicTrack(SDL_RWops *rw) + MusicTrack(SDL_RWops *rw, bool autoload = true) { SDL_zerop(this); + this->rw = rw; + this->autoload = autoload; + if (autoload) + { + Load(); + } + } + + void Load(void) + { + loaded = true; read_buf = (Uint8*) SDL_malloc(rw->size(rw)); SDL_RWread(rw, read_buf, rw->size(rw), 1); int err; @@ -385,7 +396,7 @@ public: { vlog_error("Unable to create Vorbis handle, error %d", err); VVV_free(read_buf); - goto end; + return; } vorbis_info = stb_vorbis_get_info(vorbis); format.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT; @@ -407,25 +418,54 @@ public: vorbis_comment = stb_vorbis_get_comment(vorbis); parseComments(this, vorbis_comment.comment_list, vorbis_comment.comment_list_length); valid = true; - -end: - SDL_RWclose(rw); } - void Dispose(void) + void Unload(void) { + if (!loaded) + { + return; + } VVV_freefunc(stb_vorbis_close, vorbis); VVV_free(read_buf); VVV_free(decoded_buf_playing); VVV_free(decoded_buf_reserve); + /* The song might get loaded again, so reset the read cursor */ + SDL_RWseek(rw, 0, RW_SEEK_SET); + loaded = false; + } + + void Dispose(void) + { + if (loaded) + { + Unload(); + } if (!IsHalted()) { VVV_freefunc(FAudioVoice_DestroyVoice, musicVoice); } + SDL_RWclose(rw); } bool Play(bool loop) { + Halt(); + + if (currentTrack != this) + { + if (currentTrack && !currentTrack->autoload) + { + currentTrack->Unload(); + } + currentTrack = this; + } + + if (!loaded) + { + Load(); + } + if (!valid) { return false; @@ -435,8 +475,6 @@ end: sample_pos = 0; stb_vorbis_seek_start(vorbis); - Halt(); - SDL_zero(callbacks); callbacks.OnBufferStart = &MusicTrack::refillReserve; callbacks.OnBufferEnd = &MusicTrack::swapBuffers; @@ -513,6 +551,7 @@ end: } } + SDL_RWops *rw; stb_vorbis* vorbis; int channels; Uint32 size; @@ -527,9 +566,12 @@ end: Uint8* decoded_buf_reserve; Uint8* read_buf; bool shouldloop; + bool loaded; bool valid; + bool autoload; static bool paused; + static MusicTrack *currentTrack; static FAudioSourceVoice* musicVoice; static void refillReserve(FAudioVoiceCallback* callback, void* ctx) @@ -709,6 +751,7 @@ end: }; bool MusicTrack::paused = false; FAudioSourceVoice* MusicTrack::musicVoice = NULL; +MusicTrack* MusicTrack::currentTrack = NULL; musicclass::musicclass(void) { @@ -833,7 +876,7 @@ void musicclass::init(void) } \ else \ { \ - musicTracks.push_back(MusicTrack(rw)); \ + musicTracks.push_back(MusicTrack(rw, false)); \ } TRACK_NAMES(_)