From 2b30a5a4e7ca608a5bec7e4812cb4d93796c12fe Mon Sep 17 00:00:00 2001 From: Shyotl Date: Thu, 16 May 2013 01:58:35 -0500 Subject: [PATCH] Catch case in llaudioengine where audio buffers are released with channels still consuming them(A proper fix should be done to avoid this scenario in the future). Added stricter checking for fmodex errors. Demote a harmless message from llinfos to lldebugs when audio buffers are all consumed. Initialize LLAudioBuffer member variables. -LLAudioBuffer::mInUse is inited to TRUE to avoid buffers that just got created from getting deleted during the same frame by new audio sources further down the chain. --- indra/llaudio/llaudioengine.cpp | 35 +++++++++++++++++++------- indra/llaudio/llaudioengine.h | 1 + indra/llaudio/llaudioengine_fmod.cpp | 2 +- indra/llaudio/llaudioengine_fmodex.cpp | 29 ++++++++++----------- indra/llaudio/llaudioengine_openal.cpp | 2 +- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 98587674c..558c929e1 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -368,7 +368,7 @@ void LLAudioEngine::idle(F32 max_decode_time) if (channelp) { channelp->updateBuffer(); - sourcep->getChannel()->play(); + channelp->play(); } continue; } @@ -391,8 +391,12 @@ void LLAudioEngine::idle(F32 max_decode_time) // Actually play the associated data. sourcep->setupChannel(); - channelp->updateBuffer(); - sourcep->getChannel()->play(); + channelp = sourcep->getChannel(); + if (channelp) + { + channelp->updateBuffer(); + channelp->play(); + } } else if (sourcep->isLoop()) { @@ -405,7 +409,12 @@ void LLAudioEngine::idle(F32 max_decode_time) // Actually, should do a time sync so if we're a loop master/slave // we don't drift away. sourcep->setupChannel(); - sourcep->getChannel()->play(); + channelp = sourcep->getChannel(); + if (channelp) + { + channelp->updateBuffer(); + channelp->play(); + } } } } @@ -597,6 +606,14 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer() lldebugs << "Taking over unused buffer " << buffer_id << llendl; //llinfos << "Flushing unused buffer!" << llendl; mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL; + for (U32 i = 0; i < MAX_CHANNELS; i++) + { + LLAudioChannel* channelp = mChannels[i]; + if(channelp && channelp->mCurrentBufferp == mBuffers[buffer_id]) + { + channelp->cleanup(); + } + } delete mBuffers[buffer_id]; mBuffers[buffer_id] = createBuffer(); return mBuffers[buffer_id]; @@ -1374,14 +1391,14 @@ void LLAudioSource::update() return ; //no need to update } - if (!getCurrentBuffer()) + //if (!getCurrentBuffer()) // Same as !adp->getBuffer() { LLAudioData *adp = getCurrentData(); - if (adp) + if (adp && !adp->getBuffer()) { // Hack - try and load the sound. Will do this as a callback // on decode later. - if (adp->load() && adp->getBuffer()) + if (adp->load()) { play(adp->getID()); } @@ -1847,8 +1864,8 @@ bool LLAudioData::load() if (!mBufferp) { // No free buffers, abort. - llinfos << "Not able to allocate a new audio buffer, aborting." << llendl; - return true; + lldebugs << "Not able to allocate a new audio buffer, aborting." << llendl; + return false; } std::string uuid_str; diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index cf44afee7..230168ee9 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -478,6 +478,7 @@ protected: class LLAudioBuffer { public: + LLAudioBuffer() : mInUse(true), mAudioDatap(NULL) { mLastUseTimer.reset(); } virtual ~LLAudioBuffer() {}; virtual bool loadWAV(const std::string& filename) = 0; virtual U32 getLength() = 0; diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp index 168bb5f60..f47a6cac0 100644 --- a/indra/llaudio/llaudioengine_fmod.cpp +++ b/indra/llaudio/llaudioengine_fmod.cpp @@ -647,7 +647,7 @@ bool LLAudioChannelFMOD::isPlaying() // -LLAudioBufferFMOD::LLAudioBufferFMOD() +LLAudioBufferFMOD::LLAudioBufferFMOD() : LLAudioBuffer() { mSamplep = NULL; } diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index 4b4108701..56997a888 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -525,15 +525,16 @@ bool LLAudioChannelFMODEX::updateBuffer() } // If we have a source for the channel, we need to update its gain. - if (mCurrentSourcep) + if (mCurrentSourcep && mChannelp) { // SJB: warnings can spam and hurt framerate, disabling FMOD_RESULT result; - result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); - //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); + result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); + Check_FMOD_Error(result, "FMOD::Channel::setVolume"); result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + Check_FMOD_Error(result, "FMOD::Channel::setMode"); /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) { S32 index; @@ -595,7 +596,7 @@ void LLAudioChannelFMODEX::updateLoop() // yield false negatives. // U32 cur_pos; - mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES); + Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES),"FMOD::Channel::getPosition"); if (cur_pos < (U32)mLastSamplePos) { @@ -629,12 +630,12 @@ void LLAudioChannelFMODEX::play() return; } - Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); + Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused"); getSource()->setPlayedOnce(true); if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]) - mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]); + Check_FMOD_Error(mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]),"FMOD::Channel::setChannelGroup"); } @@ -669,8 +670,8 @@ bool LLAudioChannelFMODEX::isPlaying() } bool paused, playing; - mChannelp->getPaused(&paused); - mChannelp->isPlaying(&playing); + Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused"); + Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying"); return !paused && playing; } @@ -680,7 +681,7 @@ bool LLAudioChannelFMODEX::isPlaying() // -LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL) +LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : LLAudioBuffer(), mSystemp(system), mSoundp(NULL) { } @@ -689,7 +690,7 @@ LLAudioBufferFMODEX::~LLAudioBufferFMODEX() { if(mSoundp) { - mSoundp->release(); + Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release"); mSoundp = NULL; } } @@ -714,7 +715,7 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) if (mSoundp) { // If there's already something loaded in this buffer, clean it up. - mSoundp->release(); + Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release"); mSoundp = NULL; } @@ -757,7 +758,7 @@ U32 LLAudioBufferFMODEX::getLength() } U32 length; - mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); + Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength"); return length; } @@ -765,7 +766,7 @@ U32 LLAudioBufferFMODEX::getLength() void LLAudioChannelFMODEX::set3DMode(bool use3d) { FMOD_MODE current_mode; - if(mChannelp->getMode(¤t_mode) != FMOD_OK) + if(Check_FMOD_Error(mChannelp->getMode(¤t_mode),"FMOD::Channel::getMode")) return; FMOD_MODE new_mode = current_mode; new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); @@ -773,7 +774,7 @@ void LLAudioChannelFMODEX::set3DMode(bool use3d) if(current_mode != new_mode) { - mChannelp->setMode(new_mode); + Check_FMOD_Error(mChannelp->setMode(new_mode),"FMOD::Channel::setMode"); } } diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index 17c5d860f..1b2c8c6ee 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -314,7 +314,7 @@ void LLAudioChannelOpenAL::update3DPosition() alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain()); } -LLAudioBufferOpenAL::LLAudioBufferOpenAL() +LLAudioBufferOpenAL::LLAudioBufferOpenAL() : LLAudioBuffer() { mALBuffer = AL_NONE; }