Panda3D
|
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 //]