Merge branch 'master' of git://github.com/Shyotl/SingularityViewer

This commit is contained in:
Lirusaito
2012-07-18 22:08:06 -04:00
6 changed files with 126 additions and 6 deletions

View File

@@ -95,6 +95,28 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
return true; return true;
} }
void* __stdcall decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
{
if(type & FMOD_MEMORY_STREAM_DECODE)
{
llinfos << "Decode buffer size: " << size << llendl;
}
else if(type & FMOD_MEMORY_STREAM_FILE)
{
llinfos << "Strean buffer size: " << size << llendl;
}
return new char[size];
}
void* __stdcall decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
{
memset(ptr,0,size);
return ptr;
}
void __stdcall decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr)
{
delete[] ptr;
}
bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
{ {
@@ -108,6 +130,10 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL; LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL;
result = FMOD::Memory_Initialize(NULL, NULL, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE);
if(Check_FMOD_Error(result, "FMOD::Memory_Initialize"))
return false;
result = FMOD::System_Create(&mSystem); result = FMOD::System_Create(&mSystem);
if(Check_FMOD_Error(result, "FMOD::System_Create")) if(Check_FMOD_Error(result, "FMOD::System_Create"))
return false; return false;
@@ -156,12 +182,14 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
*/ */
result = mSystem->setDSPBufferSize(1024, 10); result = mSystem->setDSPBufferSize(1024, 10);
Check_FMOD_Error(result, "FMOD::System::setDSPBufferSize"); Check_FMOD_Error(result, "FMOD::System::setDSPBufferSize");
llwarns << "Windows audio acceleration is disabled. This may introduce latency issues." << llendl;
} }
result = mSystem->getDriverInfo(0, name, 256, 0); result = mSystem->getDriverInfo(0, name, 256, 0);
Check_FMOD_Error(result, "FMOD::System::getDriverInfo"); Check_FMOD_Error(result, "FMOD::System::getDriverInfo");
if (strstr(name, "SigmaTel")) if (strstr(name, "SigmaTel"))
{ {
llwarns << "SigmaTel device detected. This may introduce audio quality issues." << llendl;
/* /*
Sigmatel sound devices crackle for some reason if the format is PCM 16bit. Sigmatel sound devices crackle for some reason if the format is PCM 16bit.
PCM floating point output seems to solve it. PCM floating point output seems to solve it.

View File

@@ -58,6 +58,9 @@ class LLStreamingAudioInterface
virtual const LLSD *getMetaData() = 0; virtual const LLSD *getMetaData() = 0;
virtual bool supportsWaveData() = 0; virtual bool supportsWaveData() = 0;
virtual bool getWaveData(float* arr, S32 count, S32 stride = 1) = 0; virtual bool getWaveData(float* arr, S32 count, S32 stride = 1) = 0;
virtual bool supportsAdjustableBufferSizes(){return false;}
virtual void setBufferSizes(U32 streambuffertime, U32 decodebuffertime){};
}; };
#endif // LL_STREAMINGAUDIO_H #endif // LL_STREAMINGAUDIO_H

View File

@@ -50,7 +50,7 @@ public:
const std::string& getURL() { return mInternetStreamURL; } const std::string& getURL() { return mInternetStreamURL; }
FMOD_OPENSTATE getOpenState(); FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
protected: protected:
FMOD::System* mSystem; FMOD::System* mSystem;
FMOD::Channel* mStreamChannel; FMOD::Channel* mStreamChannel;
@@ -70,11 +70,13 @@ LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
mCurrentInternetStreamp(NULL), mCurrentInternetStreamp(NULL),
mFMODInternetStreamChannelp(NULL), mFMODInternetStreamChannelp(NULL),
mGain(1.0f), mGain(1.0f),
mMetaData(NULL) mMetaData(NULL),
mStarvedProgress(0),
mStarvedNoProgressFrames(0)
{ {
// Number of milliseconds of audio to buffer for the audio card. // Number of milliseconds of audio to buffer for the audio card.
// Must be larger than the usual Second Life frame stutter time. // Must be larger than the usual Second Life frame stutter time.
const U32 buffer_seconds = 5; //sec const U32 buffer_seconds = 10; //sec
const U32 estimated_bitrate = 128; //kbit/sec const U32 estimated_bitrate = 128; //kbit/sec
mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
@@ -145,7 +147,10 @@ void LLStreamingAudio_FMODEX::update()
return; return;
} }
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(); unsigned int progress;
bool starving;
bool diskbusy;
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
if (open_state == FMOD_OPENSTATE_READY) if (open_state == FMOD_OPENSTATE_READY)
{ {
@@ -158,6 +163,7 @@ void LLStreamingAudio_FMODEX::update()
// Reset volume to previously set volume // Reset volume to previously set volume
setGain(getGain()); setGain(getGain());
mFMODInternetStreamChannelp->setPaused(false); mFMODInternetStreamChannelp->setPaused(false);
mLastStarved.stop();
} }
} }
else if(open_state == FMOD_OPENSTATE_ERROR) else if(open_state == FMOD_OPENSTATE_ERROR)
@@ -168,6 +174,7 @@ void LLStreamingAudio_FMODEX::update()
if(mFMODInternetStreamChannelp) if(mFMODInternetStreamChannelp)
{ {
llinfos << "progress = " << progress << llendl;
if(!mMetaData) if(!mMetaData)
mMetaData = new LLSD; mMetaData = new LLSD;
@@ -237,12 +244,46 @@ void LLStreamingAudio_FMODEX::update()
} }
} }
} }
if(starving)
{
if(!mLastStarved.getStarted())
{
llinfos << "Stream starvation detected! Muting stream audio until it clears." << llendl;
llinfos << " (diskbusy="<<diskbusy<<")" << llendl;
llinfos << " (progress="<<progress<<")" << llendl;
mFMODInternetStreamChannelp->setMute(true);
mStarvedProgress = progress;
mStarvedNoProgressFrames = 0;
}
else if(mStarvedProgress == progress)
{
if(++mStarvedNoProgressFrames >= 10)
{
//we got 10 consecutive updates of 0 progress made on the stream buffer. It probably stalled.
llinfos << "Stream unable to recover from starvation. Halting." << llendl;
stop();
return;
}
}
else
{
mStarvedNoProgressFrames = 0;
mStarvedProgress = progress;
}
mLastStarved.start();
}
else if(mLastStarved.getStarted() && mLastStarved.getElapsedTimeF32() > 5.f)
{
mLastStarved.stop();
mFMODInternetStreamChannelp->setMute(false);
}
} }
} }
} }
void LLStreamingAudio_FMODEX::stop() void LLStreamingAudio_FMODEX::stop()
{ {
mLastStarved.stop();
if(mMetaData) if(mMetaData)
{ {
delete mMetaData; delete mMetaData;
@@ -341,6 +382,11 @@ void LLStreamingAudio_FMODEX::setGain(F32 vol)
if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp) if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
return false; return false;
bool muted=false;
mFMODInternetStreamChannelp->getMute(&muted);
if(muted)
return false;
static std::vector<float> local_array(count); //Have to have an extra buffer to mix channels. Bleh. static std::vector<float> local_array(count); //Have to have an extra buffer to mix channels. Bleh.
if(count > (S32)local_array.size()) //Expand the array if needed. Try to minimize allocation calls, so don't ever shrink. if(count > (S32)local_array.size()) //Expand the array if needed. Try to minimize allocation calls, so don't ever shrink.
local_array.resize(count); local_array.resize(count);
@@ -442,9 +488,19 @@ bool LLAudioStreamManagerFMODEX::stopStream()
} }
} }
FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState() FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
{ {
FMOD_OPENSTATE state; FMOD_OPENSTATE state;
mInternetStream->getOpenState(&state,NULL,NULL,NULL); mInternetStream->getOpenState(&state,percentbuffered,starving,diskbusy);
return state; return state;
} }
void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
{
mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES);
FMOD_ADVANCEDSETTINGS settings;
memset(&settings,0,sizeof(settings));
settings.cbsize=sizeof(settings);
settings.defaultDecodeBufferSize = decodebuffertime;//ms
mSystem->setAdvancedSettings(&settings);
}

View File

@@ -37,6 +37,7 @@
#include "stdtypes.h" // from llcommon #include "stdtypes.h" // from llcommon
#include "llstreamingaudio.h" #include "llstreamingaudio.h"
#include "lltimer.h"
//Stubs //Stubs
class LLAudioStreamManagerFMODEX; class LLAudioStreamManagerFMODEX;
@@ -66,6 +67,8 @@ class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing. /*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
/*virtual*/ bool supportsWaveData(){return true;} /*virtual*/ bool supportsWaveData(){return true;}
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1); /*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1);
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
private: private:
FMOD::System *mSystem; FMOD::System *mSystem;
@@ -76,6 +79,10 @@ private:
std::string mURL; std::string mURL;
F32 mGain; F32 mGain;
LLTimer mLastStarved;
unsigned int mStarvedProgress;
unsigned int mStarvedNoProgressFrames;
LLSD *mMetaData; LLSD *mMetaData;
}; };

View File

@@ -40,6 +40,28 @@
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map>
<key>SHFMODExStreamBufferSize</key>
<map>
<key>Comment</key>
<string>Sets the streaming buffer size (in milliseconds)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>7000</integer>
</map>
<key>SHFMODExDecodeBufferSize</key>
<map>
<key>Comment</key>
<string>Sets the streaming decode buffer size (in milliseconds)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>1000</integer>
</map> </map>
<key>SHAllowScriptCommands</key> <key>SHAllowScriptCommands</key>
<map> <map>

View File

@@ -54,6 +54,7 @@
#include "llaudioengine.h" #include "llaudioengine.h"
#include "lloverlaybar.h" #include "lloverlaybar.h"
#include "slfloatermediafilter.h" #include "slfloatermediafilter.h"
#include "llstreamingaudio.h"
// Static Variables // Static Variables
@@ -661,6 +662,9 @@ void LLViewerParcelMedia::playStreamingMusic(LLParcel* parcel, bool filter)
else if (gAudiop) else if (gAudiop)
{ {
LLStringUtil::trim(music_url); LLStringUtil::trim(music_url);
LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
if(stream && stream->supportsAdjustableBufferSizes())
stream->setBufferSizes(gSavedSettings.getU32("SHFMODExStreamBufferSize"),gSavedSettings.getU32("SHFMODExDecodeBufferSize"));
gAudiop->startInternetStream(music_url); gAudiop->startInternetStream(music_url);
if (music_url.empty()) if (music_url.empty())
{ {