global.bgm = FMODGMS_Snd_LoadSound("bgm");
global.temporarySound= FMODGMS_Snd_LoadSound("temporarySound");
global.oneLastSound= FMODGMS_Snd_LoadSound("oneLastSound");
// LoadSound returns the sound's index in the internal soundList, so at this point
// bgm = 1, temporarySound = 2, and oneLastSound = 3
// (let's pretend counting starts at 1.)
You load these up and go about your game, and the internal soundsList vector looks like this:
bgm
temporarySound
oneLastSound
But eventually the time comes to unload temporarySound.
FMODGMS_Snd_Unload(global.temporarySound);
Let's have a look at what this does under the hood:
// Unload a sound and removes it from soundList
GMexport double FMODGMS_Snd_Unload(double index)
{
// ... some validation of input, etc ...
soundList.erase(soundList.begin());
return GMS_true;
}
Yikes, it for some reason removes the first item in the sound list. Let's take another look at our internal soundList now:
Sound indexes can change after removing sounds from the soundList. For example, removing temporarySound will change oneLastSound's index from 3 to 2 in the example, even if we fixed problem 1).
In this PR, we don't store sounds in a vector, instead we store them in a map. Each sound/channel/effect is allocated a unique index when it's created. When we remove something from a map, other keys are unaffected. The sound's index after being sent to Game Maker will remain valid until it's unloaded (properly, using FMOD::Sound::release).
I tested this quickly and it fixed my unloading problem, and the demo project still worked, but since there's so many changes it's still pretty risky to merge. I'd recommend some unit tests and playing around with this yourself first.
Problem scenario
Consider this:
You load these up and go about your game, and the internal
soundsList
vector looks like this:But eventually the time comes to unload
temporarySound
.Let's have a look at what this does under the hood:
Yikes, it for some reason removes the first item in the sound list. Let's take another look at our internal soundList now:
yet in GameMaker, our globals remain the same!
Holy moly. Now
PlaySound(global.bgm)
is going to start playingtemporarySound
again, even though we just unloaded that sound!The solution
We have 3 problems here:
soundList
. For example, removingtemporarySound
will changeoneLastSound
's index from 3 to 2 in the example, even if we fixed problem 1).In this PR, we don't store sounds in a vector, instead we store them in a map. Each sound/channel/effect is allocated a unique index when it's created. When we remove something from a map, other keys are unaffected. The sound's index after being sent to Game Maker will remain valid until it's unloaded (properly, using FMOD::Sound::release).
I tested this quickly and it fixed my unloading problem, and the demo project still worked, but since there's so many changes it's still pretty risky to merge. I'd recommend some unit tests and playing around with this yourself first.