I am creating a simple MP3 player and using the FMOD Core API for managing the audio. I have written a simple program to test the play()
function.
I have two functions freeSound()
and freeSystem()
to free the sound
and the system
handle respectively. Both are called through the function cleanUp()
in the destructor.
I have used gdb
to figure out that for some reason, my program gets stuck in the Sound::release()
call in freeSound()
when the destructor is called.
This problem occurs only when freeSystem()
is called before freeSound()
. Simply calling the latter first fixes this issue.
I have shared as little code as I thought was possible to show this problem. If more/less is required I will add/remove.
The main() function:
int main()
{
musicPlayer p{"music.mp3"};
std::cout << "load success\n";
p.play();
std::cout << "press enter to quit\n";
std::cin.get();
}
The class declaration (includes only relevant bits):
class musicPlayer
{
private:
FMOD::System *m_system = nullptr;
FMOD::Sound *m_sound = nullptr;
/*Some more functions*/
void cleanUp();
void freeSystem();
void freeSound();
public:
~musicPlayer();
/*Some more functions*/
};
Destructor:
musicPlayer::~musicPlayer()
{
cleanUp();
m_channel = nullptr;
}
cleanUp():
void musicPlayer::cleanUp()
{
freeSystem();
freeSound();
}
freeSound() and freeSystem():
void musicPlayer::freeSystem()
{
if(m_system == nullptr)
return;
FMOD_RESULT result = m_system -> release();
if(result != FMOD_OK){
std::cerr << "freeSystem() Error: " << FMOD_ErrorString(result) << "\n";
return;
}
else
m_system = nullptr;
}
void musicPlayer::freeSound()
{
if(m_sound == nullptr)
return;
FMOD_RESULT result = m_sound -> release();
if(result != FMOD_OK){
std::cerr << "freeSound() Error: " << FMOD_ErrorString(result) << "\n";
return;
}
else
m_sound = nullptr;
}
I expect the audio to stop playing and the program to immediately quit when enter is pressed.
Instead, on pressing enter, the audio stops and the program does not quit.
UPDATE:
Earlier, I wrote:
Blockquote I have written little test programs where I have called
System::release()
beforeSound::release()
. Such programs do not exhibit this issue.
I was wrong. The issue can be reproduced by playing a sound, calling cin.get()
and then freeing the resources in the order wrong order.
The FMOD reference FMOD System::close should explain the behaviour:
"Closing renders objects created with this System invalid. Make sure any Sound, ChannelGroup, Geometry and DSP objects are released before calling this.".
System::close is called by System::release so when releasing the system before the components you stumble into problems. As you have found out yourself simply free everything before you release the system.