Files
GTASource/rage/scaleform/Src/GSoundRenderer/GSoundEventFMOD.h

265 lines
8.1 KiB
C
Raw Permalink Normal View History

2025-02-23 17:40:52 +08:00
/**********************************************************************
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