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;
в классе.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 секунд, я получаю сбой.
редактировать: если это важно, мой mp3 довольно большой - около 9 МБ (192 кбит / с)
3 ответа
В конце концов мне удалось выяснить это, поэтому я пишу решение, которое сработало в моем случае. Мне пришлось конвертировать мой файл .mp3 в.ogg. И это все. Возможно, этот mp3-файл был каким-то образом поврежден, или это была ошибка в библиотеке SDL.
У меня фактически была та же самая проблема некоторое время назад.
Если кто-то ищет решение, и преобразование.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()
в конце вашей программы.
У меня была похожая проблема, только в C. Mix_Quit()
звонили раньше Mix_FreeMusic()
, Как только я все расставил по порядку, проблема ушла.
Я был также смущен Mix_Quit()
а также Mix_CloseAudio()
, Из моего исследования я обнаружил, что вы звоните Mix_Quit()
один раз для каждого Mix_Init()
ты звонил, и ты звонишь Mix_CloseAudio()
только один раз после того, как вы сделали с Mix_Quit()
,