Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/audiotraits/fmodAudioSound.cxx

Go to the documentation of this file.
00001 // Filename: fmodAudioSound.cxx
00002 // Created by:  cort (January 22, 2003)
00003 // Prior system by: cary
00004 //
00005 ////////////////////////////////////////////////////////////////////
00006 //
00007 // PANDA 3D SOFTWARE
00008 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00009 //
00010 // All use of this software is subject to the terms of the Panda 3d
00011 // Software license.  You should have received a copy of this license
00012 // along with this source code; you will also find a current copy of
00013 // the license at http://www.panda3d.org/license.txt .
00014 //
00015 // To contact the maintainers of this program write to
00016 // panda3d@yahoogroups.com .
00017 //
00018 ////////////////////////////////////////////////////////////////////
00019 
00020 #include <pandabase.h>
00021 #ifdef HAVE_FMOD //[
00022 
00023 #include "fmodAudioSound.h"
00024 #include "fmodAudioManager.h"
00025 
00026 #include <cmath>
00027 
00028 #ifndef NDEBUG //[
00029   #define fmod_audio_debug(x) \
00030       audio_debug("FmodAudioSound "<<" \""<<get_name()<<"\" "<< x )
00031 #else //][
00032   #define fmod_audio_debug(x) ((void)0)
00033 #endif //]
00034 
00035 FmodAudioSound::
00036 FmodAudioSound(FmodAudioManager* manager, FSOUND_STREAM *audio_data,
00037            string file_name, float length)
00038   : _manager(manager), _audio(audio_data), _file_name(file_name),
00039     _volume(1.0f), _balance(0), _loop_count(1), _length(length),
00040     _active(true), _paused(false), _channel(-1) {
00041   nassertv(!file_name.empty());
00042   nassertv(audio_data != NULL);
00043   audio_debug("FmodAudioSound(manager=0x"<<(void*)&manager
00044           <<", file_name="<<file_name<<")");
00045 }
00046 
00047 FmodAudioSound::
00048 ~FmodAudioSound() {
00049   fmod_audio_debug("~FmodAudioSound()");
00050   this->stop();
00051   _manager->release_sound(this);
00052 }
00053   
00054 void FmodAudioSound::
00055 play() {
00056   if (!_active) {
00057     return;
00058   }
00059 
00060   if(_manager->_bExclusive) {
00061     // stop any other sound that parent mgr is playing
00062     _manager->stop_all_sounds();
00063   }
00064 
00065   // If the sound is already playing, stop it.
00066   if (this->status() == AudioSound::PLAYING) {
00067     this->stop();
00068   }
00069 
00070   // Play the stream, but start it paused so we can set the volume and
00071   // panning first.
00072   assert(_audio != NULL);
00073   _channel = FSOUND_Stream_PlayEx(FSOUND_FREE, _audio, NULL, 1);
00074   if (_channel == -1) {
00075     fmod_audio_debug("play() failed");
00076     return;
00077   }
00078   
00079   // Set volume.
00080   unsigned char new_volume = (unsigned char)(_volume*255.0f);
00081   FSOUND_SetVolume(_channel, new_volume);
00082   
00083   // Set panning.
00084   unsigned char new_balance = (unsigned char)( (_balance+1.0f)*0.5f*255.0f);
00085   FSOUND_SetPan(_channel, new_balance);
00086   
00087   // Set looping -- unimplemented
00088   
00089   // Unpause and set status to playing
00090   FSOUND_SetPaused(_channel, 0);
00091 
00092   // Delay until the channel is actually playing.  This shouldn't
00093   // result in a noticeable delay, and allows you to immediately test
00094   // the status of the sound after initiating playback.
00095   while (!FSOUND_IsPlaying(_channel));
00096 }
00097 
00098 void FmodAudioSound::stop() {
00099   FSOUND_Stream_Stop(_audio);
00100   _channel = -1;
00101 }
00102 
00103 void FmodAudioSound::set_loop(bool loop) {
00104   audio_error("FmodAudioSound::set_loop() -- not yet implemented");
00105   fmod_audio_debug("set_loop() set to "<<loop);
00106   _loop_count = loop ? 0 : 1;
00107 }
00108 
00109 bool FmodAudioSound::get_loop() const {
00110   fmod_audio_debug("get_loop() returning "<<(_loop_count==0));
00111   return (_loop_count == 0);
00112 }
00113   
00114 void FmodAudioSound::set_loop_count(unsigned long loop_count) {
00115   audio_error("FmodAudioSound::set_loop_count() -- not yet implemented");
00116   fmod_audio_debug("set_loop_count() set to "<<loop_count);
00117   _loop_count = loop_count;
00118 }
00119 
00120 unsigned long FmodAudioSound::get_loop_count() const {
00121   fmod_audio_debug("get_loop_count() returning "<<_loop_count);
00122   return _loop_count;
00123 }
00124   
00125 void FmodAudioSound::set_time(float start_time) {
00126   if (start_time < 0.0f) {
00127     fmod_audio_debug("set_time(): param "<<start_time<<" out of range.");
00128     fmod_audio_debug("set_time(): clamping to zero.");
00129     start_time = 0.0f;
00130   } else if (start_time > _length) {
00131     fmod_audio_debug("set_time(): param "<<start_time<<" out of range.");
00132     fmod_audio_debug("set_time(): clamping to length ("<<_length<<".");
00133     start_time = _length - 0.01;
00134   }
00135   // FMOD measures time in milliseconds, so scale up by 1000.
00136   FSOUND_Stream_SetTime(_audio, (int)(start_time * 1000.0f));
00137 }
00138 
00139 float FmodAudioSound::get_time() const {
00140   // A bug in stream WAV files causes FSOUND_Stream_GetTime() to
00141   // divide-by-zero somewhere if the stream isn't currently playing.
00142   // In this case, we should just return zero.
00143   if (!FSOUND_IsPlaying(_channel)) {
00144     return 0.0f;
00145   }
00146 
00147   // FMOD measures time in milliseconds, so scale down by 1000.
00148   float current_time = FSOUND_Stream_GetTime(_audio) * 0.001f;
00149   //fmod_audio_debug("get_time() returning "<<current_time);
00150   return current_time;
00151 }
00152 
00153 void FmodAudioSound::set_volume(float vol) {
00154   if (vol < 0.0f) {
00155     fmod_audio_debug("set_volume(): param "<<vol<<" out of range.");
00156     fmod_audio_debug("set_volume(): clamping to zero.");
00157     vol = 0.0f;
00158   } else if (vol > 1.0f) {
00159     fmod_audio_debug("set_volume(): param "<<vol<<" out of range.");
00160     fmod_audio_debug("set_volume(): clamping to 1.0");
00161     vol = 1.0f;
00162   }
00163   _volume = vol;
00164   unsigned char new_volume = (unsigned char)(_volume*255.0f);
00165   FSOUND_SetVolume(_channel, new_volume);
00166 }
00167 
00168 float FmodAudioSound::get_volume() const {
00169   fmod_audio_debug("get_volume() returning "<<_volume);
00170   return _volume;
00171 }
00172 
00173 void FmodAudioSound::set_balance(float bal) {
00174   if (bal < -1.0f) {
00175     fmod_audio_debug("set_balance(): param "<<bal<<" out of range.");
00176     fmod_audio_debug("set_balance(): clamping to -1.0.");
00177     bal = -1.0f;
00178   } else if (bal > 1.0f) {
00179     fmod_audio_debug("set_balance(): param "<<bal<<" out of range.");
00180     fmod_audio_debug("set_balance(): clamping to 1.0");
00181     bal = 1.0f;
00182   }
00183   _balance = bal;
00184   unsigned char new_balance = (unsigned char)( (_balance+1.0f)*0.5f*255.0f);
00185   FSOUND_SetPan(_channel, new_balance);
00186 }
00187 
00188 float FmodAudioSound::get_balance() const {
00189   fmod_audio_debug("get_balance() returning "<<_balance);
00190   return _balance;
00191 }
00192 
00193 void FmodAudioSound::set_active(bool active) {
00194   fmod_audio_debug("set_active(active="<<active<<")");
00195   if (!active) {
00196     // Once looping works, a looping sound should be paused, not
00197     // stopped.  When the sound is activated again, it is unpaused.
00198     this->stop();
00199   }
00200   _active = active;
00201 }
00202 
00203 bool FmodAudioSound::get_active() const {
00204   fmod_audio_debug("get_active() returning "<<_active);
00205   return _active;
00206 }
00207 
00208 const string& FmodAudioSound::get_name() const {
00209   //fmod_audio_debug("get_name() returning "<<_file_name);
00210   return _file_name;
00211 }
00212 
00213 float FmodAudioSound::length() const {
00214   return _length;
00215 }
00216 
00217 AudioSound::SoundStatus FmodAudioSound::status() const {
00218   // If the stream's channel isn't playing anything, then the stream
00219   // definitely isn't playing.
00220   if (!FSOUND_IsPlaying(_channel)) {
00221     return AudioSound::READY;
00222   }
00223   
00224   // If the channel is playing, see whether the current time is at the
00225   // end of the file.  If not, the stream is playing.
00226   float current_time = this->get_time();
00227   if (current_time >= _length - 0.01f) {
00228     // FMOD MIDI files don't stop automatically when they hit the end of the
00229     // file.  Their channel isn't released unless the stream is stopped
00230     // explicitly.
00231     FSOUND_Stream_Stop(_audio);
00232     return AudioSound::READY;
00233   } else {
00234     return AudioSound::PLAYING;
00235   }
00236 }
00237 
00238 #endif //]

Generated on Fri May 2 00:34:31 2003 for Panda by doxygen1.3