Panda3D
|
00001 // Filename: openalAudioManager.h 00002 // Created by: Ben Buchwald <bb2@alumni.cmu.edu> 00003 // 00004 // 00005 //////////////////////////////////////////////////////////////////// 00006 // 00007 // PANDA 3D SOFTWARE 00008 // Copyright (c) Carnegie Mellon University. All rights reserved. 00009 // 00010 // All use of this software is subject to the terms of the revised BSD 00011 // license. You should have received a copy of this license along 00012 // with this source code in a file named "LICENSE." 00013 // 00014 //////////////////////////////////////////////////////////////////// 00015 00016 00017 #ifndef __OPENAL_AUDIO_MANAGER_H__ 00018 #define __OPENAL_AUDIO_MANAGER_H__ 00019 00020 #include "pandabase.h" 00021 #ifdef HAVE_OPENAL //[ 00022 00023 #include "audioManager.h" 00024 #include "plist.h" 00025 #include "pmap.h" 00026 #include "pset.h" 00027 #include "movieAudioCursor.h" 00028 #include "reMutex.h" 00029 00030 // OSX uses the OpenAL framework 00031 #ifdef IS_OSX 00032 #include <OpenAL/al.h> 00033 #include <OpenAL/alc.h> 00034 #else 00035 #include <AL/al.h> 00036 #include <AL/alc.h> 00037 #endif 00038 00039 class OpenALAudioSound; 00040 00041 extern void al_audio_errcheck(const char *context); 00042 extern void alc_audio_errcheck(const char *context,ALCdevice* device); 00043 00044 class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager { 00045 class SoundData; 00046 00047 friend class OpenALAudioSound; 00048 friend class OpenALSoundData; 00049 public: 00050 00051 //Constructor and Destructor 00052 OpenALAudioManager(); 00053 virtual ~OpenALAudioManager(); 00054 00055 virtual void shutdown(); 00056 00057 virtual bool is_valid(); 00058 00059 virtual PT(AudioSound) get_sound(const string&, bool positional = false, int mode=SM_heuristic); 00060 virtual PT(AudioSound) get_sound(MovieAudio *sound, bool positional = false, int mode=SM_heuristic); 00061 00062 virtual void uncache_sound(const string&); 00063 virtual void clear_cache(); 00064 virtual void set_cache_limit(unsigned int count); 00065 virtual unsigned int get_cache_limit() const; 00066 00067 virtual void set_volume(PN_stdfloat); 00068 virtual PN_stdfloat get_volume() const; 00069 00070 void set_play_rate(PN_stdfloat play_rate); 00071 PN_stdfloat get_play_rate() const; 00072 00073 virtual void set_active(bool); 00074 virtual bool get_active() const; 00075 00076 // This controls the "set of ears" that listens to 3D spacialized sound 00077 // px, py, pz are position coordinates. Can be 0.0f to ignore. 00078 // vx, vy, vz are a velocity vector in UNITS PER SECOND. 00079 // fx, fy and fz are the respective components of a unit forward-vector 00080 // ux, uy and uz are the respective components of a unit up-vector 00081 // These changes will NOT be invoked until audio_3d_update() is called. 00082 virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, 00083 PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz, 00084 PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, 00085 PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz); 00086 00087 virtual void audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, 00088 PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, 00089 PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, 00090 PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz); 00091 00092 // Control the "relative distance factor" for 3D spacialized audio in units-per-foot. Default is 1.0 00093 // OpenAL has no distance factor but we use this as a scale 00094 // on the min/max distances of sounds to preserve FMOD compatibility. 00095 // Also, adjusts the speed of sound to compensate for unit difference. 00096 virtual void audio_3d_set_distance_factor(PN_stdfloat factor); 00097 virtual PN_stdfloat audio_3d_get_distance_factor() const; 00098 00099 // Control the presence of the Doppler effect. Default is 1.0 00100 // Exaggerated Doppler, use >1.0 00101 // Diminshed Doppler, use <1.0 00102 virtual void audio_3d_set_doppler_factor(PN_stdfloat factor); 00103 virtual PN_stdfloat audio_3d_get_doppler_factor() const; 00104 00105 // Exaggerate or diminish the effect of distance on sound. Default is 1.0 00106 // Faster drop off, use >1.0 00107 // Slower drop off, use <1.0 00108 virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor); 00109 virtual PN_stdfloat audio_3d_get_drop_off_factor() const; 00110 00111 virtual void set_concurrent_sound_limit(unsigned int limit = 0); 00112 virtual unsigned int get_concurrent_sound_limit() const; 00113 virtual void reduce_sounds_playing_to(unsigned int count); 00114 00115 virtual void stop_all_sounds(); 00116 00117 virtual void update(); 00118 00119 private: 00120 void make_current() const; 00121 00122 bool can_use_audio(MovieAudioCursor *source); 00123 bool should_load_audio(MovieAudioCursor *source, int mode); 00124 00125 SoundData *get_sound_data(MovieAudio *source, int mode); 00126 00127 // Tell the manager that the sound dtor was called. 00128 void release_sound(OpenALAudioSound* audioSound); 00129 void increment_client_count(SoundData *sd); 00130 void decrement_client_count(SoundData *sd); 00131 void discard_excess_cache(int limit); 00132 00133 void starting_sound(OpenALAudioSound* audio); 00134 void stopping_sound(OpenALAudioSound* audio); 00135 00136 void cleanup(); 00137 00138 private: 00139 // This global lock protects all access to OpenAL library interfaces. 00140 static ReMutex _lock; 00141 00142 // An expiration queue is a list of SoundData 00143 // that are no longer being used. They are kept 00144 // around for a little while, since it is common to 00145 // stop using a sound for a brief moment and then 00146 // quickly resume. 00147 00148 typedef plist<void *> ExpirationQueue; 00149 ExpirationQueue _expiring_samples; 00150 ExpirationQueue _expiring_streams; 00151 00152 // An AudioSound that uses a SoundData is called a "client" 00153 // of the SoundData. The SoundData keeps track of how 00154 // many clients are using it. When the number of clients 00155 // drops to zero, the SoundData is no longer in use. The 00156 // expiration queue is a list of all SoundData that aren't 00157 // in use, in least-recently-used order. If a SoundData 00158 // in the expiration queue gains a new client, it is removed 00159 // from the expiration queue. When the number of sounds 00160 // in the expiration queue exceeds the cache limit, the 00161 // first sound in the expiration queue is purged. 00162 00163 class SoundData { 00164 public: 00165 SoundData(); 00166 ~SoundData(); 00167 OpenALAudioManager* _manager; 00168 PT(MovieAudio) _movie; 00169 ALuint _sample; 00170 PT(MovieAudioCursor) _stream; 00171 double _length; 00172 int _rate; 00173 int _channels; 00174 int _client_count; 00175 ExpirationQueue::iterator _expire; 00176 }; 00177 00178 00179 typedef phash_map<string, SoundData *> SampleCache; 00180 SampleCache _sample_cache; 00181 00182 typedef phash_set<PT(OpenALAudioSound)> SoundsPlaying; 00183 SoundsPlaying _sounds_playing; 00184 00185 typedef phash_set<OpenALAudioSound *> AllSounds; 00186 AllSounds _all_sounds; 00187 00188 // State: 00189 int _cache_limit; 00190 PN_stdfloat _volume; 00191 PN_stdfloat _play_rate; 00192 bool _active; 00193 bool _cleanup_required; 00194 // keep a count for startup and shutdown: 00195 static int _active_managers; 00196 static bool _openal_active; 00197 unsigned int _concurrent_sound_limit; 00198 00199 bool _is_valid; 00200 00201 typedef pset<OpenALAudioManager *> Managers; 00202 static Managers *_managers; 00203 00204 static ALCdevice* _device; 00205 static ALCcontext* _context; 00206 00207 // cache of openal sources, use only for playing sounds 00208 typedef pset<ALuint > SourceCache; 00209 static SourceCache *_al_sources; 00210 00211 PN_stdfloat _distance_factor; 00212 PN_stdfloat _doppler_factor; 00213 PN_stdfloat _drop_off_factor; 00214 00215 ALfloat _position[3]; 00216 ALfloat _velocity[3]; 00217 ALfloat _forward_up[6]; 00218 00219 //////////////////////////////////////////////////////////// 00220 //These are needed for Panda's Pointer System. DO NOT ERASE! 00221 //////////////////////////////////////////////////////////// 00222 00223 public: 00224 static TypeHandle get_class_type() { 00225 return _type_handle; 00226 } 00227 static void init_type() { 00228 AudioManager::init_type(); 00229 register_type(_type_handle, "OpenALAudioManager", AudioManager::get_class_type()); 00230 } 00231 virtual TypeHandle get_type() const { 00232 return get_class_type(); 00233 } 00234 virtual TypeHandle force_init_type() { 00235 init_type(); 00236 return get_class_type(); 00237 } 00238 00239 private: 00240 static TypeHandle _type_handle; 00241 00242 //////////////////////////////////////////////////////////// 00243 //DONE 00244 //////////////////////////////////////////////////////////// 00245 00246 }; 00247 00248 EXPCL_OPENAL_AUDIO AudioManager *Create_OpenALAudioManager(); 00249 00250 00251 #endif //] 00252 00253 #endif /* __OPENAL_AUDIO_MANAGER_H__ */