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