sfxFMODProvider.cpp
Engine/source/sfx/fmod/sfxFMODProvider.cpp
Classes:
Public Defines
define
FMOD_EVENT_FUNCTION(fn_name, fn_args) mFMod.eventIsLoaded &= (mFMod.eventDllRef, *(**)&mFMod.fn_name.fn, #fn_name);
define
FMOD_FUNCTION(fn_name, fn_args) mFMod.isLoaded &= (mFMod.dllRef, *(**)&mFMod.fn_name.fn, #fn_name);
Public Variables
Public Functions
bool
fmodBindFunction(DLibrary * dll, void *& fnAddress, const char * name)
Detailed Description
Public Defines
FMOD_EVENT_FUNCTION(fn_name, fn_args) mFMod.eventIsLoaded &= (mFMod.eventDllRef, *(**)&mFMod.fn_name.fn, #fn_name);
FMOD_FUNCTION(fn_name, fn_args) mFMod.isLoaded &= (mFMod.dllRef, *(**)&mFMod.fn_name.fn, #fn_name);
Public Variables
MODULE_END
MODULE_INIT
MODULE_SHUTDOWN
SFXFMODProvider * mProvider
Public Functions
fmodBindFunction(DLibrary * dll, void *& fnAddress, const char * name)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "sfx/sfxProvider.h" 25#include "sfx/fmod/sfxFMODDevice.h" 26#include "core/util/safeRelease.h" 27#include "console/console.h" 28#include "core/util/safeDelete.h" 29#include "core/module.h" 30#include "console/consoleTypes.h" 31 32 33class SFXFMODProvider : public SFXProvider 34{ 35public: 36 37 SFXFMODProvider() 38 : SFXProvider( "FMOD" ) 39 { 40 Con::addVariable( "$SFX::Device::fmodNumEventSources", TypeS32, &SFXFMODDevice::smStatNumEventSources, 41 "The current number of SFXFMODEventSource instances in the system.\n" 42 "This tells the number of sounds in the system that are currently playing FMOD Designer events.\n\n" 43 "@note Only relevant if an %FMOD sound device is used.\n\n" 44 "@ingroup SFXFMOD" ); 45 Con::addVariable( "$SFX::Device::fmodCoreMem", TypeS32, &SFXFMODDevice::smStatMemUsageCore, 46 "Current number of bytes allocated by the core %FMOD sound system.\n\n" 47 "@note Only relevant if an %FMOD sound device is used.\n\n" 48 "@ingroup SFXFMOD" ); 49 Con::addVariable( "$SFX::Device::fmodEventMem", TypeS32, &SFXFMODDevice::smStatMemUsageEvents, 50 "Current number of bytes allocated by the %FMOD Designer event system.\n\n" 51 "@note Only relevant if an %FMOD sound device is used and the FMOD event DLL is loaded.\n\n" 52 "@ingroup SFXFMOD" ); 53 54 Con::addVariable( "$pref::SFX::FMOD::disableSoftware", TypeBool, &SFXFMODDevice::smPrefDisableSoftware, 55 "Whether to disable the %FMOD software mixer to conserve memory.\n" 56 "All sounds not created with SFXDescription::useHardware or using DSP effects will fail to load.\n\n" 57 "@note Only applies when using an %FMOD sound device.\n\n" 58 "@ingroup SFXFMOD" ); 59 Con::addVariable( "$pref::SFX::FMOD::useSoftwareHRTF", TypeBool, &SFXFMODDevice::smPrefUseSoftwareHRTF, 60 "Whether to enable HRTF in %FMOD's software mixer.\n" 61 "This will add a lowpass filter effect to the DSP effect chain of all sounds mixed in software.\n\n" 62 "@note Only applies when using an %FMOD sound device.\n\n" 63 "@ingroup SFXFMOD" ); 64 Con::addVariable( "$pref::SFX::FMOD::enableProfile", TypeBool, &SFXFMODDevice::smPrefEnableProfile, 65 "Whether to enable support for %FMOD's profiler.\n\n" 66 "@note Only applies when using an %FMOD sound device.\n\n" 67 "@ref FMOD_profiler\n\n" 68 "@ingroup SFXFMOD" ); 69 Con::addVariable( "$pref::SFX::FMOD::DSoundHRTF", TypeString, &SFXFMODDevice::smPrefDSoundHRTF, 70 "The type of HRTF to use for hardware-mixed 3D sounds when %FMOD is using DirectSound for sound output " 71 "and hardware-acceleration is not available.\n\n" 72 "Options are\n" 73 "- \"none\": simple stereo panning/doppler/attenuation\n" 74 "- \"light\": slightly higher quality than \"none\"\n" 75 "- \"full\": full quality 3D playback\n\n" 76 "@note Only applies when using an %FMOD sound device.\n\n" 77 "@ingroup SFXFMOD" ); 78 Con::addVariable( "$pref::SFX::FMOD::pluginPath", TypeString, &SFXFMODDevice::smPrefPluginPath, 79 "%Path to additional %FMOD plugins.\n\n" 80 "@note Only applies when using an %FMOD sound device.\n\n" 81 "@ingroup SFXFMOD" ); 82 } 83 virtual ~SFXFMODProvider(); 84 85protected: 86 FModFNTable mFMod; 87 88 struct FModDeviceInfo : SFXDeviceInfo 89 { 90 FMOD_CAPS mCaps; 91 FMOD_SPEAKERMODE mSpeakerMode; 92 }; 93 94 void init(); 95 96 bool _createSystem(); 97 98public: 99 100 SFXDevice* createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ); 101 102}; 103 104MODULE_BEGIN( FMOD ) 105 106 MODULE_INIT_BEFORE( SFX ) 107 MODULE_SHUTDOWN_AFTER( SFX ) 108 109 SFXFMODProvider* mProvider; 110 111 MODULE_INIT 112 { 113 mProvider = new SFXFMODProvider; 114 } 115 116 MODULE_SHUTDOWN 117 { 118 delete mProvider; 119 } 120 121MODULE_END; 122 123 124//------------------------------------------------------------------------------ 125// Helper 126 127bool fmodBindFunction( DLibrary *dll, void *&fnAddress, const char* name ) 128{ 129 if( !dll ) 130 return false; 131 132 fnAddress = dll->bind( name ); 133 134 if (!fnAddress) 135 Con::warnf( "FMOD Loader: DLL bind failed for %s", name ); 136 137 return fnAddress != 0; 138} 139 140//------------------------------------------------------------------------------ 141 142void SFXFMODProvider::init() 143{ 144#ifdef TORQUE_FMOD_STATIC 145 146 // FMOD statically linked. 147 148 mFMod.isLoaded = true; 149 #define FMOD_FUNCTION(fn_name, fn_args) \ 150 (*(void**)&mFMod.fn_name.fn) = &fn_name; 151 152 #ifndef TORQUE_FMOD_NO_EVENTS 153 mFMod.eventIsLoaded = true; 154 #define FMOD_EVENT_FUNCTION(fn_name, fn_args) \ 155 (*(void**)&mFMod.fn_name.fn) = &fn_name; 156 #else 157 #define FMOD_EVENT_FUNCTION( fn_name, fn_args ) 158 #endif 159 160 #include FMOD_FN_FILE 161 162 #undef FMOD_FUNCTION 163 #undef FMOD_EVENT_FUNCTION 164 165#else 166 167 // FMOD dynamically linked. 168 169 const char* dllName; 170 const char* pDllName; // plugin-based DLL 171 const char* eventDllName; 172 173#ifdef _WIN64 174 dllName = "fmodex64.dll"; 175 pDllName = "fmodexp64.dll"; 176 eventDllName = "fmod_event64.dll"; 177#elif defined(TORQUE_OS_WIN) 178 dllName = "fmodex.dll"; 179 pDllName = "fmodexp.dll"; 180 eventDllName = "fmod_event.dll"; 181#elif defined( TORQUE_OS_MAC ) 182 dllName = "libfmodex.dylib"; 183 pDllName = "libfmodexp.dylib"; 184 eventDllName = "libfmodevent.dylib"; 185#else 186# warning Need to set FMOD DLL filename for platform. 187 return; 188#endif 189 190 // Grab the functions we'll want from the fmod DLL. 191 mFMod.dllRef = OsLoadLibrary( dllName ); 192 193 // Try the plugin-based version. 194 if( !mFMod.dllRef ) 195 mFMod.dllRef = OsLoadLibrary( pDllName ); 196 197 if(!mFMod.dllRef) 198 { 199 Con::warnf( "SFXFMODProvider - Could not locate '%s' or '%s' - FMOD not available.", dllName, pDllName ); 200 return; 201 } 202 203 mFMod.eventDllRef = OsLoadLibrary( eventDllName ); 204 if(!mFMod.eventDllRef) 205 Con::warnf( "SFXFMODProvider - Could not locate %s - FMOD Designer integration not available.", eventDllName ); 206 207 mFMod.isLoaded = true; 208 mFMod.eventIsLoaded = true; 209 210 #define FMOD_FUNCTION(fn_name, fn_args) \ 211 mFMod.isLoaded &= fmodBindFunction(mFMod.dllRef, *(void**)&mFMod.fn_name.fn, #fn_name); 212 #define FMOD_EVENT_FUNCTION(fn_name, fn_args) \ 213 mFMod.eventIsLoaded &= fmodBindFunction(mFMod.eventDllRef, *(void**)&mFMod.fn_name.fn, #fn_name); 214 215 #include FMOD_FN_FILE 216 217 #undef FMOD_FUNCTION 218 #undef FMOD_EVENT_FUNCTION 219 220 if(mFMod.isLoaded == false) 221 { 222 Con::warnf("SFXFMODProvider - Could not load %s - FMOD not available.", dllName); 223 return; 224 } 225 if( !mFMod.eventIsLoaded && mFMod.eventDllRef ) 226 Con::warnf("SFXFMODProvider - Could not load %s - FMOD Designer integration not available.", eventDllName); 227 228#endif 229 230 FMOD_RESULT res; 231 232 // Create the FMOD system object. 233 234 if( !_createSystem() ) 235 return; 236 237 // Check that the Ex API version is OK. 238 239 unsigned int version; 240 res = mFMod.FMOD_System_GetVersion(SFXFMODDevice::smSystem, &version); 241 FModAssert(res, "SFXFMODProvider - Failed to get FMOD version!"); 242 243 Con::printf( "SFXFMODProvider - FMOD Ex API version: %x.%x.%x", 244 ( version & 0xffff0000 ) >> 16, 245 ( version & 0x0000ff00 ) >> 8, 246 ( version & 0x000000ff ) 247 ); 248 249 if(version < FMOD_VERSION) 250 { 251 Con::warnf("SFXFMODProvider - FMOD Ex API version in DLL is too old - FMOD not available."); 252 return; 253 } 254 255 // Check that the Designer API version is ok. 256 257 if( mFMod.eventIsLoaded ) 258 { 259 res = mFMod.FMOD_EventSystem_GetVersion( SFXFMODDevice::smEventSystem, &version ); 260 FModAssert(res, "SFXFMODProvider - Failed to get FMOD version!"); 261 262 Con::printf( "SFXFMODProvider - FMOD Designer API version: %x.%x.%x", 263 ( version & 0xffff0000 ) >> 16, 264 ( version & 0x0000ff00 ) >> 8, 265 ( version & 0x000000ff ) 266 ); 267 268 if( version < FMOD_EVENT_VERSION ) 269 { 270 Con::errorf( "SFXFMODProvider - FMOD Designer API version in DLL is too old!" ); 271 return; 272 } 273 } 274 275 // Now, enumerate our devices. 276 int numDrivers; 277 res = mFMod.FMOD_System_GetNumDrivers(SFXFMODDevice::smSystem, &numDrivers); 278 FModAssert(res, "SFXFMODProvider - Failed to get driver count - FMOD not available."); 279 280 char nameBuff[256]; 281 282 for(S32 i=0; i<numDrivers; i++) 283 { 284 res = mFMod.FMOD_System_GetDriverInfo(SFXFMODDevice::smSystem, i, nameBuff, 256, ( FMOD_GUID* ) NULL); 285 if( res != FMOD_OK ) 286 { 287 Con::errorf( "SFXFMODProvider - Failed to get driver name (%s)", FMODResultToString( res ).c_str() ); 288 continue; 289 } 290 nameBuff[ 255 ] = '\0'; 291 292 FMOD_CAPS caps; 293 FMOD_SPEAKERMODE speakerMode; 294 res = mFMod.FMOD_System_GetDriverCaps( SFXFMODDevice::smSystem, i, &caps, ( int* ) 0, &speakerMode ); 295 if( res != FMOD_OK ) 296 { 297 Con::errorf( "SFXFMODProvider - Failed to get driver caps (%s)", FMODResultToString( res ).c_str() ); 298 continue; 299 } 300 301 // Great - got something - so add it to the list of options. 302 FModDeviceInfo *fmodInfo = new FModDeviceInfo(); 303 fmodInfo->name = String( nameBuff ); 304 fmodInfo->hasHardware = caps & FMOD_CAPS_HARDWARE; 305 fmodInfo->maxBuffers = 32; 306 fmodInfo->driver = String(); 307 fmodInfo->mCaps = caps; 308 fmodInfo->mSpeakerMode = speakerMode; 309 310 mDeviceInfo.push_back(fmodInfo); 311 } 312 313 // Did we get any devices? 314 if ( mDeviceInfo.empty() ) 315 { 316 Con::warnf( "SFXFMODProvider - No valid devices found - FMOD not available." ); 317 return; 318 } 319 320 // TODO: FMOD_Memory_Initialize 321#ifdef TORQUE_OS_XENON 322 const dsize_t memSz = 5 * 1024 * 1024; 323 void *memBuffer = XPhysicalAlloc( memSz, MAXULONG_PTR, 0, PAGE_READWRITE ); 324 mFMod.FMOD_Memory_Initialize( memBuffer, memSz, FMOD_MEMORY_ALLOCCALLBACK(NULL), FMOD_MEMORY_REALLOCCALLBACK(NULL), FMOD_MEMORY_FREECALLBACK(NULL) ); 325#endif 326 327 // Wow, we made it - register the provider. 328 regProvider( this ); 329} 330 331SFXFMODProvider::~SFXFMODProvider() 332{ 333 if( SFXFMODDevice::smEventSystem ) 334 { 335 mFMod.FMOD_EventSystem_Release( SFXFMODDevice::smEventSystem ); 336 SFXFMODDevice::smEventSystem = NULL; 337 SFXFMODDevice::smSystem = NULL; 338 } 339 else if( SFXFMODDevice::smSystem ) 340 { 341 mFMod.FMOD_System_Release( SFXFMODDevice::smSystem ); 342 SFXFMODDevice::smSystem = NULL; 343 } 344} 345 346SFXDevice* SFXFMODProvider::createDevice( const String& deviceName, bool useHardware, S32 maxBuffers ) 347{ 348 FModDeviceInfo* info = dynamic_cast< FModDeviceInfo* > 349 ( _findDeviceInfo( deviceName ) ); 350 351 if( !info ) 352 return NULL; 353 354 if( !SFXFMODDevice::smSystem && !_createSystem() ) 355 return false; 356 357 SFXFMODDevice* device = new SFXFMODDevice(this, &mFMod, 0, info->name ); 358 if( !device->_init() ) 359 SAFE_DELETE( device ); 360 361 return device; 362} 363 364bool SFXFMODProvider::_createSystem() 365{ 366 AssertFatal( !SFXFMODDevice::smEventSystem, "SFXFMODProvider::_createSystem() - event system already created!" ); 367 AssertFatal( !SFXFMODDevice::smSystem, "SFXFMODProvider::_createSystem() - system already created!" ); 368 369 if( mFMod.eventIsLoaded ) 370 { 371 FMOD_RESULT res = mFMod.FMOD_EventSystem_Create( &SFXFMODDevice::smEventSystem ); 372 if( res != FMOD_OK ) 373 { 374 Con::errorf( "SFXFMODProvider - could not create the FMOD event system." ); 375 return false; 376 } 377 378 res = mFMod.FMOD_EventSystem_GetSystemObject( SFXFMODDevice::smEventSystem, &SFXFMODDevice::smSystem ); 379 if( res != FMOD_OK ) 380 { 381 Con::errorf( "SFXFMODProvider - could not retrieve the FMOD system object." ); 382 return false; 383 } 384 } 385 else 386 { 387 // Allocate the FMod system. 388 389 FMOD_RESULT res = mFMod.FMOD_System_Create( &SFXFMODDevice::smSystem ); 390 if( res != FMOD_OK ) 391 { 392 // Failed - deal with it! 393 Con::errorf("SFXFMODProvider - could not create the FMOD system."); 394 return false; 395 } 396 } 397 398 return true; 399} 400