265 lines
8.1 KiB
C
265 lines
8.1 KiB
C
![]() |
/**********************************************************************
|
||
|
|
||
|
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<GSoundSample> pSample;
|
||
|
GPtr<GSoundChannel> 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<GSoundChannel> 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<GPtr<GSoundSample> >& samples, GSoundSample* psample)
|
||
|
{
|
||
|
for(UPInt i = 0; i < samples.GetSize(); ++i)
|
||
|
{
|
||
|
if(samples[i] == psample)
|
||
|
return (SInt)i;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void ReleaseStoppedSounds()
|
||
|
{
|
||
|
for(GStringHash<GPtr<GSoundChannel> >::ConstIterator it = ChannelMap.Begin();
|
||
|
it != ChannelMap.End(); ++it)
|
||
|
{
|
||
|
GPtr<GSoundChannel> pChannel = it->Second;
|
||
|
if(!pChannel->IsPlaying())
|
||
|
{
|
||
|
GPtr<GSoundSample> pSample = pChannel->GetSample();
|
||
|
SInt idx = FindSample(Samples, pSample);
|
||
|
if(idx != -1) {
|
||
|
Samples.RemoveAt(idx);
|
||
|
pSample = NULL;
|
||
|
}
|
||
|
ChannelMap.Remove(it->First);
|
||
|
pChannel = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GArray<GPtr<GSoundSample> > Samples;
|
||
|
GStringHash<GPtr<GSoundChannel> > ChannelMap;
|
||
|
bool Streaming;
|
||
|
GString MediaPath;
|
||
|
};
|
||
|
|
||
|
#if defined(GFC_SOUND_FMOD_DESIGNER) && (defined(GFC_OS_WIN32) || defined(GFC_OS_MAC))
|
||
|
|
||
|
#include <fmod_event.hpp>
|
||
|
#include <fmod_event_net.hpp>
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
|
||
|
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<FMOD::Event*>::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<FMOD::Event*>::ConstIterator it = EventMap.Begin();
|
||
|
it != EventMap.End(); ++it)
|
||
|
{
|
||
|
FMOD::Event *pEvent = it->Second;
|
||
|
pEvent->stop();
|
||
|
EventMap.Remove(it->First);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FMOD::EventGroup *pEventGroup;
|
||
|
GStringHash<FMOD::Event*> 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
|