/********************************************************************** Filename : GSoundEventFMOD.h Content : FMOD Ex/Designer (based on GSoundRender) implementation of GSoundEvent Created : March 2010 Authors : Vladislav Merker Copyright : (c) 1998-2010 Scaleform Corp. All Rights Reserved. Licensees may use this file in accordance with the valid Scaleform Commercial License Agreement provided with the software. This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE. **********************************************************************/ #ifndef INC_GSOUNDEVENTFMOD_H #define INC_GSOUNDEVENTFMOD_H #include "GConfig.h" #ifndef GFC_NO_SOUND #include "GSoundEvent.h" #include "GSoundRenderer.h" #if defined(GFC_SOUND_FMOD) #include "GArray.h" #include "GStringHash.h" ////////////////////////////////////////////////////////////////////////// // class GSoundEventFMOD : public GSoundEvent { public: GSoundEventFMOD(const char* path = "") : Streaming(true), MediaPath(path) {} virtual ~GSoundEventFMOD() {} virtual void PostEvent(GString event, GString eventId) { ReleaseStoppedSounds(); if(!eventId.IsEmpty()) { GPtr pSample; GPtr pChannel; ChannelMap.Get(eventId, &pChannel); if(event.ToLower() == "play" && !pChannel) { if(!MediaPath.IsEmpty()) eventId = MediaPath + eventId; GASSERT(pUserData); GSoundRenderer *pSoundRenderer = (GSoundRenderer *)pUserData; pSample = *pSoundRenderer->CreateSampleFromFile(eventId, Streaming); pChannel = *pSoundRenderer->PlaySample(pSample, false); if(pChannel) { Samples.PushBack(pSample); ChannelMap.Set(eventId, pChannel); pChannel->Pause(false); } return; } if(pChannel && pChannel->IsPlaying()) { if(event.ToLower() == "pause") pChannel->Pause(true); if(event.ToLower() == "resume") pChannel->Pause(false); if(event.ToLower() == "stop") pChannel->Stop(); } } } virtual void SetParam(GString param, Float paramValue, GString eventId) { //ReleaseStoppedSounds(); if(!eventId.IsEmpty()) { GPtr pChannel; ChannelMap.Get(eventId, &pChannel); if(pChannel && pChannel->IsPlaying()) { if(param.ToLower() == "volume") pChannel->SetVolume(paramValue); if(param.ToLower() == "pan") pChannel->SetPan(paramValue); } } } private: SInt FindSample(GArray >& samples, GSoundSample* psample) { for(UPInt i = 0; i < samples.GetSize(); ++i) { if(samples[i] == psample) return (SInt)i; } return -1; } void ReleaseStoppedSounds() { for(GStringHash >::ConstIterator it = ChannelMap.Begin(); it != ChannelMap.End(); ++it) { GPtr pChannel = it->Second; if(!pChannel->IsPlaying()) { GPtr pSample = pChannel->GetSample(); SInt idx = FindSample(Samples, pSample); if(idx != -1) { Samples.RemoveAt(idx); pSample = NULL; } ChannelMap.Remove(it->First); pChannel = NULL; } } } GArray > Samples; GStringHash > ChannelMap; bool Streaming; GString MediaPath; }; #if defined(GFC_SOUND_FMOD_DESIGNER) && (defined(GFC_OS_WIN32) || defined(GFC_OS_MAC)) #include #include ////////////////////////////////////////////////////////////////////////// // class GSoundEventFMODDesigner : public GSoundEvent { public: GSoundEventFMODDesigner(const char *proj, const char *group, const char* path = "") : pEventGroup(NULL), ProjectLoaded(false), Project(proj), Group(group), MediaPath(path) {} virtual ~GSoundEventFMODDesigner() { StopAllSounds(); } virtual void PostEvent(GString event, GString eventId) { if(!ProjectLoaded) { GASSERT(pUserData); FMOD::EventSystem *pEventSys = (FMOD::EventSystem *)pUserData; if(!MediaPath.IsEmpty()) pEventSys->setMediaPath(MediaPath.ToCStr()); pEventSys->load(Project.ToCStr(), 0, 0); int result = pEventSys->getGroup(Group.ToCStr(), FMOD_EVENT_DEFAULT, &pEventGroup); GASSERT(result == FMOD_OK && pEventGroup); ProjectLoaded = true; } StopNotActiveSounds(); if(!eventId.IsEmpty()) { FMOD::Event *pEvent = NULL; EventMap.Get(eventId, &pEvent); if(event.ToLower() == "play" && !pEvent) { if(pEventGroup) { int result = pEventGroup->getEvent(eventId.ToCStr(), FMOD_EVENT_DEFAULT, &pEvent); if(result == FMOD_OK && pEvent) { EventMap.Set(eventId, pEvent); pEvent->start(); } } return; } if(pEvent) { if(event.ToLower() == "stop") { pEvent->stop(); EventMap.Remove(eventId); } FMOD_EVENT_STATE eventState; int result = pEvent->getState(&eventState); if(result == FMOD_OK && (eventState & FMOD_EVENT_STATE_CHANNELSACTIVE) == FMOD_EVENT_STATE_CHANNELSACTIVE) { if(event.ToLower() == "pause") pEvent->setPaused(true); if(event.ToLower() == "resume") pEvent->setPaused(false); if(event.ToLower() == "mute") pEvent->setMute(true); if(event.ToLower() == "unmute") pEvent->setMute(false); } } } } virtual void SetParam(GString param, Float paramValue, GString eventId) { if(!eventId.IsEmpty()) { FMOD::Event *pEvent = NULL; EventMap.Get(eventId, &pEvent); if(pEvent) { FMOD_EVENT_STATE eventState; int result = pEvent->getState(&eventState); if(result == FMOD_OK && (eventState & FMOD_EVENT_STATE_CHANNELSACTIVE) == FMOD_EVENT_STATE_CHANNELSACTIVE) { if(param.ToLower() == "volume") pEvent->setVolume(paramValue); if(param.ToLower() == "pitch") pEvent->setPitch(paramValue, FMOD_EVENT_PITCHUNITS_RAW); } } } } private: void StopNotActiveSounds() { for(GStringHash::ConstIterator it = EventMap.Begin(); it != EventMap.End(); ++it) { FMOD::Event *pEvent = it->Second; FMOD_EVENT_STATE eventState; int result = pEvent->getState(&eventState); if(result == FMOD_OK && (eventState & FMOD_EVENT_STATE_CHANNELSACTIVE) != FMOD_EVENT_STATE_CHANNELSACTIVE) { pEvent->stop(); EventMap.Remove(it->First); } } } void StopAllSounds() { for(GStringHash::ConstIterator it = EventMap.Begin(); it != EventMap.End(); ++it) { FMOD::Event *pEvent = it->Second; pEvent->stop(); EventMap.Remove(it->First); } } FMOD::EventGroup *pEventGroup; GStringHash EventMap; bool ProjectLoaded; GString Project; GString Group; GString MediaPath; }; #endif // GFC_SOUND_FMOD_DESIGNER #endif // GFC_SOUND_FMOD #endif // GFC_NO_SOUND #endif // INC_GSOUNDEVENTFMOD_H