sfxFMODDevice.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "platform/threads/mutex.h"
  24. #include "sfx/fmod/sfxFMODDevice.h"
  25. #include "sfx/fmod/sfxFMODBuffer.h"
  26. #include "sfx/sfxSystem.h"
  27. #include "platform/async/asyncUpdate.h"
  28. #include "console/consoleTypes.h"
  29. #include "core/volume.h"
  30. bool SFXFMODDevice::smPrefDisableSoftware = false;
  31. bool SFXFMODDevice::smPrefUseSoftwareOcclusion = true;
  32. bool SFXFMODDevice::smPrefUseSoftwareHRTF = true;
  33. bool SFXFMODDevice::smPrefUseSoftwareReverbLowmem = false;
  34. bool SFXFMODDevice::smPrefEnableProfile = false;
  35. bool SFXFMODDevice::smPrefGeometryUseClosest = false;
  36. const char* SFXFMODDevice::smPrefDSoundHRTF = "full";
  37. const char* SFXFMODDevice::smPrefPluginPath = "";
  38. U32 SFXFMODDevice::smStatMemUsageCore;
  39. U32 SFXFMODDevice::smStatMemUsageEvents;
  40. U32 SFXFMODDevice::smStatNumEventSources;
  41. SFXFMODDevice* SFXFMODDevice::smInstance;
  42. FMOD_SYSTEM* SFXFMODDevice::smSystem;
  43. FMOD_EVENTSYSTEM* SFXFMODDevice::smEventSystem;
  44. FModFNTable* SFXFMODDevice::smFunc;
  45. Mutex* FModFNTable::mutex;
  46. //-----------------------------------------------------------------------------
  47. String FMODResultToString( FMOD_RESULT result )
  48. {
  49. switch( result )
  50. {
  51. #define FMOD_ERROR( n ) case n: return #n;
  52. #include "fmodErrors.h"
  53. #undef FMOD_ERROR
  54. default:
  55. break;
  56. }
  57. return String();
  58. }
  59. //------------------------------------------------------------------------------
  60. // FMOD filesystem wrappers.
  61. //FIXME: these are not thread-safe and cannot be used as such
  62. FMOD_RESULT F_CALLBACK fmodFileOpenCallback( const char* name, int unicode, unsigned int* filesize, void** handle, void** userdata )
  63. {
  64. String fileName;
  65. if( unicode )
  66. fileName = String( ( UTF16* ) name );
  67. else
  68. fileName = String( name );
  69. Torque::FS::FileRef file = Torque::FS::OpenFile( fileName, Torque::FS::File::Read );
  70. if( !file )
  71. return FMOD_ERR_FILE_NOTFOUND;
  72. else if( file->getStatus() != Torque::FS::File::Open )
  73. return FMOD_ERR_FILE_BAD;
  74. // Add a reference so we can pass it into FMOD.
  75. file->incRefCount();
  76. *filesize = U32( file->getSize() );
  77. *handle = file.getPointer();
  78. return FMOD_OK;
  79. }
  80. FMOD_RESULT F_CALLBACK fmodFileCloseCallback( void* handle, void* userdata )
  81. {
  82. Torque::FS::File* file = reinterpret_cast< Torque::FS::File* >( handle );
  83. file->decRefCount();
  84. return FMOD_OK;
  85. }
  86. FMOD_RESULT F_CALLBACK fmodFileReadCallback( void* handle, void* buffer, unsigned int sizebytes, unsigned int* bytesread, void* userdata )
  87. {
  88. Torque::FS::File* file = reinterpret_cast< Torque::FS::File* >( handle );
  89. U32 numRead = file->read( buffer, sizebytes );
  90. *bytesread = numRead;
  91. if( file->getStatus() == Torque::FS::File::EndOfFile )
  92. return FMOD_ERR_FILE_EOF;
  93. else if( file->getStatus() != Torque::FS::File::Open )
  94. return FMOD_ERR_FILE_BAD;
  95. return FMOD_OK;
  96. }
  97. FMOD_RESULT F_CALLBACK fmodFileSeekCallback( void* handle, unsigned int pos, void* userdata )
  98. {
  99. Torque::FS::File* file = reinterpret_cast< Torque::FS::File* >( handle );
  100. if( file->setPosition( pos, Torque::FS::File::Begin ) != pos )
  101. return FMOD_ERR_FILE_COULDNOTSEEK;
  102. return FMOD_OK;
  103. }
  104. //-----------------------------------------------------------------------------
  105. SFXFMODDevice::SFXFMODDevice( SFXProvider* provider,
  106. FModFNTable *fmodFnTbl,
  107. int deviceIdx,
  108. String name )
  109. : SFXDevice( name, provider, false, 32 ),
  110. m3drolloffmode( FMOD_3D_INVERSEROLLOFF ),
  111. mDeviceIndex( deviceIdx )
  112. {
  113. // Store off the function pointers for later use.
  114. smFunc = fmodFnTbl;
  115. smStatMemUsageCore = 0;
  116. smStatMemUsageEvents = 0;
  117. smStatNumEventSources = 0;
  118. // Register our SFXSystem plugin.
  119. SFX->addPlugin( &mPlugin );
  120. smInstance = this;
  121. }
  122. //-----------------------------------------------------------------------------
  123. SFXFMODDevice::~SFXFMODDevice()
  124. {
  125. _releaseAllResources();
  126. SFX->removePlugin( &mPlugin );
  127. if( smEventSystem )
  128. {
  129. smFunc->FMOD_EventSystem_Release( smEventSystem );
  130. smEventSystem = NULL;
  131. smSystem = NULL;
  132. }
  133. else
  134. smFunc->FMOD_System_Close( smSystem );
  135. smInstance = NULL;
  136. }
  137. //-----------------------------------------------------------------------------
  138. bool SFXFMODDevice::_init()
  139. {
  140. #define FMOD_CHECK( message ) \
  141. if( result != FMOD_OK ) \
  142. { \
  143. Con::errorf( "SFXFMODDevice::_init() - %s (%s)", \
  144. message, \
  145. FMOD_ErrorString( result ) ); \
  146. return false; \
  147. }
  148. AssertISV(smSystem,
  149. "SFXFMODDevice::_init() - can't init w/o an existing FMOD system handle!");
  150. FMOD_RESULT result;
  151. // Get some prefs.
  152. if( smPrefPluginPath && smPrefPluginPath[ 0 ] )
  153. {
  154. char fullPath[ 4096 ];
  155. Platform::makeFullPathName( smPrefPluginPath, fullPath, sizeof( fullPath ) );
  156. smFunc->FMOD_System_SetPluginPath( smSystem, fullPath );
  157. }
  158. else
  159. {
  160. smFunc->FMOD_System_SetPluginPath( smSystem, Platform::getExecutablePath() );
  161. }
  162. // Initialize everything from fmod.
  163. FMOD_SPEAKERMODE speakermode;
  164. FMOD_CAPS caps;
  165. result = smFunc->FMOD_System_GetDriverCaps(smSystem, 0, &caps, ( int* ) 0, &speakermode);
  166. FMOD_CHECK( "SFXFMODDevice::init - Failed to get driver caps" );
  167. result = smFunc->FMOD_System_SetDriver(smSystem, mDeviceIndex);
  168. FMOD_CHECK( "SFXFMODDevice::init - Failed to set driver" );
  169. result = smFunc->FMOD_System_SetSpeakerMode(smSystem, speakermode);
  170. FMOD_CHECK( "SFXFMODDevice::init - Failed to set the user selected speaker mode" );
  171. if (caps & FMOD_CAPS_HARDWARE_EMULATED) /* The user has the 'Acceleration' slider set to off! This is really bad for latency!. */
  172. { /* You might want to warn the user about this. */
  173. result = smFunc->FMOD_System_SetDSPBufferSize(smSystem, 1024, 10);
  174. FMOD_CHECK( "SFXFMODDevice::init - Failed to set DSP buffer size" );
  175. }
  176. Con::printf( "\nFMOD Device caps:" );
  177. #define PRINT_CAP( name ) \
  178. if( caps & FMOD_CAPS_ ## name ) \
  179. Con::printf( #name );
  180. PRINT_CAP( HARDWARE );
  181. PRINT_CAP( HARDWARE_EMULATED );
  182. PRINT_CAP( OUTPUT_MULTICHANNEL );
  183. PRINT_CAP( OUTPUT_FORMAT_PCM8 );
  184. PRINT_CAP( OUTPUT_FORMAT_PCM16 );
  185. PRINT_CAP( OUTPUT_FORMAT_PCM24 );
  186. PRINT_CAP( OUTPUT_FORMAT_PCM32 );
  187. PRINT_CAP( OUTPUT_FORMAT_PCMFLOAT );
  188. PRINT_CAP( REVERB_LIMITED );
  189. Con::printf( "" );
  190. bool tryAgain;
  191. do
  192. {
  193. tryAgain = false;
  194. FMOD_INITFLAGS flags = FMOD_INIT_NORMAL | FMOD_INIT_VOL0_BECOMES_VIRTUAL;
  195. if( smPrefDisableSoftware )
  196. flags |= FMOD_INIT_SOFTWARE_DISABLE;
  197. if( smPrefUseSoftwareOcclusion )
  198. flags |= FMOD_INIT_OCCLUSION_LOWPASS;
  199. if( smPrefUseSoftwareHRTF )
  200. flags |= FMOD_INIT_HRTF_LOWPASS;
  201. if( smPrefUseSoftwareReverbLowmem )
  202. flags |= FMOD_INIT_SOFTWARE_REVERB_LOWMEM;
  203. if( smPrefEnableProfile )
  204. flags |= FMOD_INIT_ENABLE_PROFILE;
  205. if( smPrefGeometryUseClosest )
  206. flags |= FMOD_INIT_GEOMETRY_USECLOSEST;
  207. if( smEventSystem )
  208. result = smFunc->FMOD_EventSystem_Init( smEventSystem, 100, flags, ( void* ) 0, FMOD_EVENT_INIT_NORMAL );
  209. else
  210. result = smFunc->FMOD_System_Init( smSystem, 100, flags, ( void* ) 0 );
  211. if( result == FMOD_ERR_OUTPUT_CREATEBUFFER ) /* Ok, the speaker mode selected isn't supported by this soundcard. Switch it back to stereo... */
  212. {
  213. result = smFunc->FMOD_System_SetSpeakerMode( smSystem, FMOD_SPEAKERMODE_STEREO );
  214. FMOD_CHECK( "SFXFMODDevice::init - failed on fallback speaker mode setup" );
  215. tryAgain = true;
  216. }
  217. } while( tryAgain );
  218. FMOD_CHECK( "SFXFMODDevice::init - failed to init system" );
  219. // Print hardware channel info.
  220. if( caps & FMOD_CAPS_HARDWARE )
  221. {
  222. int num3D, num2D, numTotal;
  223. if( smFunc->FMOD_System_GetHardwareChannels( smSystem, &num2D, &num3D, &numTotal ) == FMOD_OK )
  224. Con::printf( "FMOD Hardware channels: 2d=%i, 3d=%i, total=%i", num2D, num3D, numTotal );
  225. }
  226. // Set up filesystem.
  227. //FIXME: Don't do this for now. Crashes on Windows.
  228. #if 0
  229. smFunc->FMOD_System_SetFileSystem( smSystem, fmodFileOpenCallback, fmodFileCloseCallback, fmodFileReadCallback, fmodFileSeekCallback, -1 );
  230. #endif
  231. // Set capabilities.
  232. mCaps = CAPS_Reverb | CAPS_VoiceManagement;
  233. if( smEventSystem )
  234. mCaps |= CAPS_FMODDesigner;
  235. // Start the update thread.
  236. #ifndef TORQUE_DEDICATED // Avoid dependency on platform/async for Linx dedicated.
  237. if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
  238. {
  239. SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread
  240. ( "FMOD Update Thread", SFXInternal::gBufferUpdateList,
  241. Con::getIntVariable( "$pref::SFX::updateInterval", SFXInternal::DEFAULT_UPDATE_INTERVAL ) );
  242. SFXInternal::gUpdateThread->start();
  243. }
  244. #endif
  245. return true;
  246. }
  247. //-----------------------------------------------------------------------------
  248. SFXBuffer* SFXFMODDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description )
  249. {
  250. AssertFatal( stream, "SFXFMODDevice::createBuffer() - Got a null stream!" );
  251. AssertFatal( description, "SFXFMODDevice::createBuffer() - Got null description!" );
  252. SFXFMODBuffer *buffer = SFXFMODBuffer::create( stream, description );
  253. if ( buffer )
  254. _addBuffer( buffer );
  255. return buffer;
  256. }
  257. //-----------------------------------------------------------------------------
  258. SFXBuffer* SFXFMODDevice::createBuffer( const String& filename, SFXDescription* description )
  259. {
  260. AssertFatal( filename.isNotEmpty(), "SFXFMODDevice::createBuffer() - Got an empty filename!" );
  261. AssertFatal( description, "SFXFMODDevice::createBuffer() - Got null description!" );
  262. SFXFMODBuffer* buffer = SFXFMODBuffer::create( filename, description );
  263. if( buffer )
  264. _addBuffer( buffer );
  265. return buffer;
  266. }
  267. //-----------------------------------------------------------------------------
  268. SFXVoice* SFXFMODDevice::createVoice( bool is3D, SFXBuffer* buffer )
  269. {
  270. AssertFatal( buffer, "SFXFMODDevice::createVoice() - Got null buffer!" );
  271. SFXFMODBuffer* fmodBuffer = dynamic_cast<SFXFMODBuffer*>( buffer );
  272. AssertFatal( fmodBuffer, "SFXFMODDevice::createVoice() - Got bad buffer!" );
  273. SFXFMODVoice* voice = SFXFMODVoice::create( this, fmodBuffer );
  274. if ( !voice )
  275. return NULL;
  276. _addVoice( voice );
  277. return voice;
  278. }
  279. //-----------------------------------------------------------------------------
  280. void SFXFMODDevice::update()
  281. {
  282. Parent::update();
  283. if( smEventSystem )
  284. {
  285. FModAssert( smFunc->FMOD_EventSystem_Update( smEventSystem ), "Failed to update event system!" );
  286. }
  287. else
  288. {
  289. FModAssert(smFunc->FMOD_System_Update(smSystem), "Failed to update system!");
  290. }
  291. }
  292. //-----------------------------------------------------------------------------
  293. void SFXFMODDevice::setNumListeners( U32 num )
  294. {
  295. smFunc->FMOD_System_Set3DNumListeners( smSystem, num );
  296. }
  297. //-----------------------------------------------------------------------------
  298. void SFXFMODDevice::setListener( U32 index, const SFXListenerProperties& listener )
  299. {
  300. FMOD_VECTOR position, forward, up, velocity;
  301. TorqueTransformToFMODVectors( listener.getTransform(), position, forward, up );
  302. TorqueVectorToFMODVector( listener.getVelocity(), velocity );
  303. // Do the listener state update, then update!
  304. smFunc->FMOD_System_Set3DListenerAttributes( smSystem, index, &position, &velocity, &forward, &up );
  305. }
  306. //-----------------------------------------------------------------------------
  307. void SFXFMODDevice::setDistanceModel( SFXDistanceModel model )
  308. {
  309. switch( model )
  310. {
  311. case SFXDistanceModelLinear:
  312. m3drolloffmode = FMOD_3D_LINEARROLLOFF;
  313. break;
  314. case SFXDistanceModelLogarithmic:
  315. m3drolloffmode = FMOD_3D_INVERSEROLLOFF;
  316. break;
  317. default:
  318. AssertWarn( false, "SFXFMODDevice::setDistanceModel - model not implemented" );
  319. }
  320. }
  321. //-----------------------------------------------------------------------------
  322. void SFXFMODDevice::setDopplerFactor( F32 factor )
  323. {
  324. F32 dopplerFactor;
  325. F32 distanceFactor;
  326. F32 rolloffFactor;
  327. smFunc->FMOD_System_Get3DSettings( smSystem, &dopplerFactor, &distanceFactor, &rolloffFactor );
  328. dopplerFactor = factor;
  329. smFunc->FMOD_System_Set3DSettings( smSystem, dopplerFactor, distanceFactor, rolloffFactor );
  330. }
  331. //-----------------------------------------------------------------------------
  332. void SFXFMODDevice::setRolloffFactor( F32 factor )
  333. {
  334. F32 dopplerFactor;
  335. F32 distanceFactor;
  336. F32 rolloffFactor;
  337. smFunc->FMOD_System_Get3DSettings( smSystem, &dopplerFactor, &distanceFactor, &rolloffFactor );
  338. rolloffFactor = factor;
  339. smFunc->FMOD_System_Set3DSettings( smSystem, dopplerFactor, distanceFactor, rolloffFactor );
  340. }
  341. //-----------------------------------------------------------------------------
  342. void SFXFMODDevice::setReverb( const SFXReverbProperties& reverb )
  343. {
  344. FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_GENERIC;
  345. prop.Environment = 0;
  346. prop.EnvDiffusion = reverb.mEnvDiffusion;
  347. prop.Room = reverb.mRoom;
  348. prop.RoomHF = reverb.mRoomHF;
  349. prop.RoomLF = reverb.mRoomLF;
  350. prop.DecayTime = reverb.mDecayTime;
  351. prop.DecayLFRatio = reverb.mDecayLFRatio;
  352. prop.DecayHFRatio = reverb.mDecayHFRatio;
  353. prop.Reflections = reverb.mReflections;
  354. prop.ReflectionsDelay = reverb.mReflectionsDelay;
  355. prop.Reverb = reverb.mReverb;
  356. prop.ReverbDelay = reverb.mReverbDelay;
  357. prop.ModulationTime = reverb.mModulationTime;
  358. prop.ModulationDepth = reverb.mModulationDepth;
  359. prop.HFReference = reverb.mHFReference;
  360. prop.LFReference = reverb.mLFReference;
  361. prop.Diffusion = reverb.mDiffusion;
  362. prop.Density = reverb.mDensity;
  363. prop.Flags = reverb.mFlags;
  364. // Here we only want to affect 3D sounds. While not quite obvious from the docs,
  365. // SetReverbProperties sets the global reverb environment for 2D sounds whereas
  366. // SetAmbientReverbProperties sets the global reverb environment for 3D sounds.
  367. FMOD_RESULT result = smFunc->FMOD_System_SetReverbAmbientProperties( smSystem, &prop );
  368. if( result != FMOD_OK )
  369. Con::errorf( "SFXFMODDevice::setReverb - Failed to set reverb (%s)", FMODResultToString( result ).c_str() );
  370. }
  371. //-----------------------------------------------------------------------------
  372. void SFXFMODDevice::resetReverb()
  373. {
  374. FMOD_REVERB_PROPERTIES prop = FMOD_PRESET_OFF;
  375. smFunc->FMOD_System_SetReverbProperties( smSystem, &prop );
  376. }
  377. //-----------------------------------------------------------------------------
  378. void SFXFMODDevice::updateMemUsageStats()
  379. {
  380. smFunc->FMOD_System_GetMemoryInfo( smSystem, ( unsigned int ) FMOD_MEMBITS_ALL,
  381. ( unsigned int ) 0, ( unsigned int* ) &smStatMemUsageCore, ( unsigned int* ) 0 );
  382. if( smEventSystem )
  383. smFunc->FMOD_EventSystem_GetMemoryInfo( smEventSystem, ( unsigned int ) 0,
  384. ( unsigned int ) FMOD_EVENT_MEMBITS_ALL, ( unsigned int* ) &smStatMemUsageEvents, ( unsigned int* ) 0 );
  385. }
  386. //=============================================================================
  387. // Console Functions.
  388. //=============================================================================
  389. // MARK: ---- Console Functions ----
  390. //------------------------------------------------------------------------------
  391. ConsoleFunction( fmodDumpDSPInfo, void, 1, 1, "()"
  392. "@brief Dump information about the standard DSP effects.\n\n"
  393. "@ingroup SFXFMOD")
  394. {
  395. if( !SFXFMODDevice::smFunc )
  396. return;
  397. const U32 firstDSPType = FMOD_DSP_TYPE_MIXER;
  398. const U32 lastDSPType = FMOD_DSP_TYPE_TREMOLO;
  399. for( U32 i = firstDSPType; i <= lastDSPType; ++ i )
  400. {
  401. FMOD_DSP* dsp;
  402. if( SFXFMODDevice::smFunc->FMOD_System_CreateDSPByType( SFXFMODDevice::smSystem, ( FMOD_DSP_TYPE ) i, &dsp ) == FMOD_OK )
  403. {
  404. // Print general info.
  405. char name[ 33 ];
  406. unsigned int version;
  407. int channels;
  408. int numParameters;
  409. dMemset( name, 0, sizeof( name ) );
  410. SFXFMODDevice::smFunc->FMOD_DSP_GetInfo( dsp, name, &version, &channels, ( int* ) NULL, ( int* ) NULL );
  411. SFXFMODDevice::smFunc->FMOD_DSP_GetNumParameters( dsp, &numParameters );
  412. Con::printf( "----------------------------------------------------------------" );
  413. Con::printf( "DSP: %s", name );
  414. Con::printf( "Version: %i.%i", ( version & 0xffff0000 ) >> 16, version & 0xffff );
  415. Con::printf( "Channels: %i", channels );
  416. Con::printf( "Parameters: %i", numParameters );
  417. Con::printf( "" );
  418. // Print parameter info.
  419. for( U32 n = 0; n < numParameters; ++ n )
  420. {
  421. char name[ 17 ];
  422. char label[ 17 ];
  423. char description[ 1024 ];
  424. float minValue, maxValue;
  425. float value;
  426. char valueString[ 256 ];
  427. dMemset( name, 0, sizeof( name ) );
  428. dMemset( label, 0, sizeof( label ) );
  429. dMemset( description, 0, sizeof( description ) );
  430. dMemset( valueString, 0, sizeof( valueString ) );
  431. SFXFMODDevice::smFunc->FMOD_DSP_GetParameterInfo( dsp, n, name, label, description, sizeof( description ) - 1, &minValue, &maxValue );
  432. SFXFMODDevice::smFunc->FMOD_DSP_GetParameter( dsp, n, &value, valueString, sizeof( valueString ) - 1 );
  433. Con::printf( "* Parameter %i", n );
  434. Con::printf( "Name: %s", name );
  435. Con::printf( "Label: %s", label );
  436. Con::printf( "Description: %s", description );
  437. Con::printf( "Min: %f", minValue );
  438. Con::printf( "Max: %f", maxValue );
  439. Con::printf( "Value: %f (%s)", value, valueString );
  440. Con::printf( "" );
  441. }
  442. // Release the DSP.
  443. SFXFMODDevice::smFunc->FMOD_DSP_Release( dsp );
  444. }
  445. }
  446. }
  447. //-----------------------------------------------------------------------------
  448. ConsoleFunction( fmodDumpMemoryStats, void, 1, 1, "()"
  449. "@return Prints the current memory consumption of the FMOD module\n\n"
  450. "@ingroup SFXFMOD")
  451. {
  452. int current = 0;
  453. int max = 0;
  454. if (SFXFMODDevice::smFunc && SFXFMODDevice::smFunc->FMOD_Memory_GetStats.fn)
  455. SFXFMODDevice::smFunc->FMOD_Memory_GetStats(&current, &max);
  456. Con::printf("Fmod current: %d, max: %d", current, max);
  457. }