Panda3D
|
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