Panda3D
|
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( ¤t_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, ¢er, &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 //]