00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "pandabase.h"
00017
00018 #ifdef HAVE_OPENAL //[
00019
00020
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
00041
00042
00043 OpenALAudioManager::Managers *OpenALAudioManager::_managers = NULL;
00044
00045 OpenALAudioManager::SourceCache *OpenALAudioManager::_al_sources = NULL;
00046
00047
00048
00049
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
00067
00068
00069
00070 AudioManager *Create_OpenALAudioManager() {
00071 audio_debug("Create_OpenALAudioManager()");
00072 return new OpenALAudioManager;
00073 }
00074
00075
00076
00077
00078
00079
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
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
00121 if (_active_managers==0 || !_openal_active) {
00122 _device = alcOpenDevice(NULL);
00123 if (!_device) {
00124
00125 audio_error("OpenALAudioManager: alcOpenDevice(NULL): ALC couldn't open device");
00126 } else {
00127 alcGetError(_device);
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
00136
00137
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);
00146 alcMakeContextCurrent(_context);
00147 alc_audio_errcheck("alcMakeContextCurrent(_context)",_device);
00148
00149
00150
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
00165
00166
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
00180
00181
00182
00183
00184
00185
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
00203
00204
00205
00206
00207
00208 bool OpenALAudioManager::
00209 is_valid() {
00210 return _is_valid;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219 void OpenALAudioManager::
00220 make_current() const {
00221
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
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
00245
00246
00247
00248
00249
00250
00251 bool OpenALAudioManager::
00252 should_load_audio(MovieAudioCursor *source, int mode) {
00253 ReMutexHolder holder(_lock);
00254 if (mode == SM_stream) {
00255
00256 return false;
00257 }
00258 if (source->get_source()->get_filename().empty()) {
00259
00260 return false;
00261 }
00262 if (source->ready() != 0x40000000) {
00263
00264 return false;
00265 }
00266 if (source->length() > 3600.0) {
00267
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
00275 return false;
00276 }
00277 return true;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
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
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();
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
00376
00377
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
00395
00396
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
00426
00427
00428
00429
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
00453
00454
00455
00456 void OpenALAudioManager::
00457 clear_cache() {
00458 ReMutexHolder holder(_lock);
00459 discard_excess_cache(0);
00460 }
00461
00462
00463
00464
00465
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
00476
00477
00478
00479 unsigned int OpenALAudioManager::
00480 get_cache_limit() const {
00481 return _cache_limit;
00482 }
00483
00484
00485
00486
00487
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
00500
00501
00502
00503
00504 void OpenALAudioManager::set_volume(PN_stdfloat volume) {
00505 ReMutexHolder holder(_lock);
00506 if (_volume!=volume) {
00507 _volume = volume;
00508
00509
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
00517
00518
00519
00520
00521
00522
00523 }
00524 }
00525
00526
00527
00528
00529
00530
00531
00532 PN_stdfloat OpenALAudioManager::
00533 get_volume() const {
00534 return _volume;
00535 }
00536
00537
00538
00539
00540
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
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
00557
00558
00559
00560 PN_stdfloat OpenALAudioManager::
00561 get_play_rate() const {
00562 return _play_rate;
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 void OpenALAudioManager::
00572 set_active(bool active) {
00573 ReMutexHolder holder(_lock);
00574 if (_active!=active) {
00575 _active=active;
00576
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
00586
00587
00588
00589 bool OpenALAudioManager::
00590 get_active() const {
00591 return _active;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
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();
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
00642
00643
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
00668
00669
00670
00671
00672
00673
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();
00683
00684 if (_distance_factor>0) {
00685 alSpeedOfSound(1126.3*_distance_factor);
00686 al_audio_errcheck("alSpeedOfSound()");
00687
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
00705
00706
00707
00708 PN_stdfloat OpenALAudioManager::
00709 audio_3d_get_distance_factor() const {
00710 return _distance_factor;
00711 }
00712
00713
00714
00715
00716
00717
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();
00727 alDopplerFactor(_doppler_factor);
00728 al_audio_errcheck("alDopplerFactor()");
00729 }
00730
00731
00732
00733
00734
00735
00736 PN_stdfloat OpenALAudioManager::
00737 audio_3d_get_doppler_factor() const {
00738 return _doppler_factor;
00739 }
00740
00741
00742
00743
00744
00745
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
00760
00761
00762
00763 PN_stdfloat OpenALAudioManager::
00764 audio_3d_get_drop_off_factor() const {
00765 return _drop_off_factor;
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 void OpenALAudioManager::
00777 starting_sound(OpenALAudioSound* audio) {
00778 ReMutexHolder holder(_lock);
00779 ALuint source=0;
00780
00781
00782 if (audio->_source) {
00783 return;
00784 }
00785
00786
00787 update();
00788
00789 if (_concurrent_sound_limit) {
00790 reduce_sounds_playing_to(_concurrent_sound_limit-1);
00791 }
00792
00793
00794 if (_al_sources->empty()) {
00795 make_current();
00796 alGetError();
00797 alGenSources(1,&source);
00798 ALenum result = alGetError();
00799 if (result!=AL_NO_ERROR) {
00800 audio_error("alGenSources(): " << alGetString(result) );
00801
00802 reduce_sounds_playing_to(_sounds_playing.size()-1);
00803 source = 0;
00804 }
00805 }
00806
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
00820
00821
00822
00823
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);
00833 }
00834
00835
00836
00837
00838
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
00849
00850
00851
00852 unsigned int OpenALAudioManager::
00853 get_concurrent_sound_limit() const {
00854 return _concurrent_sound_limit;
00855 }
00856
00857
00858
00859
00860
00861
00862 void OpenALAudioManager::
00863 reduce_sounds_playing_to(unsigned int count) {
00864 ReMutexHolder holder(_lock);
00865
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
00873
00874
00875
00876
00877
00878 PT(OpenALAudioSound) s = (*sound);
00879 s->stop();
00880 }
00881 }
00882
00883
00884
00885
00886
00887
00888 void OpenALAudioManager::
00889 stop_all_sounds() {
00890 ReMutexHolder holder(_lock);
00891 reduce_sounds_playing_to(0);
00892 }
00893
00894
00895
00896
00897
00898
00899 void OpenALAudioManager::
00900 update() {
00901 ReMutexHolder holder(_lock);
00902
00903
00904
00905
00906
00907
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
00934
00935
00936
00937
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
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();
00970 alDeleteSources(_al_sources->size(),sources);
00971 al_audio_errcheck("alDeleteSources()");
00972 delete [] sources;
00973 _al_sources->clear();
00974
00975
00976 alcGetError(_device);
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
00988 _device = NULL;
00989 audio_debug("openAL Closed");
00990 }
00991
00992 _openal_active = false;
00993 }
00994 }
00995 _cleanup_required = false;
00996 }
00997
00998
00999
01000
01001
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
01018
01019
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
01035
01036
01037
01038
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
01056
01057
01058
01059
01060
01061
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
01084
01085
01086
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 //]