Panda3D

openalAudioManager.h

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__ */
 All Classes Functions Variables Enumerations