sfxFMODDevice.cpp
Engine/source/sfx/fmod/sfxFMODDevice.cpp
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(¤t, &max); 578 Con::printf("Fmod current: %d, max: %d", current, max); 579} 580