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 #include "fmodAudioManager.h"
00081 
00082 #include <fmod.hpp>
00083 #include <fmod_errors.h>
00084 
00085 class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound {
00086  public:
00087 
00088   FmodAudioSound(AudioManager *manager, Filename fn, bool positional );
00089   ~FmodAudioSound();
00090 
00091   // For best compatibility, set the loop_count, start_time,
00092   // volume, and balance, prior to calling play().  You may
00093   // set them while they're playing, but it's implementation
00094   // specific whether you get the results.
00095   void play();
00096   void stop();
00097 
00098   // loop: false = play once; true = play forever.
00099   // inits to false.
00100   void set_loop(bool loop=true);
00101   bool get_loop() const;
00102 
00103   // loop_count: 0 = forever; 1 = play once; n = play n times.
00104   // inits to 1.
00105   void set_loop_count(unsigned long loop_count=1);
00106   unsigned long get_loop_count() const;
00107 
00108   // 0 = beginning; length() = end.
00109   // inits to 0.0.
00110   void set_time(PN_stdfloat start_time=0.0);
00111   PN_stdfloat get_time() const;
00112 
00113   // 0 = minimum; 1.0 = maximum.
00114   // inits to 1.0.
00115   void set_volume(PN_stdfloat volume=1.0);
00116   PN_stdfloat get_volume() const;
00117 
00118   // -1.0 is hard left
00119   // 0.0 is centered
00120   // 1.0 is hard right
00121   // inits to 0.0.
00122   void set_balance(PN_stdfloat balance_right=0.0);
00123   PN_stdfloat get_balance() const;
00124 
00125   // play_rate is any positive float value.
00126   // inits to 1.0.
00127   void set_play_rate(PN_stdfloat play_rate=1.0f);
00128   PN_stdfloat get_play_rate() const;
00129 
00130   const string &get_name() const;
00131 
00132   // return: playing time in seconds.
00133   PN_stdfloat length() const;
00134 
00135   // Controls the position of this sound's emitter.
00136   // pos is a pointer to an xyz triplet of the emitter's position.
00137   // vel is a pointer to an xyz triplet of the emitter's velocity.
00138   void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz);
00139   void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz);
00140 
00141   void set_3d_min_distance(PN_stdfloat dist);
00142   PN_stdfloat get_3d_min_distance() const;
00143 
00144   void set_3d_max_distance(PN_stdfloat dist);
00145   PN_stdfloat get_3d_max_distance() const;
00146 
00147   AudioSound::SoundStatus status() const;
00148 
00149   virtual PN_stdfloat get_speaker_mix(AudioManager::SpeakerId speaker);
00150   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);
00151 
00152   void set_active(bool active=true);
00153   bool get_active() const;
00154 
00155   void finished();
00156   void set_finished_event(const string& event);
00157   const string& get_finished_event() const;
00158 
00159  private:
00160   PT(FmodAudioManager) _manager;
00161   FMOD::Sound      *_sound;
00162   FMOD::Channel    *_channel;
00163 
00164   Filename _file_name;
00165 
00166   float _volume; 
00167   float _balance;
00168   float _playrate;
00169   int   _priority;
00170   float _mix[AudioManager::SPK_COUNT];
00171 
00172   float _sampleFrequency;
00173   mutable float _length;   //in seconds.
00174 
00175   FMOD_SPEAKERMODE  _speakermode;
00176 
00177   FMOD_VECTOR _location;
00178   FMOD_VECTOR _velocity;
00179 
00180   PN_stdfloat _min_dist;
00181   PN_stdfloat _max_dist;
00182 
00183   void start_playing();
00184   void set_volume_on_channel();
00185   void set_balance_on_channel();
00186   void set_play_rate_on_channel();
00187   void set_speaker_mix_on_channel();
00188   void set_3d_attributes_on_channel();
00189   // void add_dsp_on_channel();
00190   void set_speaker_mix_or_balance_on_channel();
00191 
00192   virtual int get_priority();
00193   virtual void set_priority(int priority);
00194 
00195   bool _active;
00196   bool _paused;
00197   PN_stdfloat _start_time;
00198 
00199   string _finished_event;
00200 
00201   // This reference-counting pointer is set to this while the sound is
00202   // playing, and cleared when we get an indication that the sound has
00203   // stopped.  This prevents a sound from destructing while it is
00204   // playing.  We use a PT instead of managing the reference counts by
00205   // hand to help guard against accidental reference count leaks or
00206   // other mismanagement.
00207   PT(FmodAudioSound) _self_ref;
00208 
00209   static FMOD_RESULT F_CALLBACK
00210   sound_end_callback(FMOD_CHANNEL *  channel, 
00211                      FMOD_CHANNEL_CALLBACKTYPE  type, 
00212                      void *commanddata1, 
00213                      void *commanddata2);
00214 
00215   static FMOD_RESULT F_CALLBACK 
00216   open_callback(const char *name, int unicode, unsigned int *file_size,
00217                 void **handle, void **user_data);
00218 
00219   static FMOD_RESULT F_CALLBACK 
00220   close_callback(void *handle, void *user_data);
00221 
00222   static FMOD_RESULT F_CALLBACK 
00223   read_callback(void *handle, void *buffer, unsigned int size_bytes,
00224                 unsigned int *bytes_read, void *user_data);
00225   
00226   static FMOD_RESULT F_CALLBACK 
00227   seek_callback(void *handle, unsigned int pos, void *user_data);
00228   
00229 
00230   ////////////////////////////////////////////////////////////
00231   //These are needed for Panda's Pointer System. DO NOT ERASE!
00232   ////////////////////////////////////////////////////////////
00233 
00234  public:
00235   static TypeHandle get_class_type() {
00236     return _type_handle;
00237   }
00238   static void init_type() {
00239     AudioSound::init_type();
00240     register_type(_type_handle, "FmodAudioSound", AudioSound::get_class_type());
00241   }
00242   virtual TypeHandle get_type() const {
00243     return get_class_type();
00244   }
00245   virtual TypeHandle force_init_type() {
00246     init_type();
00247     return get_class_type();
00248   }
00249 
00250  private:
00251   static TypeHandle _type_handle;
00252 
00253   ////////////////////////////////////////////////////////////
00254   //DONE
00255   ////////////////////////////////////////////////////////////
00256 };
00257 
00258 #include "fmodAudioSound.I"
00259 
00260 #endif //]
00261 
00262 #endif /* __FMOD_AUDIO_SOUND_H__ */
00263 
00264 
00265 
00266 
00267