Panda3D

openalAudioManager.cxx

00001 // Filename: openalAudioManager.cxx
00002 // Created by:  Ben Buchwald <bb2@alumni.cmu.edu>
00003 //
00004 //
00005 ////////////////////////////////////////////////////////////////////
00006 //
00007 // PANDA 3D SOFTWARE
00008 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00009 //
00010 // All use of this software is subject to the terms of the revised BSD
00011 // license.  You should have received a copy of this license along
00012 // with this source code in a file named "LICENSE."
00013 //
00014 ////////////////////////////////////////////////////////////////////
00015 
00016 #include "pandabase.h"
00017 
00018 #ifdef HAVE_OPENAL //[
00019 
00020 //Panda headers.
00021 #include "config_audio.h"
00022 #include "config_util.h"
00023 #include "config_express.h"
00024 #include "openalAudioManager.h"
00025 #include "openalAudioSound.h"
00026 #include "virtualFileSystem.h"
00027 #include "movieAudio.h"
00028 
00029 #include <algorithm>
00030 
00031 TypeHandle OpenALAudioManager::_type_handle;
00032 
00033 int OpenALAudioManager::_active_managers = 0;
00034 bool OpenALAudioManager::_openal_active = false;
00035 ALCdevice* OpenALAudioManager::_device = NULL;
00036 ALCcontext* OpenALAudioManager::_context = NULL;
00037 
00038 // This is the list of all OpenALAudioManager objects in the world.  It
00039 // must be a pointer rather than a concrete object, so it won't be
00040 // destructed at exit time before we're done removing things from it.
00041 OpenALAudioManager::Managers *OpenALAudioManager::_managers = NULL;
00042 
00043 OpenALAudioManager::SourceCache *OpenALAudioManager::_al_sources = NULL;
00044 
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 // Central dispatcher for audio errors.
00048 ////////////////////////////////////////////////////////////////////
00049 void al_audio_errcheck(const char *context) {
00050   ALenum result = alGetError();
00051   if (result != AL_NO_ERROR) {
00052     audio_error(context << ": " << alGetString(result) );
00053   }
00054 }
00055 
00056 void alc_audio_errcheck(const char *context,ALCdevice* device) {
00057   ALCenum result = alcGetError(device);
00058   if (result != ALC_NO_ERROR) {
00059     audio_error(context << ": " << alcGetString(device,result) );
00060   }
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: Create_OpenALAudioManager
00065 //       Access: Private
00066 //  Description: Factory Function
00067 ////////////////////////////////////////////////////////////////////
00068 AudioManager *Create_OpenALAudioManager() {
00069   audio_debug("Create_OpenALAudioManager()");
00070   return new OpenALAudioManager;
00071 }
00072 
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: OpenALAudioManager::Constructor
00076 //       Access: Public
00077 //  Description: 
00078 ////////////////////////////////////////////////////////////////////
00079 OpenALAudioManager::
00080 OpenALAudioManager() {
00081   if (_managers == (Managers *)NULL) {
00082     _managers = new Managers;
00083     _al_sources = new SourceCache;
00084   }
00085 
00086   _managers->insert(this);
00087 
00088   _cleanup_required = true;
00089   _active = audio_active;
00090   _volume = audio_volume;
00091   _play_rate = 1.0f;
00092   
00093   _cache_limit = audio_cache_limit;
00094 
00095   _concurrent_sound_limit = 0;
00096   _is_valid = true;
00097 
00098   //Init 3D attributes
00099   _distance_factor = 3.28;
00100   _drop_off_factor = 1;
00101 
00102   _position[0] = 0;
00103   _position[1] = 0;
00104   _position[2] = 0;
00105 
00106   _velocity[0] = 0;
00107   _velocity[1] = 0;
00108   _velocity[2] = 0;
00109 
00110   _forward_up[0] = 0;
00111   _forward_up[1] = 0;
00112   _forward_up[2] = 0;
00113   _forward_up[3] = 0;
00114   _forward_up[4] = 0;
00115   _forward_up[5] = 0;
00116 
00117   // Initialization
00118   if (_active_managers==0 || !_openal_active) {
00119     _device = alcOpenDevice(NULL); // select the "preferred device"
00120     if (!_device) {
00121       // this is a unique kind of error
00122       audio_error("OpenALAudioManager: alcOpenDevice(NULL): ALC couldn't open device");
00123     } else {
00124       alcGetError(_device); // clear errors
00125       _context=alcCreateContext(_device,NULL);
00126       alc_audio_errcheck("alcCreateContext(_device,NULL)",_device);
00127       if (_context!=NULL) {
00128         _openal_active = true;
00129       }
00130     }
00131   }
00132   // We increment _active_managers regardless of possible errors above.
00133   // The shutdown call will do the right thing when it's called,
00134   // either way.
00135   ++_active_managers;
00136   nassertv(_active_managers>0);
00137 
00138   if (!_device || !_context) {
00139     audio_error("OpenALAudioManager: No open device or context");
00140     _is_valid = false;
00141   } else {
00142     alcGetError(_device); // clear errors
00143     alcMakeContextCurrent(_context);
00144     alc_audio_errcheck("alcMakeContextCurrent(_context)",_device);
00145 
00146 
00147     // set 3D sound characteristics as they are given in the configrc
00148     audio_3d_set_doppler_factor(audio_doppler_factor);
00149     audio_3d_set_distance_factor(audio_distance_factor);
00150     audio_3d_set_drop_off_factor(audio_drop_off_factor);
00151   }
00152 
00153   audio_cat->debug() << "ALC_DEVICE_SPECIFIER:" << alcGetString(_device, ALC_DEVICE_SPECIFIER) << endl;    
00154   audio_cat->debug() << "AL_RENDERER:" << alGetString(AL_RENDERER) << endl;
00155   audio_cat->debug() << "AL_VENDOR:" << alGetString(AL_VENDOR) << endl;
00156   audio_cat->debug() << "AL_VERSION:" << alGetString(AL_VERSION) << endl;
00157 
00158 }
00159 
00160 ////////////////////////////////////////////////////////////////////
00161 //     Function: OpenALAudioManager::Destructor
00162 //       Access: Public
00163 //  Description: 
00164 ////////////////////////////////////////////////////////////////////
00165 OpenALAudioManager::
00166 ~OpenALAudioManager() {
00167   nassertv(_managers != (Managers *)NULL);
00168   Managers::iterator mi = _managers->find(this);
00169   nassertv(mi != _managers->end());
00170   _managers->erase(mi);
00171   cleanup();
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: OpenALAudioManager::shutdown
00176 //       Access: Published, Virtual
00177 //  Description: Call this at exit time to shut down the audio system.
00178 //               This will invalidate all currently-active
00179 //               AudioManagers and AudioSounds in the system.  If you
00180 //               change your mind and want to play sounds again, you
00181 //               will have to recreate all of these objects.
00182 ////////////////////////////////////////////////////////////////////
00183 void OpenALAudioManager::
00184 shutdown() {
00185   if (_managers != (Managers *)NULL) {
00186     Managers::iterator mi;
00187     for (mi = _managers->begin(); mi != _managers->end(); ++mi) {
00188       (*mi)->cleanup();
00189     }
00190   }
00191 
00192   nassertv(_active_managers == 0);
00193 }
00194 
00195 
00196 ////////////////////////////////////////////////////////////////////
00197 //     Function: OpenALAudioManager::is_valid
00198 //       Access:
00199 //  Description: This is mostly for debugging, but it it could be
00200 //               used to detect errors in a release build if you
00201 //               don't mind the cpu cost.
00202 ////////////////////////////////////////////////////////////////////
00203 bool OpenALAudioManager::
00204 is_valid() {
00205   return _is_valid;
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: OpenALAudioManager::make_current
00210 //       Access: Private
00211 //  Description: This makes this manager's OpenAL context the 
00212 //         current context. Needed before any parameter sets.
00213 ////////////////////////////////////////////////////////////////////
00214 void OpenALAudioManager::
00215 make_current() const {
00216   // Since we only use one context, this is now a no-op.
00217 }
00218 
00219 ////////////////////////////////////////////////////////////////////
00220 //     Function: OpenALAudioManager::can_use_audio
00221 //       Access: Private
00222 //  Description: Returns true if the specified MovieAudioCursor
00223 //               can be used by this AudioManager.  Mostly, this
00224 //               involves checking whether or not the format is
00225 //               implemented/supported.
00226 ////////////////////////////////////////////////////////////////////
00227 bool OpenALAudioManager::
00228 can_use_audio(MovieAudioCursor *source) {
00229   int channels = source->audio_channels();
00230   if ((channels != 1)&&(channels != 2)) {
00231     audio_error("Currently, only mono and stereo are supported.");
00232     return false;
00233   }
00234   return true;
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: OpenALAudioManager::should_load_audio
00239 //       Access: Private
00240 //  Description: Returns true if the specified MovieAudio should be
00241 //               cached into RAM.  A lot of conditions have to be met
00242 //               in order to allow caching - if any are not met,
00243 //               the file will be streamed.
00244 ////////////////////////////////////////////////////////////////////
00245 bool OpenALAudioManager::
00246 should_load_audio(MovieAudioCursor *source, int mode) {
00247   if (mode == SM_stream) {
00248     // If the user asked for streaming, give him streaming.
00249     return false;
00250   }
00251   if (source->get_source()->get_filename().empty()) {
00252     // Non-files cannot be preloaded.
00253     return false;
00254   }
00255   if (source->ready() != 0x40000000) {
00256     // Streaming sources cannot be preloaded.
00257     return false;
00258   }
00259   if (source->length() > 3600.0) {
00260     // Anything longer than an hour cannot be preloaded.
00261     return false;
00262   }
00263   int channels = source->audio_channels();
00264   int samples = (int)(source->length() * source->audio_rate());
00265   int bytes = samples * channels * 2;
00266   if ((mode == SM_heuristic)&&(bytes > audio_preload_threshold)) {
00267     // In heuristic mode, if file is long, stream it.
00268     return false;
00269   }
00270   return true;
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: OpenALAudioManager::get_sound_data
00275 //       Access: Private
00276 //  Description: Obtains a SoundData for the specified sound.
00277 //
00278 //               When you are done with the SoundData, you need
00279 //               to decrement the client count.
00280 ////////////////////////////////////////////////////////////////////
00281 OpenALAudioManager::SoundData *OpenALAudioManager::
00282 get_sound_data(MovieAudio *movie, int mode) {
00283   const Filename &path = movie->get_filename();
00284   
00285   // Search for an already-cached sample or an already-opened stream.
00286   if (!path.empty()) {
00287     
00288     if (mode != SM_stream) {
00289       SampleCache::iterator lsmi=_sample_cache.find(path);
00290       if (lsmi != _sample_cache.end()) {
00291         SoundData *sd = (*lsmi).second;
00292         increment_client_count(sd);
00293         return sd;
00294       }
00295     }
00296 
00297     if (mode != SM_sample) {
00298       ExpirationQueue::iterator exqi;
00299       for (exqi=_expiring_streams.begin(); exqi!=_expiring_streams.end(); exqi++) {
00300         SoundData *sd = (SoundData*)(*exqi);
00301         if (sd->_movie->get_filename() == path) {
00302           increment_client_count(sd);
00303           return sd;
00304         }
00305       }
00306     }
00307   }
00308   
00309   PT(MovieAudioCursor) stream = movie->open();
00310   if (stream == 0) {
00311     audio_error("Cannot open file: "<<path);
00312     return NULL;
00313   }
00314   
00315   if (!can_use_audio(stream)) {
00316     audio_error("File is not in usable format: "<<path);
00317     return NULL;
00318   }
00319   
00320   SoundData *sd = new SoundData();
00321   sd->_client_count = 1;
00322   sd->_manager  = this;
00323   sd->_movie    = movie;
00324   sd->_rate     = stream->audio_rate();
00325   sd->_channels = stream->audio_channels();
00326   sd->_length   = stream->length();
00327   audio_debug("Creating: " << sd->_movie->get_filename().get_basename());
00328   audio_debug("  - Rate: " << sd->_rate);
00329   audio_debug("  - Channels: " << sd->_channels);
00330   audio_debug("  - Length: " << sd->_length);
00331 
00332   if (should_load_audio(stream, mode)) {
00333     audio_debug(path.get_basename() << ": loading as sample");
00334     make_current();
00335     alGetError(); // clear errors
00336     sd->_sample = 0;
00337     alGenBuffers(1, &sd->_sample);
00338     al_audio_errcheck("alGenBuffers");
00339     if (sd->_sample == 0) {
00340       audio_error("Could not create an OpenAL buffer object");
00341       delete sd;
00342       return NULL;
00343     }
00344     int channels = stream->audio_channels();
00345     int samples = (int)(stream->length() * stream->audio_rate());
00346     PN_int16 *data = new PN_int16[samples * channels];
00347     stream->read_samples(samples, data);
00348     alBufferData(sd->_sample,
00349                  (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
00350                  data, samples * channels * 2, stream->audio_rate());
00351     int err = alGetError();
00352     if (err != AL_NO_ERROR) {
00353       audio_error("could not fill OpenAL buffer object with data");
00354       delete sd;
00355       return NULL;
00356     }
00357     _sample_cache.insert(SampleCache::value_type(path, sd));
00358   } else {
00359     audio_debug(path.get_basename() << ": loading as stream");
00360     sd->_stream = stream;
00361   }
00362   
00363   return sd;
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: OpenALAudioManager::get_sound
00368 //       Access: Public
00369 //  Description: This is what creates a sound instance.
00370 ////////////////////////////////////////////////////////////////////
00371 PT(AudioSound) OpenALAudioManager::
00372 get_sound(MovieAudio *sound, bool positional, int mode) {
00373   if(!is_valid()) {
00374     return get_null_sound();
00375   }
00376   PT(OpenALAudioSound) oas = 
00377     new OpenALAudioSound(this, sound, positional, mode);
00378   
00379   _all_sounds.insert(oas);
00380   PT(AudioSound) res = (AudioSound*)(OpenALAudioSound*)oas;
00381   return res;
00382 }
00383 
00384 ////////////////////////////////////////////////////////////////////
00385 //     Function: OpenALAudioManager::get_sound
00386 //       Access: Public
00387 //  Description: This is what creates a sound instance.
00388 ////////////////////////////////////////////////////////////////////
00389 PT(AudioSound) OpenALAudioManager::
00390 get_sound(const string &file_name, bool positional, int mode) {
00391   if(!is_valid()) {
00392     return get_null_sound();
00393   }
00394   
00395   Filename path = file_name;
00396   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00397   vfs->resolve_filename(path, get_model_path());
00398   
00399   if (path.empty()) {
00400     audio_error("get_sound - invalid filename");
00401     return NULL;
00402   }
00403 
00404   PT(MovieAudio) mva = MovieAudio::get(path);
00405   
00406   PT(OpenALAudioSound) oas = 
00407     new OpenALAudioSound(this, mva, positional, mode);
00408   
00409   _all_sounds.insert(oas);
00410   PT(AudioSound) res = (AudioSound*)(OpenALAudioSound*)oas;
00411   return res;
00412 }
00413 
00414 ////////////////////////////////////////////////////////////////////
00415 //     Function: OpenALAudioManager::uncache_sound
00416 //       Access: Public
00417 //  Description: Deletes a sample from the expiration queues.
00418 //               If the sound is actively in use, then the sound
00419 //               cannot be deleted, and this function has no effect.
00420 ////////////////////////////////////////////////////////////////////
00421 void OpenALAudioManager::
00422 uncache_sound(const string& file_name) {
00423   assert(is_valid());
00424   Filename path = file_name;
00425   
00426   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00427   vfs->resolve_filename(path, get_model_path());
00428 
00429   SampleCache::iterator sci = _sample_cache.find(path);
00430   if (sci != _sample_cache.end()) {
00431     SoundData *sd = (*sci).second;
00432     if (sd->_client_count == 0) {
00433       _expiring_samples.erase(sd->_expire);
00434       _sample_cache.erase(sci);
00435       delete sd;
00436     }
00437   }
00438 }
00439 
00440 ////////////////////////////////////////////////////////////////////
00441 //     Function: OpenALAudioManager::clear_cache
00442 //       Access: Public
00443 //  Description: Clear out the sound cache.
00444 ////////////////////////////////////////////////////////////////////
00445 void OpenALAudioManager::
00446 clear_cache() {
00447   discard_excess_cache(0);
00448 }
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: OpenALAudioManager::set_cache_limit
00452 //       Access: Public
00453 //  Description: Set the number of sounds that the cache can hold.
00454 ////////////////////////////////////////////////////////////////////
00455 void OpenALAudioManager::
00456 set_cache_limit(unsigned int count) {
00457   _cache_limit=count;
00458   discard_excess_cache(count);
00459 }
00460 
00461 ////////////////////////////////////////////////////////////////////
00462 //     Function: OpenALAudioManager::get_cache_limit
00463 //       Access: Public
00464 //  Description:
00465 ////////////////////////////////////////////////////////////////////
00466 unsigned int OpenALAudioManager::
00467 get_cache_limit() const {
00468   return _cache_limit;
00469 }
00470 
00471 ////////////////////////////////////////////////////////////////////
00472 //     Function: OpenALAudioManager::release_sound
00473 //       Access: Public
00474 //  Description:
00475 ////////////////////////////////////////////////////////////////////
00476 void OpenALAudioManager::
00477 release_sound(OpenALAudioSound* audioSound) {
00478   AllSounds::iterator ai = _all_sounds.find(audioSound);
00479   if (ai != _all_sounds.end()) {
00480     _all_sounds.erase(ai);
00481   }
00482 }
00483 
00484 ////////////////////////////////////////////////////////////////////
00485 //     Function: OpenALAudioManager::set_volume(float volume)
00486 //       Access: Public
00487 //  Description: 
00488 //        Sets listener gain
00489 ////////////////////////////////////////////////////////////////////
00490 void OpenALAudioManager::set_volume(float volume) {
00491   if (_volume!=volume) {
00492     _volume = volume;
00493 
00494     // Tell our AudioSounds to adjust:
00495     AllSounds::iterator i=_all_sounds.begin();
00496     for (; i!=_all_sounds.end(); ++i) {
00497       (**i).set_volume((**i).get_volume());
00498     }
00499 
00500     /* 
00501     // this was neat alternative to the above look
00502     // when we had a seperate context for each manager
00503     make_current();
00504 
00505     alGetError(); // clear errors
00506     alListenerf(AL_GAIN,(ALfloat)_volume);
00507     al_audio_errcheck("alListerf(AL_GAIN)");*/
00508   }
00509 }
00510 
00511 ////////////////////////////////////////////////////////////////////
00512 //     Function: OpenALAudioManager::get_volume()
00513 //       Access: Public
00514 //  Description: 
00515 //        Gets listener gain
00516 ////////////////////////////////////////////////////////////////////
00517 float OpenALAudioManager::
00518 get_volume() const {
00519   return _volume;
00520 }
00521 
00522 ////////////////////////////////////////////////////////////////////
00523 //     Function: OpenALAudioManager::set_play_rate
00524 //       Access: Public
00525 //  Description: set the overall play rate
00526 ////////////////////////////////////////////////////////////////////
00527 void OpenALAudioManager::
00528 set_play_rate(float play_rate) {
00529   if (_play_rate!=play_rate) {
00530     _play_rate = play_rate;
00531     // Tell our AudioSounds to adjust:
00532     AllSounds::iterator i=_all_sounds.begin();
00533     for (; i!=_all_sounds.end(); ++i) {
00534       (**i).set_play_rate((**i).get_play_rate());
00535     }
00536   }
00537 }
00538 
00539 ////////////////////////////////////////////////////////////////////
00540 //     Function: OpenALAudioManager::get_play_rate
00541 //       Access: Public
00542 //  Description: get the overall speed/pitch/play rate
00543 ////////////////////////////////////////////////////////////////////
00544 float OpenALAudioManager::
00545 get_play_rate() const {
00546   return _play_rate;
00547 }
00548 
00549 ////////////////////////////////////////////////////////////////////
00550 //     Function: OpenALAudioManager::set_active(bool active)
00551 //       Access: Public
00552 //  Description: Turn on/off
00553 //               Warning: not implemented.
00554 ////////////////////////////////////////////////////////////////////
00555 void OpenALAudioManager::
00556 set_active(bool active) {
00557   if (_active!=active) {
00558     _active=active;
00559     // Tell our AudioSounds to adjust:
00560     AllSounds::iterator i=_all_sounds.begin();
00561     for (; i!=_all_sounds.end(); ++i) {
00562       (**i).set_active(_active);
00563     }
00564   }
00565 }
00566 
00567 ////////////////////////////////////////////////////////////////////
00568 //     Function: OpenALAudioManager::get_active()
00569 //       Access: Public
00570 //  Description: 
00571 ////////////////////////////////////////////////////////////////////
00572 bool OpenALAudioManager::
00573 get_active() const {
00574   return _active;
00575 }
00576 
00577 ////////////////////////////////////////////////////////////////////
00578 //     Function: OpenALAudioManager::audio_3d_set_listener_attributes
00579 //       Access: Public
00580 //  Description: Set position of the "ear" that picks up 3d sounds
00581 //        NOW LISTEN UP!!! THIS IS IMPORTANT!
00582 //        Both Panda3D and OpenAL use a right handed coordinate system.
00583 //        But there is a major difference!
00584 //        In Panda3D the Y-Axis is going into the Screen and the Z-Axis is going up.
00585 //        In OpenAL the Y-Axis is going up and the Z-Axis is coming out of the screen.
00586 //        The solution is simple, we just flip the Y and Z axis and negate the Z, as we move coordinates
00587 //        from Panda to OpenAL and back.
00588 //        What does did mean to average Panda user?  Nothing, they shouldn't notice anyway.
00589 //        But if you decide to do any 3D audio work in here you have to keep it in mind.
00590 //        I told you, so you can't say I didn't.
00591 ////////////////////////////////////////////////////////////////////
00592 void OpenALAudioManager::
00593 audio_3d_set_listener_attributes(float px, float py, float pz, float vx, float vy, float vz, float fx, float fy, float fz, float ux, float uy, float uz) {
00594   _position[0] = px;
00595   _position[1] = pz;
00596   _position[2] = -py; 
00597 
00598   _velocity[0] = vx;
00599   _velocity[1] = vz;
00600   _velocity[2] = -vy;
00601 
00602   _forward_up[0] = fx;
00603   _forward_up[1] = fz;
00604   _forward_up[2] = -fy;
00605 
00606   _forward_up[3] = ux;
00607   _forward_up[4] = uz;
00608   _forward_up[5] = -uy;
00609     
00610   
00611   make_current();
00612 
00613   alGetError(); // clear errors
00614   alListenerfv(AL_POSITION,_position);
00615   al_audio_errcheck("alListerfv(AL_POSITION)");
00616   alListenerfv(AL_VELOCITY,_velocity);
00617   al_audio_errcheck("alListerfv(AL_VELOCITY)");
00618   alListenerfv(AL_ORIENTATION,_forward_up);
00619   al_audio_errcheck("alListerfv(AL_ORIENTATION)");
00620 }
00621 
00622 ////////////////////////////////////////////////////////////////////
00623 //     Function: OpenALAudioManager::audio_3d_get_listener_attributes
00624 //       Access: Public
00625 //  Description: Get position of the "ear" that picks up 3d sounds
00626 ////////////////////////////////////////////////////////////////////
00627 void OpenALAudioManager::
00628 audio_3d_get_listener_attributes(float *px, float *py, float *pz, float *vx, float *vy, float *vz, float *fx, float *fy, float *fz, float *ux, float *uy, float *uz) {
00629   *px = _position[0];
00630   *py = -_position[2];
00631   *pz = _position[1];
00632 
00633   *vx = _velocity[0];
00634   *vy = -_velocity[2];
00635   *vz = _velocity[1];
00636 
00637   *fx = _forward_up[0];
00638   *fy = -_forward_up[2];
00639   *fz = _forward_up[1];
00640   
00641   *ux = _forward_up[3];
00642   *uy = -_forward_up[5];
00643   *uz = _forward_up[4];
00644 }
00645 
00646 
00647 ////////////////////////////////////////////////////////////////////
00648 //     Function: OpenALAudioManager::audio_3d_set_distance_factor
00649 //       Access: Public
00650 //  Description: Set units per foot
00651 //               WARNING: OpenAL has no distance factor but we use this as a scale
00652 //                        on the min/max distances of sounds to preserve FMOD compatibility.
00653 //                        Also, adjusts the speed of sound to compensate for unit difference.
00654 //                        OpenAL's default speed of sound is 343.3 m/s == 1126.3 ft/s
00655 ////////////////////////////////////////////////////////////////////
00656 void OpenALAudioManager::
00657 audio_3d_set_distance_factor(float factor) {
00658   _distance_factor = factor;
00659 
00660   make_current();
00661 
00662   alGetError(); // clear errors
00663 
00664   if (_distance_factor>0) {
00665     alSpeedOfSound(1126.3*_distance_factor);
00666     al_audio_errcheck("alSpeedOfSound()");
00667     // resets the doppler factor to the correct setting in case it was set to 0.0 by a distance_factor<=0.0
00668     alDopplerFactor(_doppler_factor);
00669     al_audio_errcheck("alDopplerFactor()");
00670   } else {
00671     audio_debug("can't set speed of sound if distance_factor <=0.0, setting doppler factor to 0.0 instead");
00672     alDopplerFactor(0.0);
00673     al_audio_errcheck("alDopplerFactor()");
00674   }
00675 
00676   AllSounds::iterator i=_all_sounds.begin();
00677   for (; i!=_all_sounds.end(); ++i) {
00678     (**i).set_3d_min_distance((**i).get_3d_min_distance());
00679     (**i).set_3d_max_distance((**i).get_3d_max_distance());
00680   }
00681 }
00682 
00683 ////////////////////////////////////////////////////////////////////
00684 //     Function: OpenALAudioManager::audio_3d_get_distance_factor
00685 //       Access: Public
00686 //  Description: Sets units per foot
00687 ////////////////////////////////////////////////////////////////////
00688 float OpenALAudioManager::
00689 audio_3d_get_distance_factor() const {
00690   return _distance_factor;
00691 }
00692 
00693 ////////////////////////////////////////////////////////////////////
00694 //     Function: OpenALAudioManager::audio_3d_set_doppler_factor
00695 //       Access: Public
00696 //  Description: Exaggerates or diminishes the Doppler effect. 
00697 //               Defaults to 1.0
00698 ////////////////////////////////////////////////////////////////////
00699 void OpenALAudioManager::
00700 audio_3d_set_doppler_factor(float factor) {
00701   _doppler_factor = factor;
00702 
00703   make_current();
00704   
00705   alGetError(); // clear errors
00706   alDopplerFactor(_doppler_factor);
00707   al_audio_errcheck("alDopplerFactor()");
00708 }
00709 
00710 ////////////////////////////////////////////////////////////////////
00711 //     Function: OpenALAudioManager::audio_3d_get_doppler_factor
00712 //       Access: Public
00713 //  Description: 
00714 ////////////////////////////////////////////////////////////////////
00715 float OpenALAudioManager::
00716 audio_3d_get_doppler_factor() const {
00717   return _doppler_factor;
00718 }
00719 
00720 ////////////////////////////////////////////////////////////////////
00721 //     Function: OpenALAudioManager::audio_3d_set_drop_off_factor
00722 //       Access: Public
00723 //  Description: Control the effect distance has on audability.
00724 //               Defaults to 1.0
00725 ////////////////////////////////////////////////////////////////////
00726 void OpenALAudioManager::
00727 audio_3d_set_drop_off_factor(float factor) {
00728   _drop_off_factor = factor;
00729 
00730   AllSounds::iterator i=_all_sounds.begin();
00731   for (; i!=_all_sounds.end(); ++i) {
00732     (**i).set_3d_drop_off_factor((**i).get_3d_drop_off_factor());
00733   }
00734 }
00735 
00736 ////////////////////////////////////////////////////////////////////
00737 //     Function: OpenALAudioManager::audio_3d_get_drop_off_factor
00738 //       Access: Public
00739 //  Description: 
00740 ////////////////////////////////////////////////////////////////////
00741 float OpenALAudioManager::
00742 audio_3d_get_drop_off_factor() const {
00743   return _drop_off_factor;
00744 }
00745 
00746 ////////////////////////////////////////////////////////////////////
00747 //     Function: OpenALAudioManager::starting_sound
00748 //       Access: 
00749 //  Description: Inform the manager that a sound is about to play.
00750 //               The manager will add this sound to the table of
00751 //               sounds that are playing, and will allocate a source
00752 //               to this sound.
00753 ////////////////////////////////////////////////////////////////////
00754 void OpenALAudioManager::
00755 starting_sound(OpenALAudioSound* audio) {
00756   ALuint source=0;
00757   
00758   // If the sound already has a source, we don't need to do anything.
00759   if (audio->_source) {
00760     return;
00761   }
00762 
00763   // first give all sounds that have finished a chance to stop, so that these get stopped first
00764   update();
00765 
00766   if (_concurrent_sound_limit) {
00767     reduce_sounds_playing_to(_concurrent_sound_limit-1); // because we're about to add one
00768   }
00769   
00770   // get a source from the source pool or create a new source
00771   if (_al_sources->empty()) {
00772     make_current();
00773     alGetError(); // clear errors
00774     alGenSources(1,&source);
00775     ALenum result = alGetError();
00776     if (result!=AL_NO_ERROR) {
00777       audio_error("alGenSources(): " << alGetString(result) );
00778       // if we can't create any more sources, set stop a sound to free a source
00779       reduce_sounds_playing_to(_sounds_playing.size()-1);
00780       source = 0;
00781     }
00782   }
00783   // get a source from the source bool if we didn't just allocate one
00784   if (!source && !_al_sources->empty()) {
00785     source = *(_al_sources->begin());
00786     _al_sources->erase(source);
00787   }
00788 
00789   audio->_source = source;
00790   
00791   if (source)
00792     _sounds_playing.insert(audio);
00793 }
00794 
00795 ////////////////////////////////////////////////////////////////////
00796 //     Function: OpenALAudioManager::stopping_sound
00797 //       Access: 
00798 //  Description: Inform the manager that a sound is finished or 
00799 //               someone called stop on the sound (this should not
00800 //               be called if a sound is only paused).
00801 ////////////////////////////////////////////////////////////////////
00802 void OpenALAudioManager::
00803 stopping_sound(OpenALAudioSound* audio) {
00804   if (audio->_source) {
00805     _al_sources->insert(audio->_source);
00806     audio->_source = 0;
00807   }
00808   _sounds_playing.erase(audio); // This could cause the sound to destruct.
00809 }
00810 
00811 ////////////////////////////////////////////////////////////////////
00812 //     Function: OpenALAudioManager::set_concurrent_sound_limit
00813 //       Access: Public
00814 //  Description: 
00815 ////////////////////////////////////////////////////////////////////
00816 void OpenALAudioManager::
00817 set_concurrent_sound_limit(unsigned int limit) {
00818   _concurrent_sound_limit = limit;
00819   reduce_sounds_playing_to(_concurrent_sound_limit);
00820 }
00821 
00822 ////////////////////////////////////////////////////////////////////
00823 //     Function: OpenALAudioManager::get_concurrent_sound_limit
00824 //       Access: Public
00825 //  Description: 
00826 ////////////////////////////////////////////////////////////////////
00827 unsigned int OpenALAudioManager::
00828 get_concurrent_sound_limit() const {
00829   return _concurrent_sound_limit;
00830 }
00831 
00832 ////////////////////////////////////////////////////////////////////
00833 //     Function: OpenALAudioManager::reduce_sounds_playing_to
00834 //       Access: Private
00835 //  Description: 
00836 ////////////////////////////////////////////////////////////////////
00837 void OpenALAudioManager::
00838 reduce_sounds_playing_to(unsigned int count) {
00839   // first give all sounds that have finished a chance to stop, so that these get stopped first
00840   update();
00841 
00842   int limit = _sounds_playing.size() - count;
00843   while (limit-- > 0) {
00844     SoundsPlaying::iterator sound = _sounds_playing.begin();
00845     assert(sound != _sounds_playing.end());
00846     // When the user stops a sound, there is still a PT in the
00847     // user's hand.  When we stop a sound here, however, 
00848     // this can remove the last PT.  This can cause an ugly
00849     // recursion where stop calls the destructor, and the
00850     // destructor calls stop.  To avoid this, we create
00851     // a temporary PT, stop the sound, and then release the PT.
00852     PT(OpenALAudioSound) s = (*sound);
00853     s->stop();
00854   }
00855 }
00856 
00857 ////////////////////////////////////////////////////////////////////
00858 //     Function: OpenALAudioManager::stop_all_sounds()
00859 //       Access: Public
00860 //  Description: Stop playback on all sounds managed by this manager.
00861 ////////////////////////////////////////////////////////////////////
00862 void OpenALAudioManager::
00863 stop_all_sounds() {
00864   reduce_sounds_playing_to(0);
00865 }
00866 
00867 ////////////////////////////////////////////////////////////////////
00868 //     Function: OpenALAudioManager::update
00869 //       Access: Public
00870 //  Description: Perform all per-frame update functions.
00871 ////////////////////////////////////////////////////////////////////
00872 void OpenALAudioManager::
00873 update() {
00874 
00875   // See if any of our playing sounds have ended
00876   // we must first collect a seperate list of finished sounds and then
00877   // iterated over those again calling their finished method. We 
00878   // can't call finished() within a loop iterating over _sounds_playing
00879   // since finished() modifies _sounds_playing
00880   SoundsPlaying sounds_finished;
00881 
00882   double rtc = TrueClock::get_global_ptr()->get_short_time();
00883   SoundsPlaying::iterator i=_sounds_playing.begin();
00884   for (; i!=_sounds_playing.end(); ++i) {
00885     OpenALAudioSound *sound = (*i);
00886     sound->pull_used_buffers();
00887     sound->push_fresh_buffers();
00888     sound->restart_stalled_audio();
00889     sound->cache_time(rtc);
00890     if ((sound->_source == 0)||
00891         ((sound->_stream_queued.size() == 0)&&
00892          (sound->_loops_completed >= sound->_playing_loops))) {
00893       sounds_finished.insert(*i);
00894     }
00895   }
00896   
00897   i=sounds_finished.begin();
00898   for (; i!=sounds_finished.end(); ++i) {
00899     (**i).finished();
00900   }
00901 }
00902 
00903 
00904 ////////////////////////////////////////////////////////////////////
00905 //     Function: OpenALAudioManager::cleanup
00906 //       Access: Private
00907 //  Description: Shuts down the audio manager and releases any
00908 //               resources associated with it.  Also cleans up all
00909 //               AudioSounds created via the manager.
00910 ////////////////////////////////////////////////////////////////////
00911 void OpenALAudioManager::
00912 cleanup() {
00913   if (!_cleanup_required) {
00914     return;
00915   }
00916 
00917   stop_all_sounds();
00918   
00919   AllSounds sounds(_all_sounds);
00920   AllSounds::iterator ai;
00921   for (ai = sounds.begin(); ai != sounds.end(); ++ai) {
00922     (*ai)->cleanup();
00923   }
00924   
00925   clear_cache();
00926   
00927   nassertv(_active_managers > 0);
00928   --_active_managers;
00929 
00930   if (_active_managers == 0) {
00931     if (_openal_active) {
00932       // empty the source cache
00933       int i=0;
00934       ALuint *sources;
00935       sources = new ALuint[_al_sources->size()];
00936       for (SourceCache::iterator si = _al_sources->begin(); si!=_al_sources->end(); ++si) {
00937         sources[i++]=*si;
00938       }
00939       make_current();
00940       alGetError(); // clear errors
00941       alDeleteSources(_al_sources->size(),sources);
00942       al_audio_errcheck("alDeleteSources()");
00943       delete [] sources;
00944       _al_sources->clear();
00945 
00946       // make sure that the context is not current when it is destroyed
00947       alcGetError(_device); // clear errors
00948       alcMakeContextCurrent(NULL);
00949       alc_audio_errcheck("alcMakeContextCurrent(NULL)",_device);
00950       
00951       alcDestroyContext(_context);
00952       alc_audio_errcheck("alcDestroyContext(_context)",_device);
00953       _context = NULL;
00954 
00955       if (_device) {
00956         audio_debug("Going to try to close openAL");
00957         alcCloseDevice(_device);
00958         //alc_audio_errcheck("alcCloseDevice(_device)",_device);
00959         _device = NULL;
00960         audio_debug("openAL Closed");
00961       }
00962 
00963       _openal_active = false;
00964     }
00965   }
00966   _cleanup_required = false;
00967 }
00968 
00969 ////////////////////////////////////////////////////////////////////
00970 //     Function: OpenALAudioManager::SoundData::Constructor
00971 //       Access: Public
00972 //  Description: 
00973 ////////////////////////////////////////////////////////////////////
00974 OpenALAudioManager::SoundData::
00975 SoundData() :
00976   _manager(0),
00977   _movie(0),
00978   _sample(0),
00979   _stream(NULL),
00980   _length(0.0),
00981   _rate(0),
00982   _channels(0),
00983   _client_count(0)
00984 {
00985 }
00986 
00987 ////////////////////////////////////////////////////////////////////
00988 //     Function: OpenALAudioManager::SoundData::Destructor
00989 //       Access: Public
00990 //  Description: 
00991 ////////////////////////////////////////////////////////////////////
00992 OpenALAudioManager::SoundData::
00993 ~SoundData() {
00994   if (_sample != 0) {
00995     if (_manager->_is_valid) {
00996       _manager->make_current();
00997       alDeleteBuffers(1,&_sample);
00998     }
00999     _sample = 0;
01000   }
01001 }
01002 
01003 ////////////////////////////////////////////////////////////////////
01004 //     Function: OpenALAudioManager::increment_client_count
01005 //       Access: Public
01006 //  Description: Increments the SoundData's client count.  Any
01007 //               SoundData that is actively in use (ie, has a client)
01008 //               is removed entirely from the expiration queue.
01009 ////////////////////////////////////////////////////////////////////
01010 void OpenALAudioManager::
01011 increment_client_count(SoundData *sd) {
01012   sd->_client_count += 1;
01013   audio_debug("Incrementing: " << sd->_movie->get_filename().get_basename() << " " << sd->_client_count);
01014   if (sd->_client_count == 1) {
01015     if (sd->_sample) {
01016       _expiring_samples.erase(sd->_expire);
01017     } else {
01018       _expiring_streams.erase(sd->_expire);
01019     }
01020   }
01021 }
01022 
01023 ////////////////////////////////////////////////////////////////////
01024 //     Function: OpenALAudioManager::decrement_client_count
01025 //       Access: Public
01026 //  Description: Decrements the SoundData's client count.  Sounds
01027 //               that are no longer in use (ie, have no clients)
01028 //               go into the expiration queue.  When the expiration
01029 //               queue reaches the cache limit, the first item on
01030 //               the queue is freed.
01031 ////////////////////////////////////////////////////////////////////
01032 void OpenALAudioManager::
01033 decrement_client_count(SoundData *sd) {
01034   sd->_client_count -= 1;
01035   audio_debug("Decrementing: " << sd->_movie->get_filename().get_basename() << " " << sd->_client_count);
01036   if (sd->_client_count == 0) {
01037     if (sd->_sample) {
01038       _expiring_samples.push_back(sd);
01039       sd->_expire = _expiring_samples.end();
01040       sd->_expire--;
01041     } else {
01042       _expiring_streams.push_back(sd);
01043       sd->_expire = _expiring_streams.end();
01044       sd->_expire--;
01045     }
01046     discard_excess_cache(_cache_limit);
01047   }
01048 }
01049 
01050 ////////////////////////////////////////////////////////////////////
01051 //     Function: OpenALAudioManager::discard_excess_cache
01052 //       Access: Public
01053 //  Description: Discards sounds from the sound cache until the
01054 //               number of sounds remaining is under the limit.
01055 ////////////////////////////////////////////////////////////////////
01056 void OpenALAudioManager::
01057 discard_excess_cache(int sample_limit) {
01058   int stream_limit = 5;
01059 
01060   while (((int)_expiring_samples.size()) > sample_limit) {
01061     SoundData *sd = (SoundData*)(_expiring_samples.front());
01062     assert(sd->_client_count == 0);
01063     assert(sd->_expire == _expiring_samples.begin());
01064     _expiring_samples.pop_front();
01065     _sample_cache.erase(_sample_cache.find(sd->_movie->get_filename()));
01066     audio_debug("Expiring: " << sd->_movie->get_filename().get_basename());
01067     delete sd;
01068   }
01069 
01070   while (((int)_expiring_streams.size()) > stream_limit) {
01071     SoundData *sd = (SoundData*)(_expiring_streams.front());
01072     assert(sd->_client_count == 0);
01073     assert(sd->_expire == _expiring_streams.begin());
01074     _expiring_streams.pop_front();
01075     audio_debug("Expiring: " << sd->_movie->get_filename().get_basename());
01076     delete sd;
01077   }
01078 }
01079 
01080 #endif //]
 All Classes Functions Variables Enumerations