fmodAudioSound.h
00001 // Filename: fmodAudioSound.h
00002 // Created by:  cort (January 22, 2003)
00003 // Prior system by: cary
00004 // Rewrite [for new Version of FMOD-EX] by: Stan Rosenbaum "Staque" - Spring 2006
00005 //
00006 //
00007 ////////////////////////////////////////////////////////////////////
00008 //
00009 // PANDA 3D SOFTWARE
00010 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00011 //
00012 // All use of this software is subject to the terms of the revised BSD
00013 // license.  You should have received a copy of this license along
00014 // with this source code in a file named "LICENSE."
00015 //
00016 ////////////////////////////////////////////////////////////////////
00017 //
00018 //
00019 //
00020 ////////////////////////////////////////////////////////////////////
00021 //
00022 // [FIRST READ FmodAudioManager for an Introduction if you haven't
00023 // already].
00024 //
00025 // Hello, all future Panda audio code people! This is my errata
00026 // documentation to Help any future programmer maintain FMOD and PANDA.
00027 //
00028 // Well, if you reading this you probably want to know how PANDA deals
00029 // with sounds directly using FMOD-EX. Well I am going to tell you.
00030 //
00031 // The first thing, you as the programmer have to understand,
00032 // especially if you never have done sound programming before, is how
00033 // the FMOD-EX API works.
00034 //
00035 // With FMOD-EX the guys at Firelight, adopted a model of managing
00036 // sounds with FMOD similar to how a Sound Designer creates sound in a
00037 // sound studio using SOUNDS and CHANNELS. Although this may seem
00038 // strange at first, if you are not familiar with sound programming,
00039 // there is a very good metaphor you are probably already familiar with
00040 // to explain how FMOD-EX works.
00041 //
00042 // Think of you standard GUI API. Usually a GUI API is made up of two
00043 // things: Windows and Widgets. These correspond to CHANNELS and
00044 // SOUNDS, where a Channel is a Window and a Sound is Widget. Sounds
00045 // are played within channels, and channels don't exist unless they
00046 // have something to display.
00047 //
00048 // Now why am I explaining all of this? When PANDA was created they set
00049 // up the basic audio classes to handle only the idea of a SOUND. The
00050 // idea of a Channel really wasn't prevalent as in more modern Audio
00051 // APIs. With this rewrite of PANDA to use the FMOD-EX API, the PANDA
00052 // FmodAudioSound Class, now has to handle two different parts of the
00053 // FMOD-EX API in order to play a sound.
00054 //
00055 // SOUND: The object the handles the audio data in form of WAV, AIF,
00056 // OGG, MID, IT, MP3, etc... And CHANNEL: The object that actually
00057 // plays the sound and manipulates it in real time.
00058 //
00059 // Ultimately this isn't a problem expect for a couple situations when
00060 // you go to play a sound, which I will explain in more detail in that
00061 // part of the code. All that you have to know right now is that
00062 // Channels in FMOD do not exist unless they are playing a sound. And
00063 // in the PANDA FmodAudioSound API class there is only ONE dedicated
00064 // channel per sound.  Otherwise there is really nothing to worry
00065 // about.
00066 //
00067 ////////////////////////////////////////////////////////////////////
00068 
00069 
00070 
00071 #ifndef __FMOD_AUDIO_SOUND_H__
00072 #define __FMOD_AUDIO_SOUND_H__
00073 
00074 #include <pandabase.h>
00075 
00076 #ifdef HAVE_FMODEX //[
00077 
00078 #include "audioSound.h"
00079 #include "reMutex.h"
00080 
00081 #include <fmod.hpp>
00082 #include <fmod_errors.h>
00083 
00084 class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound {
00085  public:
00086 
00087   FmodAudioSound(AudioManager *manager, Filename fn, bool positional );
00088   ~FmodAudioSound();
00089 
00090   // For best compatibility, set the loop_count, start_time,
00091   // volume, and balance, prior to calling play().  You may
00092   // set them while they're playing, but it's implementation
00093   // specific whether you get the results.
00094   void play();
00095   void stop();
00096 
00097   // loop: false = play once; true = play forever.
00098   // inits to false.
00099   void set_loop(bool loop=true);
00100   bool get_loop() const;
00101 
00102   // loop_count: 0 = forever; 1 = play once; n = play n times.
00103   // inits to 1.
00104   void set_loop_count(unsigned long loop_count=1);
00105   unsigned long get_loop_count() const;
00106 
00107   // 0 = beginning; length() = end.
00108   // inits to 0.0.
00109   void set_time(PN_stdfloat start_time=0.0);
00110   PN_stdfloat get_time() const;
00111 
00112   // 0 = minimum; 1.0 = maximum.
00113   // inits to 1.0.
00114   void set_volume(PN_stdfloat volume=1.0);
00115   PN_stdfloat get_volume() const;
00116 
00117   // -1.0 is hard left
00118   // 0.0 is centered
00119   // 1.0 is hard right
00120   // inits to 0.0.
00121   void set_balance(PN_stdfloat balance_right=0.0);
00122   PN_stdfloat get_balance() const;
00123 
00124   // play_rate is any positive float value.
00125   // inits to 1.0.
00126   void set_play_rate(PN_stdfloat play_rate=1.0f);
00127   PN_stdfloat get_play_rate() const;
00128 
00129   const string &get_name() const;
00130 
00131   // return: playing time in seconds.
00132   PN_stdfloat length() const;
00133 
00134   // Controls the position of this sound's emitter.
00135   // pos is a pointer to an xyz triplet of the emitter's position.
00136   // vel is a pointer to an xyz triplet of the emitter's velocity.
00137   void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz);
00138   void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz);
00139 
00140   void set_3d_min_distance(PN_stdfloat dist);
00141   PN_stdfloat get_3d_min_distance() const;
00142 
00143   void set_3d_max_distance(PN_stdfloat dist);
00144   PN_stdfloat get_3d_max_distance() const;
00145 
00146   AudioSound::SoundStatus status() const;
00147 
00148   virtual PN_stdfloat get_speaker_mix(AudioManager::SpeakerId speaker);
00149   virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat  sideright);
00150 
00151   void set_active(bool active=true);
00152   bool get_active() const;
00153 
00154   void finished();
00155   void set_finished_event(const string& event);
00156   const string& get_finished_event() const;
00157 
00158  private:
00159   PT(FmodAudioManager) _manager;
00160   FMOD::Sound      *_sound;
00161   FMOD::Channel    *_channel;
00162 
00163   Filename _file_name;
00164 
00165   float _volume; 
00166   float _balance;
00167   float _playrate;
00168   int   _priority;
00169   float _mix[AudioManager::SPK_COUNT];
00170 
00171   float _sampleFrequency;
00172   mutable float _length;   //in seconds.
00173 
00174   FMOD_SPEAKERMODE  _speakermode;
00175 
00176   FMOD_VECTOR _location;
00177   FMOD_VECTOR _velocity;
00178 
00179   PN_stdfloat _min_dist;
00180   PN_stdfloat _max_dist;
00181 
00182   void start_playing();
00183   void set_volume_on_channel();
00184   void set_balance_on_channel();
00185   void set_play_rate_on_channel();
00186   void set_speaker_mix_on_channel();
00187   void set_3d_attributes_on_channel();
00188   // void add_dsp_on_channel();
00189   void set_speaker_mix_or_balance_on_channel();
00190 
00191   virtual int get_priority();
00192   virtual void set_priority(int priority);
00193 
00194   bool _active;
00195   bool _paused;
00196   PN_stdfloat _start_time;
00197 
00198   string _finished_event;
00199 
00200   // This reference-counting pointer is set to this while the sound is
00201   // playing, and cleared when we get an indication that the sound has
00202   // stopped.  This prevents a sound from destructing while it is
00203   // playing.  We use a PT instead of managing the reference counts by
00204   // hand to help guard against accidental reference count leaks or
00205   // other mismanagement.
00206   PT(FmodAudioSound) _self_ref;
00207 
00208   static FMOD_RESULT F_CALLBACK
00209   sound_end_callback(FMOD_CHANNEL *  channel, 
00210                      FMOD_CHANNEL_CALLBACKTYPE  type, 
00211                      void *commanddata1, 
00212                      void *commanddata2);
00213 
00214   static FMOD_RESULT F_CALLBACK 
00215   open_callback(const char *name, int unicode, unsigned int *file_size,
00216                 void **handle, void **user_data);
00217 
00218   static FMOD_RESULT F_CALLBACK 
00219   close_callback(void *handle, void *user_data);
00220 
00221   static FMOD_RESULT F_CALLBACK 
00222   read_callback(void *handle, void *buffer, unsigned int size_bytes,
00223                 unsigned int *bytes_read, void *user_data);
00224   
00225   static FMOD_RESULT F_CALLBACK 
00226   seek_callback(void *handle, unsigned int pos, void *user_data);
00227   
00228 
00229   ////////////////////////////////////////////////////////////
00230   //These are needed for Panda's Pointer System. DO NOT ERASE!
00231   ////////////////////////////////////////////////////////////
00232 
00233  public:
00234   static TypeHandle get_class_type() {
00235     return _type_handle;
00236   }
00237   static void init_type() {
00238     AudioSound::init_type();
00239     register_type(_type_handle, "FmodAudioSound", AudioSound::get_class_type());
00240   }
00241   virtual TypeHandle get_type() const {
00242     return get_class_type();
00243   }
00244   virtual TypeHandle force_init_type() {
00245     init_type();
00246     return get_class_type();
00247   }
00248 
00249  private:
00250   static TypeHandle _type_handle;
00251 
00252   ////////////////////////////////////////////////////////////
00253   //DONE
00254   ////////////////////////////////////////////////////////////
00255 };
00256 
00257 #include "fmodAudioSound.I"
00258 
00259 #endif //]
00260 
00261 #endif /* __FMOD_AUDIO_SOUND_H__ */
00262 
00263 
00264 
00265 
00266