#include "sound_manager.h" #include "myfilesystem.h" #if defined(YGOPRO_USE_MINIAUDIO) && defined(YGOPRO_MINIAUDIO_SUPPORT_OPUS_VORBIS) #include #include #endif namespace ygo { SoundManager soundManager; bool SoundManager::Init() { #ifdef YGOPRO_USE_AUDIO bgm_scene = -1; RefreshBGMList(); rnd.seed(std::random_device()()); #ifdef YGOPRO_USE_MINIAUDIO engineConfig = ma_engine_config_init(); #ifdef YGOPRO_MINIAUDIO_SUPPORT_OPUS_VORBIS ma_decoding_backend_vtable* pCustomBackendVTables[] = { ma_decoding_backend_libvorbis, ma_decoding_backend_libopus }; resourceManagerConfig = ma_resource_manager_config_init(); resourceManagerConfig.ppCustomDecodingBackendVTables = pCustomBackendVTables; resourceManagerConfig.customDecodingBackendCount = sizeof(pCustomBackendVTables) / sizeof(pCustomBackendVTables[0]); resourceManagerConfig.pCustomDecodingBackendUserData = NULL; if(ma_resource_manager_init(&resourceManagerConfig, &resourceManager) != MA_SUCCESS) { return false; } engineConfig.pResourceManager = &resourceManager; #endif if(ma_engine_init(&engineConfig, &engineSound) != MA_SUCCESS || ma_engine_init(&engineConfig, &engineMusic) != MA_SUCCESS) { return false; } else { return true; } #endif // YGOPRO_USE_MINIAUDIO #endif // YGOPRO_USE_AUDIO return false; } void SoundManager::RefreshBGMList() { #ifdef YGOPRO_USE_AUDIO RefershBGMDir(L"", BGM_DUEL); RefershBGMDir(L"duel", BGM_DUEL); RefershBGMDir(L"menu", BGM_MENU); RefershBGMDir(L"deck", BGM_DECK); RefershBGMDir(L"advantage", BGM_ADVANTAGE); RefershBGMDir(L"disadvantage", BGM_DISADVANTAGE); RefershBGMDir(L"win", BGM_WIN); RefershBGMDir(L"lose", BGM_LOSE); #endif } void SoundManager::RefershBGMDir(std::wstring path, int scene) { #ifdef YGOPRO_USE_AUDIO std::wstring search = L"./sound/BGM/" + path; FileSystem::TraversalDir(search.c_str(), [this, &path, scene](const wchar_t* name, bool isdir) { if(!isdir && ( IsExtension(name, L".mp3") #if defined(YGOPRO_MINIAUDIO_SUPPORT_OPUS_VORBIS) || IsExtension(name, L".ogg") #endif )) { std::wstring filename = path + L"/" + name; BGMList[BGM_ALL].push_back(filename); BGMList[scene].push_back(filename); } }); #endif // YGOPRO_USE_AUDIO } void SoundManager::PlaySoundEffect(int sound) { #ifdef YGOPRO_USE_AUDIO if(!mainGame->chkEnableSound->isChecked()) return; std::string soundName; switch(sound) { case SOUND_SUMMON: { soundName = "summon"; break; } case SOUND_SPECIAL_SUMMON: { soundName = "specialsummon"; break; } case SOUND_ACTIVATE: { soundName = "activate"; break; } case SOUND_SET: { soundName = "set"; break; } case SOUND_FLIP: { soundName = "flip"; break; } case SOUND_REVEAL: { soundName = "reveal"; break; } case SOUND_EQUIP: { soundName = "equip"; break; } case SOUND_DESTROYED: { soundName = "destroyed"; break; } case SOUND_BANISHED: { soundName = "banished"; break; } case SOUND_TOKEN: { soundName = "token"; break; } case SOUND_NEGATE: { soundName = "negate"; break; } case SOUND_ATTACK: { soundName = "attack"; break; } case SOUND_DIRECT_ATTACK: { soundName = "directattack"; break; } case SOUND_DRAW: { soundName = "draw"; break; } case SOUND_SHUFFLE: { soundName = "shuffle"; break; } case SOUND_DAMAGE: { soundName = "damage"; break; } case SOUND_RECOVER: { soundName = "gainlp"; break; } case SOUND_COUNTER_ADD: { soundName = "addcounter"; break; } case SOUND_COUNTER_REMOVE: { soundName = "removecounter"; break; } case SOUND_COIN: { soundName = "coinflip"; break; } case SOUND_DICE: { soundName = "diceroll"; break; } case SOUND_NEXT_TURN: { soundName = "nextturn"; break; } case SOUND_PHASE: { soundName = "phase"; break; } case SOUND_MENU: { soundName = "menu"; break; } case SOUND_BUTTON: { soundName = "button"; break; } case SOUND_INFO: { soundName = "info"; break; } case SOUND_QUESTION: { soundName = "question"; break; } case SOUND_CARD_PICK: { soundName = "cardpick"; break; } case SOUND_CARD_DROP: { soundName = "carddrop"; break; } case SOUND_PLAYER_ENTER: { soundName = "playerenter"; break; } case SOUND_CHAT: { soundName = "chatmessage"; break; } default: return; } std::string soundPath = "./sound/" + soundName + ".wav"; SetSoundVolume(mainGame->gameConf.sound_volume); #ifdef YGOPRO_USE_MINIAUDIO ma_engine_play_sound(&engineSound, soundPath.c_str(), nullptr); #endif #endif // YGOPRO_USE_AUDIO } void SoundManager::PlayDialogSound(irr::gui::IGUIElement * element) { #ifdef YGOPRO_USE_AUDIO if(element == mainGame->wMessage) { PlaySoundEffect(SOUND_INFO); } else if(element == mainGame->wQuery) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wSurrender) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wOptions) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wANAttribute) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wANCard) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wANNumber) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wANRace) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wReplaySave) { PlaySoundEffect(SOUND_QUESTION); } else if(element == mainGame->wFTSelect) { PlaySoundEffect(SOUND_QUESTION); } #endif // YGOPRO_USE_AUDIO } bool SoundManager::IsPlayingMusic(wchar_t* music) { #ifdef YGOPRO_USE_MINIAUDIO if(music) { return !mywcsncasecmp(currentPlayingMusic, music, 1024) && ma_sound_is_playing(&soundBGM); } else { return currentPlayingMusic[0] && ma_sound_is_playing(&soundBGM); } #endif return false; } void SoundManager::PlayMusic(wchar_t* music, bool loop) { #ifdef YGOPRO_USE_AUDIO if(!mainGame->chkEnableMusic->isChecked()) return; if(!IsPlayingMusic(music)) { StopBGM(); SetMusicVolume(mainGame->gameConf.music_volume); #ifdef YGOPRO_USE_MINIAUDIO BufferIO::CopyWStr(music, currentPlayingMusic, 1024); ma_sound_init_from_file_w(&engineMusic, music, MA_SOUND_FLAG_ASYNC | MA_SOUND_FLAG_STREAM, nullptr, nullptr, &soundBGM); ma_sound_set_looping(&soundBGM, loop); ma_sound_start(&soundBGM); #endif } #endif } void SoundManager::PlayBGM(int scene) { #ifdef YGOPRO_USE_AUDIO if(!mainGame->chkEnableMusic->isChecked()) return; if(!mainGame->chkMusicMode->isChecked()) scene = BGM_ALL; if(scene != bgm_scene || !IsPlayingMusic()) { int count = BGMList[scene].size(); if(count <= 0) return; bgm_scene = scene; int bgm = (count > 1) ? std::uniform_int_distribution<>(0, count - 1)(rnd) : 0; auto name = BGMList[scene][bgm].c_str(); wchar_t BGMName[1024]; myswprintf(BGMName, L"./sound/BGM/%ls", name); PlayMusic(BGMName, false); } #endif } void SoundManager::StopBGM() { #ifdef YGOPRO_USE_MINIAUDIO if(!currentPlayingMusic[0]) return; memset(currentPlayingMusic, 0, sizeof(currentPlayingMusic)); ma_sound_uninit(&soundBGM); #endif } void SoundManager::SetSoundVolume(int volume) { #ifdef YGOPRO_USE_MINIAUDIO ma_engine_set_volume(&engineSound, volume / 100.0f); #endif } void SoundManager::SetMusicVolume(int volume) { #ifdef YGOPRO_USE_MINIAUDIO ma_engine_set_volume(&engineMusic, volume / 100.0f); #endif } }