Panda3D

fmodAudioSound.cxx

00001 // Filename: fmodAudioSound.cxx
00002 // Created by:  cort (January 22, 2003)
00003 // Extended by: ben  (October 22, 2003)
00004 // Prior system by: cary
00005 // Rewrite [for new Version of FMOD-EX] by: Stan Rosenbaum "Staque" - Spring 2006
00006 //
00007 //
00008 ////////////////////////////////////////////////////////////////////
00009 //
00010 // PANDA 3D SOFTWARE
00011 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00012 //
00013 // All use of this software is subject to the terms of the revised BSD
00014 // license.  You should have received a copy of this license along
00015 // with this source code in a file named "LICENSE."
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "pandabase.h"
00020 #include "dcast.h"
00021 
00022 #ifdef HAVE_FMODEX //[
00023 
00024 //Panda Headers
00025 #include "config_audio.h"
00026 #include "fmodAudioSound.h"
00027 #include "string_utils.h"
00028 
00029 TypeHandle FmodAudioSound::_type_handle;
00030 
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: FmodAudioSound::FmodAudioSound
00033 //       Access: public
00034 //  Description: Constructor
00035 //               All sound will DEFAULT load as a 2D sound unless
00036 //               otherwise specified.
00037 ////////////////////////////////////////////////////////////////////
00038 
00039 FmodAudioSound::
00040 FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) { 
00041   audio_debug("FmodAudioSound::FmodAudioSound() Creating new sound, filename: " << file_name  );
00042 
00043   _active = manager->get_active();
00044   _paused = false;
00045   _start_time = 0.0;
00046 
00047   //Local Variables that are needed.
00048   FMOD_RESULT result;
00049 
00050   //Inits 3D Attributes
00051   _location.x = 0;
00052   _location.y = 0;
00053   _location.z = 0;
00054 
00055   _velocity.x = 0;
00056   _velocity.y = 0;
00057   _velocity.z = 0;
00058 
00059   //Play Rate Variable
00060   _playrate = 1;
00061 
00062   // These set the Speaker Levels to a default if you are using a MultiChannel Setup.
00063   for (int i=0; i<AudioManager::SPK_COUNT; i++) {
00064     _mix[i] = 1.0;
00065   }
00066 
00067   //Assign the values we need
00068   FmodAudioManager *fmanager;
00069   DCAST_INTO_V(fmanager, manager);
00070   _manager = fmanager;
00071 
00072   _channel = 0;
00073   _file_name = file_name;
00074 
00075   FMOD_CREATESOUNDEXINFO *sound_info = NULL;
00076 
00077   //Get the Speaker Mode [Important for later on.]
00078   result = _manager->_system->getSpeakerMode( &_speakermode );
00079   fmod_audio_errcheck("_system->getSpeakerMode()", result);
00080 
00081   // Calculate the approximate uncompressed size of the sound.
00082   int size =  file_name.get_file_size();
00083   string ext = downcase(file_name.get_extension());
00084   if (ext != "wav") size *= 10;
00085   
00086   int flag = positional ? FMOD_3D : FMOD_2D;
00087   int streamflag = (size > 250000) ? FMOD_CREATESTREAM : FMOD_CREATESAMPLE;
00088   if (ext == "mid") {
00089     streamflag = FMOD_CREATESTREAM;
00090     sound_info = &_manager->_midi_info;
00091     
00092     if (sound_info->dlsname != NULL) {
00093       audio_debug("Using DLS file " << sound_info->dlsname);
00094     }
00095   }
00096 
00097   result = _manager->_system->createSound( file_name.c_str(), FMOD_SOFTWARE | streamflag | flag , 
00098                                            sound_info, &_sound);
00099   if (result != FMOD_OK) {
00100     audio_error("createSound(" << file_name << "): " << FMOD_ErrorString(result));
00101 
00102     // We couldn't load the sound file.  Create a blank sound record
00103     // instead.
00104     char blank_data[100];
00105     FMOD_CREATESOUNDEXINFO exinfo;
00106     memset(&exinfo, 0, sizeof(exinfo));
00107     memset(blank_data, 0, sizeof(blank_data));
00108     exinfo.cbsize = sizeof(exinfo);
00109     exinfo.length = sizeof(blank_data);
00110     exinfo.numchannels = 1;
00111     exinfo.defaultfrequency = 8000;
00112     exinfo.format = FMOD_SOUND_FORMAT_PCM16;
00113     result = _manager->_system->createSound( blank_data, FMOD_SOFTWARE | flag | FMOD_OPENMEMORY | FMOD_OPENRAW, &exinfo, &_sound);
00114     fmod_audio_errcheck("createSound (blank)", result);
00115   }
00116 
00117   // Some WAV files contain a loop bit.  This is not handled
00118   // consistently.  Override it.
00119   _sound->setLoopCount(1);
00120   _sound->setMode(FMOD_LOOP_OFF);
00121   
00122   //This is just to collect the defaults of the sound, so we don't
00123   //Have to query FMOD everytime for the info.
00124   //It is also important we get the '_sampleFrequency' variable here, for the
00125   //'set_play_rate()' and 'get_play_rate()' methods later;
00126   
00127   result = _sound->getDefaults( &_sampleFrequency, &_volume , &_balance, &_priority);
00128   fmod_audio_errcheck("_sound->getDefaults()", result);
00129 }
00130 
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: FmodAudioSound::~FmodAudioSound
00134 //       Access: public
00135 //  Description: DESTRUCTOR!!!
00136 ////////////////////////////////////////////////////////////////////
00137 FmodAudioSound::
00138 ~FmodAudioSound() {
00139   FMOD_RESULT result;
00140 
00141   //Remove me from table of all sounds.
00142   _manager->_all_sounds.erase(this);
00143 
00144   //The Release Sound
00145   result = _sound->release();
00146   fmod_audio_errcheck("_sound->release()", result);
00147 }
00148 
00149 
00150 ////////////////////////////////////////////////////////////////////
00151 //     Function: FmodAudioSound:: play
00152 //       Access: public
00153 //  Description: Plays a sound.
00154 ////////////////////////////////////////////////////////////////////
00155 void FmodAudioSound::
00156 play() {
00157   start_playing();
00158 }
00159 
00160 ////////////////////////////////////////////////////////////////////
00161 //     Function: sound_end_callback
00162 //       Access: Static
00163 //  Description: When fmod finishes playing a sound, decrements the
00164 //               reference count of the associated FmodAudioSound.
00165 ////////////////////////////////////////////////////////////////////
00166 FMOD_RESULT F_CALLBACK sound_end_callback(FMOD_CHANNEL *  channel, 
00167                       FMOD_CHANNEL_CALLBACKTYPE  type, 
00168                       void *commanddata1, 
00169                       void *commanddata2) {
00170   if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
00171     FMOD::Channel *fc = (FMOD::Channel *)channel;
00172     void *userdata = NULL;
00173     FMOD_RESULT result = fc->getUserData(&userdata);
00174     fmod_audio_errcheck("channel->getUserData()", result);
00175     FmodAudioSound *fsound = (FmodAudioSound*)userdata;
00176     fsound->_self_ref = fsound;
00177   }
00178   return FMOD_OK;
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: FmodAudioSound::stop
00183 //       Access: public
00184 //  Description: Stop a sound
00185 ////////////////////////////////////////////////////////////////////
00186 void FmodAudioSound::
00187 stop() {
00188   FMOD_RESULT result;
00189 
00190   if (_channel != 0) {
00191     result =_channel->stop();
00192     if (result == FMOD_OK) {
00193       _self_ref.clear();
00194     }
00195     fmod_audio_errcheck("_channel->stop()", result);
00196   }
00197   _start_time = 0.0;
00198 }
00199 
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: FmodAudioSound::set_loop
00203 //       Access: public
00204 //  Description: Turns looping on and off
00205 ////////////////////////////////////////////////////////////////////
00206 void FmodAudioSound::
00207 set_loop(bool loop) {
00208   if (loop) {
00209     set_loop_count(0);
00210   } else {
00211     set_loop_count(1);
00212   }
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: FmodAudioSound::get_loop
00217 //       Access: public
00218 //  Description: Returns whether looping is on or off
00219 ////////////////////////////////////////////////////////////////////
00220 bool FmodAudioSound::
00221 get_loop() const {
00222   if (get_loop_count() == 1) {
00223     return false;
00224   } else {
00225     return true;
00226   }
00227 }
00228 
00229 ////////////////////////////////////////////////////////////////////
00230 //     Function: FmodAudioSound::set_loop_count
00231 //       Access: public
00232 //  Description: 
00233 //        Panda uses 0 to mean loop forever.
00234 //        Fmod uses negative numbers to mean loop forever.
00235 //        (0 means don't loop, 1 means play twice, etc.
00236 //        We must convert!
00237 ////////////////////////////////////////////////////////////////////
00238 void FmodAudioSound::
00239 set_loop_count(unsigned long loop_count) {
00240 
00241   audio_debug("FmodAudioSound::set_loop_count()   Setting the sound's loop count to: " << loop_count);
00242 
00243   //LOCALS
00244   FMOD_RESULT result;
00245 
00246   if (loop_count == 0) {
00247     result = _sound->setLoopCount( -1 );
00248     fmod_audio_errcheck("_sound->setLoopCount()", result);
00249     result =_sound->setMode(FMOD_LOOP_NORMAL);    
00250     fmod_audio_errcheck("_sound->setMode()", result);
00251   } else if (loop_count == 1) {
00252     result = _sound->setLoopCount( 1 );
00253     fmod_audio_errcheck("_sound->setLoopCount()", result);
00254     result =_sound->setMode(FMOD_LOOP_OFF);    
00255     fmod_audio_errcheck("_sound->setMode()", result);
00256   } else {
00257     result = _sound->setLoopCount( loop_count );
00258     fmod_audio_errcheck("_sound->setLoopCount()", result);
00259     result =_sound->setMode(FMOD_LOOP_NORMAL);
00260     fmod_audio_errcheck("_sound->setMode()", result);
00261   }
00262 
00263   audio_debug("FmodAudioSound::set_loop_count()   Sound's loop count should be set to: " << loop_count);
00264 }
00265 
00266 ////////////////////////////////////////////////////////////////////
00267 //     Function: FmodAudioSound::get_loop_count
00268 //       Access: public
00269 //  Description: Return how many times a sound will loop.
00270 ////////////////////////////////////////////////////////////////////
00271 unsigned long FmodAudioSound::
00272 get_loop_count() const {
00273   FMOD_RESULT result;
00274   int loop_count;
00275 
00276   result = _sound->getLoopCount( &loop_count );
00277   fmod_audio_errcheck("_sound->getLoopCount()", result);
00278 
00279   if (loop_count <= 0) {
00280     return 0;
00281   } else {
00282     return (unsigned long)loop_count;
00283   }
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: FmodAudioSound::set_time
00288 //       Access: public
00289 //  Description: Sets the time at which the next play() operation will
00290 //               begin.  If we are already playing, skips to that time
00291 //               immediatey.
00292 ////////////////////////////////////////////////////////////////////
00293 void FmodAudioSound::
00294 set_time(float start_time) {
00295   _start_time = start_time;
00296 
00297   if (status() == PLAYING) {
00298     // Already playing; skip to the indicated time.
00299     start_playing();
00300   }
00301 }
00302 
00303 ////////////////////////////////////////////////////////////////////
00304 //     Function: FmodAudioSound::get_time
00305 //       Access: public
00306 //  Description: Gets the play position within the sound
00307 ////////////////////////////////////////////////////////////////////
00308 float FmodAudioSound::
00309 get_time() const {
00310   FMOD_RESULT result;
00311   unsigned int current_time;
00312 
00313   if (_channel == 0) {
00314     return 0.0f;
00315   }
00316 
00317   result = _channel->getPosition( &current_time , FMOD_TIMEUNIT_MS );
00318   if (result == FMOD_ERR_INVALID_HANDLE) {
00319     return 0.0f;
00320   }
00321   fmod_audio_errcheck("_channel->getPosition()", result);
00322   
00323   return ((double)current_time) / 1000.0;
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: FmodAudioSound::set_volume(float vol)
00328 //       Access: public
00329 //  Description: 0.0 to 1.0 scale of volume converted to Fmod's
00330 //               internal 0.0 to 255.0 scale.
00331 ////////////////////////////////////////////////////////////////////
00332 void FmodAudioSound::
00333 set_volume(float vol) {
00334   _volume = vol;
00335   set_volume_on_channel();
00336 }
00337 
00338 ////////////////////////////////////////////////////////////////////
00339 //     Function: FmodAudioSound::get_volume
00340 //       Access: public
00341 //  Description: Gets the current volume of a sound.  1 is Max. O is Min.
00342 ////////////////////////////////////////////////////////////////////
00343 float FmodAudioSound::
00344 get_volume() const {
00345   return _volume;
00346 }
00347 
00348 ////////////////////////////////////////////////////////////////////
00349 //     Function: FmodAudioSound::start_playing
00350 //       Access: Private
00351 //  Description: Starts the sound playing at _start_time.
00352 ////////////////////////////////////////////////////////////////////
00353 void FmodAudioSound::
00354 start_playing() {
00355   FMOD_RESULT result;
00356 
00357   if (!_active) {
00358     _paused = true;
00359     return;
00360   }
00361   
00362   int startTime = (int)(_start_time * 1000);
00363   
00364   if (_channel != 0) {
00365     // try backing up current sound.
00366     result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
00367     if (result == FMOD_ERR_INVALID_HANDLE ||
00368         result == FMOD_ERR_CHANNEL_STOLEN) {
00369       _channel = 0;
00370 
00371     } else {
00372       fmod_audio_errcheck("_channel->setPosition()", result);
00373 
00374       bool playing;
00375       result = _channel->isPlaying(&playing);
00376       fmod_audio_errcheck("_channel->isPlaying()", result);
00377       if (result != FMOD_OK || !playing) {
00378         _channel = 0;
00379       }
00380     }
00381   }
00382   
00383   if (_channel == 0) {
00384     result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound, true, &_channel);
00385     fmod_audio_errcheck("_system->playSound()", result);
00386     result = _channel->setChannelGroup(_manager->_channelgroup);
00387     fmod_audio_errcheck("_channel->setChannelGroup()", result);
00388     result = _channel->setUserData(this);
00389     fmod_audio_errcheck("_channel->setUserData()", result);
00390     result = _channel->setCallback(sound_end_callback);
00391     fmod_audio_errcheck("_channel->setCallback()", result);
00392     result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
00393     fmod_audio_errcheck("_channel->setPosition()", result);
00394 
00395     set_volume_on_channel();
00396     set_play_rate_on_channel();
00397     set_speaker_mix_or_balance_on_channel();
00398     // add_dsp_on_channel();
00399     set_3d_attributes_on_channel();
00400 
00401     result = _channel->setPaused(false);
00402     fmod_audio_errcheck("_channel->setPaused()", result);
00403     
00404     _self_ref = this;
00405   }
00406 }
00407 
00408 ////////////////////////////////////////////////////////////////////
00409 //     Function: FmodAudioSound::set_volume_on_channel()
00410 //       Access: Private
00411 //  Description: Set the volume on a prepared Sound channel.
00412 ////////////////////////////////////////////////////////////////////
00413 void FmodAudioSound::
00414 set_volume_on_channel() {
00415   FMOD_RESULT result;
00416 
00417   if (_channel != 0) {
00418     result = _channel->setVolume( _volume );
00419     if (result == FMOD_ERR_INVALID_HANDLE) {
00420       _channel = 0;
00421     } else {
00422       fmod_audio_errcheck("_channel->setVolume()", result);
00423     }
00424   }
00425 }
00426 
00427 ////////////////////////////////////////////////////////////////////
00428 //     Function: FmodAudioSound::set_balance(float bal)
00429 //       Access: public
00430 //  Description: -1.0 to 1.0 scale
00431 ////////////////////////////////////////////////////////////////////
00432 void FmodAudioSound::
00433 set_balance(float bal) {
00434   _balance = bal;
00435   set_speaker_mix_or_balance_on_channel();
00436 }
00437 
00438 ////////////////////////////////////////////////////////////////////
00439 //     Function: FmodAudioSound::get_balance
00440 //       Access: public
00441 //  Description: -1.0 to 1.0 scale 
00442 //        -1 should be all the way left.
00443 //        1 is all the way to the right.
00444 ////////////////////////////////////////////////////////////////////
00445 float FmodAudioSound::
00446 get_balance() const {
00447   return _balance;
00448 }
00449 
00450 ////////////////////////////////////////////////////////////////////
00451 //     Function: FmodAudioSound::set_play_rate(float rate)
00452 //       Access: public
00453 //  Description: Sets the speed at which a sound plays back.
00454 //        The rate is a multiple of the sound, normal playback speed.
00455 //        IE 2 would play back 2 times fast, 3 would play 3 times, and so on.
00456 //        This can also be set to a negative number so a sound plays backwards.
00457 //        But rememeber if the sound is not playing, you must set the 
00458 //        sound's time to its end to hear a song play backwards.
00459 ////////////////////////////////////////////////////////////////////
00460 void FmodAudioSound::
00461 set_play_rate(float rate) {
00462   _playrate = rate;
00463   set_play_rate_on_channel();
00464 }
00465 
00466 ////////////////////////////////////////////////////////////////////
00467 //     Function: FmodAudioSound::get_play_rate
00468 //       Access: public
00469 //  Description: 
00470 ////////////////////////////////////////////////////////////////////
00471 float FmodAudioSound::
00472 get_play_rate() const {
00473   return _playrate;
00474 }
00475 
00476 ////////////////////////////////////////////////////////////////////
00477 //     Function: FmodAudioSound::set_play_rate_on_channel()
00478 //       Access: public
00479 //  Description: Set the play rate on a prepared Sound channel.
00480 ////////////////////////////////////////////////////////////////////
00481 void FmodAudioSound::
00482 set_play_rate_on_channel() {
00483   FMOD_RESULT result;
00484   float frequency = _sampleFrequency * _playrate;
00485   
00486   if (_channel != 0) {
00487     result = _channel->setFrequency( frequency );
00488     if (result == FMOD_ERR_INVALID_HANDLE) {
00489       _channel = 0;
00490     } else {
00491       fmod_audio_errcheck("_channel->setFrequency()", result);
00492     }
00493   }
00494 }
00495 
00496 ////////////////////////////////////////////////////////////////////
00497 //     Function: FmodAudioSound::get_name
00498 //       Access: public
00499 //  Description: Get name of sound file
00500 ////////////////////////////////////////////////////////////////////
00501 const string& FmodAudioSound::
00502 get_name() const {
00503   return _file_name;
00504 }
00505 
00506 ////////////////////////////////////////////////////////////////////
00507 //     Function: FmodAudioSound::length
00508 //       Access: public
00509 //  Description: Get length
00510 //        FMOD returns the time in MS  so we have to convert to seconds.
00511 ////////////////////////////////////////////////////////////////////
00512 float FmodAudioSound::
00513 length() const {
00514   FMOD_RESULT result;
00515   unsigned int length;
00516 
00517   result = _sound->getLength( &length, FMOD_TIMEUNIT_MS );
00518   fmod_audio_errcheck("_sound->getLength()", result);
00519 
00520   return ((double)length) / 1000.0;
00521 }
00522 
00523 ////////////////////////////////////////////////////////////////////
00524 //     Function: FmodAudioSound::set_3d_attributes
00525 //       Access: public
00526 //  Description: Set position and velocity of this sound
00527 //        NOW LISTEN UP!!! THIS IS IMPORTANT!
00528 //        Both Panda3D and FMOD use a left handed coordinate system.
00529 //        But there is a major difference!
00530 //        In Panda3D the Y-Axis is going into the Screen and the Z-Axis is going up.
00531 //        In FMOD the Y-Axis is going up and the Z-Axis is going into the screen.
00532 //        The solution is simple, we just flip the Y and Z axis, as we move coordinates
00533 //        from Panda to FMOD and back.
00534 //        What does did mean to average Panda user?  Nothing, they shouldn't notice anyway.
00535 //        But if you decide to do any 3D audio work in here you have to keep it in mind.
00536 //        I told you, so you can't say I didn't.
00537 ////////////////////////////////////////////////////////////////////
00538 void FmodAudioSound::
00539 set_3d_attributes(float px, float py, float pz, float vx, float vy, float vz) {
00540   _location.x = px;
00541   _location.y = pz;
00542   _location.z = py;
00543   
00544   _velocity.x = vx;
00545   _velocity.y = vz;
00546   _velocity.z = vy;
00547 
00548   set_3d_attributes_on_channel();
00549 }
00550 
00551 ////////////////////////////////////////////////////////////////////
00552 //     Function: FmodAudioSound::set_3d_attributes_on_channel
00553 //       Access: public
00554 //  Description: 
00555 ////////////////////////////////////////////////////////////////////
00556 void FmodAudioSound::
00557 set_3d_attributes_on_channel() {
00558   FMOD_RESULT result;
00559   FMOD_MODE soundMode;
00560 
00561   result = _sound->getMode(&soundMode);
00562   fmod_audio_errcheck("_sound->getMode()", result);
00563   
00564   if ((_channel != 0) && (soundMode & FMOD_3D)) {
00565     result = _channel->set3DAttributes( &_location, &_velocity );
00566     if (result == FMOD_ERR_INVALID_HANDLE) {
00567       _channel = 0;
00568     } else {
00569       fmod_audio_errcheck("_channel->set3DAttributes()", result);
00570     }
00571   }
00572 }
00573 
00574 ////////////////////////////////////////////////////////////////////
00575 //     Function: FmodAudioSound::get_3d_attributes
00576 //       Access: public
00577 //  Description: Get position and velocity of this sound
00578 //         Currently unimplemented. Get the attributes of the attached object.
00579 ////////////////////////////////////////////////////////////////////
00580 void FmodAudioSound::
00581 get_3d_attributes(float *px, float *py, float *pz, float *vx, float *vy, float *vz) {
00582   audio_error("get3dAttributes: Currently unimplemented. Get the attributes of the attached object.");
00583 }
00584 
00585 ////////////////////////////////////////////////////////////////////
00586 //     Function: FmodAudioSound::set_3d_min_distance
00587 //       Access: public
00588 //  Description: Set the distance that this sound begins to fall off. Also
00589 //               affects the rate it falls off.
00590 ////////////////////////////////////////////////////////////////////
00591 void FmodAudioSound::
00592 set_3d_min_distance(float dist) {
00593   FMOD_RESULT result;
00594 
00595   _min_dist = dist;
00596 
00597   result = _sound->set3DMinMaxDistance( dist, _max_dist );
00598   fmod_audio_errcheck("_sound->set3DMinMaxDistance()", result);
00599 }
00600 
00601 ////////////////////////////////////////////////////////////////////
00602 //     Function: FmodAudioSound::get_3d_min_distance
00603 //       Access: public
00604 //  Description: Get the distance that this sound begins to fall off
00605 ////////////////////////////////////////////////////////////////////
00606 float FmodAudioSound::
00607 get_3d_min_distance() const {
00608   return _min_dist;
00609 }
00610 
00611 ////////////////////////////////////////////////////////////////////
00612 //     Function: FmodAudioSound::set_3d_max_distance
00613 //       Access: public
00614 //  Description: Set the distance that this sound stops falling off
00615 ////////////////////////////////////////////////////////////////////
00616 void FmodAudioSound::
00617 set_3d_max_distance(float dist) {
00618   FMOD_RESULT result;
00619 
00620   _max_dist = dist;
00621 
00622   result = _sound->set3DMinMaxDistance( _min_dist, dist );
00623   fmod_audio_errcheck("_sound->set3DMinMaxDistance()", result);
00624 }
00625 
00626 ////////////////////////////////////////////////////////////////////
00627 //     Function: FmodAudioSound::get_3d_max_distance
00628 //       Access: public
00629 //  Description: Get the distance that this sound stops falling off
00630 ////////////////////////////////////////////////////////////////////
00631 float FmodAudioSound::
00632 get_3d_max_distance() const {
00633   return _max_dist;
00634 }
00635 
00636 ////////////////////////////////////////////////////////////////////
00637 //     Function: FmodAudioSound::get_speaker_mix
00638 //       Access: Published
00639 //  Description: In Multichannel Speaker systems [like Surround].
00640 //
00641 //        Speakers which don't exist in some systems will simply be ignored.
00642 //        But I haven't been able to test this yet, so I am jsut letting you know.
00643 //
00644 //        BTW This will also work in Stereo speaker systems, but since
00645 //        PANDA/FMOD has a balance [pan] function what is the point?
00646 ////////////////////////////////////////////////////////////////////
00647 float FmodAudioSound::
00648 get_speaker_mix(AudioManager::SpeakerId speaker) {
00649   if (_channel == 0) {
00650     return 0.0;
00651   }
00652 
00653   FMOD_RESULT result;
00654   float frontleft;
00655   float frontright;
00656   float center;
00657   float sub;
00658   float backleft;
00659   float backright; 
00660   float sideleft;
00661   float sideright;
00662 
00663   result = _channel->getSpeakerMix( &frontleft, &frontright, &center, &sub, &backleft, &backright, &sideleft, &sideright );
00664   fmod_audio_errcheck("_channel->getSpeakerMix()", result);
00665 
00666   switch(speaker) {
00667   case AudioManager::SPK_frontleft:  return frontleft;
00668   case AudioManager::SPK_frontright: return frontright;
00669   case AudioManager::SPK_center:     return center;
00670   case AudioManager::SPK_sub:        return sub;
00671   case AudioManager::SPK_backleft:   return backleft;
00672   case AudioManager::SPK_backright:  return backright;
00673   case AudioManager::SPK_sideleft:   return sideleft;
00674   case AudioManager::SPK_sideright:  return sideright;
00675   default: return 0.0;
00676   }
00677 }
00678 
00679 ////////////////////////////////////////////////////////////////////
00680 //     Function: FmodAudioSound::set_speaker_mix
00681 //       Access: Published
00682 //  Description: This sets the speaker mix for Surround Sound sytems.
00683 //               It required 8 parameters which match up to the following:
00684 //
00685 //               * 1 = Front Left
00686 //               * 2 = Front Right
00687 //               * 3 = Center
00688 //               * 4 = Subwoofer
00689 //               * 5 = Back Left
00690 //               * 6 = Back Right
00691 //               * 7 = Side Left
00692 //               * 8 = Side Right
00693 //
00694 ////////////////////////////////////////////////////////////////////
00695 void FmodAudioSound::
00696 set_speaker_mix(float frontleft, float frontright, float center, float sub, float backleft, float backright, float sideleft, float  sideright) {
00697   _mix[AudioManager::SPK_frontleft]  = frontleft;
00698   _mix[AudioManager::SPK_frontright] = frontright;
00699   _mix[AudioManager::SPK_center]     = center;
00700   _mix[AudioManager::SPK_sub]        = sub;
00701   _mix[AudioManager::SPK_backleft]   = backleft;
00702   _mix[AudioManager::SPK_backright]  = backright;
00703   _mix[AudioManager::SPK_sideleft]   = sideleft;
00704   _mix[AudioManager::SPK_sideright]  = sideright;
00705 
00706   set_speaker_mix_or_balance_on_channel();
00707 }
00708 
00709 ////////////////////////////////////////////////////////////////////
00710 //     Function: FmodAudioSound::set_speaker_mix_or_balance_on_channel
00711 //       Access: Private
00712 //  Description: This is simply a safety catch.
00713 //        If you are using a Stero speaker setup Panda will only pay attention
00714 //        to 'set_balance()' command when setting speaker balances.
00715 //        Other wise it will use 'set_speaker_mix'.
00716 //        I put this in, because other wise you end up with a sitation,
00717 //        where 'set_speaker_mix()' or 'set_balace()' will override any
00718 //        previous speaker balance setups.  It all depends on which was called last.
00719 ////////////////////////////////////////////////////////////////////
00720 void FmodAudioSound::
00721 set_speaker_mix_or_balance_on_channel() {
00722   FMOD_RESULT result;
00723   FMOD_MODE soundMode;
00724 
00725   result = _sound->getMode(&soundMode);
00726   fmod_audio_errcheck("_sound->getMode()", result);
00727 
00728   if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) {
00729     if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) {
00730       result = _channel->setPan( _balance );
00731     } else {
00732       result = _channel->setSpeakerMix( _mix[AudioManager::SPK_frontleft],
00733                                         _mix[AudioManager::SPK_frontright],
00734                                         _mix[AudioManager::SPK_center],
00735                                         _mix[AudioManager::SPK_sub],
00736                                         _mix[AudioManager::SPK_backleft],
00737                                         _mix[AudioManager::SPK_backright],
00738                                         _mix[AudioManager::SPK_sideleft],
00739                                         _mix[AudioManager::SPK_sideright] 
00740                                         );
00741     }
00742     if (result == FMOD_ERR_INVALID_HANDLE) {
00743       _channel = 0;
00744     } else {
00745       fmod_audio_errcheck("_channel->setSpeakerMix()/setPan()", result);
00746     }
00747   }
00748 }
00749 
00750 ////////////////////////////////////////////////////////////////////
00751 //     Function: FmodAudioSound::get_priority
00752 //       Access: Published
00753 //  Description: Sets the priority of a sound.
00754 //        This is what FMOD uses to determine is a sound will
00755 //        play if all the other real channels have been used up.
00756 ////////////////////////////////////////////////////////////////////
00757 int FmodAudioSound::
00758 get_priority() {
00759   audio_debug("FmodAudioSound::get_priority()");
00760   return _priority;
00761 }
00762 
00763 ////////////////////////////////////////////////////////////////////
00764 //     Function: FmodAudioSound::set_priority(int priority)
00765 //       Access: Published
00766 //  Description: Sets the Sound Priority [Whether is will be played
00767 //        over other sound when real audio channels become short.
00768 ////////////////////////////////////////////////////////////////////
00769 void FmodAudioSound::
00770 set_priority(int priority) {
00771   // intentionally blank
00772 
00773   audio_debug("FmodAudioSound::set_priority()");
00774 
00775   FMOD_RESULT result;
00776 
00777   _priority = priority;
00778 
00779   result = _sound->setDefaults( _sampleFrequency, _volume , _balance, _priority);
00780   fmod_audio_errcheck("_sound->setDefaults()", result);
00781 }
00782 
00783 ////////////////////////////////////////////////////////////////////
00784 //     Function: FmodAudioSound::status
00785 //       Access: public
00786 //  Description: Get status of the sound.
00787 ////////////////////////////////////////////////////////////////////
00788 AudioSound::SoundStatus FmodAudioSound::
00789 status() const {
00790   FMOD_RESULT result;
00791   bool playingState;
00792 
00793   if ( _channel == 0 ) {
00794     return READY;
00795   }
00796 
00797   result = _channel->isPlaying( &playingState );
00798   if ((result == FMOD_OK) && (playingState == true)) {
00799     return PLAYING;
00800   } else {
00801     return READY;
00802   }
00803 }
00804 
00805 ////////////////////////////////////////////////////////////////////
00806 //     Function: FmodAudioSound::set_active
00807 //       Access: public
00808 //  Description: Sets whether the sound is marked "active".  By
00809 //               default, the active flag true for all sounds.  If the
00810 //               active flag is set to false for any particular sound,
00811 //               the sound will not be heard.
00812 ////////////////////////////////////////////////////////////////////
00813 void FmodAudioSound::
00814 set_active(bool active) {
00815   if (_active != active) {
00816     _active = active;
00817     if (_active) {
00818       // ...activate the sound.
00819       if (_paused && get_loop_count()==0) {
00820         // ...this sound was looping when it was paused.
00821         _paused = false;
00822         play();
00823       }
00824 
00825     } else {
00826       // ...deactivate the sound.
00827       if (status() == PLAYING) {
00828         if (get_loop_count() == 0) {
00829           // ...we're pausing a looping sound.
00830           _paused = true;
00831           _start_time = get_time();
00832         }
00833         stop();
00834       }
00835     }
00836   }
00837 }
00838 
00839 
00840 ////////////////////////////////////////////////////////////////////
00841 //     Function: FmodAudioSound::get_active 
00842 //       Access: public
00843 //  Description: Returns whether the sound has been marked "active".
00844 ////////////////////////////////////////////////////////////////////
00845 bool FmodAudioSound::
00846 get_active() const {
00847   return _active;
00848 }
00849 
00850 ////////////////////////////////////////////////////////////////////
00851 //     Function: FmodAudioSound::finished
00852 //       Access: public
00853 //  Description: Not implemented.
00854 ////////////////////////////////////////////////////////////////////
00855 void FmodAudioSound::
00856 finished() {
00857   audio_error("finished: not implemented under FMOD-EX");
00858 }
00859 
00860 ////////////////////////////////////////////////////////////////////
00861 //     Function: FmodAudioSound::set_finished_event
00862 //       Access: public
00863 //  Description: NOT USED ANYMORE!!!
00864 //        Assign a string for the finished event to be referenced 
00865 //              by in python by an accept method
00866 //
00867 ////////////////////////////////////////////////////////////////////
00868 void FmodAudioSound::
00869 set_finished_event(const string& event) {
00870   audio_error("set_finished_event: not implemented under FMOD-EX");
00871 }
00872 
00873 ////////////////////////////////////////////////////////////////////
00874 //     Function: FmodAudioSound::get_finished_event
00875 //       Access: public
00876 //  Description:NOT USED ANYMORE!!!
00877 //        Return the string the finished event is referenced by
00878 //
00879 //        
00880 ////////////////////////////////////////////////////////////////////
00881 const string& FmodAudioSound::
00882 get_finished_event() const {
00883   audio_error("get_finished_event: not implemented under FMOD-EX");
00884   return _finished_event;
00885 }
00886 
00887 #endif //]
 All Classes Functions Variables Enumerations