From 3b82193a4063f19d64793f12201929dcf0dd47fb Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 2 Oct 2006 19:03:37 +0000 Subject: [PATCH] Added heuristic to choose streaming or preloaded --- panda/src/audiotraits/fmodAudioManager.cxx | 7 +- panda/src/audiotraits/fmodAudioManager.h | 2 +- panda/src/audiotraits/fmodAudioSound.cxx | 520 +++++++-------------- panda/src/audiotraits/fmodAudioSound.h | 25 +- 4 files changed, 178 insertions(+), 376 deletions(-) diff --git a/panda/src/audiotraits/fmodAudioManager.cxx b/panda/src/audiotraits/fmodAudioManager.cxx index aebf549752..704d98c77c 100644 --- a/panda/src/audiotraits/fmodAudioManager.cxx +++ b/panda/src/audiotraits/fmodAudioManager.cxx @@ -190,7 +190,7 @@ get_sound(const string &file_name, bool positional) { // Build a new AudioSound from the audio data. PT(AudioSound) audioSound = 0; - PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path.to_os_specific(), positional ); + PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional ); _all_sounds.insert(fmodAudioSound); @@ -339,12 +339,9 @@ getSpeakerSetup() { // one can init or re-init the AudioManagers after Panda is running. //////////////////////////////////////////////////////////////////// void FmodAudioManager:: -setSpeakerSetup(AudioManager::SPEAKERMODE_category cat) { - //Local Variables that are needed. +setSpeakerSetup(AudioManager::SpeakerModeCategory cat) { FMOD_RESULT result; - FMOD_SPEAKERMODE speakerModeType = (FMOD_SPEAKERMODE)cat; - result = _system->setSpeakerMode( speakerModeType); fmod_audio_errcheck(result); } diff --git a/panda/src/audiotraits/fmodAudioManager.h b/panda/src/audiotraits/fmodAudioManager.h index 5fe32ec346..0ee7522bda 100644 --- a/panda/src/audiotraits/fmodAudioManager.h +++ b/panda/src/audiotraits/fmodAudioManager.h @@ -103,7 +103,7 @@ class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager { virtual bool remove_dsp(PT(AudioDSP) x); virtual int getSpeakerSetup(); - virtual void setSpeakerSetup(SPEAKERMODE_category cat); + virtual void setSpeakerSetup(SpeakerModeCategory cat); virtual void set_volume(float); virtual float get_volume() const; diff --git a/panda/src/audiotraits/fmodAudioSound.cxx b/panda/src/audiotraits/fmodAudioSound.cxx index 752e5eee02..d1bd3ede86 100644 --- a/panda/src/audiotraits/fmodAudioSound.cxx +++ b/panda/src/audiotraits/fmodAudioSound.cxx @@ -29,6 +29,7 @@ #include "config_audio.h" #include "fmodAudioSound.h" #include "fmodAudioDSP.h" +#include "string_utils.h" TypeHandle FmodAudioSound::_type_handle; @@ -41,7 +42,7 @@ TypeHandle FmodAudioSound::_type_handle; //////////////////////////////////////////////////////////////////// FmodAudioSound:: -FmodAudioSound(AudioManager *manager, string file_name, bool positional) { +FmodAudioSound(AudioManager *manager, Filename file_name, bool positional) { audio_debug("FmodAudioSound::FmodAudioSound() Creating new sound, filename: " << file_name ); //Local Variables that are needed. @@ -60,14 +61,9 @@ FmodAudioSound(AudioManager *manager, string file_name, bool positional) { _playrate = 1; // These set the Speaker Levels to a default if you are using a MultiChannel Setup. - _frontleft = 1; - _frontright = 1; - _center = 1; - _sub = 1; - _backleft = 1; - _backright = 1; - _sideleft = 1; - _sideright = 1; + for (int i=0; i_system->getSpeakerMode( &_speakermode ); fmod_audio_errcheck(result); + // Calculate the approximate uncompressed size of the sound. + int size = file_name.get_file_size(); + string ext = downcase(file_name.get_extension()); + if (ext != "wav") size *= 10; + int flag = positional ? FMOD_3D : FMOD_2D; - - result = _manager->_system->createSound( file_name.c_str(), FMOD_SOFTWARE | flag , 0, &_sound); + int streamflag = (size > 250000) ? FMOD_CREATESTREAM : FMOD_CREATESAMPLE; + + result = _manager->_system->createSound( file_name.to_os_specific().c_str(), FMOD_SOFTWARE | streamflag | flag , 0, &_sound); if (result != FMOD_OK) { char blank_data[100]; FMOD_CREATESOUNDEXINFO exinfo; @@ -116,9 +118,6 @@ FmodAudioSound(AudioManager *manager, string file_name, bool positional) { //////////////////////////////////////////////////////////////////// FmodAudioSound:: ~FmodAudioSound() { - - audio_debug("FmodAudioSound::~FmodAudioSound() Closing this Sound Instance Down."); - FMOD_RESULT result; //Remove me from table of all sounds. @@ -130,9 +129,6 @@ FmodAudioSound:: //The Release Sound result = _sound->release(); fmod_audio_errcheck(result); - - audio_debug("FmodAudioSound::~FmodAudioSound() FMOD Sound Released and Closed."); - } @@ -140,171 +136,28 @@ FmodAudioSound:: // Function: FmodAudioSound:: play // Access: public // Description: Plays a sound. -// OK when you play a Sound a couple of things are going -// to happen. -// First Panda is going to check if the sound is in a pause -// State because of if a 'set_time()' has been called on the sound. -// Second, remember when I said channels don't exist unless a sound, -// is playing on them? Well they don't and therefore any associated -// DSP, looping, playback rate, pan, volume, or 3D information associated with -// that sound is not going to be known by that channel either. -// So all we do, is load a sound on a channel PAUSED. -// While the sound is paused, it sets up all the sound attributes, and -// then plays the sound. This all happens really fast, so you should -// notice a hit. -// And yes this is the FMOD way of doing things. -// -// The biggest problem with this comes when you are 'looping' sounds. -// In the 'prepare2DSound()' and prepare3DSound' [private methods -// which set up their respected type of sounds], I had to impliment the -// 'FMOD_CHANNEL_REUSE' flag. -// Remember back in the header file, where I said there is only one dedicated, -// Channel for each sound, where there is a reason for that. -// If you were to use 'FMOD_CHANNEL_FREE' each time you played a sound, -// FMOD would grab the first available channel and play the sound on that. -// This is bad for Panda because the FmodAudioSound class is only set up to -// remember only channel at a time. If we play a sound that is set to loop, and -// then trigger that sound to loop again, the reference to the Channel Object for a particular -// sound is replaced with the new, instance of the loop. Thus the previous sound keeps playing -// forever because we have lost the reference to it. -// But using the 'FMOD_CHANNEL_REUSE' flag, we avoid this problem, because the new call to play -// the looping sound will, play the sound on the previous allocated channel. -// The only to downside to this, is that playing a looping sound a second time, will cause the -// Previous instance to be cut off. -// -// Honestly, it should be easy to create a work around for this. So you could -// use the 'FMOD_CHANNEL_FREE' which will prevent the cutoff program, by creating -// a set, that keeps track of channels playing the same looping sound, when the sound is looping -// [or is really long, another possible scenerio for this problem]. -// -// But honestly the cutoff shouldn't be a big problem, in most cases. -// I just wanted to explain my reasoning here. -// //////////////////////////////////////////////////////////////////// void FmodAudioSound:: play() { - FMOD_RESULT result; - set_time(0.0); - result = _channel->setPaused(false); - fmod_audio_errcheck(result); } - + //////////////////////////////////////////////////////////////////// // Function: sound_end_callback // Access: Static -// Description: When fmod finishes playing a sound, the channel -// handle of the sound becomes invalid. This callback -// removes the invalid channel handle from the relevant -// fmodAudioSound. +// Description: When fmod finishes playing a sound, decrements the +// reference count of the associated FmodAudioSound. //////////////////////////////////////////////////////////////////// -static FMOD_RESULT F_CALLBACK sound_end_callback(FMOD_CHANNEL * channel, - FMOD_CHANNEL_CALLBACKTYPE type, - int command, - unsigned int commanddata1, - unsigned int commanddata2) { +static FMOD_RESULT F_CALLBACK sound_end_callback(FMOD_CHANNEL * channel, + FMOD_CHANNEL_CALLBACKTYPE type, + int command, + unsigned int commanddata1, + unsigned int commanddata2) { FmodAudioSound *fsound = (FmodAudioSound*)command; - if (fsound->_channel != 0) { - fsound->_channel = 0; - fsound->unref(); - } + fsound->unref(); return FMOD_OK; } -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioSound::prepareSound -// Access: Private -// Description: Prepares a sound [GENERAL] -//////////////////////////////////////////////////////////////////// - -void FmodAudioSound:: -prepareSound() { - - if (_channel != 0) { - return; - } - - audio_debug("FmodAudioSound::prepareSound()" ); - - FMOD_RESULT result; - bool paused = 0; - FMOD_MODE soundMode; - - audio_debug("FmodAudioSound::play() Going to perpare a sound." ); - - result = _sound->getMode(&soundMode); - fmod_audio_errcheck(result); - - if ( soundMode & FMOD_3D ) { - prepare3DSound(); - } else { - prepare2DSound(); - } - - // This function sets up an fmod callback, which will - // clear the _channel variable when the sound stops playing. - // We want to make sure this fmodAudioSound doesn't go away - // until after the _channel is cleared, so I increment the - // ref-count. - this->ref(); - - result = _channel->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, sound_end_callback, (int)this); - fmod_audio_errcheck(result); -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioSound::prepare2DSound -// Access: Private -// Description: Prepares a 2D sound. -// We need seperate 3D and 2D play commands, because of -// the way FMOD sets the 3D Attributes to the 'channel' a -// sound is playing on. -// Since a 'channel' is initialize when a sound is set to -// play to one, and then subsiquenctly destroyed once the -// sound is finished playing. -// -//////////////////////////////////////////////////////////////////// -void FmodAudioSound:: -prepare2DSound() { - - audio_debug("FmodAudioSound::prepare2DSound()" ); - - FMOD_RESULT result; - - result = _manager->_system->playSound(FMOD_CHANNEL_REUSE, _sound, true, &_channel); - fmod_audio_errcheck(result); - -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioSound::prepare3DSound -// Access: Private -// Description: Prepares a 3D sound -// We need seperate 3D and 2D play commands, because of -// the way FMOD sets the 3D Attributes to the 'channel' a -// sound is playing on. -// Since a 'channel' is initialize when a sound is set to -// play to one, and then subsiquenctly destroyed once the -// sound is finished playing. -// -//////////////////////////////////////////////////////////////////// -void FmodAudioSound:: -prepare3DSound() { - - audio_debug("FmodAudioSound::prepare2DSound()" ); - - FMOD_RESULT result; - - result = _manager->_system->playSound(FMOD_CHANNEL_REUSE, _sound, true, &_channel); - fmod_audio_errcheck(result); - - result = _channel->set3DAttributes( &_location, &_velocity ); - fmod_audio_errcheck(result); - -} - - - //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::stop // Access: public @@ -312,23 +165,18 @@ prepare3DSound() { //////////////////////////////////////////////////////////////////// void FmodAudioSound:: stop() { - audio_debug("FmodAudioSound::stop() Going to stop a sound." ); - - //LOCALS FMOD_RESULT result; if (_channel != 0) { - result = _channel->stop(); + result =_channel->stop(); + if (result == FMOD_OK) { + unref(); + } fmod_audio_errcheck(result); - _channel = 0; - unref(); } - - audio_debug("FmodAudioSound::stop() Sound should be stopped."); } - //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::set_loop // Access: public @@ -336,17 +184,13 @@ stop() { //////////////////////////////////////////////////////////////////// void FmodAudioSound:: set_loop(bool loop) { - audio_debug("FmodAudioSound::set_loop() Setting loop state to " << loop); FMOD_RESULT result; if ( loop ) { result = _sound->setMode(FMOD_LOOP_NORMAL); fmod_audio_errcheck(result); - audio_debug("This sound is set to loop." ); - } else { result = _sound->setMode(FMOD_LOOP_OFF); fmod_audio_errcheck(result); - audio_debug("FmodAudioSound::set_loop() This sound is set to one-shot." ); } } @@ -357,9 +201,6 @@ set_loop(bool loop) { //////////////////////////////////////////////////////////////////// bool FmodAudioSound:: get_loop() const { - - audio_debug( "FmodAudioSound::get_loop() Retreiving a sound's loop state." ); - // 0 means loop forever, // >1 means loop that many times // So _loop_count != 1 means we're looping @@ -443,21 +284,48 @@ get_loop_count() const { //////////////////////////////////////////////////////////////////// void FmodAudioSound:: set_time(float start_time) { - FMOD_RESULT result; - audio_debug("FmodAudioSound::set_time() Going to set a sounds start position" ); - - prepareSound(); - - set_volume_on_channel(); - set_play_rate_on_channel(); - set_speaker_mix_or_balance_on_channel(); - add_dsp_on_channel(); - set_3d_attributes_on_channel(); + bool playing; int startTime = start_time * 1000; - result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS ); + if (_channel != 0) { + // try backing up current sound. + result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS ); + if (result == FMOD_ERR_INVALID_HANDLE) { + _channel = 0; + } else { + fmod_audio_errcheck(result); + } + result = _channel->isPlaying(&playing); + if ((result == FMOD_ERR_INVALID_HANDLE) || (playing == false)) { + _channel = 0; + } else { + fmod_audio_errcheck(result); + } + } + + if (_channel == 0) { + + result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound, true, &_channel); + fmod_audio_errcheck(result); + result = _channel->setCallback(FMOD_CHANNEL_CALLBACKTYPE_END, sound_end_callback, (int)this); + fmod_audio_errcheck(result); + result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS ); + fmod_audio_errcheck(result); + + set_volume_on_channel(); + set_play_rate_on_channel(); + set_speaker_mix_or_balance_on_channel(); + add_dsp_on_channel(); + set_3d_attributes_on_channel(); + + result = _channel->setPaused(false); + fmod_audio_errcheck(result); + + this->ref(); + } + fmod_audio_errcheck(result); } @@ -468,16 +336,17 @@ set_time(float start_time) { //////////////////////////////////////////////////////////////////// float FmodAudioSound:: get_time() const { - audio_debug("FmodAudioSound::get_time() Going to get a sound's position" ); + FMOD_RESULT result; + unsigned int current_time; if (_channel == 0) { return 0.0f; } - FMOD_RESULT result; - unsigned int current_time; - result = _channel->getPosition( ¤t_time , FMOD_TIMEUNIT_MS ); + if (result == FMOD_ERR_INVALID_HANDLE) { + return 0.0f; + } fmod_audio_errcheck(result); current_time = current_time / 1000; @@ -497,6 +366,16 @@ set_volume(float vol) { set_volume_on_channel(); } +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::get_volume +// Access: public +// Description: Gets the current volume of a sound. 1 is Max. O is Min. +//////////////////////////////////////////////////////////////////// +float FmodAudioSound:: +get_volume() const { + return _volume; +} + //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::set_volume_on_channel() // Access: Private @@ -506,22 +385,14 @@ void FmodAudioSound:: set_volume_on_channel() { FMOD_RESULT result; - if (_channel == 0) { - return; + if (_channel != 0) { + result = _channel->setVolume( _volume ); + if (result == FMOD_ERR_INVALID_HANDLE) { + _channel = 0; + } else { + fmod_audio_errcheck(result); + } } - - result = _channel->setVolume( _volume ); - fmod_audio_errcheck(result); -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioSound::get_volume -// Access: public -// Description: Gets the current volume of a sound. 1 is Max. O is Min. -//////////////////////////////////////////////////////////////////// -float FmodAudioSound:: -get_volume() const { - return _volume; } //////////////////////////////////////////////////////////////////// @@ -563,30 +434,6 @@ set_play_rate(float rate) { set_play_rate_on_channel(); } -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioSound::set_play_rate_on_channel() -// Access: public -// Description: Set the play rate on a prepared Sound channel. -//////////////////////////////////////////////////////////////////// -void FmodAudioSound:: -set_play_rate_on_channel() { - FMOD_RESULT result; - - if (_channel == 0) { - return; - } - - float frequencyToSetChannelTo; - if ( _playrate == 1) { - result = _channel->setFrequency( _sampleFrequency ); - fmod_audio_errcheck(result); - } else { - frequencyToSetChannelTo = _sampleFrequency * _playrate ; - result = _channel->setFrequency( frequencyToSetChannelTo ); - fmod_audio_errcheck(result); - } -} - //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::get_play_rate // Access: public @@ -597,6 +444,26 @@ get_play_rate() const { return _playrate; } +//////////////////////////////////////////////////////////////////// +// Function: FmodAudioSound::set_play_rate_on_channel() +// Access: public +// Description: Set the play rate on a prepared Sound channel. +//////////////////////////////////////////////////////////////////// +void FmodAudioSound:: +set_play_rate_on_channel() { + FMOD_RESULT result; + float frequency = _sampleFrequency * _playrate; + + if (_channel != 0) { + result = _channel->setFrequency( frequency ); + if (result == FMOD_ERR_INVALID_HANDLE) { + _channel = 0; + } else { + fmod_audio_errcheck(result); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::get_name // Access: public @@ -655,7 +522,7 @@ set_3d_attributes(float px, float py, float pz, float vx, float vy, float vz) { } //////////////////////////////////////////////////////////////////// -// Function: FmodAudioSound::set_3d_attributes +// Function: FmodAudioSound::set_3d_attributes_on_channel // Access: public // Description: //////////////////////////////////////////////////////////////////// @@ -664,16 +531,16 @@ set_3d_attributes_on_channel() { FMOD_RESULT result; FMOD_MODE soundMode; - if (_channel == 0) { - return; - } - result = _sound->getMode(&soundMode); fmod_audio_errcheck(result); - if ( soundMode & FMOD_3D ) { + if ((_channel != 0) && (soundMode & FMOD_3D)) { result = _channel->set3DAttributes( &_location, &_velocity ); - fmod_audio_errcheck(result); + if (result == FMOD_ERR_INVALID_HANDLE) { + _channel = 0; + } else { + fmod_audio_errcheck(result); + } } } @@ -790,15 +657,17 @@ add_dsp( PT(AudioDSP) x) { //////////////////////////////////////////////////////////////////// void FmodAudioSound:: add_dsp_on_channel() { - audio_debug("FmodAudioManager()::add_dsp_on_channel"); - FMOD_RESULT result; for (DSPSet::iterator i = _sound_dsp.begin(); i != _sound_dsp.end(); ++i) { - - result = _channel->addDSP( (*i)->_dsp ); - fmod_audio_errcheck( result ); - + if (_channel != 0) { + result = _channel->addDSP( (*i)->_dsp ); + if (result == FMOD_ERR_INVALID_HANDLE) { + _channel = 0; + } else { + fmod_audio_errcheck( result ); + } + } } } @@ -812,10 +681,6 @@ add_dsp_on_channel() { //////////////////////////////////////////////////////////////////// bool FmodAudioSound:: remove_dsp(PT(AudioDSP) x) { - // intentionally blank - - audio_debug("FmodAudioManager()::remove_dsp()"); - FMOD_RESULT result; FmodAudioDSP *fdsp; @@ -847,30 +712,15 @@ remove_dsp(PT(AudioDSP) x) { // Function: FmodAudioSound::get_speaker_mix // Access: Published // Description: In Multichannel Speaker systems [like Surround]. -// Can pass in the ID of a specific speaker and get itself Volume level. -// Currenly that is set to the Following: -// 1 = Front Left -// 2 = Front Right -// 3 = Center -// 4 = Subwoofer -// 5 = Back Left -// 6 = Back Right -// 7 = Side Left -// 8 = Side Right -// Speakers which don't exist in some systems will simply be ignored. -// IE So a quadsystem would only return values on 1,2,5,6. // +// Speakers which don't exist in some systems will simply be ignored. // But I haven't been able to test this yet, so I am jsut letting you know. // // BTW This will also work in Stereo speaker systems, but since // PANDA/FMOD has a balance [pan] function what is the point? //////////////////////////////////////////////////////////////////// float FmodAudioSound:: -get_speaker_mix(int speaker) { - // intentionally blank - - audio_debug("FmodAudioSound::getSpeakerMix()"); - +get_speaker_mix(AudioManager::SpeakerId speaker) { if (_channel == 0) { return 0.0; } @@ -885,69 +735,48 @@ get_speaker_mix(int speaker) { float sideleft; float sideright; - float returnValue; - result = _channel->getSpeakerMix( &frontleft, &frontright, ¢er, &sub, &backleft, &backright, &sideleft, &sideright ); fmod_audio_errcheck(result); switch(speaker) { - - case 1: - returnValue = frontleft; - break; - case 2: - returnValue = frontright; - break; - case 3: - returnValue = center; - break; - case 4: - returnValue = sub; - break; - case 5: - returnValue = backleft; - break; - case 6: - returnValue = backright; - break; - case 7: - returnValue = sideleft; - break; - case 8: - returnValue = sideright; - break; - default: - audio_error("You specified a speaker which doesn't exist."); + case AudioManager::SPK_frontleft: return frontleft; + case AudioManager::SPK_frontright: return frontright; + case AudioManager::SPK_center: return center; + case AudioManager::SPK_sub: return sub; + case AudioManager::SPK_backleft: return backleft; + case AudioManager::SPK_backright: return backright; + case AudioManager::SPK_sideleft: return sideleft; + case AudioManager::SPK_sideright: return sideright; + default: return 0.0; } - - return returnValue; } //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::set_speaker_mix // Access: Published // Description: This sets the speaker mix for Surround Sound sytems. -// It required 8 parameters which match up to the following: -// 1 = Front Left -// 2 = Front Right -// 3 = Center -// 4 = Subwoofer -// 5 = Back Left -// 6 = Back Right -// 7 = Side Left -// 8 = Side Right -// Speakers which don't exist in some systems will simply be ignored. +// It required 8 parameters which match up to the following: +// +// * 1 = Front Left +// * 2 = Front Right +// * 3 = Center +// * 4 = Subwoofer +// * 5 = Back Left +// * 6 = Back Right +// * 7 = Side Left +// * 8 = Side Right +// //////////////////////////////////////////////////////////////////// void FmodAudioSound:: set_speaker_mix(float frontleft, float frontright, float center, float sub, float backleft, float backright, float sideleft, float sideright) { - _frontleft = frontleft; - _frontright = frontright; - _center = center; - _sub = sub; - _backleft = backleft; - _backright = backright; - _sideleft = sideleft; - _sideright = sideright; + _mix[AudioManager::SPK_frontleft] = frontleft; + _mix[AudioManager::SPK_frontright] = frontright; + _mix[AudioManager::SPK_center] = center; + _mix[AudioManager::SPK_sub] = sub; + _mix[AudioManager::SPK_backleft] = backleft; + _mix[AudioManager::SPK_backright] = backright; + _mix[AudioManager::SPK_sideleft] = sideleft; + _mix[AudioManager::SPK_sideright] = sideright; set_speaker_mix_or_balance_on_channel(); } @@ -971,23 +800,28 @@ set_speaker_mix_or_balance_on_channel() { result = _sound->getMode(&soundMode); fmod_audio_errcheck(result); - if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) { - //FMOD Returns an error is you try and pan a sound in 3D Audio. - //Which makes sense. - //It is nothing serious, but might as well avoid it while we can. - if (( soundMode & FMOD_3D ) == 0) { + if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) { + if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) { result = _channel->setPan( _balance ); - fmod_audio_errcheck(result); + } else { + result = _channel->setSpeakerMix( _mix[AudioManager::SPK_frontleft], + _mix[AudioManager::SPK_frontright], + _mix[AudioManager::SPK_center], + _mix[AudioManager::SPK_sub], + _mix[AudioManager::SPK_backleft], + _mix[AudioManager::SPK_backright], + _mix[AudioManager::SPK_sideleft], + _mix[AudioManager::SPK_sideright] + ); } - } else { - if (( soundMode & FMOD_3D ) == 0) { - result = _channel->setSpeakerMix( _frontleft, _frontright, _center, _sub, _backleft, _backright, _sideleft, _sideright ); + if (result == FMOD_ERR_INVALID_HANDLE) { + _channel = 0; + } else { fmod_audio_errcheck(result); } } } - //////////////////////////////////////////////////////////////////// // Function: FmodAudioSound::get_priority // Access: Published @@ -1028,31 +862,19 @@ set_priority(int priority) { //////////////////////////////////////////////////////////////////// AudioSound::SoundStatus FmodAudioSound:: status() const { - // If the stream's channel isn't playing anything, then the stream - // definitely isn't playing. - - audio_debug("FmodAudioSound::status() "); - FMOD_RESULT result; bool playingState; - if ( _channel != 0 ) { - result = _channel->isPlaying( &playingState ); - fmod_audio_errcheck(result); + if ( _channel == 0 ) { + return READY; } - //audio_debug("If you get 'FMOD State: 32 An invalid object handle was used.' "); - //audio_debug("It doesn't mean there is a problem with FMOD or the sound."); - //audio_debug( "It just means your sound isn't playing." ); - - - if (playingState) { + result = _channel->isPlaying( &playingState ); + if ((result == FMOD_OK) && (playingState == true)) { return PLAYING; } else { return READY; } - - //return BAD; } //////////////////////////////////////////////////////////////////// @@ -1064,7 +886,6 @@ status() const { //////////////////////////////////////////////////////////////////// void FmodAudioSound:: set_active(bool active) { - audio_debug( "set_active(active=" << active << ")" ); audio_debug("NOT USED ANYMORE in FMOD-EX version of PANDA."); } @@ -1097,7 +918,6 @@ void FmodAudioSound:: finished() { audio_debug("FmodAudioSound::finished()"); audio_debug("NOT USED ANYMORE in FMOD-EX version of PANDA."); - stop(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/audiotraits/fmodAudioSound.h b/panda/src/audiotraits/fmodAudioSound.h index a6527ddb55..4ec6f6e1ce 100644 --- a/panda/src/audiotraits/fmodAudioSound.h +++ b/panda/src/audiotraits/fmodAudioSound.h @@ -84,7 +84,7 @@ class FmodAudioDSP; class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound { public: - FmodAudioSound(AudioManager *manager, string file_name, bool positional ); + FmodAudioSound(AudioManager *manager, Filename fn, bool positional ); ~FmodAudioSound(); // For best compatability, set the loop_count, start_time, @@ -148,7 +148,7 @@ class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound { virtual bool add_dsp( PT(AudioDSP) dspToAdd ); virtual bool remove_dsp( PT(AudioDSP) x); - virtual float get_speaker_mix(int speaker); + virtual float get_speaker_mix(AudioManager::SpeakerId speaker); virtual void set_speaker_mix(float frontleft, float frontright, float center, float sub, float backleft, float backright, float sideleft, float sideright); //THESE ARE NOT USED ANYMORE. @@ -170,40 +170,25 @@ class EXPCL_FMOD_AUDIO FmodAudioSound : public AudioSound { FMOD::Sound *_sound; FMOD::Channel *_channel; - string _file_name; + Filename _file_name; float _volume; float _balance; float _playrate; - int _priority; + int _priority; + float _mix[AudioManager::SPK_COUNT]; float _sampleFrequency; mutable float _length; //in seconds. FMOD_SPEAKERMODE _speakermode; - float _frontleft; - float _frontright; - float _center; - float _sub; - float _backleft; - float _backright; - float _sideleft; - float _sideright; - FMOD_VECTOR _location; FMOD_VECTOR _velocity; float _min_dist; float _max_dist; - void play2DSound(); - void play3DSound(); - - void prepareSound(); - void prepare2DSound(); - void prepare3DSound(); - void set_volume_on_channel(); void set_balance_on_channel(); void set_play_rate_on_channel();