void LLStreamingAudio_FMOD::stop() { if (mFMODInternetStreamChannel != -1) { FMOD_API(FSOUND_SetPaused)(mFMODInternetStreamChannel, true); FMOD_API(FSOUND_SetPriority)(mFMODInternetStreamChannel, 0); mFMODInternetStreamChannel = -1; } if (mCurrentInternetStreamp) { llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl; if (mCurrentInternetStreamp->stopStream()) { delete mCurrentInternetStreamp; } else { llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl; mDeadStreams.push_back(mCurrentInternetStreamp); } mCurrentInternetStreamp = NULL; //mURL.clear(); } }
int LLAudioStreamManagerFMOD::startStream() { // We need a live and opened stream before we try and play it. if (!mInternetStream || getOpenState()) { llwarns << "No internet stream to start playing!" << llendl; return -1; } // Make sure the stream is set to 2D mode. FMOD_API(FSOUND_Stream_SetMode)(mInternetStream, FSOUND_2D); return FMOD_API(FSOUND_Stream_PlayEx)(FSOUND_FREE, mInternetStream, NULL, true); }
LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) : mInternetStream(NULL), mReady(false) { mInternetStreamURL = url; mInternetStream = FMOD_API(FSOUND_Stream_Open)(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); if (!mInternetStream) { llwarns << "Couldn't open fmod stream, error " << FMOD_ErrorString(FMOD_API(FSOUND_GetError)()) << llendl; mReady = false; return; } mReady = true; }
void LLStreamingAudio_FMOD::setGain(F32 vol) { mGain = vol; if (mFMODInternetStreamChannel != -1) { vol = llclamp(vol, 0.f, 1.f); int vol_int = llround(vol * 255.f); FMOD_API(FSOUND_SetVolumeAbsolute)(mFMODInternetStreamChannel, vol_int); } }
//----------------------------------------------------------------------- void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) { LLListener::orient(up, at); // Welcome to the transition between right and left // (coordinate systems, that is) // Leaving the at vector alone results in a L/R reversal // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed at = -at; FMOD_API(FSOUND_3D_Listener_SetAttributes)(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); }
bool LLAudioStreamManagerFMOD::stopStream() { if (mInternetStream) { int read_percent = 0; int status = 0; int bitrate = 0; unsigned int flags = 0x0; FMOD_API(FSOUND_Stream_Net_GetStatus)(mInternetStream, &status, &read_percent, &bitrate, &flags); bool close = true; switch (status) { case FSOUND_STREAM_NET_CONNECTING: close = false; break; case FSOUND_STREAM_NET_NOTCONNECTED: case FSOUND_STREAM_NET_BUFFERING: case FSOUND_STREAM_NET_READY: case FSOUND_STREAM_NET_ERROR: default: close = true; } if (close) { FMOD_API(FSOUND_Stream_Close)(mInternetStream); mInternetStream = NULL; return true; } else { return false; } } else { return true; } }
//--------------------------------------------------------------------------- // Internet Streaming //--------------------------------------------------------------------------- LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : mCurrentInternetStreamp(NULL), mFMODInternetStreamChannel(-1), mGain(1.0f) { // Number of milliseconds of audio to buffer for the audio card. // Must be larger than the usual Second Life frame stutter time. FMOD_API(FSOUND_Stream_SetBufferSize)(200); // 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); }
int LLAudioStreamManagerFMOD::getOpenState() { int open_state = FMOD_API(FSOUND_Stream_GetOpenState)(mInternetStream); return open_state; }
void LLStreamingAudio_FMOD::update() { // Kill dead internet streams, if possible std::list<LLAudioStreamManagerFMOD *>::iterator iter; for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) { LLAudioStreamManagerFMOD *streamp = *iter; if (streamp->stopStream()) { llinfos << "Closed dead stream" << llendl; delete streamp; mDeadStreams.erase(iter++); } else { iter++; } } // Don't do anything if there are no streams playing if (!mCurrentInternetStreamp) { return; } int open_state = mCurrentInternetStreamp->getOpenState(); if (!open_state) { // Stream is live // start the stream if it's ready if (mFMODInternetStreamChannel < 0) { mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream(); if (mFMODInternetStreamChannel != -1) { // Reset volume to previously set volume setGain(getGain()); FMOD_API(FSOUND_SetPaused)(mFMODInternetStreamChannel, false); } } } switch(open_state) { default: case 0: // success break; case -1: // stream handle is invalid llwarns << "InternetStream - invalid handle" << llendl; stop(); return; case -2: // opening break; case -3: // failed to open, file not found, perhaps llwarns << "InternetSteam - failed to open" << llendl; stop(); return; case -4: // connecting break; case -5: // buffering break; } }
//----------------------------------------------------------------------- void LLListener_FMOD::setVelocity(LLVector3 vel) { LLListener::setVelocity(vel); FMOD_API(FSOUND_3D_Listener_SetAttributes)(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); }
//----------------------------------------------------------------------- void LLListener_FMOD::setPosition(LLVector3 pos) { LLListener::setPosition(pos); FMOD_API(FSOUND_3D_Listener_SetAttributes)(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); }
//----------------------------------------------------------------------- void LLListener_FMOD::translate(LLVector3 offset) { LLListener::translate(offset); FMOD_API(FSOUND_3D_Listener_SetAttributes)(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); }
void LLListener_FMOD::setDistanceFactor(F32 factor) { mDistanceFactor = factor; FMOD_API(FSOUND_3D_SetDistanceFactor)(factor); }
void LLListener_FMOD::setDopplerFactor(F32 factor) { mDopplerFactor = factor; FMOD_API(FSOUND_3D_SetDopplerFactor)(factor); }
void LLListener_FMOD::setRolloffFactor(F32 factor) { mRolloffFactor = factor; FMOD_API(FSOUND_3D_SetRolloffFactor)(factor); }
//----------------------------------------------------------------------- void LLListener_FMOD::commitDeferredChanges() { FMOD_API(FSOUND_Update)(); }