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__ */
ReMutex
A reentrant mutex.
Definition: reMutex.h:32
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
register_type
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
OpenALAudioSound
Definition: openalAudioSound.h:32
plist.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
pmap.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AudioManager::shutdown
virtual void shutdown()
Call this at exit time to shut down the audio system.
Definition: audioManager.cxx:146
AudioManager::update
virtual void update()
Must be called every frame.
Definition: audioManager.cxx:210
plist< void * >
Create_OpenALAudioManager
EXPCL_OPENAL_AUDIO AudioManager * Create_OpenALAudioManager()
Factory Function.
Definition: openalAudioManager.cxx:73
OpenALAudioManager
Definition: openalAudioManager.h:39
movieAudioCursor.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MovieAudioCursor
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudioCursor.h:34
MovieAudio
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:44
AudioSound
Definition: audioSound.h:25
pset.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
audioManager.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AudioManager
Definition: audioManager.h:28
reMutex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
pset
This is our own Panda specialization on the default STL set.
Definition: pset.h:49