Panda3D
 All Classes Functions Variables Enumerations
openalAudioManager.cxx
1 // Filename: openalAudioManager.cxx
2 // Created by: Ben Buchwald <bb2@alumni.cmu.edu>
3 //
4 //
5 ////////////////////////////////////////////////////////////////////
6 //
7 // PANDA 3D SOFTWARE
8 // Copyright (c) Carnegie Mellon University. All rights reserved.
9 //
10 // All use of this software is subject to the terms of the revised BSD
11 // license. You should have received a copy of this license along
12 // with this source code in a file named "LICENSE."
13 //
14 ////////////////////////////////////////////////////////////////////
15 
16 #include "pandabase.h"
17 
18 //Panda headers.
19 #include "config_audio.h"
20 #include "config_util.h"
21 #include "config_express.h"
22 #include "config_openalAudio.h"
23 #include "openalAudioManager.h"
24 #include "openalAudioSound.h"
25 #include "virtualFileSystem.h"
26 #include "movieAudio.h"
27 #include "reMutexHolder.h"
28 
29 #include <algorithm>
30 
31 #ifndef ALC_DEFAULT_ALL_DEVICES_SPECIFIER
32 #define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
33 #endif
34 
35 #ifndef ALC_ALL_DEVICES_SPECIFIER
36 #define ALC_ALL_DEVICES_SPECIFIER 0x1013
37 #endif
38 
39 TypeHandle OpenALAudioManager::_type_handle;
40 
41 ReMutex OpenALAudioManager::_lock;
42 int OpenALAudioManager::_active_managers = 0;
43 bool OpenALAudioManager::_openal_active = false;
44 ALCdevice* OpenALAudioManager::_device = NULL;
45 ALCcontext* OpenALAudioManager::_context = NULL;
46 
47 // This is the list of all OpenALAudioManager objects in the world. It
48 // must be a pointer rather than a concrete object, so it won't be
49 // destructed at exit time before we're done removing things from it.
50 OpenALAudioManager::Managers *OpenALAudioManager::_managers = NULL;
51 
52 OpenALAudioManager::SourceCache *OpenALAudioManager::_al_sources = NULL;
53 
54 
55 ////////////////////////////////////////////////////////////////////
56 // Central dispatcher for audio errors.
57 ////////////////////////////////////////////////////////////////////
58 void al_audio_errcheck(const char *context) {
59  ALenum result = alGetError();
60  if (result != AL_NO_ERROR) {
61  audio_error(context << ": " << alGetString(result) );
62  }
63 }
64 
65 void alc_audio_errcheck(const char *context,ALCdevice* device) {
66  ALCenum result = alcGetError(device);
67  if (result != ALC_NO_ERROR) {
68  audio_error(context << ": " << alcGetString(device,result) );
69  }
70 }
71 
72 ////////////////////////////////////////////////////////////////////
73 // Function: Create_OpenALAudioManager
74 // Access: Private
75 // Description: Factory Function
76 ////////////////////////////////////////////////////////////////////
77 AudioManager *Create_OpenALAudioManager() {
78  audio_debug("Create_OpenALAudioManager()");
79  return new OpenALAudioManager;
80 }
81 
82 
83 ////////////////////////////////////////////////////////////////////
84 // Function: OpenALAudioManager::Constructor
85 // Access: Public
86 // Description:
87 ////////////////////////////////////////////////////////////////////
88 OpenALAudioManager::
89 OpenALAudioManager() {
90  ReMutexHolder holder(_lock);
91  if (_managers == (Managers *)NULL) {
92  _managers = new Managers;
93  _al_sources = new SourceCache;
94  }
95 
96  _managers->insert(this);
97 
98  _cleanup_required = true;
99  _active = audio_active;
100  _volume = audio_volume;
101  _play_rate = 1.0f;
102 
103  _cache_limit = audio_cache_limit;
104 
105  _concurrent_sound_limit = 0;
106  _is_valid = true;
107 
108  //Init 3D attributes
109  _distance_factor = 3.28;
110  _drop_off_factor = 1;
111 
112  _position[0] = 0;
113  _position[1] = 0;
114  _position[2] = 0;
115 
116  _velocity[0] = 0;
117  _velocity[1] = 0;
118  _velocity[2] = 0;
119 
120  _forward_up[0] = 0;
121  _forward_up[1] = 0;
122  _forward_up[2] = 0;
123  _forward_up[3] = 0;
124  _forward_up[4] = 0;
125  _forward_up[5] = 0;
126 
127  // Initialization
128  audio_cat.init();
129  if (_active_managers == 0 || !_openal_active) {
130  _device = NULL;
131  string dev_name = select_audio_device();
132 
133  if (!dev_name.empty()) {
134  // Open a specific device by name.
135  audio_cat.info() << "Using OpenAL device " << dev_name << "\n";
136  _device = alcOpenDevice(dev_name.c_str());
137 
138  if (_device == NULL) {
139  audio_cat.error()
140  << "Couldn't open OpenAL device \"" << dev_name << "\", falling back to default device\n";
141  }
142  } else {
143  audio_cat.info() << "Using default OpenAL device\n";
144  }
145 
146  if (_device == NULL) {
147  // Open the default device.
148  _device = alcOpenDevice(NULL);
149 
150  if (_device == NULL && dev_name != "OpenAL Soft") {
151  // Try the OpenAL Soft driver instead, which is fairly reliable.
152  _device = alcOpenDevice("OpenAL Soft");
153 
154  if (_device == NULL) {
155  audio_cat.error()
156  << "Couldn't open default OpenAL device\n";
157  }
158  }
159  }
160 
161  if (_device != NULL) {
162  // We managed to get a device open.
163  alcGetError(_device); // clear errors
164  _context = alcCreateContext(_device, NULL);
165  alc_audio_errcheck("alcCreateContext(_device, NULL)", _device);
166  if (_context != NULL) {
167  _openal_active = true;
168  }
169  }
170  }
171 
172  // We increment _active_managers regardless of possible errors above.
173  // The shutdown call will do the right thing when it's called,
174  // either way.
175  ++_active_managers;
176  nassertv(_active_managers>0);
177 
178  if (!_device || !_context) {
179  audio_error("OpenALAudioManager: No open device or context");
180  _is_valid = false;
181  } else {
182  alcGetError(_device); // clear errors
183  alcMakeContextCurrent(_context);
184  alc_audio_errcheck("alcMakeContextCurrent(_context)", _device);
185 
186  // set 3D sound characteristics as they are given in the configrc
187  audio_3d_set_doppler_factor(audio_doppler_factor);
188  audio_3d_set_distance_factor(audio_distance_factor);
189  audio_3d_set_drop_off_factor(audio_drop_off_factor);
190 
191  if (audio_cat.is_debug()) {
192  audio_cat.debug()
193  << "ALC_DEVICE_SPECIFIER:" << alcGetString(_device, ALC_DEVICE_SPECIFIER) << endl;
194  }
195  }
196 
197  if (audio_cat.is_debug()) {
198  audio_cat.debug() << "AL_RENDERER:" << alGetString(AL_RENDERER) << endl;
199  audio_cat.debug() << "AL_VENDOR:" << alGetString(AL_VENDOR) << endl;
200  audio_cat.debug() << "AL_VERSION:" << alGetString(AL_VERSION) << endl;
201  }
202 }
203 
204 ////////////////////////////////////////////////////////////////////
205 // Function: OpenALAudioManager::Destructor
206 // Access: Public
207 // Description:
208 ////////////////////////////////////////////////////////////////////
209 OpenALAudioManager::
210 ~OpenALAudioManager() {
211  ReMutexHolder holder(_lock);
212  nassertv(_managers != (Managers *)NULL);
213  Managers::iterator mi = _managers->find(this);
214  nassertv(mi != _managers->end());
215  _managers->erase(mi);
216  cleanup();
217 }
218 
219 ////////////////////////////////////////////////////////////////////
220 // Function: OpenALAudioManager::shutdown
221 // Access: Published, Virtual
222 // Description: Call this at exit time to shut down the audio system.
223 // This will invalidate all currently-active
224 // AudioManagers and AudioSounds in the system. If you
225 // change your mind and want to play sounds again, you
226 // will have to recreate all of these objects.
227 ////////////////////////////////////////////////////////////////////
230  ReMutexHolder holder(_lock);
231  if (_managers != (Managers *)NULL) {
232  Managers::iterator mi;
233  for (mi = _managers->begin(); mi != _managers->end(); ++mi) {
234  (*mi)->cleanup();
235  }
236  }
237 
238  nassertv(_active_managers == 0);
239 }
240 
241 
242 ////////////////////////////////////////////////////////////////////
243 // Function: OpenALAudioManager::is_valid
244 // Access:
245 // Description: This is mostly for debugging, but it it could be
246 // used to detect errors in a release build if you
247 // don't mind the cpu cost.
248 ////////////////////////////////////////////////////////////////////
251  return _is_valid;
252 }
253 
254 ////////////////////////////////////////////////////////////////////
255 // Function: OpenALAudioManager::select_audio_device
256 // Access: Private
257 // Description: Enumerate the audio devices, selecting the one that
258 // is most appropriate or has been selected by the user.
259 ////////////////////////////////////////////////////////////////////
260 string OpenALAudioManager::
261 select_audio_device() {
262  string selected_device = openal_device;
263 
264  const char *devices = NULL;
265 
266  // This extension gives us all audio paths on all drivers.
267  if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE) {
268  string default_device = alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
269  devices = (const char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
270 
271  if (devices) {
272  audio_cat.debug() << "All OpenAL devices:\n";
273 
274  while (*devices) {
275  string device(devices);
276  devices += device.size() + 1;
277 
278  if (audio_cat.is_debug()) {
279  if (device == selected_device) {
280  audio_cat.debug() << " " << device << " [selected]\n";
281  } else if (device == default_device) {
282  audio_cat.debug() << " " << device << " [default]\n";
283  } else {
284  audio_cat.debug() << " " << device << "\n";
285  }
286  }
287  }
288  }
289  } else {
290  audio_cat.debug() << "ALC_ENUMERATE_ALL_EXT not supported\n";
291  }
292 
293  // This extension just gives us generic driver names, like "OpenAL Soft"
294  // and "Generic Software", rather than individual outputs.
295  if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_TRUE) {
296  string default_device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
297  devices = (const char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
298 
299  if (devices) {
300  audio_cat.debug() << "OpenAL drivers:\n";
301 
302  while (*devices) {
303  string device(devices);
304  devices += device.size() + 1;
305 
306  if (selected_device.empty() && device == "OpenAL Soft" &&
307  default_device == "Generic Software") {
308  // Prefer OpenAL Soft over the buggy Generic Software driver.
309  selected_device = "OpenAL Soft";
310  }
311 
312  if (audio_cat.is_debug()) {
313  if (device == selected_device) {
314  audio_cat.debug() << " " << device << " [selected]\n";
315  } else if (device == default_device) {
316  audio_cat.debug() << " " << device << " [default]\n";
317  } else {
318  audio_cat.debug() << " " << device << "\n";
319  }
320  }
321  }
322  }
323  } else {
324  audio_cat.debug() << "ALC_ENUMERATION_EXT not supported\n";
325  }
326 
327  return selected_device;
328 }
329 
330 ////////////////////////////////////////////////////////////////////
331 // Function: OpenALAudioManager::make_current
332 // Access: Private
333 // Description: This makes this manager's OpenAL context the
334 // current context. Needed before any parameter sets.
335 ////////////////////////////////////////////////////////////////////
336 void OpenALAudioManager::
337 make_current() const {
338  // Since we only use one context, this is now a no-op.
339 }
340 
341 ////////////////////////////////////////////////////////////////////
342 // Function: OpenALAudioManager::can_use_audio
343 // Access: Private
344 // Description: Returns true if the specified MovieAudioCursor
345 // can be used by this AudioManager. Mostly, this
346 // involves checking whether or not the format is
347 // implemented/supported.
348 ////////////////////////////////////////////////////////////////////
349 bool OpenALAudioManager::
350 can_use_audio(MovieAudioCursor *source) {
351  ReMutexHolder holder(_lock);
352  int channels = source->audio_channels();
353  if ((channels != 1)&&(channels != 2)) {
354  audio_error("Currently, only mono and stereo are supported.");
355  return false;
356  }
357  return true;
358 }
359 
360 ////////////////////////////////////////////////////////////////////
361 // Function: OpenALAudioManager::should_load_audio
362 // Access: Private
363 // Description: Returns true if the specified MovieAudio should be
364 // cached into RAM. A lot of conditions have to be met
365 // in order to allow caching - if any are not met,
366 // the file will be streamed.
367 ////////////////////////////////////////////////////////////////////
368 bool OpenALAudioManager::
369 should_load_audio(MovieAudioCursor *source, int mode) {
370  ReMutexHolder holder(_lock);
371  if (mode == SM_stream) {
372  // If the user asked for streaming, give him streaming.
373  return false;
374  }
375  if (source->get_source()->get_filename().empty()) {
376  // Non-files cannot be preloaded.
377  return false;
378  }
379  if (source->ready() != 0x40000000) {
380  // Streaming sources cannot be preloaded.
381  return false;
382  }
383  if (source->length() > 3600.0) {
384  // Anything longer than an hour cannot be preloaded.
385  return false;
386  }
387  int channels = source->audio_channels();
388  int samples = (int)(source->length() * source->audio_rate());
389  int bytes = samples * channels * 2;
390  if ((mode == SM_heuristic)&&(bytes > audio_preload_threshold)) {
391  // In heuristic mode, if file is long, stream it.
392  return false;
393  }
394  return true;
395 }
396 
397 ////////////////////////////////////////////////////////////////////
398 // Function: OpenALAudioManager::get_sound_data
399 // Access: Private
400 // Description: Obtains a SoundData for the specified sound.
401 //
402 // When you are done with the SoundData, you need
403 // to decrement the client count.
404 ////////////////////////////////////////////////////////////////////
405 OpenALAudioManager::SoundData *OpenALAudioManager::
406 get_sound_data(MovieAudio *movie, int mode) {
407  ReMutexHolder holder(_lock);
408  const Filename &path = movie->get_filename();
409 
410  // Search for an already-cached sample or an already-opened stream.
411  if (!path.empty()) {
412 
413  if (mode != SM_stream) {
414  SampleCache::iterator lsmi=_sample_cache.find(path);
415  if (lsmi != _sample_cache.end()) {
416  SoundData *sd = (*lsmi).second;
417  increment_client_count(sd);
418  return sd;
419  }
420  }
421 
422  if (mode != SM_sample) {
423  ExpirationQueue::iterator exqi;
424  for (exqi=_expiring_streams.begin(); exqi!=_expiring_streams.end(); exqi++) {
425  SoundData *sd = (SoundData*)(*exqi);
426  if (sd->_movie->get_filename() == path) {
427  increment_client_count(sd);
428  return sd;
429  }
430  }
431  }
432  }
433 
434  PT(MovieAudioCursor) stream = movie->open();
435  if (stream == 0) {
436  audio_error("Cannot open file: "<<path);
437  return NULL;
438  }
439 
440  if (!can_use_audio(stream)) {
441  audio_error("File is not in usable format: "<<path);
442  return NULL;
443  }
444 
445  SoundData *sd = new SoundData();
446  sd->_client_count = 1;
447  sd->_manager = this;
448  sd->_movie = movie;
449  sd->_rate = stream->audio_rate();
450  sd->_channels = stream->audio_channels();
451  sd->_length = stream->length();
452  audio_debug("Creating: " << sd->_movie->get_filename().get_basename());
453  audio_debug(" - Rate: " << sd->_rate);
454  audio_debug(" - Channels: " << sd->_channels);
455  audio_debug(" - Length: " << sd->_length);
456 
457  if (should_load_audio(stream, mode)) {
458  audio_debug(path.get_basename() << ": loading as sample");
459  make_current();
460  alGetError(); // clear errors
461  sd->_sample = 0;
462  alGenBuffers(1, &sd->_sample);
463  al_audio_errcheck("alGenBuffers");
464  if (sd->_sample == 0) {
465  audio_error("Could not create an OpenAL buffer object");
466  delete sd;
467  return NULL;
468  }
469  int channels = stream->audio_channels();
470  int samples = (int)(stream->length() * stream->audio_rate());
471  PN_int16 *data = new PN_int16[samples * channels];
472  stream->read_samples(samples, data);
473  alBufferData(sd->_sample,
474  (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
475  data, samples * channels * 2, stream->audio_rate());
476  int err = alGetError();
477  if (err != AL_NO_ERROR) {
478  audio_error("could not fill OpenAL buffer object with data");
479  delete sd;
480  return NULL;
481  }
482  _sample_cache.insert(SampleCache::value_type(path, sd));
483  } else {
484  audio_debug(path.get_basename() << ": loading as stream");
485  sd->_stream = stream;
486  }
487 
488  return sd;
489 }
490 
491 ////////////////////////////////////////////////////////////////////
492 // Function: OpenALAudioManager::get_sound
493 // Access: Public
494 // Description: This is what creates a sound instance.
495 ////////////////////////////////////////////////////////////////////
497 get_sound(MovieAudio *sound, bool positional, int mode) {
498  ReMutexHolder holder(_lock);
499  if(!is_valid()) {
500  return get_null_sound();
501  }
502  PT(OpenALAudioSound) oas =
503  new OpenALAudioSound(this, sound, positional, mode);
504 
505  _all_sounds.insert(oas);
506  PT(AudioSound) res = (AudioSound*)(OpenALAudioSound*)oas;
507  return res;
508 }
509 
510 ////////////////////////////////////////////////////////////////////
511 // Function: OpenALAudioManager::get_sound
512 // Access: Public
513 // Description: This is what creates a sound instance.
514 ////////////////////////////////////////////////////////////////////
516 get_sound(const string &file_name, bool positional, int mode) {
517  ReMutexHolder holder(_lock);
518  if(!is_valid()) {
519  return get_null_sound();
520  }
521 
522  Filename path = file_name;
524  vfs->resolve_filename(path, get_model_path());
525 
526  if (path.empty()) {
527  audio_error("get_sound - invalid filename");
528  return NULL;
529  }
530 
531  PT(MovieAudio) mva = MovieAudio::get(path);
532 
533  PT(OpenALAudioSound) oas =
534  new OpenALAudioSound(this, mva, positional, mode);
535 
536  _all_sounds.insert(oas);
537  PT(AudioSound) res = (AudioSound*)(OpenALAudioSound*)oas;
538  return res;
539 }
540 
541 ////////////////////////////////////////////////////////////////////
542 // Function: OpenALAudioManager::uncache_sound
543 // Access: Public
544 // Description: Deletes a sample from the expiration queues.
545 // If the sound is actively in use, then the sound
546 // cannot be deleted, and this function has no effect.
547 ////////////////////////////////////////////////////////////////////
548 void OpenALAudioManager::
549 uncache_sound(const string& file_name) {
550  ReMutexHolder holder(_lock);
551  assert(is_valid());
552  Filename path = file_name;
553 
555  vfs->resolve_filename(path, get_model_path());
556 
557  SampleCache::iterator sci = _sample_cache.find(path);
558  if (sci != _sample_cache.end()) {
559  SoundData *sd = (*sci).second;
560  if (sd->_client_count == 0) {
561  _expiring_samples.erase(sd->_expire);
562  _sample_cache.erase(sci);
563  delete sd;
564  }
565  }
566 }
567 
568 ////////////////////////////////////////////////////////////////////
569 // Function: OpenALAudioManager::clear_cache
570 // Access: Public
571 // Description: Clear out the sound cache.
572 ////////////////////////////////////////////////////////////////////
575  ReMutexHolder holder(_lock);
576  discard_excess_cache(0);
577 }
578 
579 ////////////////////////////////////////////////////////////////////
580 // Function: OpenALAudioManager::set_cache_limit
581 // Access: Public
582 // Description: Set the number of sounds that the cache can hold.
583 ////////////////////////////////////////////////////////////////////
585 set_cache_limit(unsigned int count) {
586  ReMutexHolder holder(_lock);
587  _cache_limit=count;
588  discard_excess_cache(count);
589 }
590 
591 ////////////////////////////////////////////////////////////////////
592 // Function: OpenALAudioManager::get_cache_limit
593 // Access: Public
594 // Description:
595 ////////////////////////////////////////////////////////////////////
596 unsigned int OpenALAudioManager::
597 get_cache_limit() const {
598  return _cache_limit;
599 }
600 
601 ////////////////////////////////////////////////////////////////////
602 // Function: OpenALAudioManager::release_sound
603 // Access: Public
604 // Description:
605 ////////////////////////////////////////////////////////////////////
606 void OpenALAudioManager::
607 release_sound(OpenALAudioSound* audioSound) {
608  ReMutexHolder holder(_lock);
609  AllSounds::iterator ai = _all_sounds.find(audioSound);
610  if (ai != _all_sounds.end()) {
611  _all_sounds.erase(ai);
612  }
613 }
614 
615 ////////////////////////////////////////////////////////////////////
616 // Function: OpenALAudioManager::set_volume(PN_stdfloat volume)
617 // Access: Public
618 // Description:
619 // Sets listener gain
620 ////////////////////////////////////////////////////////////////////
621 void OpenALAudioManager::set_volume(PN_stdfloat volume) {
622  ReMutexHolder holder(_lock);
623  if (_volume!=volume) {
624  _volume = volume;
625 
626  // Tell our AudioSounds to adjust:
627  AllSounds::iterator i=_all_sounds.begin();
628  for (; i!=_all_sounds.end(); ++i) {
629  (**i).set_volume((**i).get_volume());
630  }
631 
632  /*
633  // this was neat alternative to the above look
634  // when we had a seperate context for each manager
635  make_current();
636 
637  alGetError(); // clear errors
638  alListenerf(AL_GAIN,(ALfloat)_volume);
639  al_audio_errcheck("alListerf(AL_GAIN)");*/
640  }
641 }
642 
643 ////////////////////////////////////////////////////////////////////
644 // Function: OpenALAudioManager::get_volume()
645 // Access: Public
646 // Description:
647 // Gets listener gain
648 ////////////////////////////////////////////////////////////////////
649 PN_stdfloat OpenALAudioManager::
650 get_volume() const {
651  return _volume;
652 }
653 
654 ////////////////////////////////////////////////////////////////////
655 // Function: OpenALAudioManager::set_play_rate
656 // Access: Public
657 // Description: set the overall play rate
658 ////////////////////////////////////////////////////////////////////
660 set_play_rate(PN_stdfloat play_rate) {
661  ReMutexHolder holder(_lock);
662  if (_play_rate!=play_rate) {
663  _play_rate = play_rate;
664  // Tell our AudioSounds to adjust:
665  AllSounds::iterator i=_all_sounds.begin();
666  for (; i!=_all_sounds.end(); ++i) {
667  (**i).set_play_rate((**i).get_play_rate());
668  }
669  }
670 }
671 
672 ////////////////////////////////////////////////////////////////////
673 // Function: OpenALAudioManager::get_play_rate
674 // Access: Public
675 // Description: get the overall speed/pitch/play rate
676 ////////////////////////////////////////////////////////////////////
677 PN_stdfloat OpenALAudioManager::
678 get_play_rate() const {
679  return _play_rate;
680 }
681 
682 ////////////////////////////////////////////////////////////////////
683 // Function: OpenALAudioManager::set_active(bool active)
684 // Access: Public
685 // Description: Turn on/off
686 // Warning: not implemented.
687 ////////////////////////////////////////////////////////////////////
689 set_active(bool active) {
690  ReMutexHolder holder(_lock);
691  if (_active!=active) {
692  _active=active;
693  // Tell our AudioSounds to adjust:
694  AllSounds::iterator i=_all_sounds.begin();
695  for (; i!=_all_sounds.end(); ++i) {
696  (**i).set_active(_active);
697  }
698  }
699 }
700 
701 ////////////////////////////////////////////////////////////////////
702 // Function: OpenALAudioManager::get_active()
703 // Access: Public
704 // Description:
705 ////////////////////////////////////////////////////////////////////
706 bool OpenALAudioManager::
707 get_active() const {
708  return _active;
709 }
710 
711 ////////////////////////////////////////////////////////////////////
712 // Function: OpenALAudioManager::audio_3d_set_listener_attributes
713 // Access: Public
714 // Description: Set position of the "ear" that picks up 3d sounds
715 // NOW LISTEN UP!!! THIS IS IMPORTANT!
716 // Both Panda3D and OpenAL use a right handed coordinate system.
717 // But there is a major difference!
718 // In Panda3D the Y-Axis is going into the Screen and the Z-Axis is going up.
719 // In OpenAL the Y-Axis is going up and the Z-Axis is coming out of the screen.
720 // The solution is simple, we just flip the Y and Z axis and negate the Z, as we move coordinates
721 // from Panda to OpenAL and back.
722 // What does did mean to average Panda user? Nothing, they shouldn't notice anyway.
723 // But if you decide to do any 3D audio work in here you have to keep it in mind.
724 // I told you, so you can't say I didn't.
725 ////////////////////////////////////////////////////////////////////
727 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) {
728  ReMutexHolder holder(_lock);
729  _position[0] = px;
730  _position[1] = pz;
731  _position[2] = -py;
732 
733  _velocity[0] = vx;
734  _velocity[1] = vz;
735  _velocity[2] = -vy;
736 
737  _forward_up[0] = fx;
738  _forward_up[1] = fz;
739  _forward_up[2] = -fy;
740 
741  _forward_up[3] = ux;
742  _forward_up[4] = uz;
743  _forward_up[5] = -uy;
744 
745 
746  make_current();
747 
748  alGetError(); // clear errors
749  alListenerfv(AL_POSITION,_position);
750  al_audio_errcheck("alListerfv(AL_POSITION)");
751  alListenerfv(AL_VELOCITY,_velocity);
752  al_audio_errcheck("alListerfv(AL_VELOCITY)");
753  alListenerfv(AL_ORIENTATION,_forward_up);
754  al_audio_errcheck("alListerfv(AL_ORIENTATION)");
755 }
756 
757 ////////////////////////////////////////////////////////////////////
758 // Function: OpenALAudioManager::audio_3d_get_listener_attributes
759 // Access: Public
760 // Description: Get position of the "ear" that picks up 3d sounds
761 ////////////////////////////////////////////////////////////////////
763 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) {
764  ReMutexHolder holder(_lock);
765  *px = _position[0];
766  *py = -_position[2];
767  *pz = _position[1];
768 
769  *vx = _velocity[0];
770  *vy = -_velocity[2];
771  *vz = _velocity[1];
772 
773  *fx = _forward_up[0];
774  *fy = -_forward_up[2];
775  *fz = _forward_up[1];
776 
777  *ux = _forward_up[3];
778  *uy = -_forward_up[5];
779  *uz = _forward_up[4];
780 }
781 
782 
783 ////////////////////////////////////////////////////////////////////
784 // Function: OpenALAudioManager::audio_3d_set_distance_factor
785 // Access: Public
786 // Description: Set units per foot
787 // WARNING: OpenAL has no distance factor but we use this as a scale
788 // on the min/max distances of sounds to preserve FMOD compatibility.
789 // Also, adjusts the speed of sound to compensate for unit difference.
790 // OpenAL's default speed of sound is 343.3 m/s == 1126.3 ft/s
791 ////////////////////////////////////////////////////////////////////
793 audio_3d_set_distance_factor(PN_stdfloat factor) {
794  ReMutexHolder holder(_lock);
795  _distance_factor = factor;
796 
797  make_current();
798 
799  alGetError(); // clear errors
800 
801  if (_distance_factor>0) {
802  alSpeedOfSound(1126.3*_distance_factor);
803  al_audio_errcheck("alSpeedOfSound()");
804  // resets the doppler factor to the correct setting in case it was set to 0.0 by a distance_factor<=0.0
805  alDopplerFactor(_doppler_factor);
806  al_audio_errcheck("alDopplerFactor()");
807  } else {
808  audio_debug("can't set speed of sound if distance_factor <=0.0, setting doppler factor to 0.0 instead");
809  alDopplerFactor(0.0);
810  al_audio_errcheck("alDopplerFactor()");
811  }
812 
813  AllSounds::iterator i=_all_sounds.begin();
814  for (; i!=_all_sounds.end(); ++i) {
815  (**i).set_3d_min_distance((**i).get_3d_min_distance());
816  (**i).set_3d_max_distance((**i).get_3d_max_distance());
817  }
818 }
819 
820 ////////////////////////////////////////////////////////////////////
821 // Function: OpenALAudioManager::audio_3d_get_distance_factor
822 // Access: Public
823 // Description: Sets units per foot
824 ////////////////////////////////////////////////////////////////////
825 PN_stdfloat OpenALAudioManager::
827  return _distance_factor;
828 }
829 
830 ////////////////////////////////////////////////////////////////////
831 // Function: OpenALAudioManager::audio_3d_set_doppler_factor
832 // Access: Public
833 // Description: Exaggerates or diminishes the Doppler effect.
834 // Defaults to 1.0
835 ////////////////////////////////////////////////////////////////////
837 audio_3d_set_doppler_factor(PN_stdfloat factor) {
838  ReMutexHolder holder(_lock);
839  _doppler_factor = factor;
840 
841  make_current();
842 
843  alGetError(); // clear errors
844  alDopplerFactor(_doppler_factor);
845  al_audio_errcheck("alDopplerFactor()");
846 }
847 
848 ////////////////////////////////////////////////////////////////////
849 // Function: OpenALAudioManager::audio_3d_get_doppler_factor
850 // Access: Public
851 // Description:
852 ////////////////////////////////////////////////////////////////////
853 PN_stdfloat OpenALAudioManager::
854 audio_3d_get_doppler_factor() const {
855  return _doppler_factor;
856 }
857 
858 ////////////////////////////////////////////////////////////////////
859 // Function: OpenALAudioManager::audio_3d_set_drop_off_factor
860 // Access: Public
861 // Description: Control the effect distance has on audability.
862 // Defaults to 1.0
863 ////////////////////////////////////////////////////////////////////
865 audio_3d_set_drop_off_factor(PN_stdfloat factor) {
866  ReMutexHolder holder(_lock);
867  _drop_off_factor = factor;
868 
869  AllSounds::iterator i=_all_sounds.begin();
870  for (; i!=_all_sounds.end(); ++i) {
871  (**i).set_3d_drop_off_factor((**i).get_3d_drop_off_factor());
872  }
873 }
874 
875 ////////////////////////////////////////////////////////////////////
876 // Function: OpenALAudioManager::audio_3d_get_drop_off_factor
877 // Access: Public
878 // Description:
879 ////////////////////////////////////////////////////////////////////
880 PN_stdfloat OpenALAudioManager::
881 audio_3d_get_drop_off_factor() const {
882  return _drop_off_factor;
883 }
884 
885 ////////////////////////////////////////////////////////////////////
886 // Function: OpenALAudioManager::starting_sound
887 // Access:
888 // Description: Inform the manager that a sound is about to play.
889 // The manager will add this sound to the table of
890 // sounds that are playing, and will allocate a source
891 // to this sound.
892 ////////////////////////////////////////////////////////////////////
893 void OpenALAudioManager::
894 starting_sound(OpenALAudioSound* audio) {
895  ReMutexHolder holder(_lock);
896  ALuint source=0;
897 
898  // If the sound already has a source, we don't need to do anything.
899  if (audio->_source) {
900  return;
901  }
902 
903  // first give all sounds that have finished a chance to stop, so that these get stopped first
904  update();
905 
906  if (_concurrent_sound_limit) {
907  reduce_sounds_playing_to(_concurrent_sound_limit-1); // because we're about to add one
908  }
909 
910  // get a source from the source pool or create a new source
911  if (_al_sources->empty()) {
912  make_current();
913  alGetError(); // clear errors
914  alGenSources(1,&source);
915  ALenum result = alGetError();
916  if (result!=AL_NO_ERROR) {
917  audio_error("alGenSources(): " << alGetString(result) );
918  // if we can't create any more sources, set stop a sound to free a source
919  reduce_sounds_playing_to(_sounds_playing.size()-1);
920  source = 0;
921  }
922  }
923  // get a source from the source bool if we didn't just allocate one
924  if (!source && !_al_sources->empty()) {
925  source = *(_al_sources->begin());
926  _al_sources->erase(source);
927  }
928 
929  audio->_source = source;
930 
931  if (source)
932  _sounds_playing.insert(audio);
933 }
934 
935 ////////////////////////////////////////////////////////////////////
936 // Function: OpenALAudioManager::stopping_sound
937 // Access:
938 // Description: Inform the manager that a sound is finished or
939 // someone called stop on the sound (this should not
940 // be called if a sound is only paused).
941 ////////////////////////////////////////////////////////////////////
942 void OpenALAudioManager::
943 stopping_sound(OpenALAudioSound* audio) {
944  ReMutexHolder holder(_lock);
945  if (audio->_source) {
946  _al_sources->insert(audio->_source);
947  audio->_source = 0;
948  }
949  _sounds_playing.erase(audio); // This could cause the sound to destruct.
950 }
951 
952 ////////////////////////////////////////////////////////////////////
953 // Function: OpenALAudioManager::set_concurrent_sound_limit
954 // Access: Public
955 // Description:
956 ////////////////////////////////////////////////////////////////////
957 void OpenALAudioManager::
958 set_concurrent_sound_limit(unsigned int limit) {
959  ReMutexHolder holder(_lock);
960  _concurrent_sound_limit = limit;
961  reduce_sounds_playing_to(_concurrent_sound_limit);
962 }
963 
964 ////////////////////////////////////////////////////////////////////
965 // Function: OpenALAudioManager::get_concurrent_sound_limit
966 // Access: Public
967 // Description:
968 ////////////////////////////////////////////////////////////////////
969 unsigned int OpenALAudioManager::
970 get_concurrent_sound_limit() const {
971  return _concurrent_sound_limit;
972 }
973 
974 ////////////////////////////////////////////////////////////////////
975 // Function: OpenALAudioManager::reduce_sounds_playing_to
976 // Access: Private
977 // Description:
978 ////////////////////////////////////////////////////////////////////
979 void OpenALAudioManager::
980 reduce_sounds_playing_to(unsigned int count) {
981  ReMutexHolder holder(_lock);
982  // first give all sounds that have finished a chance to stop, so that these get stopped first
983  update();
984 
985  int limit = _sounds_playing.size() - count;
986  while (limit-- > 0) {
987  SoundsPlaying::iterator sound = _sounds_playing.begin();
988  assert(sound != _sounds_playing.end());
989  // When the user stops a sound, there is still a PT in the
990  // user's hand. When we stop a sound here, however,
991  // this can remove the last PT. This can cause an ugly
992  // recursion where stop calls the destructor, and the
993  // destructor calls stop. To avoid this, we create
994  // a temporary PT, stop the sound, and then release the PT.
995  PT(OpenALAudioSound) s = (*sound);
996  s->stop();
997  }
998 }
999 
1000 ////////////////////////////////////////////////////////////////////
1001 // Function: OpenALAudioManager::stop_all_sounds()
1002 // Access: Public
1003 // Description: Stop playback on all sounds managed by this manager.
1004 ////////////////////////////////////////////////////////////////////
1005 void OpenALAudioManager::
1007  ReMutexHolder holder(_lock);
1008  reduce_sounds_playing_to(0);
1009 }
1010 
1011 ////////////////////////////////////////////////////////////////////
1012 // Function: OpenALAudioManager::update
1013 // Access: Public
1014 // Description: Perform all per-frame update functions.
1015 ////////////////////////////////////////////////////////////////////
1018  ReMutexHolder holder(_lock);
1019 
1020  // See if any of our playing sounds have ended
1021  // we must first collect a seperate list of finished sounds and then
1022  // iterated over those again calling their finished method. We
1023  // can't call finished() within a loop iterating over _sounds_playing
1024  // since finished() modifies _sounds_playing
1025  SoundsPlaying sounds_finished;
1026 
1027  double rtc = TrueClock::get_global_ptr()->get_short_time();
1028  SoundsPlaying::iterator i=_sounds_playing.begin();
1029  for (; i!=_sounds_playing.end(); ++i) {
1030  OpenALAudioSound *sound = (*i);
1031  sound->pull_used_buffers();
1032  sound->push_fresh_buffers();
1033  sound->restart_stalled_audio();
1034  sound->cache_time(rtc);
1035  if ((sound->_source == 0)||
1036  ((sound->_stream_queued.size() == 0)&&
1037  (sound->_loops_completed >= sound->_playing_loops))) {
1038  sounds_finished.insert(*i);
1039  }
1040  }
1041 
1042  i=sounds_finished.begin();
1043  for (; i!=sounds_finished.end(); ++i) {
1044  (**i).finished();
1045  }
1046 }
1047 
1048 
1049 ////////////////////////////////////////////////////////////////////
1050 // Function: OpenALAudioManager::cleanup
1051 // Access: Private
1052 // Description: Shuts down the audio manager and releases any
1053 // resources associated with it. Also cleans up all
1054 // AudioSounds created via the manager.
1055 ////////////////////////////////////////////////////////////////////
1056 void OpenALAudioManager::
1057 cleanup() {
1058  ReMutexHolder holder(_lock);
1059  if (!_cleanup_required) {
1060  return;
1061  }
1062 
1063  stop_all_sounds();
1064 
1065  AllSounds sounds(_all_sounds);
1066  AllSounds::iterator ai;
1067  for (ai = sounds.begin(); ai != sounds.end(); ++ai) {
1068  (*ai)->cleanup();
1069  }
1070 
1071  clear_cache();
1072 
1073  nassertv(_active_managers > 0);
1074  --_active_managers;
1075 
1076  if (_active_managers == 0) {
1077  if (_openal_active) {
1078  // empty the source cache
1079  int i=0;
1080  ALuint *sources;
1081  sources = new ALuint[_al_sources->size()];
1082  for (SourceCache::iterator si = _al_sources->begin(); si!=_al_sources->end(); ++si) {
1083  sources[i++]=*si;
1084  }
1085  make_current();
1086  alGetError(); // clear errors
1087  alDeleteSources(_al_sources->size(),sources);
1088  al_audio_errcheck("alDeleteSources()");
1089  delete [] sources;
1090  _al_sources->clear();
1091 
1092  // make sure that the context is not current when it is destroyed
1093  alcGetError(_device); // clear errors
1094  alcMakeContextCurrent(NULL);
1095  alc_audio_errcheck("alcMakeContextCurrent(NULL)",_device);
1096 
1097  alcDestroyContext(_context);
1098  alc_audio_errcheck("alcDestroyContext(_context)",_device);
1099  _context = NULL;
1100 
1101  if (_device) {
1102  audio_debug("Going to try to close openAL");
1103  alcCloseDevice(_device);
1104  //alc_audio_errcheck("alcCloseDevice(_device)",_device);
1105  _device = NULL;
1106  audio_debug("openAL Closed");
1107  }
1108 
1109  _openal_active = false;
1110  }
1111  }
1112  _cleanup_required = false;
1113 }
1114 
1115 ////////////////////////////////////////////////////////////////////
1116 // Function: OpenALAudioManager::SoundData::Constructor
1117 // Access: Public
1118 // Description:
1119 ////////////////////////////////////////////////////////////////////
1120 OpenALAudioManager::SoundData::
1121 SoundData() :
1122  _manager(0),
1123  _movie(0),
1124  _sample(0),
1125  _stream(NULL),
1126  _length(0.0),
1127  _rate(0),
1128  _channels(0),
1129  _client_count(0)
1130 {
1131 }
1132 
1133 ////////////////////////////////////////////////////////////////////
1134 // Function: OpenALAudioManager::SoundData::Destructor
1135 // Access: Public
1136 // Description:
1137 ////////////////////////////////////////////////////////////////////
1138 OpenALAudioManager::SoundData::
1139 ~SoundData() {
1140  ReMutexHolder holder(OpenALAudioManager::_lock);
1141  if (_sample != 0) {
1142  if (_manager->_is_valid) {
1143  _manager->make_current();
1144  alDeleteBuffers(1,&_sample);
1145  }
1146  _sample = 0;
1147  }
1148 }
1149 
1150 ////////////////////////////////////////////////////////////////////
1151 // Function: OpenALAudioManager::increment_client_count
1152 // Access: Public
1153 // Description: Increments the SoundData's client count. Any
1154 // SoundData that is actively in use (ie, has a client)
1155 // is removed entirely from the expiration queue.
1156 ////////////////////////////////////////////////////////////////////
1157 void OpenALAudioManager::
1158 increment_client_count(SoundData *sd) {
1159  ReMutexHolder holder(_lock);
1160  sd->_client_count += 1;
1161  audio_debug("Incrementing: " << sd->_movie->get_filename().get_basename() << " " << sd->_client_count);
1162  if (sd->_client_count == 1) {
1163  if (sd->_sample) {
1164  _expiring_samples.erase(sd->_expire);
1165  } else {
1166  _expiring_streams.erase(sd->_expire);
1167  }
1168  }
1169 }
1170 
1171 ////////////////////////////////////////////////////////////////////
1172 // Function: OpenALAudioManager::decrement_client_count
1173 // Access: Public
1174 // Description: Decrements the SoundData's client count. Sounds
1175 // that are no longer in use (ie, have no clients)
1176 // go into the expiration queue. When the expiration
1177 // queue reaches the cache limit, the first item on
1178 // the queue is freed.
1179 ////////////////////////////////////////////////////////////////////
1180 void OpenALAudioManager::
1181 decrement_client_count(SoundData *sd) {
1182  ReMutexHolder holder(_lock);
1183  sd->_client_count -= 1;
1184  audio_debug("Decrementing: " << sd->_movie->get_filename().get_basename() << " " << sd->_client_count);
1185  if (sd->_client_count == 0) {
1186  if (sd->_sample) {
1187  _expiring_samples.push_back(sd);
1188  sd->_expire = _expiring_samples.end();
1189  sd->_expire--;
1190  } else {
1191  _expiring_streams.push_back(sd);
1192  sd->_expire = _expiring_streams.end();
1193  sd->_expire--;
1194  }
1195  discard_excess_cache(_cache_limit);
1196  }
1197 }
1198 
1199 ////////////////////////////////////////////////////////////////////
1200 // Function: OpenALAudioManager::discard_excess_cache
1201 // Access: Public
1202 // Description: Discards sounds from the sound cache until the
1203 // number of sounds remaining is under the limit.
1204 ////////////////////////////////////////////////////////////////////
1205 void OpenALAudioManager::
1206 discard_excess_cache(int sample_limit) {
1207  ReMutexHolder holder(_lock);
1208  int stream_limit = 5;
1209 
1210  while (((int)_expiring_samples.size()) > sample_limit) {
1211  SoundData *sd = (SoundData*)(_expiring_samples.front());
1212  assert(sd->_client_count == 0);
1213  assert(sd->_expire == _expiring_samples.begin());
1214  _expiring_samples.pop_front();
1215  _sample_cache.erase(_sample_cache.find(sd->_movie->get_filename()));
1216  audio_debug("Expiring: " << sd->_movie->get_filename().get_basename());
1217  delete sd;
1218  }
1219 
1220  while (((int)_expiring_streams.size()) > stream_limit) {
1221  SoundData *sd = (SoundData*)(_expiring_streams.front());
1222  assert(sd->_client_count == 0);
1223  assert(sd->_expire == _expiring_streams.begin());
1224  _expiring_streams.pop_front();
1225  audio_debug("Expiring: " << sd->_movie->get_filename().get_basename());
1226  delete sd;
1227  }
1228 }
virtual void 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)
Get position of the &quot;ear&quot; that picks up 3d sounds.
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
Definition: trueClock.I:81
const Filename & get_filename() const
Returns the movie&#39;s filename.
Definition: movieAudio.I:23
virtual PN_stdfloat audio_3d_get_distance_factor() const
Sets units per foot.
virtual void set_cache_limit(unsigned int count)
Set the number of sounds that the cache can hold.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS&#39;s file system.
virtual void set_volume(PN_stdfloat)
Sets listener gain.
PN_stdfloat get_play_rate() const
get the overall speed/pitch/play rate
virtual PN_stdfloat get_volume() const
Gets listener gain.
virtual void clear_cache()
Clear out the sound cache.
virtual void stop_all_sounds()
Stop playback on all sounds managed by this manager.
virtual void audio_3d_set_doppler_factor(PN_stdfloat factor)
Exaggerates or diminishes the Doppler effect.
virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor)
Control the effect distance has on audability.
virtual bool is_valid()
This is mostly for debugging, but it it could be used to detect errors in a release build if you don&#39;...
virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz)
Set position of the &quot;ear&quot; that picks up 3d sounds NOW LISTEN UP!!! THIS IS IMPORTANT! Both Panda3D an...
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
void set_play_rate(PN_stdfloat play_rate)
set the overall play rate
A MovieAudio is actually any source that provides a sequence of audio samples.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
Similar to MutexHolder, but for a reentrant mutex.
Definition: reMutexHolder.h:27
virtual void audio_3d_set_distance_factor(PN_stdfloat factor)
Set units per foot WARNING: OpenAL has no distance factor but we use this as a scale on the min/max d...
virtual void update()
Perform all per-frame update functions.
string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:436
virtual void set_active(bool)
Turn on/off Warning: not implemented.
int audio_channels() const
Returns the number of audio channels (ie, two for stereo, one for mono).
This is our own Panda specialization on the default STL set.
Definition: pset.h:52
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:48
virtual void shutdown()
Call this at exit time to shut down the audio system.
double length() const
Returns the length of the movie.
A reentrant mutex.
Definition: reMutex.h:36
virtual int ready() const
Returns the number of audio samples that are ready to read.