c++mp3fmod

Why is my code not completing the Sound::release() call?


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() before Sound::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.


Solution

  • 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.