Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SDL_Mixer: crash Mix_FreeMusic();

Tags:

c++

sdl

sdl-mixer

I'm working on my project in SDL, with SDL_mixer. Everything sounds ok, but when I attempt to quit, my app crash. I think that it's related to Mix_FreeMusic function (I figured that out after using a lot of breakpoints) - I marked that line in code below:

In main.cpp, function RunEverything,

//sound-related code:
if(SDL_Init(SDL_INIT_EVERYTHING) == -1) { printf("error: %s\n", SDL_GetError()); return NULL; }

int audio_rate = 22050;
Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
int audio_channels = 2;
int audio_buffers = 4096;
if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) { printf("Unable to open audio!\n"); return NULL; }

Later in main.cpp:

int Screen_MainMenu(SDL_Surface *screen)
{
    SDL_Event event;
    CL_Menu Menu;
    /* ... */
    Mix_AllocateChannels(2);
    Mix_PlayMusic(Menu.mMusic, -1);

    while(quit==false) 
    {
        // some time-management, drawing stuff on screen etc., nothing audio-related

        while(SDL_PollEvent(&event))    
        {
            switch(event.type) 
            {
                case SDL_KEYDOWN:
                        switch(event.key.keysym.sym)
                        {
                        case SDLK_ESCAPE:
                            quit = true;
                            break;
                        case SDLK_UP:
                            Menu.kKlik = Mix_PlayChannel(-1, Menu.mKlik, 0);
                            break;
                        case SDLK_DOWN:
                            Menu.kKlik = Mix_PlayChannel(-1, Menu.mKlik, 0);
                            break;
                        }
                    break;
                case SDL_QUIT:
                    quit = true;
                    break;
            }
        }
    }
    Menu.FreeMem();
    return 0;

in class.h:

class CL_Menu
{
public:
    // some SDL_Surface & TTF_Font
    Mix_Music *mMusic;
    int kKlik;
    Mix_Chunk *mKlik;

    CL_Menu();
    void FreeMem();
};

in class.cpp:

CL_Menu::CL_Menu()
{
//loading .png & .ttf
    mMusic = Mix_LoadMUS("MP3/Sirio-Dance_Of_Stars.mp3");
    mKlik = Mix_LoadWAV("MP3/klik.wav");
};

void CL_Menu::FreeMem()
{
    //while(Mix_Playing(kKlik) != 0);
    Mix_HaltChannel(kKlik);
    Mix_HaltMusic();    
    Mix_FreeChunk(mKlik);   

// CloseFont & FreeSurface

    Mix_HaltMusic();
    SDL_Delay(100);
    Mix_FreeMusic(mMusic); // <-- that line probably causes crash
    mMusic = NULL;
};

I'm using win7 x64, Visual Studio 2010 and latest SDL libs. Also I noticed, that when I close my program within 10-15 seconds, it works fine. Only when it runs about 20-30 seconds, I get a crash.

edit: If it's important, my mp3 is rather big - about 9 MB (192 kb/s)

like image 845
Greg Witczak Avatar asked Oct 25 '25 04:10

Greg Witczak


2 Answers

Finally I managed to figure it out, so I'm writing a solution that worked in my case. I had to convert my .mp3 file to .ogg. And that's all. Probably that mp3 file was somehow corrupted, or it was an error in the SDL library.

like image 114
Greg Witczak Avatar answered Oct 26 '25 18:10

Greg Witczak


I actually had the same problem just a while ago.

If anyone is searching for a solution and the .ogg conversion does not work, here are some quick hints as to what you can check:

Correct Deinitialization Order

In my personal case, the SDL_mixer quit before deallocation of the music file, giving an error on Free_Music() not because the file was corrupted, but because SDL_mixer was closed and still being called.

You can use the return value of Mix_QueryMusic(0,0,0) to see if your Audio is still open and available for use, or if there's an error (int 0).

This can happen quite quickly if you somewhere use a wrapper, to which you point a smart pointer. Be sure ALL smart pointers are out of scope BEFORE Mix_Quit() or Mix_AudioClose()! This can usually be done if you look a bit deeper into ownership of your pointers. In my case, having only the AudioManager class use shared_ptr and the rest use weak_ptr did the trick. I simply told the AudioManager class to deinitialize BEFORE closing my audio or quitting Mix_Music.

Setting Flags correctly and using the AudioClose

Secondly, see if your Mix_Init flags include all files that should be opened, like Mix_INIT_MP3 and Mix_INIT_OGG.

Furthermore, you should also close your audio by Mix_AudioClose() at the end of your program.

like image 20
trashy Avatar answered Oct 26 '25 17:10

trashy