Merge branch 'master' of git://github.com/Shyotl/SingularityViewer
This commit is contained in:
@@ -95,6 +95,28 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -108,6 +130,10 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
|
||||
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);
|
||||
if(Check_FMOD_Error(result, "FMOD::System_Create"))
|
||||
return false;
|
||||
@@ -156,12 +182,14 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
|
||||
*/
|
||||
result = mSystem->setDSPBufferSize(1024, 10);
|
||||
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);
|
||||
Check_FMOD_Error(result, "FMOD::System::getDriverInfo");
|
||||
|
||||
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.
|
||||
PCM floating point output seems to solve it.
|
||||
|
||||
@@ -58,6 +58,9 @@ class LLStreamingAudioInterface
|
||||
virtual const LLSD *getMetaData() = 0;
|
||||
virtual bool supportsWaveData() = 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
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
|
||||
const std::string& getURL() { return mInternetStreamURL; }
|
||||
|
||||
FMOD_OPENSTATE getOpenState();
|
||||
FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
|
||||
protected:
|
||||
FMOD::System* mSystem;
|
||||
FMOD::Channel* mStreamChannel;
|
||||
@@ -70,11 +70,13 @@ LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
|
||||
mCurrentInternetStreamp(NULL),
|
||||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f),
|
||||
mMetaData(NULL)
|
||||
mMetaData(NULL),
|
||||
mStarvedProgress(0),
|
||||
mStarvedNoProgressFrames(0)
|
||||
{
|
||||
// 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 = 5; //sec
|
||||
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);
|
||||
|
||||
@@ -145,7 +147,10 @@ void LLStreamingAudio_FMODEX::update()
|
||||
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)
|
||||
{
|
||||
@@ -158,6 +163,7 @@ void LLStreamingAudio_FMODEX::update()
|
||||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
mFMODInternetStreamChannelp->setPaused(false);
|
||||
mLastStarved.stop();
|
||||
}
|
||||
}
|
||||
else if(open_state == FMOD_OPENSTATE_ERROR)
|
||||
@@ -168,6 +174,7 @@ void LLStreamingAudio_FMODEX::update()
|
||||
|
||||
if(mFMODInternetStreamChannelp)
|
||||
{
|
||||
llinfos << "progress = " << progress << llendl;
|
||||
if(!mMetaData)
|
||||
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()
|
||||
{
|
||||
mLastStarved.stop();
|
||||
if(mMetaData)
|
||||
{
|
||||
delete mMetaData;
|
||||
@@ -341,6 +382,11 @@ void LLStreamingAudio_FMODEX::setGain(F32 vol)
|
||||
if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
|
||||
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.
|
||||
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);
|
||||
@@ -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;
|
||||
mInternetStream->getOpenState(&state,NULL,NULL,NULL);
|
||||
mInternetStream->getOpenState(&state,percentbuffered,starving,diskbusy);
|
||||
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);
|
||||
}
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "stdtypes.h" // from llcommon
|
||||
|
||||
#include "llstreamingaudio.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//Stubs
|
||||
class LLAudioStreamManagerFMODEX;
|
||||
@@ -66,6 +67,8 @@ class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
|
||||
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
|
||||
/*virtual*/ bool supportsWaveData(){return true;}
|
||||
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1);
|
||||
/*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
|
||||
/*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
|
||||
private:
|
||||
FMOD::System *mSystem;
|
||||
|
||||
@@ -76,6 +79,10 @@ private:
|
||||
std::string mURL;
|
||||
F32 mGain;
|
||||
|
||||
LLTimer mLastStarved;
|
||||
unsigned int mStarvedProgress;
|
||||
unsigned int mStarvedNoProgressFrames;
|
||||
|
||||
LLSD *mMetaData;
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,28 @@
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<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>
|
||||
<key>SHAllowScriptCommands</key>
|
||||
<map>
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "llaudioengine.h"
|
||||
#include "lloverlaybar.h"
|
||||
#include "slfloatermediafilter.h"
|
||||
#include "llstreamingaudio.h"
|
||||
|
||||
// Static Variables
|
||||
|
||||
@@ -661,6 +662,9 @@ void LLViewerParcelMedia::playStreamingMusic(LLParcel* parcel, bool filter)
|
||||
else if (gAudiop)
|
||||
{
|
||||
LLStringUtil::trim(music_url);
|
||||
LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
|
||||
if(stream && stream->supportsAdjustableBufferSizes())
|
||||
stream->setBufferSizes(gSavedSettings.getU32("SHFMODExStreamBufferSize"),gSavedSettings.getU32("SHFMODExDecodeBufferSize"));
|
||||
gAudiop->startInternetStream(music_url);
|
||||
if (music_url.empty())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user