Audio Engine and FMOD Ex improvements and fixes from Shyotl Kuhr and Drake Arconis
parent
80f42dfdd4
commit
c12f153b68
|
|
@ -72,6 +72,8 @@ LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl()
|
|||
|
||||
void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl)
|
||||
{
|
||||
if (mStreamingAudioImpl)
|
||||
delete mStreamingAudioImpl;
|
||||
mStreamingAudioImpl = impl;
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +136,10 @@ bool LLAudioEngine::init(const S32 num_channels, void* userdata)
|
|||
|
||||
void LLAudioEngine::shutdown()
|
||||
{
|
||||
// Clean up streaming audio
|
||||
delete mStreamingAudioImpl;
|
||||
mStreamingAudioImpl = NULL;
|
||||
|
||||
// Clean up decode manager
|
||||
delete gAudioDecodeMgrp;
|
||||
gAudioDecodeMgrp = NULL;
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const cha
|
|||
}
|
||||
else if(type & FMOD_MEMORY_STREAM_FILE)
|
||||
{
|
||||
LL_INFOS() << "Strean buffer size: " << size << LL_ENDL;
|
||||
LL_INFOS() << "Stream buffer size: " << size << LL_ENDL;
|
||||
}
|
||||
return new char[size];
|
||||
}
|
||||
|
|
@ -180,10 +180,6 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
|||
if(mEnableProfiler)
|
||||
{
|
||||
fmod_flags |= FMOD_INIT_ENABLE_PROFILE;
|
||||
mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]);
|
||||
mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]);
|
||||
mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]);
|
||||
mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]);
|
||||
}
|
||||
|
||||
#if LL_LINUX
|
||||
|
|
@ -194,7 +190,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
|||
if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL;
|
||||
if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK &&
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL;
|
||||
|
|
@ -215,7 +211,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
|||
if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
|
||||
if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK &&
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
|
||||
|
|
@ -236,7 +232,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
|||
if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
|
||||
if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK &&
|
||||
if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_OSS)) == FMOD_OK &&
|
||||
(result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
|
||||
|
|
@ -261,20 +257,22 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
|||
// We're interested in logging which output method we
|
||||
// ended up with, for QA purposes.
|
||||
FMOD_OUTPUTTYPE output_type;
|
||||
mSystem->getOutput(&output_type);
|
||||
switch (output_type)
|
||||
if(!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput"))
|
||||
{
|
||||
case FMOD_OUTPUTTYPE_NOSOUND:
|
||||
LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_PULSEAUDIO:
|
||||
LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_ALSA:
|
||||
LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_OSS:
|
||||
LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
|
||||
default:
|
||||
LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
|
||||
};
|
||||
switch (output_type)
|
||||
{
|
||||
case FMOD_OUTPUTTYPE_NOSOUND:
|
||||
LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_PULSEAUDIO:
|
||||
LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_ALSA:
|
||||
LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
|
||||
case FMOD_OUTPUTTYPE_OSS:
|
||||
LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
|
||||
default:
|
||||
LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
|
||||
};
|
||||
}
|
||||
#else // LL_LINUX
|
||||
|
||||
// initialize the FMOD engine
|
||||
|
|
@ -296,6 +294,14 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
|||
return false;
|
||||
#endif
|
||||
|
||||
if (mEnableProfiler)
|
||||
{
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup");
|
||||
Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup");
|
||||
}
|
||||
|
||||
// set up our favourite FMOD-native streaming audio implementation if none has already been added
|
||||
if (!getStreamingAudioImpl()) // no existing implementation added
|
||||
setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem));
|
||||
|
|
@ -358,18 +364,16 @@ void LLAudioEngine_FMODEX::allocateListener(void)
|
|||
|
||||
void LLAudioEngine_FMODEX::shutdown()
|
||||
{
|
||||
stopInternetStream();
|
||||
|
||||
LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL;
|
||||
LLAudioEngine::shutdown();
|
||||
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << LL_ENDL;
|
||||
if ( mSystem ) // speculative fix for MAINT-2657
|
||||
{
|
||||
mSystem->close();
|
||||
// <FS:Ansariel> Additional debug message; viewer might hang somewhere in here
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() FMOD Ex system closed. Now releasing..." << LL_ENDL;
|
||||
mSystem->release();
|
||||
Check_FMOD_Error(mSystem->close(), "FMOD::System::close");
|
||||
// <FS:Ansariel> Additional debug message; viewer might hang somewhere in here
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() FMOD Ex system closed. Now releasing..." << LL_ENDL;
|
||||
Check_FMOD_Error(mSystem->release(), "FMOD::System::release");
|
||||
}
|
||||
LL_INFOS() << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << LL_ENDL;
|
||||
|
||||
|
|
@ -425,8 +429,8 @@ void LLAudioEngine_FMODEX::cleanupWind()
|
|||
{
|
||||
if (mWindDSP)
|
||||
{
|
||||
mWindDSP->remove();
|
||||
mWindDSP->release();
|
||||
Check_FMOD_Error(mWindDSP->remove(), "FMOD::DSP::remove");
|
||||
Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release");
|
||||
mWindDSP = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -478,8 +482,8 @@ void LLAudioEngine_FMODEX::setInternalGain(F32 gain)
|
|||
gain = llclamp( gain, 0.0f, 1.0f );
|
||||
|
||||
FMOD::ChannelGroup *master_group;
|
||||
mSystem->getMasterChannelGroup(&master_group);
|
||||
|
||||
if(Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup"))
|
||||
return;
|
||||
master_group->setVolume(gain);
|
||||
|
||||
LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
|
||||
|
|
@ -607,7 +611,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)
|
||||
{
|
||||
|
|
@ -641,12 +645,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");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -681,8 +685,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;
|
||||
}
|
||||
|
||||
|
|
@ -701,7 +705,7 @@ LLAudioBufferFMODEX::~LLAudioBufferFMODEX()
|
|||
{
|
||||
if(mSoundp)
|
||||
{
|
||||
mSoundp->release();
|
||||
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release");
|
||||
mSoundp = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -717,7 +721,7 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
|
||||
if (!gDirUtilp->fileExists(filename))
|
||||
{
|
||||
// File not found, abort.
|
||||
return false;
|
||||
|
|
@ -726,7 +730,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;
|
||||
}
|
||||
|
||||
|
|
@ -769,7 +773,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;
|
||||
}
|
||||
|
||||
|
|
@ -777,7 +781,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);
|
||||
|
|
@ -785,7 +789,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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -804,10 +808,9 @@ FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbu
|
|||
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
|
||||
|
||||
thisdsp->getUserData((void **)&windgen);
|
||||
S32 channels, configwidth, configheight;
|
||||
thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight);
|
||||
|
||||
windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
if (windgen)
|
||||
windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,18 +33,13 @@
|
|||
|
||||
#include "llstreamingaudio_fmodex.h"
|
||||
|
||||
// <FS:CR> FmodEX Error checking
|
||||
bool fmod_error_check(FMOD_RESULT result)
|
||||
inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
LL_DEBUGS("FmodEX") << result << " " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
if (result == FMOD_OK)
|
||||
return false;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
// </FS:CR>
|
||||
|
||||
class LLAudioStreamManagerFMODEX
|
||||
{
|
||||
|
|
@ -56,7 +51,7 @@ public:
|
|||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
|
||||
FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL);
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
|
|
@ -77,28 +72,30 @@ LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
|
|||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
const U32 buffer_seconds = 10; //sec
|
||||
const U32 estimated_bitrate = 128; //kbit/sec
|
||||
mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
|
||||
// Here's where we set the size of the network buffer and some buffering
|
||||
// parameters. In this case we want a network buffer of 16k, we want it
|
||||
// to prebuffer 40% of that when we first connect, and we want it
|
||||
// to rebuffer 80% of that whenever we encounter a buffer underrun.
|
||||
|
||||
// Leave the net buffer properties at the default.
|
||||
//FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
|
||||
result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize");
|
||||
}
|
||||
|
||||
|
||||
LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX()
|
||||
{
|
||||
// nothing interesting/safe to do.
|
||||
LL_INFOS() << "LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() destructing FMOD Ex Streaming" << LL_ENDL;
|
||||
stop();
|
||||
for (U32 i = 0; i < 100; ++i)
|
||||
{
|
||||
if (releaseDeadStreams())
|
||||
break;
|
||||
ms_sleep(10);
|
||||
}
|
||||
LL_INFOS() << "LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX() finished" << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
void LLStreamingAudio_FMODEX::start(const std::string& url)
|
||||
{
|
||||
//if (!mInited)
|
||||
|
|
@ -112,9 +109,17 @@ void LLStreamingAudio_FMODEX::start(const std::string& url)
|
|||
|
||||
if (!url.empty())
|
||||
{
|
||||
LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
|
||||
mURL = url;
|
||||
if(mDeadStreams.empty())
|
||||
{
|
||||
LL_INFOS() << "Starting internet stream: " << url << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
|
||||
mURL = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL;
|
||||
mPendingURL = url;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -126,21 +131,19 @@ void LLStreamingAudio_FMODEX::start(const std::string& url)
|
|||
|
||||
void LLStreamingAudio_FMODEX::update()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
if (!releaseDeadStreams())
|
||||
{
|
||||
LLAudioStreamManagerFMODEX *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
LL_INFOS() << "Closed dead stream" << LL_ENDL;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!mPendingURL.empty())
|
||||
{
|
||||
llassert_always(mCurrentInternetStreamp == NULL);
|
||||
LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL;
|
||||
mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,mPendingURL);
|
||||
mURL = mPendingURL;
|
||||
mPendingURL.clear();
|
||||
}
|
||||
|
||||
// Don't do anything if there are no streams playing
|
||||
|
|
@ -152,9 +155,15 @@ void LLStreamingAudio_FMODEX::update()
|
|||
unsigned int progress;
|
||||
bool starving;
|
||||
bool diskbusy;
|
||||
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
|
||||
FMOD_OPENSTATE open_state;
|
||||
FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy);
|
||||
|
||||
if (open_state == FMOD_OPENSTATE_READY)
|
||||
if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
{
|
||||
// Stream is live
|
||||
|
||||
|
|
@ -164,14 +173,9 @@ void LLStreamingAudio_FMODEX::update()
|
|||
{
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
mFMODInternetStreamChannelp->setPaused(false);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if(open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
|
|
@ -179,7 +183,7 @@ void LLStreamingAudio_FMODEX::update()
|
|||
|
||||
// <FS:CR> FmodEX Error checking
|
||||
//if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
|
||||
if (fmod_error_check(mFMODInternetStreamChannelp->getCurrentSound(&sound)) && sound)
|
||||
if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getCurrentSound(&sound), "FMOD::Channel::getCurrentSound") && sound)
|
||||
// </FS:CR>
|
||||
{
|
||||
FMOD_TAG tag;
|
||||
|
|
@ -187,7 +191,7 @@ void LLStreamingAudio_FMODEX::update()
|
|||
|
||||
// <FS:CR> FmodEX Error checking
|
||||
//if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
|
||||
if(fmod_error_check(sound->getNumTags(&tagcount, &dirtytagcount)) && dirtytagcount)
|
||||
if (!Check_FMOD_Error(sound->getNumTags(&tagcount, &dirtytagcount), "FMOD::Sound::getNumTags") && dirtytagcount)
|
||||
// </FS:CR>
|
||||
{
|
||||
// <FS:CR> Stream metadata - originally by Shyotl Khur
|
||||
|
|
@ -284,18 +288,17 @@ void LLStreamingAudio_FMODEX::update()
|
|||
if(starving)
|
||||
{
|
||||
bool paused = false;
|
||||
mFMODInternetStreamChannelp->getPaused(&paused);
|
||||
if(!paused)
|
||||
if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused)
|
||||
{
|
||||
LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL;
|
||||
LL_INFOS() << " (diskbusy="<<diskbusy<<")" << LL_ENDL;
|
||||
LL_INFOS() << " (progress="<<progress<<")" << LL_ENDL;
|
||||
mFMODInternetStreamChannelp->setPaused(true);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
else if(progress > 80)
|
||||
{
|
||||
mFMODInternetStreamChannelp->setPaused(false);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -303,10 +306,12 @@ void LLStreamingAudio_FMODEX::update()
|
|||
|
||||
void LLStreamingAudio_FMODEX::stop()
|
||||
{
|
||||
mPendingURL.clear();
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
mFMODInternetStreamChannelp->setPaused(true);
|
||||
mFMODInternetStreamChannelp->setPriority(0);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused");
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority");
|
||||
mFMODInternetStreamChannelp = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +328,6 @@ void LLStreamingAudio_FMODEX::stop()
|
|||
mDeadStreams.push_back(mCurrentInternetStreamp);
|
||||
}
|
||||
mCurrentInternetStreamp = NULL;
|
||||
//mURL.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +360,7 @@ int LLStreamingAudio_FMODEX::isPlaying()
|
|||
{
|
||||
return 1; // Active and playing
|
||||
}
|
||||
else if (!mURL.empty())
|
||||
else if (!mURL.empty() || !mPendingURL.empty())
|
||||
{
|
||||
return 2; // "Paused"
|
||||
}
|
||||
|
|
@ -387,7 +391,7 @@ void LLStreamingAudio_FMODEX::setGain(F32 vol)
|
|||
{
|
||||
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
|
||||
|
||||
mFMODInternetStreamChannelp->setVolume(vol);
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -440,7 +444,8 @@ LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, con
|
|||
FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
|
||||
{
|
||||
// We need a live and opened stream before we try and play it.
|
||||
if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY)
|
||||
{
|
||||
LL_WARNS() << "No internet stream to start playing!" << LL_ENDL;
|
||||
return NULL;
|
||||
|
|
@ -449,7 +454,7 @@ FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
|
|||
if(mStreamChannel)
|
||||
return mStreamChannel; //Already have a channel for this stream.
|
||||
|
||||
mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel);
|
||||
Check_FMOD_Error(mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel), "FMOD::System::playSound");
|
||||
return mStreamChannel;
|
||||
}
|
||||
|
||||
|
|
@ -457,21 +462,22 @@ bool LLAudioStreamManagerFMODEX::stopStream()
|
|||
{
|
||||
if (mInternetStream)
|
||||
{
|
||||
|
||||
|
||||
bool close = true;
|
||||
switch (getOpenState())
|
||||
FMOD_OPENSTATE open_state;
|
||||
if (getOpenState(open_state) == FMOD_OK)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
switch (open_state)
|
||||
{
|
||||
case FMOD_OPENSTATE_CONNECTING:
|
||||
close = false;
|
||||
break;
|
||||
default:
|
||||
close = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (close)
|
||||
if (close && mInternetStream->release() == FMOD_OK)
|
||||
{
|
||||
mInternetStream->release();
|
||||
mStreamChannel = NULL;
|
||||
mInternetStream = NULL;
|
||||
return true;
|
||||
|
|
@ -487,19 +493,43 @@ bool LLAudioStreamManagerFMODEX::stopStream()
|
|||
}
|
||||
}
|
||||
|
||||
FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
FMOD_RESULT LLAudioStreamManagerFMODEX::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy)
|
||||
{
|
||||
FMOD_OPENSTATE state;
|
||||
mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
return state;
|
||||
if (!mInternetStream)
|
||||
return FMOD_ERR_INVALID_HANDLE;
|
||||
FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
|
||||
Check_FMOD_Error(result, "FMOD::Sound::getOpenState");
|
||||
return result;
|
||||
}
|
||||
|
||||
void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
|
||||
{
|
||||
mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES);
|
||||
Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize");
|
||||
FMOD_ADVANCEDSETTINGS settings;
|
||||
memset(&settings,0,sizeof(settings));
|
||||
settings.cbsize=sizeof(settings);
|
||||
settings.defaultDecodeBufferSize = decodebuffertime;//ms
|
||||
mSystem->setAdvancedSettings(&settings);
|
||||
Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings");
|
||||
}
|
||||
|
||||
bool LLStreamingAudio_FMODEX::releaseDeadStreams()
|
||||
{
|
||||
// Kill dead internet streams, if possible
|
||||
std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
|
||||
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
|
||||
{
|
||||
LLAudioStreamManagerFMODEX *streamp = *iter;
|
||||
if (streamp->stopStream())
|
||||
{
|
||||
LL_INFOS() << "Closed dead stream" << LL_ENDL;
|
||||
delete streamp;
|
||||
mDeadStreams.erase(iter++);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return mDeadStreams.empty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
|
|||
// </FS:CR>
|
||||
|
||||
private:
|
||||
bool releaseDeadStreams();
|
||||
|
||||
FMOD::System *mSystem;
|
||||
|
||||
LLAudioStreamManagerFMODEX *mCurrentInternetStreamp;
|
||||
|
|
@ -71,8 +73,9 @@ private:
|
|||
std::list<LLAudioStreamManagerFMODEX *> mDeadStreams;
|
||||
|
||||
std::string mURL;
|
||||
std::string mPendingURL;
|
||||
F32 mGain;
|
||||
|
||||
|
||||
// <FS:CR> Streamtitle display
|
||||
bool mNewMetadata;
|
||||
LLSD mMetadata;
|
||||
|
|
|
|||
|
|
@ -2135,14 +2135,8 @@ bool LLAppViewer::cleanup()
|
|||
|
||||
if (gAudiop)
|
||||
{
|
||||
// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
|
||||
|
||||
LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
|
||||
delete sai;
|
||||
gAudiop->setStreamingAudioImpl(NULL);
|
||||
|
||||
// shut down the audio subsystem
|
||||
gAudiop->shutdown();
|
||||
gAudiop->shutdown();
|
||||
|
||||
delete gAudiop;
|
||||
gAudiop = NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue