Torque3D Documentation / _generateds / sfxFMODProvider.cpp

sfxFMODProvider.cpp

Engine/source/sfx/fmod/sfxFMODProvider.cpp

More...

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 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