Torque3D/Engine/source/sfx/fmod/sfxFMODDevice.h

343 lines
9.5 KiB
C
Raw Normal View History

2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
#ifndef _SFXFMODDEVICE_H_
#define _SFXFMODDEVICE_H_
#ifndef _SFXDEVICE_H_
#include "sfx/sfxDevice.h"
#endif
#ifndef _SFXFMODVOICE_H_
#include "sfx/fmod/sfxFMODVoice.h"
#endif
#ifndef _SFXFMODBUFFER_H_
#include "sfx/fmod/sfxFMODBuffer.h"
#endif
#ifndef _SFXFMODPLUGIN_H_
#include "sfx/fmod/sfxFMODPlugin.h"
#endif
#include "core/util/tDictionary.h"
// Disable warning for unused static functions.
#ifdef TORQUE_COMPILER_VISUALC
#pragma warning( disable : 4505 )
#endif
#if defined( TORQUE_OS_XENON ) || defined( TORQUE_OS_PS3 )
#define TORQUE_FMOD_STATIC
#define TORQUE_FMOD_NO_EVENTS //TEMP
#endif
#include "fmod.h"
#include "fmod_errors.h"
#include "fmod_event.h"
#include "platform/platformDlibrary.h"
#include "platform/threads/mutex.h"
// This doesn't appear to exist in some contexts, so let's just add it.
#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XENON)
2012-09-19 15:15:01 +00:00
#ifndef WINAPI
#define WINAPI __stdcall
#endif
#else
#define WINAPI
#endif
#define FModAssert(x, msg) \
{ FMOD_RESULT result = ( x ); \
AssertISV( result == FMOD_OK, String::ToString( "%s: %s", msg, FMOD_ErrorString( result ) ) ); }
#define FMOD_FN_FILE "sfx/fmod/fmodFunctions.h"
// Typedefs
#define FMOD_FUNCTION(fn_name, fn_args) \
typedef FMOD_RESULT (WINAPI *FMODFNPTR##fn_name)fn_args;
#define FMOD_EVENT_FUNCTION(fn_name, fn_args) \
2012-09-19 15:15:01 +00:00
typedef FMOD_RESULT (WINAPI *FMODFNPTR##fn_name)fn_args;
#include FMOD_FN_FILE
#undef FMOD_FUNCTION
#undef FMOD_EVENT_FUNCTION
/// FMOD API function table.
///
/// FMOD doesn't want to be called concurrently so in order to
/// not force everything to the main thread (where sound updates
/// would just stall during loading), we thunk all the API
/// calls and lock all API entry points to a single mutex.
struct FModFNTable
{
FModFNTable()
: isLoaded( false ),
eventIsLoaded( false ),
dllRef( NULL ),
eventDllRef( NULL )
{
AssertFatal( mutex == NULL,
"FModFNTable::FModFNTable() - this should be a singleton" );
mutex = new Mutex;
}
~FModFNTable()
{
eventDllRef = NULL;
dllRef = NULL;
delete mutex;
}
bool isLoaded;
bool eventIsLoaded;
DLibraryRef dllRef;
DLibraryRef eventDllRef;
static Mutex* mutex;
template< typename FN >
struct Thunk
{
FN fn;
template< typename A >
FMOD_RESULT operator()( A a )
{
mutex->lock();
FMOD_RESULT result = fn( a );
mutex->unlock();
return result;
}
template< typename A, typename B >
FMOD_RESULT operator()( A a, B b )
{
mutex->lock();
FMOD_RESULT result = fn( a, b );
mutex->unlock();
return result;
}
template< typename A, typename B, typename C >
FMOD_RESULT operator()( A a, B b, C c )
{
mutex->lock();
FMOD_RESULT result = fn( a, b, c );
mutex->unlock();
return result;
}
template< typename A, typename B, typename C, typename D >
FMOD_RESULT operator()( A a, B b, C c, D d )
{
mutex->lock();
FMOD_RESULT result = fn( a, b, c, d );
mutex->unlock();
return result;
}
template< typename A, typename B, typename C, typename D, typename E >
FMOD_RESULT operator()( A a, B b, C c, D d, E e )
{
mutex->lock();
FMOD_RESULT result = fn( a, b, c, d, e );
mutex->unlock();
return result;
}
template< typename A, typename B, typename C, typename D, typename E, typename F >
FMOD_RESULT operator()( A a, B b, C c, D d, E e, F f )
{
mutex->lock();
FMOD_RESULT result = fn( a, b, c, d, e, f );
mutex->unlock();
return result;
}
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G >
FMOD_RESULT operator()( A a, B b, C c, D d, E e, F f, G g )
{
mutex->lock();
FMOD_RESULT result = fn( a, b, c, d, e, f, g );
mutex->unlock();
return result;
}
template< typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H >
FMOD_RESULT operator()( A a, B b, C c, D d, E e, F f, G g, H h )
{
mutex->lock();
FMOD_RESULT result = fn( a, b, c, d, e, f, g, h );
mutex->unlock();
return result;
}
};
#define FMOD_FUNCTION(fn_name, fn_args) \
Thunk< FMODFNPTR##fn_name > fn_name;
#define FMOD_EVENT_FUNCTION(fn_name, fn_args) \
2012-09-19 15:15:01 +00:00
Thunk< FMODFNPTR##fn_name > fn_name;
#include FMOD_FN_FILE
#undef FMOD_FUNCTION
#undef FMOD_EVENT_FUNCTION
};
inline void TorqueVectorToFMODVector( const Point3F& torque, FMOD_VECTOR& fmod )
{
fmod.x = torque.x;
fmod.y = torque.z;
fmod.z = torque.y;
}
inline void TorqueTransformToFMODVectors( const MatrixF& transform, FMOD_VECTOR& position, FMOD_VECTOR& forward, FMOD_VECTOR& up )
{
Point3F _pos, _fwd, _up;
transform.getColumn( 3, &_pos );
transform.getColumn( 1, &_fwd );
transform.getColumn( 2, &_up );
TorqueVectorToFMODVector( _pos, position );
TorqueVectorToFMODVector( _fwd, forward );
TorqueVectorToFMODVector( _up, up );
}
inline int TorquePriorityToFMODPriority( F32 priority )
{
// Map [-2,2] to [256,0].
F32 n = mClampF( priority, -2.0f, 2.0f ) + 2.0f;
return ( n * 256.0f / 4.0f );
}
inline String FMODEventPathToTorqueName( const String& path )
{
String p = path;
p.replace( '/', '_' );
p.replace( '-', '_' );
p.replace( ' ', '_' );
p.replace( '(', '_' );
p.replace( ')', '_' );
p.replace( '%', '_' );
p.replace( '$', '_' );
return p;
}
inline String FMODEventPathToTorqueName( const String& projectName, const String& path )
{
return String::ToString( "%s_%s", projectName.c_str(), FMODEventPathToTorqueName( path ).c_str() );
}
extern String FMODResultToString( FMOD_RESULT result );
class SFXProvider;
class SFXFMODPlugin;
class SFXFMODDevice : public SFXDevice
{
public:
typedef SFXDevice Parent;
friend class SFXFMODProvider; // _init
friend class SFXFMODEventSource; // smStatNumEventSources
explicit SFXFMODDevice();
SFXFMODDevice( SFXProvider* provider, FModFNTable *fmodFnTbl, int deviceIdx, String name );
virtual ~SFXFMODDevice();
protected:
FMOD_MODE m3drolloffmode;
int mDeviceIndex;
/// The FMOD SFXSystemPlugin instance.
SFXFMODPlugin mPlugin;
/// @name Console Variables
/// @{
/// Current core FMOD memory usage in bytes.
static U32 smStatMemUsageCore;
/// Current FMOD Event DLL memory usage in bytes.
static U32 smStatMemUsageEvents;
/// Current number of SFXFMODEventSource instances.
static U32 smStatNumEventSources;
///
static bool smPrefDisableSoftware;
///
static bool smPrefUseSoftwareOcclusion;
///
static bool smPrefUseSoftwareHRTF;
///
static bool smPrefEnableProfile;
///
static bool smPrefGeometryUseClosest;
///
static const char* smPrefDSoundHRTF;
///
static const char* smPrefPluginPath;
/// @}
bool _init();
static SFXFMODDevice* smInstance;
public:
static SFXFMODDevice* instance() { return smInstance; }
FMOD_MODE get3dRollOffMode() { return m3drolloffmode; }
static FMOD_SYSTEM* smSystem;
static FMOD_EVENTSYSTEM* smEventSystem;
static FModFNTable* smFunc;
// Update memory usage stats for metrics display.
void updateMemUsageStats();
// SFXDevice.
virtual SFXBuffer* createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description );
virtual SFXBuffer* createBuffer( const String& filename, SFXDescription* description );
virtual SFXVoice* createVoice( bool is3D, SFXBuffer* buffer );
virtual void update();
virtual void setNumListeners( U32 num );
virtual void setListener( U32 index, const SFXListenerProperties& listener );
virtual void setDistanceModel( SFXDistanceModel model );
virtual void setDopplerFactor( F32 factor );
virtual void setRolloffFactor( F32 factor );
virtual void setReverb( const SFXReverbProperties& reverb );
virtual void resetReverb();
};
#endif // _SFXFMODDEVICE_H_