Torque3D Documentation / _generateds / sfxFMODDevice.cpp

sfxFMODDevice.cpp

Engine/source/sfx/fmod/sfxFMODDevice.cpp

More...

Public Defines

define
FMOD_CHECK(message)       ( result != FMOD_OK )                                  \
      {                                                        \
         ( "SFXFMODDevice::_init() - %s (%s)",      \
            message,                                           \
            FMOD_ErrorString( result ) );                      \
         return false;                                         \
      }
define
FMOD_ERROR(n) case n: return #;
define
PRINT_CAP(name)       ( caps & FMOD_CAPS_ ## name )     \
         ( #name );

Public Functions

ConsoleFunction(fmodDumpDSPInfo , void , 1 , 1 , "()" "@brief Dump information about the standard DSP <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n\n</a>" "@ingroup SFXFMOD" )
ConsoleFunction(fmodDumpMemoryStats , void , 1 , 1 , "()" "@return Prints the current memory consumption of the FMOD <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">module\n\n</a>" "@ingroup SFXFMOD" )
FMOD_RESULT F_CALLBACK
fmodFileCloseCallback(void * handle, void * userdata)
FMOD_RESULT F_CALLBACK
fmodFileOpenCallback(const char * name, int unicode, unsigned int * filesize, void ** handle, void ** userdata)
FMOD_RESULT F_CALLBACK
fmodFileReadCallback(void * handle, void * buffer, unsigned int sizebytes, unsigned int * bytesread, void * userdata)
FMOD_RESULT F_CALLBACK
fmodFileSeekCallback(void * handle, unsigned int pos, void * userdata)
FMODResultToString(FMOD_RESULT result)

Detailed Description

Public Defines

FMOD_CHECK(message)       ( result != FMOD_OK )                                  \
      {                                                        \
         ( "SFXFMODDevice::_init() - %s (%s)",      \
            message,                                           \
            FMOD_ErrorString( result ) );                      \
         return false;                                         \
      }
FMOD_ERROR(n) case n: return #;
PRINT_CAP(name)       ( caps & FMOD_CAPS_ ## name )     \
         ( #name );

Public Functions

ConsoleFunction(fmodDumpDSPInfo , void , 1 , 1 , "()" "@brief Dump information about the standard DSP <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effects.\n\n</a>" "@ingroup SFXFMOD" )

ConsoleFunction(fmodDumpMemoryStats , void , 1 , 1 , "()" "@return Prints the current memory consumption of the FMOD <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">module\n\n</a>" "@ingroup SFXFMOD" )

fmodFileCloseCallback(void * handle, void * userdata)

fmodFileOpenCallback(const char * name, int unicode, unsigned int * filesize, void ** handle, void ** userdata)

fmodFileReadCallback(void * handle, void * buffer, unsigned int sizebytes, unsigned int * bytesread, void * userdata)

fmodFileSeekCallback(void * handle, unsigned int pos, void * userdata)

FMODResultToString(FMOD_RESULT result)

  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 "platform/platform.h"
 25#include "platform/threads/mutex.h"
 26#include "sfx/fmod/sfxFMODDevice.h"
 27#include "sfx/fmod/sfxFMODBuffer.h"
 28#include "sfx/sfxSystem.h"
 29#include "platform/async/asyncUpdate.h"
 30#include "console/consoleTypes.h"
 31#include "core/volume.h"
 32
 33
 34bool                 SFXFMODDevice::smPrefDisableSoftware = false;
 35bool                 SFXFMODDevice::smPrefUseSoftwareOcclusion = true;
 36bool                 SFXFMODDevice::smPrefUseSoftwareHRTF = true;
 37bool                 SFXFMODDevice::smPrefEnableProfile = false;
 38bool                 SFXFMODDevice::smPrefGeometryUseClosest = false;
 39const char*          SFXFMODDevice::smPrefDSoundHRTF = "full";
 40const char*          SFXFMODDevice::smPrefPluginPath = "";
 41U32                  SFXFMODDevice::smStatMemUsageCore;
 42U32                  SFXFMODDevice::smStatMemUsageEvents;
 43U32                  SFXFMODDevice::smStatNumEventSources;
 44SFXFMODDevice*       SFXFMODDevice::smInstance;
 45FMOD_SYSTEM*         SFXFMODDevice::smSystem;
 46FMOD_EVENTSYSTEM*    SFXFMODDevice::smEventSystem;
 47FModFNTable*         SFXFMODDevice::smFunc;
 48Mutex*               FModFNTable::mutex;
 49
 50
 51//-----------------------------------------------------------------------------
 52
 53String FMODResultToString( FMOD_RESULT result )
 54{
 55   switch( result )
 56   {
 57      #define FMOD_ERROR( n ) case n: return #n;
 58      #include "fmodErrors.h"
 59      #undef FMOD_ERROR
 60      
 61      default:
 62         break;
 63   }
 64   
 65   return String();
 66}
 67
 68//------------------------------------------------------------------------------
 69// FMOD filesystem wrappers.
 70//FIXME: these are not thread-safe and cannot be used as such
 71
 72FMOD_RESULT F_CALLBACK fmodFileOpenCallback( const char* name, int unicode, unsigned int* filesize, void** handle, void** userdata )
 73{
 74   String fileName;
 75   if( unicode )
 76      fileName = String( ( UTF16* ) name );
 77   else
 78      fileName = String( name );
 79      
 80   Torque::FS::FileRef file = Torque::FS::OpenFile( fileName, Torque::FS::File::Read );
 81   if( !file )
 82      return FMOD_ERR_FILE_NOTFOUND;
 83   else if( file->getStatus() != Torque::FS::File::Open )
 84      return FMOD_ERR_FILE_BAD;
 85      
 86   // Add a reference so we can pass it into FMOD.
 87   file->incRefCount();
 88      
 89   *filesize = U32( file->getSize() );
 90   *handle = file.getPointer();
 91
 92   return FMOD_OK;
 93}
 94
 95FMOD_RESULT F_CALLBACK fmodFileCloseCallback( void* handle, void* userdata )
 96{
 97   Torque::FS::File* file = reinterpret_cast< Torque::FS::File* >( handle );
 98   file->decRefCount();
 99   return FMOD_OK;
100}
101
102FMOD_RESULT F_CALLBACK fmodFileReadCallback( void* handle, void* buffer, unsigned int sizebytes, unsigned int* bytesread, void* userdata )
103{
104   Torque::FS::File* file = reinterpret_cast< Torque::FS::File* >( handle );
105
106   U32 numRead = file->read( buffer, sizebytes );
107   *bytesread = numRead;
108   
109   if( file->getStatus() == Torque::FS::File::EndOfFile )
110      return FMOD_ERR_FILE_EOF;
111   else if( file->getStatus() != Torque::FS::File::Open )
112      return FMOD_ERR_FILE_BAD;
113      
114   return FMOD_OK;
115}
116
117FMOD_RESULT F_CALLBACK fmodFileSeekCallback( void* handle, unsigned int pos, void* userdata )
118{
119   Torque::FS::File* file = reinterpret_cast< Torque::FS::File* >( handle );
120   
121   if( file->setPosition( pos, Torque::FS::File::Begin ) != pos )
122      return FMOD_ERR_FILE_COULDNOTSEEK;
123      
124   return FMOD_OK;
125}
126
127//-----------------------------------------------------------------------------
128
129SFXFMODDevice::SFXFMODDevice( SFXProvider* provider, 
130                              FModFNTable *fmodFnTbl, 
131                              int deviceIdx, 
132                              String name )
133   :  SFXDevice( name, provider, false, 32 ),
134      m3drolloffmode( FMOD_3D_INVERSEROLLOFF ),
135      mDeviceIndex( deviceIdx )
136{
137   // Store off the function pointers for later use.
138   smFunc = fmodFnTbl;
139
140   smStatMemUsageCore = 0;
141   smStatMemUsageEvents = 0;
142   smStatNumEventSources = 0;
143      
144   // Register our SFXSystem plugin.
145   
146   SFX->addPlugin( &mPlugin );
147   
148   smInstance = this;
149}
150
151//-----------------------------------------------------------------------------
152
153SFXFMODDevice::~SFXFMODDevice()
154{
155   _releaseAllResources();
156   
157   SFX->removePlugin( &mPlugin );
158   
159   if( smEventSystem )
160   {
161      smFunc->FMOD_EventSystem_Release( smEventSystem );
162      smEventSystem = NULL;
163      smSystem = NULL;
164   }
165   else
166      smFunc->FMOD_System_Close( smSystem );
167      
168   smInstance = NULL;
169}
170
171//-----------------------------------------------------------------------------
172
173bool SFXFMODDevice::_init()
174{
175   #define FMOD_CHECK( message )                               \
176      if( result != FMOD_OK )                                  \
177      {                                                        \
178         Con::errorf( "SFXFMODDevice::_init() - %s (%s)",      \
179            message,                                           \
180            FMOD_ErrorString( result ) );                      \
181         return false;                                         \
182      }
183
184   AssertISV(smSystem, 
185      "SFXFMODDevice::_init() - can't init w/o an existing FMOD system handle!");
186
187   FMOD_RESULT result;
188   
189   // Get some prefs.
190   
191   if( smPrefPluginPath && smPrefPluginPath[ 0 ] )
192   {
193      char fullPath[ 4096 ];
194      Platform::makeFullPathName( smPrefPluginPath, fullPath, sizeof( fullPath ) );
195      
196      smFunc->FMOD_System_SetPluginPath( smSystem, fullPath );
197   }
198   else
199   {
200      smFunc->FMOD_System_SetPluginPath( smSystem, Platform::getExecutablePath() );
201   }
202   
203   // Initialize everything from fmod.
204   FMOD_SPEAKERMODE speakermode;
205   FMOD_CAPS        caps;
206   result = smFunc->FMOD_System_GetDriverCaps(smSystem, 0, &caps, ( int* ) 0, &speakermode);
207   FMOD_CHECK( "SFXFMODDevice::init - Failed to get driver caps" );
208
209   result = smFunc->FMOD_System_SetDriver(smSystem, mDeviceIndex);
210   FMOD_CHECK( "SFXFMODDevice::init - Failed to set driver" );
211
212   result = smFunc->FMOD_System_SetSpeakerMode(smSystem, speakermode);
213   FMOD_CHECK( "SFXFMODDevice::init - Failed to set the user selected speaker mode" );
214
215   if (caps & FMOD_CAPS_HARDWARE_EMULATED)             /* The user has the 'Acceleration' slider set to off!  This is really bad for latency!. */
216   {                                                   /* You might want to warn the user about this. */
217      result = smFunc->FMOD_System_SetDSPBufferSize(smSystem, 1024, 10);
218      FMOD_CHECK( "SFXFMODDevice::init - Failed to set DSP buffer size" );
219   }
220   
221   Con::printf( "\nFMOD Device caps:" );
222   #define PRINT_CAP( name )              \
223      if( caps & FMOD_CAPS_ ## name )     \
224         Con::printf( #name );
225         
226   PRINT_CAP( HARDWARE );
227   PRINT_CAP( HARDWARE_EMULATED );
228   PRINT_CAP( OUTPUT_MULTICHANNEL );
229   PRINT_CAP( OUTPUT_FORMAT_PCM8 );
230   PRINT_CAP( OUTPUT_FORMAT_PCM16 );
231   PRINT_CAP( OUTPUT_FORMAT_PCM24 );
232   PRINT_CAP( OUTPUT_FORMAT_PCM32 );
233   PRINT_CAP( OUTPUT_FORMAT_PCMFLOAT );
234   PRINT_CAP( REVERB_LIMITED );
235   
236   Con::printf( "" );
237   
238   bool tryAgain;
239   do
240   {
241      tryAgain = false;
242      
243      FMOD_INITFLAGS flags = FMOD_INIT_NORMAL | FMOD_INIT_VOL0_BECOMES_VIRTUAL;
244      
245      if( smPrefDisableSoftware )
246         flags |= FMOD_INIT_SOFTWARE_DISABLE;
247      if( smPrefUseSoftwareOcclusion )
248         flags |= FMOD_INIT_OCCLUSION_LOWPASS;
249      if( smPrefUseSoftwareHRTF )
250         flags |= FMOD_INIT_HRTF_LOWPASS;
251      if( smPrefEnableProfile )
252         flags |= FMOD_INIT_ENABLE_PROFILE;
253      if( smPrefGeometryUseClosest )
254         flags |= FMOD_INIT_GEOMETRY_USECLOSEST;
255      
256      if( smEventSystem )
257         result = smFunc->FMOD_EventSystem_Init( smEventSystem, 100, flags, ( void* ) 0, FMOD_EVENT_INIT_NORMAL );
258      else
259         result = smFunc->FMOD_System_Init( smSystem, 100, flags, ( void* ) 0 );
260         
261      if( result == FMOD_ERR_OUTPUT_CREATEBUFFER )         /* Ok, the speaker mode selected isn't supported by this soundcard.  Switch it back to stereo... */
262      {
263         result = smFunc->FMOD_System_SetSpeakerMode( smSystem, FMOD_SPEAKERMODE_STEREO );
264         FMOD_CHECK( "SFXFMODDevice::init - failed on fallback speaker mode setup" );
265         tryAgain = true;
266      }
267   } while( tryAgain );
268   FMOD_CHECK( "SFXFMODDevice::init - failed to init system" );
269   
270   // Print hardware channel info.
271
272   if( caps & FMOD_CAPS_HARDWARE )
273   {
274      int num3D, num2D, numTotal;
275      
276      if( smFunc->FMOD_System_GetHardwareChannels( smSystem, &num2D, &num3D, &numTotal ) == FMOD_OK )
277         Con::printf( "FMOD Hardware channels: 2d=%i, 3d=%i, total=%i", num2D, num3D, numTotal );
278   }
279
280   // Set up filesystem.
281   
282   //FIXME: Don't do this for now.  Crashes on Windows.
283   #if 0
284   fmodFileSeekCallback, -1 );
285   #endif
286      
287   // Set capabilities.
288   
289   mCaps = CAPS_Reverb | CAPS_VoiceManagement;
290   if( smEventSystem )
291      mCaps |= CAPS_FMODDesigner;
292
293   // Start the update thread.
294   
295   #ifndef TORQUE_DEDICATED // Avoid dependency on platform/async for Linx dedicated.
296   
297   if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
298   {
299      SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread
300         ( "FMOD Update Thread", SFXInternal::gBufferUpdateList,
301           Con::getIntVariable( "$pref::SFX::updateInterval", SFXInternal::DEFAULT_UPDATE_INTERVAL ) );
302      SFXInternal::gUpdateThread->start();
303   }
304   
305   #endif
306   
307   return true;
308}
309
310//-----------------------------------------------------------------------------
311
312SFXBuffer* SFXFMODDevice::createBuffer( const ThreadSafeRef< SFXStream>& stream, SFXDescription* description )
313{
314   AssertFatal( stream, "SFXFMODDevice::createBuffer() - Got a null stream!" );
315   AssertFatal( description, "SFXFMODDevice::createBuffer() - Got null description!" );
316
317   SFXFMODBuffer *buffer = SFXFMODBuffer::create( stream, description );
318   if ( buffer )
319      _addBuffer( buffer );
320
321   return buffer;
322}
323
324//-----------------------------------------------------------------------------
325
326SFXBuffer* SFXFMODDevice::createBuffer( const String& filename, SFXDescription* description )
327{
328   AssertFatal( filename.isNotEmpty(), "SFXFMODDevice::createBuffer() - Got an empty filename!" );
329   AssertFatal( description, "SFXFMODDevice::createBuffer() - Got null description!" );
330
331   SFXFMODBuffer* buffer = SFXFMODBuffer::create( filename, description );
332   if( buffer )
333      _addBuffer( buffer );
334      
335   return buffer;
336}
337
338//-----------------------------------------------------------------------------
339
340SFXVoice* SFXFMODDevice::createVoice( bool is3D, SFXBuffer* buffer )
341{
342   AssertFatal( buffer, "SFXFMODDevice::createVoice() - Got null buffer!" );
343
344   SFXFMODBuffer* fmodBuffer = dynamic_cast<SFXFMODBuffer*>( buffer );
345   AssertFatal( fmodBuffer, "SFXFMODDevice::createVoice() - Got bad buffer!" );
346
347   SFXFMODVoice* voice = SFXFMODVoice::create( this, fmodBuffer );
348   if ( !voice )
349      return NULL;
350
351   _addVoice( voice );
352   return voice;
353}
354
355//-----------------------------------------------------------------------------
356
357void SFXFMODDevice::update()
358{
359   Parent::update();
360
361   if( smEventSystem )
362   {
363      FModAssert( smFunc->FMOD_EventSystem_Update( smEventSystem ), "Failed to update event system!" );
364   }
365   else
366   {
367      FModAssert(smFunc->FMOD_System_Update(smSystem), "Failed to update system!");
368   }
369}
370
371//-----------------------------------------------------------------------------
372
373void SFXFMODDevice::setNumListeners( U32 num )
374{
375   smFunc->FMOD_System_Set3DNumListeners( smSystem, num );
376}
377
378//-----------------------------------------------------------------------------
379
380void SFXFMODDevice::setListener( U32 index, const SFXListenerProperties& listener )
381{
382   FMOD_VECTOR position, forward, up, velocity;
383   
384   TorqueTransformToFMODVectors( listener.getTransform(), position, forward, up );
385   TorqueVectorToFMODVector( listener.getVelocity(), velocity );
386
387   // Do the listener state update, then update!
388   smFunc->FMOD_System_Set3DListenerAttributes( smSystem, index, &position, &velocity, &forward, &up );
389}
390
391//-----------------------------------------------------------------------------
392
393void SFXFMODDevice::setDistanceModel( SFXDistanceModel model )
394{
395   switch( model )
396   {
397      case SFXDistanceModelLinear:
398         m3drolloffmode = FMOD_3D_LINEARROLLOFF;
399         break;
400         
401      case SFXDistanceModelLogarithmic:
402         m3drolloffmode = FMOD_3D_INVERSEROLLOFF;
403         break;
404         
405      default:
406         AssertWarn( false, "SFXFMODDevice::setDistanceModel - model not implemented" );
407   }
408}
409
410//-----------------------------------------------------------------------------
411
412void SFXFMODDevice::setDopplerFactor( F32 factor )
413{
414   F32 dopplerFactor;
415   F32 distanceFactor;
416   F32 rolloffFactor;
417   
418   smFunc->FMOD_System_Get3DSettings( smSystem, &dopplerFactor, &distanceFactor, &rolloffFactor );
419   dopplerFactor = factor;
420   smFunc->FMOD_System_Set3DSettings( smSystem, dopplerFactor, distanceFactor, rolloffFactor );
421}
422
423//-----------------------------------------------------------------------------
424
425void SFXFMODDevice::setRolloffFactor( F32 factor )
426{
427   F32 dopplerFactor;
428   F32 distanceFactor;
429   F32 rolloffFactor;
430   
431   smFunc->FMOD_System_Get3DSettings( smSystem, &dopplerFactor, &distanceFactor, &rolloffFactor );
432   rolloffFactor = factor;
433   smFunc->FMOD_System_Set3DSettings( smSystem, dopplerFactor, distanceFactor, rolloffFactor );
434}
435
436//-----------------------------------------------------------------------------
437
438void SFXFMODDevice::setReverb( const SFXReverbProperties& reverb )
439{
440   FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_GENERIC;
441
442   prop.Environment           = 0;
443   prop.EnvDiffusion          = reverb.mEnvDiffusion;
444   prop.Room                  = reverb.mRoom;
445   prop.RoomHF                = reverb.mRoomHF;
446   prop.RoomLF                = reverb.mRoomLF;
447   prop.DecayTime             = reverb.mDecayTime;
448   prop.DecayLFRatio          = reverb.mDecayLFRatio;
449   prop.DecayHFRatio          = reverb.mDecayHFRatio;
450   prop.Reflections           = reverb.mReflections;
451   prop.ReflectionsDelay      = reverb.mReflectionsDelay;
452   prop.Reverb                = reverb.mReverb;
453   prop.ReverbDelay           = reverb.mReverbDelay;
454   prop.ModulationTime        = reverb.mModulationTime;
455   prop.ModulationDepth       = reverb.mModulationDepth;
456   prop.HFReference           = reverb.mHFReference;
457   prop.LFReference           = reverb.mLFReference;
458   prop.Diffusion             = reverb.mDiffusion;
459   prop.Density               = reverb.mDensity;
460   prop.Flags                 = reverb.mFlags;
461   
462   // Here we only want to affect 3D sounds.  While not quite obvious from the docs,
463   // SetReverbProperties sets the global reverb environment for 2D sounds whereas
464   // SetAmbientReverbProperties sets the global reverb environment for 3D sounds.
465   
466   FMOD_RESULT result = smFunc->FMOD_System_SetReverbAmbientProperties( smSystem, &prop );
467   if( result != FMOD_OK )
468      Con::errorf( "SFXFMODDevice::setReverb - Failed to set reverb (%s)", FMODResultToString( result ).c_str() );
469}
470
471//-----------------------------------------------------------------------------
472
473void SFXFMODDevice::resetReverb()
474{
475   FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_OFF;
476   smFunc->FMOD_System_SetReverbProperties( smSystem, &prop );
477}
478
479//-----------------------------------------------------------------------------
480
481void SFXFMODDevice::updateMemUsageStats()
482{
483   smFunc->FMOD_System_GetMemoryInfo( smSystem, ( unsigned int ) FMOD_MEMBITS_ALL,
484      ( unsigned int ) 0, ( unsigned int* ) &smStatMemUsageCore, ( unsigned int* ) 0 );
485      
486   if( smEventSystem )
487      smFunc->FMOD_EventSystem_GetMemoryInfo( smEventSystem, ( unsigned int ) 0,
488         ( unsigned int ) FMOD_EVENT_MEMBITS_ALL, ( unsigned int* ) &smStatMemUsageEvents, ( unsigned int* ) 0 );
489}
490
491//=============================================================================
492//    Console Functions.
493//=============================================================================
494// MARK: ---- Console Functions ----
495
496//------------------------------------------------------------------------------
497
498ConsoleFunction( fmodDumpDSPInfo, void, 1, 1, "()"
499            "@brief Dump information about the standard DSP effects.\n\n"
500            "@ingroup SFXFMOD")
501{
502   if( !SFXFMODDevice::smFunc )
503      return;
504      
505   const U32 firstDSPType = FMOD_DSP_TYPE_MIXER;
506   const U32 lastDSPType = FMOD_DSP_TYPE_TREMOLO;
507   
508   for( U32 i = firstDSPType; i <= lastDSPType; ++ i )
509   {
510      FMOD_DSP* dsp;
511      if( SFXFMODDevice::smFunc->FMOD_System_CreateDSPByType( SFXFMODDevice::smSystem, ( FMOD_DSP_TYPE ) i, &dsp ) == FMOD_OK )
512      {
513         // Print general info.
514         
515         char name[ 33 ];
516         unsigned int version;
517         int channels;
518         int numParameters;
519         
520         dMemset( name, 0, sizeof( name ) );
521         SFXFMODDevice::smFunc->FMOD_DSP_GetInfo( dsp, name, &version, &channels, ( int* ) NULL, ( int* ) NULL );
522         SFXFMODDevice::smFunc->FMOD_DSP_GetNumParameters( dsp, &numParameters );
523         
524         Con::printf( "----------------------------------------------------------------" );
525         Con::printf( "DSP: %s", name );
526         Con::printf( "Version: %i.%i", ( version & 0xffff0000 ) >> 16, version & 0xffff );
527         Con::printf( "Channels: %i", channels );
528         Con::printf( "Parameters: %i", numParameters );
529         Con::printf( "" );
530         
531         // Print parameter info.
532         
533         for( U32 n = 0; n < numParameters; ++ n )
534         {
535            char name[ 17 ];
536            char label[ 17 ];
537            char description[ 1024 ];
538            float minValue, maxValue;
539            float value;
540            char valueString[ 256 ];
541            
542            dMemset( name, 0, sizeof( name ) );
543            dMemset( label, 0, sizeof( label ) );
544            dMemset( description, 0, sizeof( description ) );
545            dMemset( valueString, 0, sizeof( valueString ) );
546            
547            SFXFMODDevice::smFunc->FMOD_DSP_GetParameterInfo( dsp, n, name, label, description, sizeof( description ) - 1, &minValue, &maxValue );
548            SFXFMODDevice::smFunc->FMOD_DSP_GetParameter( dsp, n, &value, valueString, sizeof( valueString ) - 1 );
549            
550            Con::printf( "* Parameter %i", n );
551            Con::printf( "Name: %s", name );
552            Con::printf( "Label: %s", label );
553            Con::printf( "Description: %s", description );
554            Con::printf( "Min: %f", minValue );
555            Con::printf( "Max: %f", maxValue );
556            Con::printf( "Value: %f (%s)", value, valueString );
557            Con::printf( "" );
558         }
559         
560         // Release the DSP.
561         
562         SFXFMODDevice::smFunc->FMOD_DSP_Release( dsp );
563      }
564   }
565}
566
567//-----------------------------------------------------------------------------
568
569ConsoleFunction( fmodDumpMemoryStats, void, 1, 1, "()"
570            "@return Prints the current memory consumption of the FMOD module\n\n"
571            "@ingroup SFXFMOD")
572{
573   int current = 0;
574   int max = 0;
575
576   if (SFXFMODDevice::smFunc && SFXFMODDevice::smFunc->FMOD_Memory_GetStats.fn)
577         SFXFMODDevice::smFunc->FMOD_Memory_GetStats(&current, &max);
578   Con::printf("Fmod current: %d, max: %d", current, max);
579}
580