Panda3D
|
00001 // Filename: fmodAudioManager.cxx 00002 // Created by: cort (January 22, 2003) 00003 // Prior system by: cary 00004 // Rewrite [for new Version of FMOD-EX] by: Stan Rosenbaum "Staque" - Spring 2006 00005 // 00006 // 00007 //////////////////////////////////////////////////////////////////// 00008 // 00009 // PANDA 3D SOFTWARE 00010 // Copyright (c) Carnegie Mellon University. All rights reserved. 00011 // 00012 // All use of this software is subject to the terms of the revised BSD 00013 // license. You should have received a copy of this license along 00014 // with this source code in a file named "LICENSE." 00015 // 00016 //////////////////////////////////////////////////////////////////// 00017 00018 #include "pandabase.h" 00019 #include "config_audio.h" 00020 #include "dcast.h" 00021 00022 #ifdef HAVE_FMODEX //[ 00023 00024 //Panda headers. 00025 #include "config_audio.h" 00026 #include "config_util.h" 00027 #include "fmodAudioManager.h" 00028 #include "fmodAudioSound.h" 00029 #include "filename.h" 00030 #include "virtualFileSystem.h" 00031 #include "reMutexHolder.h" 00032 00033 //FMOD Headers. 00034 #include <fmod.hpp> 00035 #include <fmod_errors.h> 00036 00037 #define USER_DSP_MAGIC ((void*)0x7012AB35) 00038 00039 TypeHandle FmodAudioManager::_type_handle; 00040 00041 ReMutex FmodAudioManager::_lock; 00042 FMOD::System *FmodAudioManager::_system; 00043 00044 pset<FmodAudioManager *> FmodAudioManager::_all_managers; 00045 00046 bool FmodAudioManager::_system_is_valid = false; 00047 00048 00049 // This sets the distance factor for 3D audio to use feet. 00050 // FMOD uses meters by default. 00051 // Since Panda use feet we need to compensate for that with a factor of 3.28 00052 // 00053 // This can be overwritten. You just need to call 00054 // audio_3d_set_distance_factor(PN_stdfloat factor) and set your new factor. 00055 00056 PN_stdfloat FmodAudioManager::_doppler_factor = 1; 00057 PN_stdfloat FmodAudioManager::_distance_factor = 3.28; 00058 PN_stdfloat FmodAudioManager::_drop_off_factor = 1; 00059 00060 00061 //////////////////////////////////////////////////////////////////// 00062 // Central dispatcher for audio errors. 00063 //////////////////////////////////////////////////////////////////// 00064 00065 void fmod_audio_errcheck(const char *context, FMOD_RESULT result) { 00066 if (result != 0) { 00067 audio_error(context << ": " << FMOD_ErrorString(result) ); 00068 } 00069 } 00070 00071 //////////////////////////////////////////////////////////////////// 00072 // Function: Create_FmodAudioManager 00073 // Access: Private 00074 // Description: Factory Function 00075 //////////////////////////////////////////////////////////////////// 00076 AudioManager *Create_FmodAudioManager() { 00077 audio_debug("Create_FmodAudioManager()"); 00078 return new FmodAudioManager; 00079 } 00080 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: FmodAudioManager::Constructor 00084 // Access: Public 00085 // Description: 00086 //////////////////////////////////////////////////////////////////// 00087 FmodAudioManager:: 00088 FmodAudioManager() { 00089 ReMutexHolder holder(_lock); 00090 FMOD_RESULT result; 00091 00092 //We need a varible temporary to check the FMOD Version. 00093 unsigned int version; 00094 00095 _all_managers.insert(this); 00096 00097 //Init 3D attributes 00098 _position.x = 0; 00099 _position.y = 0; 00100 _position.z = 0; 00101 00102 _velocity.x = 0; 00103 _velocity.y = 0; 00104 _velocity.z = 0; 00105 00106 _forward.x = 0; 00107 _forward.y = 0; 00108 _forward.z = 0; 00109 00110 _up.x = 0; 00111 _up.y = 0; 00112 _up.z = 0; 00113 00114 if (_system == (FMOD::System *)NULL) { 00115 // Create the global FMOD System object. This one object must be 00116 // shared by all FmodAudioManagers (this is particularly true on 00117 // OSX, but the FMOD documentation is unclear as to whether this 00118 // is the intended design on all systems). 00119 00120 result = FMOD::System_Create(&_system); 00121 fmod_audio_errcheck("FMOD::System_Create()", result); 00122 00123 // Let check the Version of FMOD to make sure the Headers and Libraries are correct. 00124 result = _system->getVersion(&version); 00125 fmod_audio_errcheck("_system->getVersion()", result); 00126 00127 if (version < FMOD_VERSION){ 00128 audio_error("You are using an old version of FMOD. This program requires:" << FMOD_VERSION); 00129 } 00130 00131 //Stick Surround Sound 5.1 thing Here. 00132 if (fmod_use_surround_sound) { 00133 audio_debug("Setting FMOD to use 5.1 Surround Sound."); 00134 result = _system->setSpeakerMode(FMOD_SPEAKERMODE_5POINT1); 00135 fmod_audio_errcheck("_system->setSpeakerMode()", result); 00136 } 00137 00138 //Now we Initialize the System. 00139 int nchan = fmod_number_of_sound_channels; 00140 int flags = FMOD_INIT_NORMAL; 00141 00142 result = _system->init(nchan, flags, 0); 00143 if (result == FMOD_ERR_TOOMANYCHANNELS) { 00144 fmodAudio_cat.error() 00145 << "Value too large for fmod-number-of-sound-channels: " << nchan 00146 << "\n"; 00147 } else { 00148 fmod_audio_errcheck("_system->init()", result); 00149 } 00150 00151 _system_is_valid = (result == FMOD_OK); 00152 00153 if (_system_is_valid) { 00154 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor); 00155 fmod_audio_errcheck("_system->set3DSettings()", result); 00156 } 00157 } 00158 00159 _is_valid = _system_is_valid; 00160 00161 memset(&_midi_info, 0, sizeof(_midi_info)); 00162 _midi_info.cbsize = sizeof(_midi_info); 00163 00164 Filename dls_pathname = get_dls_pathname(); 00165 00166 #ifdef IS_OSX 00167 // Here's a big kludge. Don't ever let FMOD try to load this 00168 // OSX-provided file; it crashes messily if you do. 00169 if (dls_pathname == "/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls") { 00170 dls_pathname = ""; 00171 } 00172 #endif // IS_OSX 00173 00174 if (!dls_pathname.empty()) { 00175 _dlsname = dls_pathname.to_os_specific(); 00176 _midi_info.dlsname = _dlsname.c_str(); 00177 } 00178 00179 if (_is_valid) { 00180 result = _system->createChannelGroup("UserGroup", &_channelgroup); 00181 fmod_audio_errcheck("_system->createChannelGroup()", result); 00182 } 00183 } 00184 00185 //////////////////////////////////////////////////////////////////// 00186 // Function: FmodAudioManager::Destructor 00187 // Access: Public 00188 // Description: 00189 //////////////////////////////////////////////////////////////////// 00190 FmodAudioManager:: 00191 ~FmodAudioManager() { 00192 ReMutexHolder holder(_lock); 00193 // Be sure to delete associated sounds before deleting the manager! 00194 FMOD_RESULT result; 00195 00196 //Release Sounds Next 00197 _all_sounds.clear(); 00198 00199 // Remove me from the managers list. 00200 _all_managers.erase(this); 00201 00202 if (_all_managers.empty()) { 00203 result = _system->release(); 00204 fmod_audio_errcheck("_system->release()", result); 00205 _system = NULL; 00206 _system_is_valid = false; 00207 } 00208 } 00209 00210 //////////////////////////////////////////////////////////////////// 00211 // Function: FmodAudioManager::is_valid 00212 // Access: Public 00213 // Description: This just check to make sure the FMOD System is 00214 // up and running correctly. 00215 //////////////////////////////////////////////////////////////////// 00216 bool FmodAudioManager:: 00217 is_valid() { 00218 return _is_valid; 00219 } 00220 00221 //////////////////////////////////////////////////////////////////// 00222 // Function: FmodAudioManager::make_dsp 00223 // Access: Private 00224 // Description: Converts a FilterConfig to an FMOD_DSP 00225 //////////////////////////////////////////////////////////////////// 00226 FMOD::DSP *FmodAudioManager:: 00227 make_dsp(const FilterProperties::FilterConfig &conf) { 00228 ReMutexHolder holder(_lock); 00229 FMOD_DSP_TYPE dsptype; 00230 FMOD_RESULT result; 00231 FMOD::DSP *dsp; 00232 switch (conf._type) { 00233 case FilterProperties::FT_lowpass: dsptype = FMOD_DSP_TYPE_LOWPASS; break; 00234 case FilterProperties::FT_highpass: dsptype = FMOD_DSP_TYPE_HIGHPASS; break; 00235 case FilterProperties::FT_echo: dsptype = FMOD_DSP_TYPE_ECHO; break; 00236 case FilterProperties::FT_flange: dsptype = FMOD_DSP_TYPE_FLANGE; break; 00237 case FilterProperties::FT_distort: dsptype = FMOD_DSP_TYPE_DISTORTION; break; 00238 case FilterProperties::FT_normalize: dsptype = FMOD_DSP_TYPE_NORMALIZE; break; 00239 case FilterProperties::FT_parameq: dsptype = FMOD_DSP_TYPE_PARAMEQ; break; 00240 case FilterProperties::FT_pitchshift: dsptype = FMOD_DSP_TYPE_PITCHSHIFT; break; 00241 case FilterProperties::FT_chorus: dsptype = FMOD_DSP_TYPE_CHORUS; break; 00242 case FilterProperties::FT_reverb: dsptype = FMOD_DSP_TYPE_REVERB; break; 00243 case FilterProperties::FT_compress: dsptype = FMOD_DSP_TYPE_COMPRESSOR; break; 00244 default: 00245 audio_error("Garbage in DSP configuration data"); 00246 return NULL; 00247 } 00248 00249 result = _system->createDSPByType( dsptype, &dsp); 00250 if (result != 0) { 00251 audio_error("Could not create DSP object"); 00252 return NULL; 00253 } 00254 00255 FMOD_RESULT res1=FMOD_OK; 00256 FMOD_RESULT res2=FMOD_OK; 00257 FMOD_RESULT res3=FMOD_OK; 00258 FMOD_RESULT res4=FMOD_OK; 00259 FMOD_RESULT res5=FMOD_OK; 00260 FMOD_RESULT res6=FMOD_OK; 00261 FMOD_RESULT res7=FMOD_OK; 00262 FMOD_RESULT res8=FMOD_OK; 00263 00264 switch (conf._type) { 00265 case FilterProperties::FT_lowpass: 00266 res1=dsp->setParameter(FMOD_DSP_LOWPASS_CUTOFF, conf._a); 00267 res2=dsp->setParameter(FMOD_DSP_LOWPASS_RESONANCE, conf._b); 00268 break; 00269 case FilterProperties::FT_highpass: 00270 res1=dsp->setParameter(FMOD_DSP_HIGHPASS_CUTOFF, conf._a); 00271 res2=dsp->setParameter(FMOD_DSP_HIGHPASS_RESONANCE, conf._b); 00272 break; 00273 case FilterProperties::FT_echo: 00274 res1=dsp->setParameter(FMOD_DSP_ECHO_DRYMIX, conf._a); 00275 res2=dsp->setParameter(FMOD_DSP_ECHO_WETMIX, conf._b); 00276 res3=dsp->setParameter(FMOD_DSP_ECHO_DELAY, conf._c); 00277 res4=dsp->setParameter(FMOD_DSP_ECHO_DECAYRATIO, conf._d); 00278 break; 00279 case FilterProperties::FT_flange: 00280 res1=dsp->setParameter(FMOD_DSP_FLANGE_DRYMIX, conf._a); 00281 res2=dsp->setParameter(FMOD_DSP_FLANGE_WETMIX, conf._b); 00282 res3=dsp->setParameter(FMOD_DSP_FLANGE_DEPTH, conf._c); 00283 res4=dsp->setParameter(FMOD_DSP_FLANGE_RATE, conf._d); 00284 break; 00285 case FilterProperties::FT_distort: 00286 res1=dsp->setParameter(FMOD_DSP_DISTORTION_LEVEL, conf._a); 00287 break; 00288 case FilterProperties::FT_normalize: 00289 res1=dsp->setParameter(FMOD_DSP_NORMALIZE_FADETIME, conf._a); 00290 res2=dsp->setParameter(FMOD_DSP_NORMALIZE_THRESHHOLD,conf._b); 00291 res3=dsp->setParameter(FMOD_DSP_NORMALIZE_MAXAMP, conf._c); 00292 break; 00293 case FilterProperties::FT_parameq: 00294 res1=dsp->setParameter(FMOD_DSP_PARAMEQ_CENTER, conf._a); 00295 res2=dsp->setParameter(FMOD_DSP_PARAMEQ_BANDWIDTH, conf._b); 00296 res3=dsp->setParameter(FMOD_DSP_PARAMEQ_GAIN, conf._c); 00297 break; 00298 case FilterProperties::FT_pitchshift: 00299 res1=dsp->setParameter(FMOD_DSP_PITCHSHIFT_PITCH, conf._a); 00300 res2=dsp->setParameter(FMOD_DSP_PITCHSHIFT_FFTSIZE, conf._b); 00301 res3=dsp->setParameter(FMOD_DSP_PITCHSHIFT_OVERLAP, conf._c); 00302 break; 00303 case FilterProperties::FT_chorus: 00304 res1=dsp->setParameter(FMOD_DSP_CHORUS_DRYMIX, conf._a); 00305 res2=dsp->setParameter(FMOD_DSP_CHORUS_WETMIX1, conf._b); 00306 res3=dsp->setParameter(FMOD_DSP_CHORUS_WETMIX2, conf._c); 00307 res4=dsp->setParameter(FMOD_DSP_CHORUS_WETMIX3, conf._d); 00308 res5=dsp->setParameter(FMOD_DSP_CHORUS_DELAY, conf._e); 00309 res6=dsp->setParameter(FMOD_DSP_CHORUS_RATE, conf._f); 00310 res7=dsp->setParameter(FMOD_DSP_CHORUS_DEPTH, conf._g); 00311 res8=dsp->setParameter(FMOD_DSP_CHORUS_FEEDBACK, conf._h); 00312 break; 00313 case FilterProperties::FT_reverb: 00314 res1=dsp->setParameter(FMOD_DSP_REVERB_DRYMIX, conf._a); 00315 res2=dsp->setParameter(FMOD_DSP_REVERB_WETMIX, conf._b); 00316 res3=dsp->setParameter(FMOD_DSP_REVERB_ROOMSIZE, conf._c); 00317 res4=dsp->setParameter(FMOD_DSP_REVERB_DAMP, conf._d); 00318 res5=dsp->setParameter(FMOD_DSP_REVERB_WIDTH, conf._e); 00319 break; 00320 case FilterProperties::FT_compress: 00321 res1=dsp->setParameter(FMOD_DSP_COMPRESSOR_THRESHOLD, conf._a); 00322 res2=dsp->setParameter(FMOD_DSP_COMPRESSOR_ATTACK, conf._b); 00323 res3=dsp->setParameter(FMOD_DSP_COMPRESSOR_RELEASE, conf._c); 00324 res4=dsp->setParameter(FMOD_DSP_COMPRESSOR_GAINMAKEUP,conf._d); 00325 break; 00326 } 00327 00328 if ((res1!=FMOD_OK)||(res2!=FMOD_OK)||(res3!=FMOD_OK)||(res4!=FMOD_OK)|| 00329 (res5!=FMOD_OK)||(res6!=FMOD_OK)||(res7!=FMOD_OK)||(res8!=FMOD_OK)) { 00330 audio_error("Could not configure DSP"); 00331 dsp->release(); 00332 return NULL; 00333 } 00334 00335 dsp->setUserData(USER_DSP_MAGIC); 00336 00337 return dsp; 00338 } 00339 00340 //////////////////////////////////////////////////////////////////// 00341 // Function: FmodAudioManager::update_dsp_chain 00342 // Access: Public 00343 // Description: Alters a DSP chain to make it match the specified 00344 // configuration. 00345 // 00346 // This is an inadequate implementation - it just 00347 // clears the whole DSP chain and rebuilds it from 00348 // scratch. A better implementation would compare 00349 // the existing DSP chain to the desired one, and 00350 // make incremental changes. This would prevent 00351 // a "pop" sound when the changes are made. 00352 //////////////////////////////////////////////////////////////////// 00353 void FmodAudioManager:: 00354 update_dsp_chain(FMOD::DSP *head, FilterProperties *config) { 00355 ReMutexHolder holder(_lock); 00356 const FilterProperties::ConfigVector &conf = config->get_config(); 00357 FMOD_RESULT result; 00358 00359 while (1) { 00360 int numinputs; 00361 result = head->getNumInputs(&numinputs); 00362 fmod_audio_errcheck("head->getNumInputs()", result); 00363 if (numinputs != 1) { 00364 break; 00365 } 00366 FMOD::DSP *prev; 00367 result = head->getInput(0, &prev, NULL); 00368 fmod_audio_errcheck("head->getInput()", result); 00369 void *userdata; 00370 result = prev->getUserData(&userdata); 00371 fmod_audio_errcheck("prev->getUserData()", result); 00372 if (userdata != USER_DSP_MAGIC) { 00373 break; 00374 } 00375 result = prev->remove(); 00376 fmod_audio_errcheck("prev->remove()", result); 00377 result = prev->release(); 00378 fmod_audio_errcheck("prev->release()", result); 00379 } 00380 00381 for (int i=0; i<(int)(conf.size()); i++) { 00382 FMOD::DSP *dsp = make_dsp(conf[i]); 00383 result = _channelgroup->addDSP(dsp, NULL); 00384 fmod_audio_errcheck("_channelgroup->addDSP()", result); 00385 } 00386 } 00387 00388 //////////////////////////////////////////////////////////////////// 00389 // Function: FmodAudioManager::configure_filters 00390 // Access: Public 00391 // Description: Configure the global DSP filter chain. 00392 // 00393 // FMOD has a relatively powerful DSP 00394 // implementation. It is likely that most 00395 // configurations will be supported. 00396 //////////////////////////////////////////////////////////////////// 00397 bool FmodAudioManager:: 00398 configure_filters(FilterProperties *config) { 00399 ReMutexHolder holder(_lock); 00400 FMOD_RESULT result; 00401 FMOD::DSP *head; 00402 result = _channelgroup->getDSPHead(&head); 00403 if (result != 0) { 00404 audio_error("Getting DSP head: " << FMOD_ErrorString(result) ); 00405 return false; 00406 } 00407 update_dsp_chain(head, config); 00408 return true; 00409 } 00410 00411 //////////////////////////////////////////////////////////////////// 00412 // Function: FmodAudioManager::get_sound 00413 // Access: Public 00414 // Description: This is what creates a sound instance. 00415 //////////////////////////////////////////////////////////////////// 00416 PT(AudioSound) FmodAudioManager:: 00417 get_sound(const string &file_name, bool positional, int) { 00418 ReMutexHolder holder(_lock); 00419 //Needed so People use Panda's Generic UNIX Style Paths for Filename. 00420 //path.to_os_specific() converts it back to the proper OS version later on. 00421 00422 Filename path = file_name; 00423 00424 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00425 vfs->resolve_filename(path, get_model_path()); 00426 00427 // Build a new AudioSound from the audio data. 00428 PT(AudioSound) audioSound = 0; 00429 PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional ); 00430 00431 _all_sounds.insert(fmodAudioSound); 00432 00433 audioSound = fmodAudioSound; 00434 00435 return audioSound; 00436 } 00437 00438 //////////////////////////////////////////////////////////////////// 00439 // Function: FmodAudioManager::get_sound 00440 // Access: Public 00441 // Description: This is what creates a sound instance. 00442 //////////////////////////////////////////////////////////////////// 00443 PT(AudioSound) FmodAudioManager:: 00444 get_sound(MovieAudio *source, bool positional, int) { 00445 nassert_raise("FMOD audio manager does not support MovieAudio sources"); 00446 return NULL; 00447 } 00448 00449 //////////////////////////////////////////////////////////////////// 00450 // Function: FmodAudioManager::getSpeakerSetup() 00451 // Access: Published 00452 // Description: This is to query if you are using a MultiChannel Setup. 00453 //////////////////////////////////////////////////////////////////// 00454 int FmodAudioManager:: 00455 getSpeakerSetup() { 00456 ReMutexHolder holder(_lock); 00457 FMOD_RESULT result; 00458 FMOD_SPEAKERMODE speakerMode; 00459 int returnMode; 00460 00461 result = _system->getSpeakerMode( &speakerMode ); 00462 fmod_audio_errcheck("_system->getSpeakerMode()", result); 00463 00464 switch (speakerMode) { 00465 case FMOD_SPEAKERMODE_RAW: 00466 returnMode = 0; 00467 break; 00468 case FMOD_SPEAKERMODE_MONO: 00469 returnMode = 1; 00470 break; 00471 case FMOD_SPEAKERMODE_STEREO: 00472 returnMode = 2; 00473 break; 00474 case FMOD_SPEAKERMODE_QUAD: 00475 returnMode = 3; 00476 break; 00477 case FMOD_SPEAKERMODE_SURROUND: 00478 returnMode = 4; 00479 break; 00480 case FMOD_SPEAKERMODE_5POINT1: 00481 returnMode = 5; 00482 break; 00483 case FMOD_SPEAKERMODE_7POINT1: 00484 returnMode = 6; 00485 break; 00486 case FMOD_SPEAKERMODE_PROLOGIC: 00487 returnMode = 7; 00488 break; 00489 case FMOD_SPEAKERMODE_MAX: 00490 returnMode = 8; 00491 break; 00492 default: 00493 returnMode = -1; 00494 } 00495 00496 return returnMode; 00497 } 00498 00499 //////////////////////////////////////////////////////////////////// 00500 // Function: FmodAudioManager::setSpeakerSetup() 00501 // Access: Published 00502 // Description: This is to set up FMOD to use a MultiChannel Setup. 00503 // This method is pretty much useless. 00504 // To set a speaker setup in FMOD for Surround Sound, 00505 // stereo, or whatever you have to set the SpeakerMode 00506 // BEFORE you Initialize FMOD. 00507 // Since Panda Inits the FmodAudioManager right when you 00508 // Start it up, you are never given an oppertunity to call 00509 // this function. 00510 // That is why I stuck a BOOL in the CONFIG.PRC file, whichs 00511 // lets you flag if you want to use a Multichannel or not. 00512 // That will set the speaker setup when an instance of this 00513 // class is constructed. 00514 // Still I put this here as a measure of good faith, since you 00515 // can query the speaker setup after everything in Init. 00516 // Also, maybe someone will completely hack Panda someday, in which 00517 // one can init or re-init the AudioManagers after Panda is running. 00518 //////////////////////////////////////////////////////////////////// 00519 void FmodAudioManager:: 00520 setSpeakerSetup(AudioManager::SpeakerModeCategory cat) { 00521 ReMutexHolder holder(_lock); 00522 FMOD_RESULT result; 00523 FMOD_SPEAKERMODE speakerModeType = (FMOD_SPEAKERMODE)cat; 00524 result = _system->setSpeakerMode( speakerModeType); 00525 fmod_audio_errcheck("_system->setSpeakerMode()", result); 00526 } 00527 00528 //////////////////////////////////////////////////////////////////// 00529 // Function: FmodAudioManager::set_volume(PN_stdfloat volume) 00530 // Access: Public 00531 // Description: Sets the volume of the AudioManager. 00532 // It is not an override, but a multiplier. 00533 //////////////////////////////////////////////////////////////////// 00534 void FmodAudioManager:: 00535 set_volume(PN_stdfloat volume) { 00536 ReMutexHolder holder(_lock); 00537 FMOD_RESULT result; 00538 result = _channelgroup->setVolume(volume); 00539 fmod_audio_errcheck("_channelgroup->setVolume()", result); 00540 } 00541 00542 //////////////////////////////////////////////////////////////////// 00543 // Function: FmodAudioManager::get_volume() 00544 // Access: Public 00545 // Description: Returns the AudioManager's volume. 00546 //////////////////////////////////////////////////////////////////// 00547 PN_stdfloat FmodAudioManager:: 00548 get_volume() const { 00549 ReMutexHolder holder(_lock); 00550 float volume; 00551 FMOD_RESULT result; 00552 result = _channelgroup->getVolume(&volume); 00553 fmod_audio_errcheck("_channelgroup->getVolume()", result); 00554 return (PN_stdfloat)volume; 00555 } 00556 00557 //////////////////////////////////////////////////////////////////// 00558 // Function: FmodAudioManager::set_active(bool active) 00559 // Access: Public 00560 // Description: Turn on/off 00561 // Warning: not implemented. 00562 //////////////////////////////////////////////////////////////////// 00563 void FmodAudioManager:: 00564 set_active(bool active) { 00565 ReMutexHolder holder(_lock); 00566 if (_active != active) { 00567 _active = active; 00568 00569 // Tell our AudioSounds to adjust: 00570 for (SoundSet::iterator i = _all_sounds.begin(); 00571 i != _all_sounds.end(); 00572 ++i) { 00573 (*i)->set_active(_active); 00574 } 00575 } 00576 } 00577 00578 //////////////////////////////////////////////////////////////////// 00579 // Function: FmodAudioManager::get_active() 00580 // Access: Public 00581 // Description: 00582 //////////////////////////////////////////////////////////////////// 00583 bool FmodAudioManager:: 00584 get_active() const { 00585 return _active; 00586 } 00587 00588 //////////////////////////////////////////////////////////////////// 00589 // Function: FmodAudioManager::stop_all_sounds() 00590 // Access: Public 00591 // Description: Stop playback on all sounds managed by this manager. 00592 //////////////////////////////////////////////////////////////////// 00593 void FmodAudioManager:: 00594 stop_all_sounds() { 00595 ReMutexHolder holder(_lock); 00596 // We have to walk through this list with some care, since stopping 00597 // a sound may also remove it from the set (if there are no other 00598 // references to the sound). 00599 SoundSet::iterator i; 00600 i = _all_sounds.begin(); 00601 while (i != _all_sounds.end()) { 00602 SoundSet::iterator next = i; 00603 ++next; 00604 00605 (*i)->stop(); 00606 i = next; 00607 } 00608 } 00609 00610 //////////////////////////////////////////////////////////////////// 00611 // Function: FmodAudioManager::update 00612 // Access: Public 00613 // Description: Perform all per-frame update functions. 00614 //////////////////////////////////////////////////////////////////// 00615 void FmodAudioManager:: 00616 update() { 00617 ReMutexHolder holder(_lock); 00618 _system->update(); 00619 } 00620 00621 //////////////////////////////////////////////////////////////////// 00622 // Function: FmodAudioManager::audio_3d_set_listener_attributes 00623 // Access: Public 00624 // Description: Set position of the "ear" that picks up 3d sounds 00625 // NOW LISTEN UP!!! THIS IS IMPORTANT! 00626 // Both Panda3D and FMOD use a left handed coordinate system. 00627 // But there is a major difference! 00628 // In Panda3D the Y-Axis is going into the Screen and the Z-Axis is going up. 00629 // In FMOD the Y-Axis is going up and the Z-Axis is going into the screen. 00630 // The solution is simple, we just flip the Y and Z axis, as we move coordinates 00631 // from Panda to FMOD and back. 00632 // What does did mean to average Panda user? Nothing, they shouldn't notice anyway. 00633 // But if you decide to do any 3D audio work in here you have to keep it in mind. 00634 // I told you, so you can't say I didn't. 00635 //////////////////////////////////////////////////////////////////// 00636 void FmodAudioManager:: 00637 audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz) { 00638 ReMutexHolder holder(_lock); 00639 audio_debug("FmodAudioManager::audio_3d_set_listener_attributes()"); 00640 00641 FMOD_RESULT result; 00642 00643 _position.x = px; 00644 _position.y = pz; 00645 _position.z = py; 00646 00647 _velocity.x = vx; 00648 _velocity.y = vz; 00649 _velocity.z = vy; 00650 00651 _forward.x = fx; 00652 _forward.y = fz; 00653 _forward.z = fy; 00654 00655 _up.x = ux; 00656 _up.y = uz; 00657 _up.z = uy; 00658 00659 result = _system->set3DListenerAttributes( 0, &_position, &_velocity, &_forward, &_up); 00660 fmod_audio_errcheck("_system->set3DListenerAttributes()", result); 00661 00662 } 00663 00664 //////////////////////////////////////////////////////////////////// 00665 // Function: FmodAudioManager::audio_3d_get_listener_attributes 00666 // Access: Public 00667 // Description: Get position of the "ear" that picks up 3d sounds 00668 //////////////////////////////////////////////////////////////////// 00669 void FmodAudioManager:: 00670 audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz) { 00671 audio_error("audio3dGetListenerAttributes: currently unimplemented. Get the attributes of the attached object"); 00672 00673 } 00674 00675 00676 //////////////////////////////////////////////////////////////////// 00677 // Function: FmodAudioManager::audio_3d_set_distance_factor 00678 // Access: Public 00679 // Description: Set units per meter (Fmod uses meters internally for 00680 // its sound-spacialization calculations) 00681 //////////////////////////////////////////////////////////////////// 00682 void FmodAudioManager:: 00683 audio_3d_set_distance_factor(PN_stdfloat factor) { 00684 ReMutexHolder holder(_lock); 00685 audio_debug( "FmodAudioManager::audio_3d_set_distance_factor( factor= " << factor << ")" ); 00686 00687 FMOD_RESULT result; 00688 00689 _distance_factor = factor; 00690 00691 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor); 00692 fmod_audio_errcheck("_system->set3DSettings()", result); 00693 00694 00695 } 00696 00697 //////////////////////////////////////////////////////////////////// 00698 // Function: FmodAudioManager::audio_3d_get_distance_factor 00699 // Access: Public 00700 // Description: Gets units per meter (Fmod uses meters internally for 00701 // its sound-spacialization calculations) 00702 //////////////////////////////////////////////////////////////////// 00703 PN_stdfloat FmodAudioManager:: 00704 audio_3d_get_distance_factor() const { 00705 audio_debug("FmodAudioManager::audio_3d_get_distance_factor()"); 00706 00707 return _distance_factor; 00708 } 00709 00710 //////////////////////////////////////////////////////////////////// 00711 // Function: FmodAudioManager::audio_3d_set_doppler_factor 00712 // Access: Public 00713 // Description: Exaggerates or diminishes the Doppler effect. 00714 // Defaults to 1.0 00715 //////////////////////////////////////////////////////////////////// 00716 void FmodAudioManager:: 00717 audio_3d_set_doppler_factor(PN_stdfloat factor) { 00718 ReMutexHolder holder(_lock); 00719 audio_debug("FmodAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<")"); 00720 00721 FMOD_RESULT result; 00722 00723 _doppler_factor = factor; 00724 00725 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor); 00726 fmod_audio_errcheck("_system->set3DSettings()", result); 00727 00728 } 00729 00730 //////////////////////////////////////////////////////////////////// 00731 // Function: FmodAudioManager::audio_3d_get_doppler_factor 00732 // Access: Public 00733 // Description: 00734 //////////////////////////////////////////////////////////////////// 00735 PN_stdfloat FmodAudioManager:: 00736 audio_3d_get_doppler_factor() const { 00737 audio_debug("FmodAudioManager::audio_3d_get_doppler_factor()"); 00738 00739 return _doppler_factor; 00740 } 00741 00742 //////////////////////////////////////////////////////////////////// 00743 // Function: FmodAudioManager::audio_3d_set_drop_off_factor 00744 // Access: Public 00745 // Description: Control the effect distance has on audability. 00746 // Defaults to 1.0 00747 //////////////////////////////////////////////////////////////////// 00748 void FmodAudioManager:: 00749 audio_3d_set_drop_off_factor(PN_stdfloat factor) { 00750 ReMutexHolder holder(_lock); 00751 audio_debug("FmodAudioManager::audio_3d_set_drop_off_factor("<<factor<<")"); 00752 00753 FMOD_RESULT result; 00754 00755 _drop_off_factor = factor; 00756 00757 result = _system->set3DSettings( _doppler_factor, _distance_factor, _drop_off_factor); 00758 fmod_audio_errcheck("_system->set3DSettings()", result); 00759 00760 } 00761 00762 //////////////////////////////////////////////////////////////////// 00763 // Function: FmodAudioManager::audio_3d_get_drop_off_factor 00764 // Access: Public 00765 // Description: 00766 //////////////////////////////////////////////////////////////////// 00767 PN_stdfloat FmodAudioManager:: 00768 audio_3d_get_drop_off_factor() const { 00769 ReMutexHolder holder(_lock); 00770 audio_debug("FmodAudioManager::audio_3d_get_drop_off_factor()"); 00771 00772 return _drop_off_factor; 00773 00774 } 00775 00776 00777 00778 //////////////////////////////////////////////////////////////////// 00779 // Function: FmodAudioManager::set_concurrent_sound_limit 00780 // Access: Public 00781 // Description: NOT USED FOR FMOD-EX!!! 00782 //////////////////////////////////////////////////////////////////// 00783 void FmodAudioManager:: 00784 set_concurrent_sound_limit(unsigned int limit) { 00785 00786 } 00787 00788 //////////////////////////////////////////////////////////////////// 00789 // Function: FmodAudioManager::get_concurrent_sound_limit 00790 // Access: Public 00791 // Description: NOT USED FOR FMOD-EX!!! 00792 //////////////////////////////////////////////////////////////////// 00793 unsigned int FmodAudioManager:: 00794 get_concurrent_sound_limit() const { 00795 return 1000000; 00796 } 00797 00798 //////////////////////////////////////////////////////////////////// 00799 // Function: FmodAudioManager::reduce_sounds_playing_to 00800 // Access: Private 00801 // Description: NOT USED FOR FMOD-EX!!! 00802 //////////////////////////////////////////////////////////////////// 00803 void FmodAudioManager:: 00804 reduce_sounds_playing_to(unsigned int count) { 00805 00806 } 00807 00808 00809 //////////////////////////////////////////////////////////////////// 00810 // Function: FmodAudioManager::uncache_sound 00811 // Access: Public 00812 // Description: NOT USED FOR FMOD-EX!!! 00813 // Clears a sound out of the sound cache. 00814 //////////////////////////////////////////////////////////////////// 00815 void FmodAudioManager:: 00816 uncache_sound(const string& file_name) { 00817 audio_debug("FmodAudioManager::uncache_sound(\""<<file_name<<"\")"); 00818 00819 } 00820 00821 00822 //////////////////////////////////////////////////////////////////// 00823 // Function: FmodAudioManager::clear_cache 00824 // Access: Public 00825 // Description: NOT USED FOR FMOD-EX!!! 00826 // Clear out the sound cache. 00827 //////////////////////////////////////////////////////////////////// 00828 void FmodAudioManager:: 00829 clear_cache() { 00830 audio_debug("FmodAudioManager::clear_cache()"); 00831 00832 } 00833 00834 //////////////////////////////////////////////////////////////////// 00835 // Function: FmodAudioManager::set_cache_limit 00836 // Access: Public 00837 // Description: NOT USED FOR FMOD-EX!!! 00838 // Set the number of sounds that the cache can hold. 00839 //////////////////////////////////////////////////////////////////// 00840 void FmodAudioManager:: 00841 set_cache_limit(unsigned int count) { 00842 audio_debug("FmodAudioManager::set_cache_limit(count="<<count<<")"); 00843 00844 } 00845 00846 //////////////////////////////////////////////////////////////////// 00847 // Function: FmodAudioManager::get_cache_limit 00848 // Access: Public 00849 // Description: NOT USED FOR FMOD-EX!!! 00850 // Gets the number of sounds that the cache can hold. 00851 //////////////////////////////////////////////////////////////////// 00852 unsigned int FmodAudioManager:: 00853 get_cache_limit() const { 00854 audio_debug("FmodAudioManager::get_cache_limit() returning "); 00855 //return _cache_limit; 00856 return 0; 00857 } 00858 00859 #endif //]