Panda3D
openalAudioManager.h
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file openalAudioManager.h
10  * @author Ben Buchwald <bb2@alumni.cmu.edu>
11  */
12 
13 #ifndef __OPENAL_AUDIO_MANAGER_H__
14 #define __OPENAL_AUDIO_MANAGER_H__
15 
16 #include "pandabase.h"
17 
18 #include "audioManager.h"
19 #include "plist.h"
20 #include "pmap.h"
21 #include "pset.h"
22 #include "movieAudioCursor.h"
23 #include "reMutex.h"
24 
25 // OSX uses the OpenAL framework
26 #ifdef HAVE_OPENAL_FRAMEWORK
27  #include <OpenAL/al.h>
28  #include <OpenAL/alc.h>
29 #else
30  #include <AL/al.h>
31  #include <AL/alc.h>
32 #endif
33 
34 class OpenALAudioSound;
35 
36 extern void al_audio_errcheck(const char *context);
37 extern void alc_audio_errcheck(const char *context,ALCdevice* device);
38 
39 class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager {
40  class SoundData;
41 
42  friend class OpenALAudioSound;
43  friend class OpenALSoundData;
44 
45  public:
46  // Constructor and Destructor
48  virtual ~OpenALAudioManager();
49 
50  virtual void shutdown();
51 
52  virtual bool is_valid();
53 
54  virtual PT(AudioSound) get_sound(const Filename &, bool positional = false, int mode=SM_heuristic);
55  virtual PT(AudioSound) get_sound(MovieAudio *sound, bool positional = false, int mode=SM_heuristic);
56 
57  virtual void uncache_sound(const Filename &);
58  virtual void clear_cache();
59  virtual void set_cache_limit(unsigned int count);
60  virtual unsigned int get_cache_limit() const;
61 
62  virtual void set_volume(PN_stdfloat);
63  virtual PN_stdfloat get_volume() const;
64 
65  void set_play_rate(PN_stdfloat play_rate);
66  PN_stdfloat get_play_rate() const;
67 
68  virtual void set_active(bool);
69  virtual bool get_active() const;
70 
71  // This controls the "set of ears" that listens to 3D spacialized sound px,
72  // py, pz are position coordinates. Can be 0.0f to ignore. vx, vy, vz are
73  // a velocity vector in UNITS PER SECOND. fx, fy and fz are the respective
74  // components of a unit forward-vector ux, uy and uz are the respective
75  // components of a unit up-vector These changes will NOT be invoked until
76  // audio_3d_update() is called.
77  virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz,
78  PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz,
79  PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz,
80  PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz);
81 
82  virtual void audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz,
83  PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz,
84  PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz,
85  PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz);
86 
87 
88  // Control the "relative scale that sets the distance factor" units for 3D
89  // spacialized audio. This is a float in units-per-meter. Default value is
90  // 1.0, which means that Panda units are understood as meters; for e.g.
91  // feet, set 3.28. This factor is applied only to Fmod and OpenAL at the
92  // moment.
93  // OpenAL in fact has no distance factor like Fmod, but works with the speed
94  // of sound instead, so we use this factor to scale the speed of sound.
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 Exaggerated
99  // Doppler, use >1.0 Diminshed Doppler, use <1.0
100  virtual void audio_3d_set_doppler_factor(PN_stdfloat factor);
101  virtual PN_stdfloat audio_3d_get_doppler_factor() const;
102 
103  // Exaggerate or diminish the effect of distance on sound. Default is 1.0
104  // Faster drop off, use >1.0 Slower drop off, use <1.0
105  virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor);
106  virtual PN_stdfloat audio_3d_get_drop_off_factor() const;
107 
108  virtual void set_concurrent_sound_limit(unsigned int limit = 0);
109  virtual unsigned int get_concurrent_sound_limit() const;
110  virtual void reduce_sounds_playing_to(unsigned int count);
111 
112  virtual void stop_all_sounds();
113 
114  virtual void update();
115 
116 private:
117  std::string select_audio_device();
118 
119  void make_current() const;
120 
121  bool can_use_audio(MovieAudioCursor *source);
122  bool should_load_audio(MovieAudioCursor *source, int mode);
123 
124  SoundData *get_sound_data(MovieAudio *source, int mode);
125 
126  // Tell the manager that the sound dtor was called.
127  void release_sound(OpenALAudioSound* audioSound);
128  void increment_client_count(SoundData *sd);
129  void decrement_client_count(SoundData *sd);
130  void discard_excess_cache(int limit);
131 
132  void delete_buffer(ALuint buffer);
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 that are no longer being used.
144  // They are kept around for a little while, since it is common to stop using
145  // a sound for a brief moment and then quickly resume.
146 
148  ExpirationQueue _expiring_samples;
149  ExpirationQueue _expiring_streams;
150 
151 /*
152  * An AudioSound that uses a SoundData is called a "client" of the SoundData.
153  * The SoundData keeps track of how many clients are using it. When the
154  * number of clients drops to zero, the SoundData is no longer in use. The
155  * expiration queue is a list of all SoundData that aren't in use, in least-
156  * recently-used order. If a SoundData in the expiration queue gains a new
157  * client, it is removed from the expiration queue. When the number of sounds
158  * in the expiration queue exceeds the cache limit, the first sound in the
159  * expiration queue is purged.
160  */
161 
162  class SoundData {
163  public:
164  SoundData();
165  ~SoundData();
166  OpenALAudioManager* _manager;
167  PT(MovieAudio) _movie;
168  ALuint _sample;
169  PT(MovieAudioCursor) _stream;
170  double _length;
171  int _rate;
172  int _channels;
173  int _client_count;
174  ExpirationQueue::iterator _expire;
175  };
176 
177 
178  typedef phash_map<std::string, SoundData *> SampleCache;
179  SampleCache _sample_cache;
180 
181  typedef phash_set<PT(OpenALAudioSound)> SoundsPlaying;
182  SoundsPlaying _sounds_playing;
183 
184  typedef phash_set<OpenALAudioSound *> AllSounds;
185  AllSounds _all_sounds;
186 
187  // State:
188  int _cache_limit;
189  PN_stdfloat _volume;
190  PN_stdfloat _play_rate;
191  bool _active;
192  bool _cleanup_required;
193  // keep a count for startup and shutdown:
194  static int _active_managers;
195  static bool _openal_active;
196  unsigned int _concurrent_sound_limit;
197 
198  bool _is_valid;
199 
201  static Managers *_managers;
202 
203  static ALCdevice* _device;
204  static ALCcontext* _context;
205 
206  // cache of openal sources, use only for playing sounds
207  typedef pset<ALuint > SourceCache;
208  static SourceCache *_al_sources;
209 
210  PN_stdfloat _distance_factor;
211  PN_stdfloat _doppler_factor;
212  PN_stdfloat _drop_off_factor;
213 
214  ALfloat _position[3];
215  ALfloat _velocity[3];
216  ALfloat _forward_up[6];
217 
218  // These are needed for Panda's Pointer System. DO NOT ERASE!
219 
220  public:
221  static TypeHandle get_class_type() {
222  return _type_handle;
223  }
224  static void init_type() {
225  AudioManager::init_type();
226  register_type(_type_handle, "OpenALAudioManager", AudioManager::get_class_type());
227  }
228  virtual TypeHandle get_type() const {
229  return get_class_type();
230  }
231  virtual TypeHandle force_init_type() {
232  init_type();
233  return get_class_type();
234  }
235 
236  private:
237  static TypeHandle _type_handle;
238 
239  // DONE
240 
241 };
242 
243 EXPCL_OPENAL_AUDIO AudioManager *Create_OpenALAudioManager();
244 
245 #endif /* __OPENAL_AUDIO_MANAGER_H__ */
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EXPCL_OPENAL_AUDIO AudioManager * Create_OpenALAudioManager()
Factory Function.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
Definition: register_type.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void update()
Must be called every frame.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A MovieAudio is actually any source that provides a sequence of audio samples.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void shutdown()
Call this at exit time to shut down the audio system.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL set.
Definition: pset.h:49
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:44
A reentrant mutex.
Definition: reMutex.h:32