/*============================================================================== Load From Memory Example Copyright (c), Firelight Technologies Pty, Ltd 2004-2020. This example is simply a variant of the [Play Sound Example](play_sound.html), but it loads the data into memory then uses the 'load from memory' feature of System::createSound. ==============================================================================*/ #include "fmod.h" #include "common.h" #include #include #include #include static FMOD_SYSTEM *msystem; class FmodSoundTag { public: FMOD_SOUND *sound; unsigned int count; FmodSoundTag() :sound(0) , count(0) { }; }; class manager { public: manager() {} ~manager() { FMOD_RESULT result = FMOD_OK; for (auto it : FMODSoundManager) { result = FMOD_Sound_Release(it.second.sound); ERRCHECK(result); } FMODSoundManager.clear(); } FMOD_SOUND *createFmodSound(const std::string &name, const void *pBuff, unsigned int len) { auto it = FMODSoundManager.find(name); if (it != FMODSoundManager.end()) { it->second.count += 1; return it->second.sound; } FMOD_RESULT res = FMOD_OK; FmodSoundTag tag; FMOD_CREATESOUNDEXINFO exinfo = { 0 };; memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.length = len; res = FMOD_System_CreateSound(msystem, (const char *)pBuff, FMOD_OPENMEMORY | FMOD_LOOP_NORMAL | FMOD_3D | FMOD_NONBLOCKING | FMOD_LOWMEM, &exinfo, &tag.sound); ERRCHECK(res); tag.count += 1; FMODSoundManager.insert(std::make_pair(name, tag)); return tag.sound; } void removeFmodSound(const std::string &name) { FMOD_RESULT result = FMOD_OK; auto it = FMODSoundManager.find(name); if (it == FMODSoundManager.end()) return; it->second.count -= 1; if (it->second.count == 0) { result = FMOD_Sound_Release(it->second.sound); ERRCHECK(result); FMODSoundManager.erase(it); } } int getFmodSoundRefCount(const std::string & name) { auto it = FMODSoundManager.find(name); if (it != FMODSoundManager.end()) { return it->second.count; } return 0; } private: std::map FMODSoundManager; }; static manager m_manager; class TestSound { public: TestSound(const char * res_name) { Common_LoadFileMemory(Common_MediaPath(res_name), &filebuff, &length); sound = m_manager.createFmodSound(res_name, filebuff, length); res = res_name; } ~TestSound() { if (channel) { FMOD_RESULT result = FMOD_Channel_Stop(channel); channel = 0; } if (sound) { m_manager.removeFmodSound(res); sound = 0; } Common_UnloadFileMemory(filebuff); filebuff = 0; length = 0; count = 0; } FMOD_SOUND *sound = 0; FMOD_CHANNEL *channel = 0; void *filebuff = 0; int length = 0; std::string res; int count = 0; }; int FMOD_Main() { FMOD_RESULT result; unsigned int version; void *extradriverdata = 0; void *buff = 0; int length = 0; FMOD_CREATESOUNDEXINFO exinfo; Common_Init(&extradriverdata); /* Create a System object and initialize */ result = FMOD_System_Create(&msystem); ERRCHECK(result); result = FMOD_System_GetVersion(msystem, &version); ERRCHECK(result); if (version < FMOD_VERSION) { Common_Fatal("FMOD lib version %08x doesn't match header version %08x", version, FMOD_VERSION); } result = FMOD_System_SetSoftwareChannels(msystem, 32); ERRCHECK(result); FMOD_INITFLAGS initFlags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_VOL0_BECOMES_VIRTUAL | FMOD_INIT_PROFILE_ENABLE; result = FMOD_System_Init(msystem, 1000, initFlags, extradriverdata); ERRCHECK(result); FMOD_ADVANCEDSETTINGS fAdvSettings = { sizeof(FMOD_ADVANCEDSETTINGS), }; result = FMOD_System_GetAdvancedSettings(msystem, &fAdvSettings); ERRCHECK(result); fAdvSettings.vol0virtualvol = 0.001f; result = FMOD_System_SetAdvancedSettings(msystem, &fAdvSettings); ERRCHECK(result); result = FMOD_System_Set3DSettings(msystem, 1.f, 1.f, 1.f); ERRCHECK(result); std::set testSounds; int loopCut = 0; int index = 0; bool hadDel = false; FMOD_BOOL isPlaying = false; do { for (size_t i = 0; i < 3; ++i) { index = rand() % 20; TestSound *pSound = new TestSound("stereo.ogg"); if (pSound) testSounds.insert(pSound); } result = FMOD_System_Update(msystem); ERRCHECK(result); for (auto iter = testSounds.begin(); iter != testSounds.end();) { hadDel = false; FMOD_OPENSTATE state = FMOD_OPENSTATE_READY; TestSound *pSound = (*iter); result = FMOD_Sound_GetOpenState(pSound->sound, &state, 0, 0, 0); ERRCHECK(result); if ((*iter)->channel == 0) { if (state == FMOD_OPENSTATE_READY || state == FMOD_OPENSTATE_PLAYING) { result = FMOD_System_PlaySound(msystem, pSound->sound, 0, 1, &pSound->channel); ERRCHECK(result); } } else { isPlaying = 0; result = FMOD_Channel_IsPlaying(pSound->channel, &isPlaying); if (isPlaying != 0) { int priority = rand() % 64; FMOD_Channel_SetPriority(pSound->channel, priority + 1); } } ++iter; } int index = 0; for (auto _it = testSounds.begin(); _it != testSounds.end(); ) { if (index % 10 == 0) { delete *_it; _it = testSounds.erase(_it); } else { ++_it; } index++; } } while (!Common_BtnPress(BTN_QUIT)); result = FMOD_System_Close(msystem); ERRCHECK(result); result = FMOD_System_Release(msystem); ERRCHECK(result); Common_Close(); return 0; }