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

panda/src/audiotraits/milesAudioSound.cxx

Go to the documentation of this file.
00001 // Filename: milesAudioSound.cxx
00002 // Created by:  skyler (June 6, 2001)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include <pandabase.h>
00020 #ifdef HAVE_RAD_MSS //[
00021 
00022 #include "milesAudioSound.h"
00023 #include "milesAudioManager.h"
00024 
00025 #define NEED_MILES_LENGTH_WORKAROUND
00026 
00027 #if (((MSS_MAJOR_VERSION == 6) && (MSS_MINOR_VERSION >= 5)) || (MSS_MAJOR_VERSION >= 7))
00028 #define MILES_6_5
00029 #endif
00030 
00031 #ifndef NDEBUG //[
00032   namespace {
00033     char
00034     getStatusChar(HAUDIO audio) {
00035       if (!audio) {
00036         return '0'; // NULL.
00037       }
00038       switch (AIL_quick_status(audio)) {
00039         case QSTAT_LOADED:
00040         case QSTAT_DONE:
00041           return 'r'; // Ready.
00042         case QSTAT_PLAYING:
00043           return 'p'; // Playing.
00044         default:
00045           return 'x'; // bad.
00046       }
00047     }
00048   }
00049 
00050   #define miles_audio_debug(x) \
00051       audio_debug("MilesAudioSound "<<getStatusChar(_audio)<<" \""<<get_name() \
00052       <<"\" "<< x )
00053 #else //][
00054   #define miles_audio_debug(x) ((void)0)
00055 #endif //]
00056 
00057 MilesAudioSound::
00058 MilesAudioSound(MilesAudioManager* manager,
00059     HAUDIO audio, string file_name, float length)
00060     : _manager(manager), _file_name(file_name),
00061     _volume(1.0f), _balance(0),
00062     _loop_count(1), _length(length),
00063     _active(true), _paused(false) {
00064   nassertv(audio);
00065   nassertv(!file_name.empty());
00066   audio_debug("MilesAudioSound(manager=0x"<<(void*)&manager
00067       <<", audio=0x"<<(void*)audio<<", file_name="<<file_name<<")");
00068   // Make our own copy of the sound header data:
00069   _audio=AIL_quick_copy(audio);
00070 }
00071 
00072 MilesAudioSound::
00073 ~MilesAudioSound() {
00074   miles_audio_debug("~MilesAudioSound()");
00075   _manager->release_sound(this);
00076   AIL_quick_unload(_audio);
00077 }
00078 
00079 void MilesAudioSound::
00080 play() {
00081   #if 0
00082   if(_file_name.find(".mid")!=string::npos) {
00083      miles_audio_debug("play() midi");
00084   }
00085   #endif
00086   
00087   miles_audio_debug("play()");
00088   if (_active) {
00089     if(_manager->_bExclusive) {
00090         // stop any other sound that parent mgr is playing
00091         _manager->stop_all_sounds();
00092     }
00093     // Start playing:
00094     if (AIL_quick_play(_audio, _loop_count)) {
00095       audio_debug("  started sound " << _file_name );
00096     } else {
00097       audio_debug("  sound " << _file_name<<" failed to start, err: " <<AIL_last_error());
00098     }
00099   } else {
00100     // In case _loop_count gets set to forever (zero):
00101     audio_debug("  paused "<<_file_name );
00102     _paused=true;
00103   }
00104 }
00105 
00106 void MilesAudioSound::
00107 stop() {
00108   #if 0
00109   if(_file_name.find(".mid")!=string::npos) {
00110         miles_audio_debug("stop() midi");
00111   } 
00112   #endif
00113   miles_audio_debug("stopping snd " << _file_name);
00114   _paused=false;
00115   AIL_quick_halt(_audio);
00116 }
00117 
00118 void MilesAudioSound::
00119 halt() {
00120   #if 0
00121   if(_file_name.find(".mid")!=string::npos) {
00122         miles_audio_debug("halt() midi");
00123         int i=1;
00124   }
00125   #endif
00126 
00127   miles_audio_debug("halt()");
00128   AIL_quick_halt(_audio);
00129 }
00130 
00131 void MilesAudioSound::
00132 set_loop(bool loop) {
00133   miles_audio_debug("set_loop(loop="<<loop<<")");
00134   // loop count of 0 means always loop
00135   set_loop_count((loop)?0:1);
00136 }
00137 
00138 bool MilesAudioSound::
00139 get_loop() const {
00140   miles_audio_debug("get_loop() returning "<<(_loop_count==0));
00141   return (_loop_count == 0);
00142 }
00143 
00144 void MilesAudioSound::
00145 set_loop_count(unsigned long loop_count) {
00146   miles_audio_debug("set_loop_count(loop_count="<<loop_count<<")");
00147   if (_loop_count!=loop_count) {
00148     _loop_count=loop_count;
00149     if (status()==PLAYING) {
00150       // hack:
00151       // For now, the loop count is picked up when the sound starts playing.
00152       // There may be a way to change the loop count of a playing sound, but
00153       // I'm going to focus on other things.  If you would like to change the
00154       // need to stop and start the sound, feel free.  Or, maybe I'll spend
00155       // time on it in the future.  Please set the loop option before starting
00156       // the sound.
00157       halt();
00158       play();
00159     }
00160   }
00161 }
00162 
00163 unsigned long MilesAudioSound::
00164 get_loop_count() const {
00165   miles_audio_debug("get_loop_count() returning "<<_loop_count);
00166   return _loop_count;
00167 }
00168 
00169 void MilesAudioSound::
00170 set_time(float time) {
00171   miles_audio_debug("set_time(time="<<time<<")");
00172   S32 milisecond_time=S32(1000*time);
00173   AIL_quick_set_ms_position(_audio, milisecond_time);
00174 }
00175 
00176 float MilesAudioSound::
00177 get_time() const {
00178   S32 milisecond_time=AIL_quick_ms_position(_audio);
00179   float time=float(milisecond_time*.001);
00180   miles_audio_debug("get_time() returning "<<time);
00181   return time;
00182 }
00183 
00184 void MilesAudioSound::
00185 set_volume(float volume) {
00186   miles_audio_debug("set_volume(volume="<<volume<<")");
00187   // *Set the volume even if our volume is not changing, because the
00188   // *MilesAudioManager will call set_volume when *its* volume changes.
00189   // Set the volume:
00190   _volume=volume;
00191   // Account for the category of sound:
00192   volume*=_manager->get_volume();
00193   #ifdef MILES_6_5
00194     // Change to Miles volume, range 0 to 1.0:
00195     F32 milesVolume=volume;
00196     milesVolume=min(milesVolume,1.0f);
00197     milesVolume=max(milesVolume,0.0f);
00198   #else
00199     // Change to Miles volume, range 0 to 127:
00200     S32 milesVolume=((S32)(127*volume))%128;
00201   #endif
00202   // Account for type:
00203   S32 audioType=AIL_quick_type(_audio);
00204   if ((audioType==AIL_QUICK_XMIDI_TYPE) || (audioType==AIL_QUICK_DLS_XMIDI_TYPE)) {
00205     // ...it's a midi file.
00206 
00207     // 0 delay, set to this volume immediately    
00208     #ifdef MILES_6_5
00209       F32 midiVolDelay =0.0f; 
00210     #else
00211       S32 midiVolDelay =0;
00212     #endif
00213     
00214     AIL_quick_set_volume(_audio, milesVolume, midiVolDelay); 
00215     audio_debug("  volume for this midi is now "<<milesVolume);
00216   } else {
00217     // ...it's a wav or mp3.
00218     #ifdef MILES_6_5
00219       // Convert balance of -1.0..1.0 to 0-1.0:
00220       F32 milesBalance=(F32)((_balance+1.0f)*0.5f);
00221     #else
00222       // Convert balance of -1.0..1.0 to 0..127:
00223       S32 milesBalance=((S32)(63.5f*(_balance+1.0f)))%128;  
00224     #endif
00225     AIL_quick_set_volume(_audio, milesVolume, milesBalance);
00226     audio_debug("  volume for this wav or mp3 is now " << milesVolume
00227         <<", balance="<<milesBalance);
00228   }
00229 }
00230 
00231 float MilesAudioSound::
00232 get_volume() const {
00233   miles_audio_debug("get_volume() returning "<<_volume);
00234   return _volume;
00235 }
00236 
00237 void MilesAudioSound::
00238 set_active(bool active) {
00239   miles_audio_debug("set_active(active="<<active<<")");
00240   if (_active!=active) {
00241     _active=active;
00242     if (_active) {
00243       // ...activate the sound.
00244       if (_paused
00245           &&
00246           _loop_count==0) {
00247         // ...this sound was looping when it was paused.
00248         _paused=false;
00249         play();
00250       }
00251     } else {
00252       // ...deactivate the sound.
00253       if (status()==PLAYING) {
00254         if (_loop_count==0) {
00255           // ...we're pausing a looping sound.
00256           _paused=true;
00257         }
00258 
00259         // unlike the user fn stop(), halt() does NOT alter the 'paused' status
00260         // this is important, dont want to 'stop' infin looping sounds unless user
00261         // explicitly uses "stop()"
00262         halt();
00263       }
00264     }
00265   }
00266 }
00267 
00268 bool MilesAudioSound::
00269 get_active() const {
00270   miles_audio_debug("get_active() returning "<<_active);
00271   return _active;
00272 }
00273 
00274 void MilesAudioSound::
00275 set_balance(float balance_right) {
00276   miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
00277   _balance=balance_right;
00278   // Call set_volume to effect the change:
00279   set_volume(_volume);
00280 }
00281 
00282 float MilesAudioSound::
00283 get_balance() const {
00284   audio_debug("MilesAudioSound::get_balance() returning "<<_balance);
00285   return _balance;
00286 }
00287 
00288 float MilesAudioSound::
00289 length() const {
00290   if (_length == 0.0f) {
00291    #ifndef NEED_MILES_LENGTH_WORKAROUND
00292         _length=((float)AIL_quick_ms_length(_audio))*0.001f;
00293         if (_length == 0.0f) {
00294             audio_error("ERROR: Miles returned length 0 for "<<_file_name << "!");
00295         }
00296    #else
00297         // hack:
00298         // For now, the sound needs to be playing, in order to
00299         // get the right length.  I'm in contact with RAD about the problem.  I've
00300         // sent them example code.  They've told me they're looking into it.
00301         // Until then, we'll play the sound to get the length.
00302 
00303         // Miles 6.5c note:  seems to be fixed for .mid, .mp3 also seems mostly fixed,
00304         // but not 100% positive (need to look for errors with CATCH_ERROR on)
00305 
00306         // #define CATCH_MILES_LENGTH_ERROR
00307         #ifdef CATCH_MILES_LENGTH_ERROR     
00308         _length=((float)AIL_quick_ms_length(_audio))*0.001f;
00309         if (_length == 0.0f) {
00310             audio_error("ERROR: Miles returned length 0 for "<<_file_name << "!");
00311             exit(1);
00312         }
00313         #endif
00314 
00315         if (AIL_quick_status(_audio)==QSTAT_PLAYING) {
00316           _length=((float)AIL_quick_ms_length(_audio))*0.001f;
00317         } else {
00318           AIL_quick_play(_audio, 1);
00319           _length=((float)AIL_quick_ms_length(_audio))*0.001f;
00320           AIL_quick_halt(_audio);
00321         }
00322    #endif
00323   }
00324 
00325   //audio_cat->info() << "MilesAudioSound::length() returning " << _length << endl;
00326   audio_debug("MilesAudioSound::length() returning "<<_length);
00327   return _length;
00328 }
00329 
00330 const string& MilesAudioSound::
00331 get_name() const {
00332   //audio_debug("MilesAudioSound::get_name() returning "<<_file_name);
00333   return _file_name;
00334 }
00335 
00336 AudioSound::SoundStatus MilesAudioSound::
00337 status() const {
00338   if (!_audio) {
00339     return AudioSound::BAD;
00340   }
00341   switch (AIL_quick_status(_audio)) {
00342     case QSTAT_LOADED:
00343     case QSTAT_DONE:
00344       return AudioSound::READY;
00345     case QSTAT_PLAYING:
00346       return AudioSound::PLAYING;
00347     default:
00348       return AudioSound::BAD;
00349   }
00350 }
00351 
00352 
00353 #endif //]

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