Torque3D/Engine/source/sfx/fmod/sfxFMODEventSource.cpp
2012-09-19 11:15:01 -04:00

338 lines
10 KiB
C++

//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "sfx/fmod/sfxFMODEventSource.h"
#include "sfx/fmod/sfxFMODEvent.h"
#include "sfx/fmod/sfxFMODEventGroup.h"
#include "sfx/fmod/sfxFMODDevice.h"
#include "sfx/sfxDescription.h"
IMPLEMENT_CONOBJECT( SFXFMODEventSource );
ConsoleDocClass( SFXFMODEventSource,
"@brief A sound source controller playing an %FMOD Designer event (SFXFMODEvent).\n\n"
"%FMOD event sources are internally created by the sound system to play events from imported %FMOD Designer projects.\n\n"
"@note This class cannot be instantiated directly by the user. Instead, instances of SFXFMODEventSource will be "
"implicitly created by the sound system when playing an SFXFMODEvent.\n\n"
"@ingroup SFXFMOD\n"
);
//-----------------------------------------------------------------------------
SFXFMODEventSource::SFXFMODEventSource()
: mHandle( NULL )
{
SFXFMODDevice::instance()->smStatNumEventSources ++;
}
//-----------------------------------------------------------------------------
SFXFMODEventSource::SFXFMODEventSource( SFXFMODEvent* event )
: Parent( event ),
mHandle( NULL )
{
SFXFMODDevice::instance()->smStatNumEventSources ++;
// Make sure the group has its data loaded.
SFXFMODEventGroup* group = event->getEventGroup();
if( !group->loadData() )
return;
// Create an event instance.
if( SFXFMODDevice::smFunc->FMOD_EventGroup_GetEvent(
event->getEventGroup()->mHandle,
event->getEventName(),
FMOD_EVENT_DEFAULT,
&mHandle ) != FMOD_OK )
{
Con::errorf( "SFXFMODEventSource::SFXFMODEventSource - failed to open event '%s'", event->getQualifiedName().c_str() );
mHandle = NULL;
}
}
//-----------------------------------------------------------------------------
SFXFMODEventSource::~SFXFMODEventSource()
{
SFXFMODDevice::instance()->smStatNumEventSources --;
if( mHandle )
SFXFMODDevice::smFunc->FMOD_Event_Release( mHandle, true, true );
if( getEvent() )
getEvent()->getEventGroup()->freeData();
}
//-----------------------------------------------------------------------------
SFXFMODEventSource* SFXFMODEventSource::create( SFXFMODEvent* event )
{
AssertFatal( event != NULL, "SFXFMODEventSource::create - got a NULL event!" );
// Create the source.
SFXFMODEventSource* source = new SFXFMODEventSource( event );
if( source->mHandle )
source->registerObject();
else
{
delete source;
source = NULL;
}
return source;
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::play( F32 fadeInTime )
{
if( getStatus() == SFXStatusPlaying )
return;
if( isPaused() )
SFXFMODDevice::smFunc->FMOD_Event_SetPaused( mHandle, false );
else
{
AssertFatal( getEvent()->getEventGroup()->isDataLoaded(), "SFXFMODEventSource::play() - event data for group not loaded" );
if( fadeInTime != -1.f )
{
U32 fade = U32( fadeInTime * 1000.f );
SFXFMODDevice::smFunc->FMOD_Event_SetPropertyByIndex(
mHandle, FMOD_EVENTPROPERTY_FADEIN,
&fade, true
);
}
FMOD_RESULT result = SFXFMODDevice::smFunc->FMOD_Event_Start( mHandle );
if( result != FMOD_OK )
{
Con::errorf( "SFXFMODEventSoure::play() - failed to start event: %s", FMODResultToString( result ).c_str() );
return;
}
}
mPlayTimer.start();
_setStatus( SFXStatusPlaying );
_play();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::stop( F32 fadeOutTime )
{
if( getStatus() == SFXStatusStopped )
return;
AssertFatal( mHandle, "SFXFMODEvent::stop() - event not acquired" );
bool immediate = ( fadeOutTime == 0.f );
FMOD_RESULT result = SFXFMODDevice::smFunc->FMOD_Event_Stop( mHandle, immediate );
if( result != FMOD_OK )
Con::errorf( "SFXFMODEventSource::stop() - failed to stop event: %s", FMODResultToString( result ).c_str() );
mPlayTimer.stop();
_setStatus( SFXStatusStopped );
// Reset fade-in to default in case it got overwritten
// in play().
U32 fade = U32( mFadeInTime * 1000.f );
SFXFMODDevice::smFunc->FMOD_Event_SetPropertyByIndex(
mHandle, FMOD_EVENTPROPERTY_FADEIN,
&fade, true
);
_stop();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::pause( F32 fadeOutTime )
{
if( getStatus() != SFXStatusPlaying )
return;
SFXFMODDevice::smFunc->FMOD_Event_SetPaused( mHandle, true );
mPlayTimer.pause();
_setStatus( SFXStatusPaused );
_pause();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::setTransform( const MatrixF& transform )
{
Parent::setTransform( transform );
_update3DAttributes();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::setVelocity( const VectorF& velocity )
{
Parent::setVelocity( velocity );
_update3DAttributes();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_update3DAttributes()
{
FMOD_VECTOR position;
FMOD_VECTOR velocity;
FMOD_VECTOR orientation;
Point3F direction;
getTransform().getColumn( 1, &direction );
TorqueVectorToFMODVector( getTransform().getPosition(), position );
TorqueVectorToFMODVector( getVelocity(), velocity );
TorqueVectorToFMODVector( direction, orientation );
SFXFMODDevice::smFunc->FMOD_Event_Set3DAttributes( mHandle, &position, &velocity, &orientation );
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_updateStatus()
{
if( mStatus == SFXStatusPlaying )
{
if( !getEvent() )
_setStatus( SFXStatusStopped );
else
{
FMOD_EVENT_STATE state;
SFXFMODDevice::smFunc->FMOD_Event_GetState( mHandle, &state );
if( !( state & FMOD_EVENT_STATE_PLAYING ) )
_setStatus( SFXStatusStopped );
}
}
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_updateVolume( const MatrixF& listener )
{
F32 oldPreAttenuatedVolume = mPreAttenuatedVolume;
Parent::_updateVolume( listener );
if( oldPreAttenuatedVolume != mPreAttenuatedVolume )
SFXFMODDevice::smFunc->FMOD_Event_SetVolume( mHandle, mPreAttenuatedVolume );
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_updatePitch()
{
F32 oldEffectivePitch = mEffectivePitch;
Parent::_updatePitch();
if( mEffectivePitch != oldEffectivePitch )
SFXFMODDevice::smFunc->FMOD_Event_SetPitch( mHandle, mEffectivePitch - 1.0f, FMOD_EVENT_PITCHUNITS_RAW );
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_updatePriority()
{
//TODO
Parent::_updatePriority();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_setMinMaxDistance( F32 min, F32 max )
{
Parent::_setMinMaxDistance( min, max );
_update3DAttributes();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_setFadeTimes( F32 fadeInTime, F32 fadeOutTime )
{
Parent::_setFadeTimes( fadeInTime, fadeOutTime );
U32 fadeIn = U32( mFadeInTime * 1000.f );
SFXFMODDevice::smFunc->FMOD_Event_SetPropertyByIndex(
mHandle, FMOD_EVENTPROPERTY_FADEIN,
&fadeIn, true
);
U32 fadeOut = U32( mFadeOutTime * 1000.f );
SFXFMODDevice::smFunc->FMOD_Event_SetPropertyByIndex(
mHandle, FMOD_EVENTPROPERTY_FADEOUT,
&fadeOut, true
);
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume )
{
Parent::_setCone( innerAngle, outerAngle, outerVolume );
_update3DAttributes();
}
//-----------------------------------------------------------------------------
void SFXFMODEventSource::_onParameterEvent( SFXParameter* parameter, SFXParameterEvent event )
{
Parent::_onParameterEvent( parameter, event );
// If it's a value-change on a custom parameter,
// pass it along to FMOD.
if( getEvent()
&& event == SFXParameterEvent_ValueChanged
&& parameter->getChannel() == SFXChannelUser0 )
{
const char* name = parameter->getInternalName();
FMOD_EVENTPARAMETER* fmodParameter;
if( SFXFMODDevice::smFunc->FMOD_Event_GetParameter( mHandle, name, &fmodParameter ) != FMOD_OK )
{
Con::errorf( "SFXFMODEventSource::_onParameterEvent - could not access parameter '%s' of event '%s'",
name, getEvent()->getQualifiedName().c_str() );
return;
}
SFXFMODDevice::smFunc->FMOD_EventParameter_SetValue( fmodParameter, parameter->getValue() );
}
}