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.
This commit is contained in:
Alberto Mardegan 2024-01-23 18:38:28 +03:00
parent 448c4a5514
commit 349ab399dc
1 changed files with 52 additions and 9 deletions

View File

@ -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(_)