Panda3D
 All Classes Functions Variables Enumerations
fmodAudioManager.cxx
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 //]
 All Classes Functions Variables Enumerations