Panda3D
 All Classes Functions Variables Enumerations
openalAudioManager.h
1 // Filename: openalAudioManager.h
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 
17 #ifndef __OPENAL_AUDIO_MANAGER_H__
18 #define __OPENAL_AUDIO_MANAGER_H__
19 
20 #include "pandabase.h"
21 
22 #include "audioManager.h"
23 #include "plist.h"
24 #include "pmap.h"
25 #include "pset.h"
26 #include "movieAudioCursor.h"
27 #include "reMutex.h"
28 
29 // OSX uses the OpenAL framework
30 #ifdef IS_OSX
31  #include <OpenAL/al.h>
32  #include <OpenAL/alc.h>
33 #else
34  #include <AL/al.h>
35  #include <AL/alc.h>
36 #endif
37 
38 class OpenALAudioSound;
39 
40 extern void al_audio_errcheck(const char *context);
41 extern void alc_audio_errcheck(const char *context,ALCdevice* device);
42 
43 class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager {
44  class SoundData;
45 
46  friend class OpenALAudioSound;
47  friend class OpenALSoundData;
48 
49  public:
50  //Constructor and Destructor
52  virtual ~OpenALAudioManager();
53 
54  virtual void shutdown();
55 
56  virtual bool is_valid();
57 
58  virtual PT(AudioSound) get_sound(const string&, bool positional = false, int mode=SM_heuristic);
59  virtual PT(AudioSound) get_sound(MovieAudio *sound, bool positional = false, int mode=SM_heuristic);
60 
61  virtual void uncache_sound(const string&);
62  virtual void clear_cache();
63  virtual void set_cache_limit(unsigned int count);
64  virtual unsigned int get_cache_limit() const;
65 
66  virtual void set_volume(PN_stdfloat);
67  virtual PN_stdfloat get_volume() const;
68 
69  void set_play_rate(PN_stdfloat play_rate);
70  PN_stdfloat get_play_rate() const;
71 
72  virtual void set_active(bool);
73  virtual bool get_active() const;
74 
75  // This controls the "set of ears" that listens to 3D spacialized sound
76  // px, py, pz are position coordinates. Can be 0.0f to ignore.
77  // vx, vy, vz are a velocity vector in UNITS PER SECOND.
78  // fx, fy and fz are the respective components of a unit forward-vector
79  // ux, uy and uz are the respective components of a unit up-vector
80  // These changes will NOT be invoked until audio_3d_update() is called.
81  virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz,
82  PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz,
83  PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz,
84  PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz);
85 
86  virtual void audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz,
87  PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz,
88  PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz,
89  PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz);
90 
91  // Control the "relative distance factor" for 3D spacialized audio in units-per-foot. Default is 1.0
92  // OpenAL has no distance factor but we use this as a scale
93  // on the min/max distances of sounds to preserve FMOD compatibility.
94  // Also, adjusts the speed of sound to compensate for unit difference.
95  virtual void audio_3d_set_distance_factor(PN_stdfloat factor);
96  virtual PN_stdfloat audio_3d_get_distance_factor() const;
97 
98  // Control the presence of the Doppler effect. Default is 1.0
99  // Exaggerated Doppler, use >1.0
100  // Diminshed Doppler, use <1.0
101  virtual void audio_3d_set_doppler_factor(PN_stdfloat factor);
102  virtual PN_stdfloat audio_3d_get_doppler_factor() const;
103 
104  // Exaggerate or diminish the effect of distance on sound. Default is 1.0
105  // Faster drop off, use >1.0
106  // Slower drop off, use <1.0
107  virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor);
108  virtual PN_stdfloat audio_3d_get_drop_off_factor() const;
109 
110  virtual void set_concurrent_sound_limit(unsigned int limit = 0);
111  virtual unsigned int get_concurrent_sound_limit() const;
112  virtual void reduce_sounds_playing_to(unsigned int count);
113 
114  virtual void stop_all_sounds();
115 
116  virtual void update();
117 
118 private:
119  string select_audio_device();
120 
121  void make_current() const;
122 
123  bool can_use_audio(MovieAudioCursor *source);
124  bool should_load_audio(MovieAudioCursor *source, int mode);
125 
126  SoundData *get_sound_data(MovieAudio *source, int mode);
127 
128  // Tell the manager that the sound dtor was called.
129  void release_sound(OpenALAudioSound* audioSound);
130  void increment_client_count(SoundData *sd);
131  void decrement_client_count(SoundData *sd);
132  void discard_excess_cache(int limit);
133 
134  void starting_sound(OpenALAudioSound* audio);
135  void stopping_sound(OpenALAudioSound* audio);
136 
137  void cleanup();
138 
139 private:
140  // This global lock protects all access to OpenAL library interfaces.
141  static ReMutex _lock;
142 
143  // An expiration queue is a list of SoundData
144  // that are no longer being used. They are kept
145  // around for a little while, since it is common to
146  // stop using a sound for a brief moment and then
147  // quickly resume.
148 
150  ExpirationQueue _expiring_samples;
151  ExpirationQueue _expiring_streams;
152 
153  // An AudioSound that uses a SoundData is called a "client"
154  // of the SoundData. The SoundData keeps track of how
155  // many clients are using it. When the number of clients
156  // drops to zero, the SoundData is no longer in use. The
157  // expiration queue is a list of all SoundData that aren't
158  // in use, in least-recently-used order. If a SoundData
159  // in the expiration queue gains a new client, it is removed
160  // from the expiration queue. When the number of sounds
161  // in the expiration queue exceeds the cache limit, the
162  // first sound in the expiration queue is purged.
163 
164  class SoundData {
165  public:
166  SoundData();
167  ~SoundData();
168  OpenALAudioManager* _manager;
169  PT(MovieAudio) _movie;
170  ALuint _sample;
171  PT(MovieAudioCursor) _stream;
172  double _length;
173  int _rate;
174  int _channels;
175  int _client_count;
176  ExpirationQueue::iterator _expire;
177  };
178 
179 
180  typedef phash_map<string, SoundData *> SampleCache;
181  SampleCache _sample_cache;
182 
183  typedef phash_set<PT(OpenALAudioSound)> SoundsPlaying;
184  SoundsPlaying _sounds_playing;
185 
186  typedef phash_set<OpenALAudioSound *> AllSounds;
187  AllSounds _all_sounds;
188 
189  // State:
190  int _cache_limit;
191  PN_stdfloat _volume;
192  PN_stdfloat _play_rate;
193  bool _active;
194  bool _cleanup_required;
195  // keep a count for startup and shutdown:
196  static int _active_managers;
197  static bool _openal_active;
198  unsigned int _concurrent_sound_limit;
199 
200  bool _is_valid;
201 
203  static Managers *_managers;
204 
205  static ALCdevice* _device;
206  static ALCcontext* _context;
207 
208  // cache of openal sources, use only for playing sounds
209  typedef pset<ALuint > SourceCache;
210  static SourceCache *_al_sources;
211 
212  PN_stdfloat _distance_factor;
213  PN_stdfloat _doppler_factor;
214  PN_stdfloat _drop_off_factor;
215 
216  ALfloat _position[3];
217  ALfloat _velocity[3];
218  ALfloat _forward_up[6];
219 
220  ////////////////////////////////////////////////////////////
221  //These are needed for Panda's Pointer System. DO NOT ERASE!
222  ////////////////////////////////////////////////////////////
223 
224  public:
225  static TypeHandle get_class_type() {
226  return _type_handle;
227  }
228  static void init_type() {
229  AudioManager::init_type();
230  register_type(_type_handle, "OpenALAudioManager", AudioManager::get_class_type());
231  }
232  virtual TypeHandle get_type() const {
233  return get_class_type();
234  }
235  virtual TypeHandle force_init_type() {
236  init_type();
237  return get_class_type();
238  }
239 
240  private:
241  static TypeHandle _type_handle;
242 
243  ////////////////////////////////////////////////////////////
244  //DONE
245  ////////////////////////////////////////////////////////////
246 
247 };
248 
249 EXPCL_OPENAL_AUDIO AudioManager *Create_OpenALAudioManager();
250 
251 #endif /* __OPENAL_AUDIO_MANAGER_H__ */
virtual void update()
Must be called every frame.
A MovieAudio is actually any source that provides a sequence of audio samples.
virtual void shutdown()
Call this at exit time to shut down the audio system.
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
A reentrant mutex.
Definition: reMutex.h:36