SDL_Mixer: сбой Mix_FreeMusic();

Я работаю над своим проектом в SDL с помощью SDL_mixer. Все вроде нормально, но когда я пытаюсь выйти, мое приложение вылетает. Я думаю, что это связано с функцией Mix_FreeMusic (я понял это после использования множества точек останова) — я отметил эту строку в коде ниже:

В main.cpp функция 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; }

Далее в 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;

в class.h:

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

    CL_Menu();
    void FreeMem();
};

в 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;
};

Я использую win7 x64, Visual Studio 2010 и последние библиотеки SDL. Также я заметил, что когда я закрываю свою программу в течение 10-15 секунд, она работает нормально. Только когда он работает около 20-30 секунд, я получаю вылет.

edit: Если это важно, мой mp3 довольно большой - около 9 МБ (192 кб/с)


person Greg Witczak    schedule 26.12.2011    source источник
comment
Не ответ, но Mix_FreeMusic() задокументировано как остановка музыки при необходимости. Проблема сохраняется, если вы удалите вызовы Mix_HaltMusic() и SDL_Delay()?   -  person Frédéric Hamidi    schedule 26.12.2011
comment
Я знал это, но из соображений безопасности решил остановить музыку сам. Удаление этих строк или увеличение SDL_Delay до 10 секунд не решает проблему.   -  person Greg Witczak    schedule 26.12.2011
comment
Как ваша библиотека SDL обрабатывает ваш mp3? Вы связаны libs (хромой, я думаю), хорошо?   -  person dzen    schedule 06.01.2012


Ответы (3)


Наконец мне удалось это выяснить, поэтому я пишу решение, которое сработало в моем случае. Мне пришлось конвертировать файл .mp3 в .ogg. И это все. Вероятно, этот mp3-файл был каким-то образом поврежден или это была ошибка в библиотеке SDL.

person Greg Witczak    schedule 05.01.2012
comment
У меня была такая же проблема с воспроизведением мп3 файлов, решения не нашел. - person ; 16.02.2013

У меня действительно была такая же проблема некоторое время назад.

Если кто-то ищет решение, а преобразование .ogg не работает, вот несколько быстрых советов о том, что вы можете проверить:

Правильный порядок деинициализации

В моем личном случае SDL_mixer завершал работу до освобождения музыкального файла, выдавая ошибку Free_Music() не потому, что файл был поврежден, а потому, что SDL_mixer был закрыт и все еще вызывается.

Вы можете использовать возвращаемое значение Mix_QueryMusic(0,0,0), чтобы узнать, открыто ли ваше аудио и доступно ли оно для использования, или есть ли ошибка (int 0).

Это может произойти довольно быстро, если вы где-то используете обертку, на которую указываете смарт-указатель. Убедитесь, что ВСЕ интеллектуальные указатели находятся вне области действия ПЕРЕД Mix_Quit() или Mix_AudioClose()! Это обычно можно сделать, если вы немного глубже изучите право собственности на свои указатели. В моем случае, если только класс AudioManager использует shared_ptr, а остальные используют weak_ptr, это помогло. Я просто сказал классу AudioManager деинициализировать ПЕРЕД закрытием аудио или выходом из Mix_Music.

Правильная установка флагов и использование AudioClose

Во-вторых, посмотрите, включают ли ваши флаги Mix_Init все файлы, которые должны быть открыты, например Mix_INIT_MP3 и Mix_INIT_OGG.

Кроме того, вы также должны закрыть звук с помощью Mix_AudioClose() в конце вашей программы.

person trashy    schedule 08.01.2017

У меня была аналогичная проблема, только в C. Mix_Quit() вызывался до Mix_FreeMusic(). Как только я поставил все в правильном порядке, проблема исчезла.

Меня также смутили Mix_Quit() и Mix_CloseAudio(). Из моего исследования я обнаружил, что вы звоните Mix_Quit() один раз для каждого Mix_Init(), который вы вызвали, и вы звоните Mix_CloseAudio() только один раз после того, как закончите с Mix_Quit().

person Neil Roy    schedule 06.04.2017