703 lines
25 KiB
C++
703 lines
25 KiB
C++
/**
|
|
* @file llvieweraudio.cpp
|
|
* @brief Audio functions that used to be in viewer.cpp
|
|
*
|
|
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llaudioengine.h"
|
|
#include "llagent.h"
|
|
#include "llagentcamera.h"
|
|
#include "llappviewer.h"
|
|
#include "lldeferredsounds.h"
|
|
#include "llvieweraudio.h"
|
|
#include "llviewercamera.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llviewerwindow.h"
|
|
#include "llvoiceclient.h"
|
|
#include "llviewermedia.h"
|
|
#include "llviewerregion.h"
|
|
#include "llprogressview.h"
|
|
#include "llcallbacklist.h"
|
|
#include "llstartup.h"
|
|
#include "llviewerparcelmgr.h"
|
|
#include "llparcel.h"
|
|
#include "llviewermessage.h"
|
|
|
|
#include "llstreamingaudio.h"
|
|
|
|
#include "llvoavatarself.h"
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
LLViewerAudio::LLViewerAudio() :
|
|
mDone(true),
|
|
mFadeState(FADE_IDLE),
|
|
mFadeTime(),
|
|
mIdleListnerActive(false),
|
|
mForcedTeleportFade(false),
|
|
mWasPlaying(false)
|
|
{
|
|
mTeleportFailedConnection = LLViewerParcelMgr::getInstance()->
|
|
setTeleportFailedCallback(boost::bind(&LLViewerAudio::onTeleportFailed, this));
|
|
mTeleportFinishedConnection = LLViewerParcelMgr::getInstance()->
|
|
setTeleportFinishedCallback(boost::bind(&LLViewerAudio::onTeleportFinished, this, _1, _2));
|
|
mTeleportStartedConnection = LLViewerMessage::getInstance()->
|
|
setTeleportStartedCallback(boost::bind(&LLViewerAudio::onTeleportStarted, this));
|
|
}
|
|
|
|
LLViewerAudio::~LLViewerAudio()
|
|
{
|
|
mTeleportFailedConnection.disconnect();
|
|
mTeleportFinishedConnection.disconnect();
|
|
mTeleportStartedConnection.disconnect();
|
|
}
|
|
|
|
void LLViewerAudio::registerIdleListener()
|
|
{
|
|
if(mIdleListnerActive==false)
|
|
{
|
|
mIdleListnerActive = true;
|
|
doOnIdleRepeating(boost::bind(boost::bind(&LLViewerAudio::onIdleUpdate, this)));
|
|
}
|
|
}
|
|
|
|
void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI)
|
|
{
|
|
// Old and new stream are identical
|
|
if (mNextStreamURI == streamURI)
|
|
{
|
|
/// <FS:CR> FIRE-8419 - Don't return here. It can keep the user from toggling audio streams off/on.
|
|
/// We handle identical stream URIs with FIRE-7093 anyways.
|
|
//return;
|
|
LL_DEBUGS() << "Identical URI's: " << mNextStreamURI << " and " << streamURI << LL_ENDL;
|
|
// </FS:CR>
|
|
}
|
|
|
|
// Record the URI we are going to be switching to
|
|
mNextStreamURI = streamURI;
|
|
|
|
// <FS:Ansariel> Optional audio stream fading
|
|
if (!gSavedSettings.getBOOL("FSFadeAudioStream"))
|
|
{
|
|
gAudiop->startInternetStream(mNextStreamURI);
|
|
return;
|
|
}
|
|
// </FS:Ansariel>
|
|
|
|
switch (mFadeState)
|
|
{
|
|
case FADE_IDLE:
|
|
if (!gAudiop)
|
|
{
|
|
LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
|
|
break;
|
|
}
|
|
// If a stream is playing fade it out first
|
|
if (!gAudiop->getInternetStreamURL().empty())
|
|
{
|
|
// The order of these tests is important, state FADE_OUT will be processed below
|
|
mFadeState = FADE_OUT;
|
|
}
|
|
// Otherwise the new stream can be faded in
|
|
else
|
|
{
|
|
mFadeState = FADE_IN;
|
|
|
|
LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
|
|
if(stream && stream->supportsAdjustableBufferSizes())
|
|
stream->setBufferSizes(gSavedSettings.getU32("FMODStreamBufferSize"),gSavedSettings.getU32("FMODDecodeBufferSize"));
|
|
|
|
gAudiop->startInternetStream(mNextStreamURI);
|
|
startFading();
|
|
registerIdleListener();
|
|
break;
|
|
}
|
|
|
|
case FADE_OUT:
|
|
startFading();
|
|
registerIdleListener();
|
|
break;
|
|
|
|
case FADE_IN:
|
|
registerIdleListener();
|
|
break;
|
|
|
|
default:
|
|
LL_WARNS() << "Unknown fading state: " << mFadeState << LL_ENDL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// A return of false from onIdleUpdate means it will be called again next idle update.
|
|
// A return of true means we have finished with it and the callback will be deleted.
|
|
bool LLViewerAudio::onIdleUpdate()
|
|
{
|
|
bool fadeIsFinished = false;
|
|
|
|
// There is a delay in the login sequence between when the parcel information has
|
|
// arrived and the music stream is started and when the audio system is called to set
|
|
// initial volume levels. This code extends the fade time so you hear a full fade in.
|
|
if ((LLStartUp::getStartupState() < STATE_STARTED))
|
|
{
|
|
stream_fade_timer.reset();
|
|
stream_fade_timer.setTimerExpirySec(mFadeTime);
|
|
}
|
|
|
|
if (mDone)
|
|
{
|
|
// This should be a rare or never occurring state.
|
|
if (mFadeState == FADE_IDLE)
|
|
{
|
|
deregisterIdleListener();
|
|
fadeIsFinished = true; // Stop calling onIdleUpdate
|
|
}
|
|
|
|
// we have finished the current fade operation
|
|
if (mFadeState == FADE_OUT)
|
|
{
|
|
if (gAudiop)
|
|
{
|
|
// Clear URI
|
|
gAudiop->startInternetStream(LLStringUtil::null);
|
|
gAudiop->stopInternetStream();
|
|
}
|
|
|
|
if (!mNextStreamURI.empty())
|
|
{
|
|
mFadeState = FADE_IN;
|
|
|
|
if (gAudiop)
|
|
{
|
|
LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
|
|
if(stream && stream->supportsAdjustableBufferSizes())
|
|
stream->setBufferSizes(gSavedSettings.getU32("FMODStreamBufferSize"),gSavedSettings.getU32("FMODDecodeBufferSize"));
|
|
|
|
gAudiop->startInternetStream(mNextStreamURI);
|
|
}
|
|
|
|
startFading();
|
|
}
|
|
else
|
|
{
|
|
mFadeState = FADE_IDLE;
|
|
deregisterIdleListener();
|
|
fadeIsFinished = true; // Stop calling onIdleUpdate
|
|
}
|
|
}
|
|
else if (mFadeState == FADE_IN)
|
|
{
|
|
if (gAudiop && mNextStreamURI != gAudiop->getInternetStreamURL())
|
|
{
|
|
mFadeState = FADE_OUT;
|
|
startFading();
|
|
}
|
|
else
|
|
{
|
|
mFadeState = FADE_IDLE;
|
|
deregisterIdleListener();
|
|
fadeIsFinished = true; // Stop calling onIdleUpdate
|
|
}
|
|
}
|
|
}
|
|
|
|
return fadeIsFinished;
|
|
}
|
|
|
|
void LLViewerAudio::stopInternetStreamWithAutoFade()
|
|
{
|
|
// <FS:Ansariel> Optional audio stream fading
|
|
if (!gSavedSettings.getBOOL("FSFadeAudioStream"))
|
|
{
|
|
mNextStreamURI = LLStringUtil::null;
|
|
gAudiop->stopInternetStream();
|
|
return;
|
|
}
|
|
// </FS:Ansariel>
|
|
|
|
mFadeState = FADE_IDLE;
|
|
mNextStreamURI = LLStringUtil::null;
|
|
mDone = true;
|
|
|
|
if (gAudiop)
|
|
{
|
|
gAudiop->startInternetStream(LLStringUtil::null);
|
|
gAudiop->stopInternetStream();
|
|
}
|
|
}
|
|
|
|
void LLViewerAudio::startFading()
|
|
{
|
|
// <FS:Ansariel> Make fadint time configurable again
|
|
//const F32 AUDIO_MUSIC_FADE_IN_TIME = 3.0f;
|
|
//const F32 AUDIO_MUSIC_FADE_OUT_TIME = 2.0f;
|
|
F32 AUDIO_MUSIC_FADE_IN_TIME = gSavedSettings.getF32("FSAudioMusicFadeIn");
|
|
F32 AUDIO_MUSIC_FADE_OUT_TIME = gSavedSettings.getF32("FSAudioMusicFadeOut");
|
|
// </FS:Ansariel>
|
|
// This minimum fade time prevents divide by zero and negative times
|
|
const F32 AUDIO_MUSIC_MINIMUM_FADE_TIME = 0.01f;
|
|
|
|
if(mDone)
|
|
{
|
|
// The fade state here should only be one of FADE_IN or FADE_OUT, but, in case it is not,
|
|
// rather than check for both states assume a fade in and check for the fade out case.
|
|
mFadeTime = AUDIO_MUSIC_FADE_IN_TIME;
|
|
if (LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT)
|
|
{
|
|
mFadeTime = AUDIO_MUSIC_FADE_OUT_TIME;
|
|
}
|
|
|
|
// Prevent invalid fade time
|
|
mFadeTime = llmax(mFadeTime, AUDIO_MUSIC_MINIMUM_FADE_TIME);
|
|
|
|
stream_fade_timer.reset();
|
|
stream_fade_timer.setTimerExpirySec(mFadeTime);
|
|
mDone = false;
|
|
}
|
|
}
|
|
|
|
F32 LLViewerAudio::getFadeVolume()
|
|
{
|
|
F32 fade_volume = 1.0f;
|
|
|
|
if (stream_fade_timer.hasExpired())
|
|
{
|
|
mDone = true;
|
|
// If we have been fading out set volume to 0 until the next fade state occurs to prevent
|
|
// an audio transient.
|
|
if (LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT)
|
|
{
|
|
fade_volume = 0.0f;
|
|
}
|
|
}
|
|
|
|
if (!mDone)
|
|
{
|
|
// Calculate how far we are into the fade time
|
|
fade_volume = stream_fade_timer.getElapsedTimeF32() / mFadeTime;
|
|
|
|
if (LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT)
|
|
{
|
|
// If we are not fading in then we are fading out, so invert the fade
|
|
// direction; start loud and move towards zero volume.
|
|
fade_volume = 1.0f - fade_volume;
|
|
}
|
|
}
|
|
|
|
return fade_volume;
|
|
}
|
|
|
|
void LLViewerAudio::onTeleportStarted()
|
|
{
|
|
if (gAudiop && !LLViewerAudio::getInstance()->getForcedTeleportFade())
|
|
{
|
|
// Even though the music was turned off it was starting up (with autoplay disabled) occasionally
|
|
// after a failed teleport or after an intra-parcel teleport. Also, the music sometimes was not
|
|
// restarting after a successful intra-parcel teleport. Setting mWasPlaying fixes these issues.
|
|
LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty());
|
|
|
|
// <FS:Ansariel> Optional audio stream fading
|
|
if (!gSavedSettings.getBOOL("FSFadeAudioStream"))
|
|
{
|
|
return;
|
|
}
|
|
// </FS:Ansariel>
|
|
|
|
// <FS:TM> FIRE-7093 - Don't attempt to switch music streams when the URL hasn't changed
|
|
if (mNextStreamURI == gAudiop->getInternetStreamURL())
|
|
{
|
|
return;
|
|
}
|
|
//</FS:TM>
|
|
|
|
LLViewerAudio::getInstance()->setForcedTeleportFade(true);
|
|
LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
|
|
LLViewerAudio::getInstance()->setNextStreamURI(LLStringUtil::null);
|
|
}
|
|
}
|
|
|
|
void LLViewerAudio::onTeleportFailed()
|
|
{
|
|
// Calling audio_update_volume makes sure that the music stream is properly set to be restored to
|
|
// its previous value
|
|
audio_update_volume(false);
|
|
|
|
if (gAudiop && mWasPlaying)
|
|
{
|
|
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
|
if (parcel)
|
|
{
|
|
mNextStreamURI = parcel->getMusicURL();
|
|
LL_INFOS() << "Teleport failed -- setting music stream to " << mNextStreamURI << LL_ENDL;
|
|
}
|
|
}
|
|
mWasPlaying = false;
|
|
}
|
|
|
|
void LLViewerAudio::onTeleportFinished(const LLVector3d& pos, const bool& local)
|
|
{
|
|
// Calling audio_update_volume makes sure that the music stream is properly set to be restored to
|
|
// its previous value
|
|
audio_update_volume(false);
|
|
|
|
if (gAudiop && local && mWasPlaying)
|
|
{
|
|
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
|
if (parcel)
|
|
{
|
|
mNextStreamURI = parcel->getMusicURL();
|
|
LL_INFOS() << "Intraparcel teleport -- setting music stream to " << mNextStreamURI << LL_ENDL;
|
|
}
|
|
}
|
|
mWasPlaying = false;
|
|
}
|
|
|
|
void init_audio()
|
|
{
|
|
if (!gAudiop)
|
|
{
|
|
LL_WARNS() << "Failed to create an appropriate Audio Engine" << LL_ENDL;
|
|
return;
|
|
}
|
|
LLVector3d lpos_global = gAgentCamera.getCameraPositionGlobal();
|
|
LLVector3 lpos_global_f;
|
|
|
|
lpos_global_f.setVec(lpos_global);
|
|
|
|
gAudiop->setListener(lpos_global_f,
|
|
LLVector3::zero, // LLViewerCamera::getInstance()->getVelocity(), // !!! BUG need to replace this with smoothed velocity!
|
|
LLViewerCamera::getInstance()->getUpAxis(),
|
|
LLViewerCamera::getInstance()->getAtAxis());
|
|
|
|
// load up our initial set of sounds we'll want so they're in memory and ready to be played
|
|
|
|
BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio");
|
|
|
|
if (!mute_audio && FALSE == gSavedSettings.getBOOL("NoPreload"))
|
|
{
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndAlert")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndBadKeystroke")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndChatFromObject")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndClick")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndClickRelease")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndHealthReductionF")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndHealthReductionM")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndIncomingChat")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndIncomingIM")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndInvApplyToObject")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndInvalidOp")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndInventoryCopyToInv")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndMoneyChangeDown")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndMoneyChangeUp")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectCopyToInv")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectCreate")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectDelete")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezIn")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezOut")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndSnapshot")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartAutopilot")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartFollowpilot")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartIM")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStopAutopilot")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTeleportOut")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTextureApplyToObject")));
|
|
//gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTextureCopyToInv")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTyping")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowClose")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowOpen")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndRestart")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndRestartOpenSim"))); // <FS:Ansariel> Preload OpenSim restart sound
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndScriptFloaterOpen"))); // <FS:PP> Separate sound for opening script dialogs
|
|
// <FS:Zi> Pie menu
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuAppear")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuHide")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight0")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight1")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight2")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight3")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight4")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight5")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight6")));
|
|
gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight7")));
|
|
// </FS:Zi> Pie menu
|
|
}
|
|
|
|
audio_update_volume(true);
|
|
}
|
|
|
|
void audio_update_volume(bool force_update)
|
|
{
|
|
// <FS:Ansariel> Replace frequently called gSavedSettings
|
|
//F32 master_volume = gSavedSettings.getF32("AudioLevelMaster");
|
|
//BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio");
|
|
static LLCachedControl<F32> sAudioLevelMaster(gSavedSettings, "AudioLevelMaster");
|
|
static LLCachedControl<bool> sMuteAudio(gSavedSettings, "MuteAudio");
|
|
F32 master_volume = sAudioLevelMaster();
|
|
BOOL mute_audio = (BOOL)sMuteAudio;
|
|
// </FS:Ansariel>
|
|
|
|
LLProgressView* progress = gViewerWindow->getProgressView();
|
|
BOOL progress_view_visible = FALSE;
|
|
|
|
if (progress)
|
|
{
|
|
progress_view_visible = progress->getVisible();
|
|
}
|
|
|
|
if (!gViewerWindow->getActive() && gSavedSettings.getBOOL("MuteWhenMinimized"))
|
|
{
|
|
mute_audio = TRUE;
|
|
}
|
|
F32 mute_volume = mute_audio ? 0.0f : 1.0f;
|
|
|
|
if (gAudiop)
|
|
{
|
|
// Sound Effects
|
|
|
|
gAudiop->setMasterGain ( master_volume );
|
|
|
|
// <FS:Ansariel> Replace frequently called gSavedSettings
|
|
//gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
|
|
|
|
//if(!LLViewerCamera::getInstance()->cameraUnderWater())
|
|
//gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
|
|
//else
|
|
// gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelUnderwaterRolloff"));
|
|
|
|
static LLCachedControl<F32> sAudioLevelDoppler(gSavedSettings, "AudioLevelDoppler");
|
|
static LLCachedControl<F32> sAudioLevelRolloff(gSavedSettings, "AudioLevelRolloff");
|
|
static LLCachedControl<F32> sAudioLevelUnderwaterRolloff(gSavedSettings, "AudioLevelUnderwaterRolloff");
|
|
|
|
gAudiop->setDopplerFactor(sAudioLevelDoppler);
|
|
|
|
if(!LLViewerCamera::getInstance()->cameraUnderWater())
|
|
gAudiop->setRolloffFactor(sAudioLevelRolloff);
|
|
else
|
|
gAudiop->setRolloffFactor(sAudioLevelUnderwaterRolloff);
|
|
// </FS:Ansariel>
|
|
|
|
gAudiop->setMuted(mute_audio || progress_view_visible);
|
|
|
|
//Play any deferred sounds when unmuted
|
|
if(!gAudiop->getMuted())
|
|
{
|
|
LLDeferredSounds::instance().playdeferredSounds();
|
|
}
|
|
|
|
if (force_update)
|
|
{
|
|
audio_update_wind(true);
|
|
}
|
|
|
|
// handle secondary gains
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_SFX,
|
|
// gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX"));
|
|
//gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_UI,
|
|
// gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"));
|
|
//gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT,
|
|
// gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient"));
|
|
|
|
static LLCachedControl<bool> muteSounds(gSavedSettings, "MuteSounds");
|
|
static LLCachedControl<bool> muteUI(gSavedSettings, "MuteUI");
|
|
static LLCachedControl<bool> muteAmbient(gSavedSettings, "MuteAmbient");
|
|
static LLCachedControl<F32> audioLevelSFX(gSavedSettings, "AudioLevelSFX");
|
|
static LLCachedControl<F32> audioLevelUI(gSavedSettings, "AudioLevelUI");
|
|
static LLCachedControl<F32> audioLevelAmbient(gSavedSettings, "AudioLevelAmbient");
|
|
|
|
gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_SFX,
|
|
muteSounds ? 0.f : (F32)audioLevelSFX);
|
|
gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_UI,
|
|
muteUI ? 0.f : (F32)audioLevelUI);
|
|
gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT,
|
|
muteAmbient ? 0.f : (F32)audioLevelAmbient);
|
|
|
|
// <FS:Ansariel>
|
|
|
|
// Streaming Music
|
|
|
|
if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade())
|
|
{
|
|
LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty());
|
|
LLViewerAudio::getInstance()->setForcedTeleportFade(false);
|
|
}
|
|
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");
|
|
//BOOL music_muted = gSavedSettings.getBOOL("MuteMusic");
|
|
|
|
static LLCachedControl<F32> audioLevelMusic(gSavedSettings, "AudioLevelMusic");
|
|
static LLCachedControl<bool> muteMusic(gSavedSettings, "MuteMusic");
|
|
F32 music_volume = (F32)audioLevelMusic;
|
|
BOOL music_muted = (BOOL)muteMusic;
|
|
// </FS:Ansariel>
|
|
F32 fade_volume = LLViewerAudio::getInstance()->getFadeVolume();
|
|
|
|
music_volume = mute_volume * master_volume * music_volume * fade_volume;
|
|
gAudiop->setInternetStreamGain (music_muted ? 0.f : music_volume);
|
|
}
|
|
|
|
// Streaming Media
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");
|
|
//BOOL media_muted = gSavedSettings.getBOOL("MuteMedia");
|
|
|
|
static LLCachedControl<F32> audioLevelMedia(gSavedSettings, "AudioLevelMedia");
|
|
static LLCachedControl<bool> muteMedia(gSavedSettings, "MuteMedia");
|
|
F32 media_volume = (F32)audioLevelMedia;
|
|
BOOL media_muted = (BOOL)muteMedia;
|
|
// </FS:Ansariel>
|
|
media_volume = mute_volume * master_volume * media_volume;
|
|
LLViewerMedia::getInstance()->setVolume( media_muted ? 0.0f : media_volume );
|
|
|
|
// Voice, this is parametric singleton, it gets initialized when ready
|
|
if (LLVoiceClient::instanceExists())
|
|
{
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
|
|
static LLCachedControl<F32> audioLevelVoice(gSavedSettings, "AudioLevelVoice");
|
|
F32 voice_volume = (F32)audioLevelVoice;
|
|
// </FS:Ansariel>
|
|
voice_volume = mute_volume * master_volume * voice_volume;
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//BOOL voice_mute = gSavedSettings.getBOOL("MuteVoice");
|
|
static LLCachedControl<bool> muteVoice(gSavedSettings, "MuteVoice");
|
|
BOOL voice_mute = (BOOL)muteVoice;
|
|
LLVoiceClient *voice_inst = LLVoiceClient::getInstance();
|
|
// </FS:Ansariel>
|
|
voice_inst->setVoiceVolume(voice_mute ? 0.f : voice_volume);
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//voice_inst->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
|
|
static LLCachedControl<F32> audioLevelMic(gSavedSettings, "AudioLevelMic");
|
|
voice_inst->setMicGain(voice_mute ? 0.f : (F32)audioLevelMic);
|
|
// </FS:Ansariel>
|
|
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
|
|
static LLCachedControl<bool> muteWhenMinimized(gSavedSettings, "MuteWhenMinimized");
|
|
if (!gViewerWindow->getActive() && muteWhenMinimized)
|
|
// </FS:Ansariel>
|
|
{
|
|
voice_inst->setMuteMic(true);
|
|
}
|
|
else
|
|
{
|
|
voice_inst->setMuteMic(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
void audio_update_listener()
|
|
{
|
|
if (gAudiop)
|
|
{
|
|
// update listener position because agent has moved
|
|
LLVector3d lpos_global = gAgentCamera.getCameraPositionGlobal();
|
|
LLVector3 lpos_global_f;
|
|
lpos_global_f.setVec(lpos_global);
|
|
|
|
gAudiop->setListener(lpos_global_f,
|
|
// LLViewerCamera::getInstance()VelocitySmoothed,
|
|
// LLVector3::zero,
|
|
gAgent.getVelocity(), // !!! *TODO: need to replace this with smoothed velocity!
|
|
LLViewerCamera::getInstance()->getUpAxis(),
|
|
LLViewerCamera::getInstance()->getAtAxis());
|
|
}
|
|
}
|
|
|
|
void audio_update_wind(bool force_update)
|
|
{
|
|
#ifdef kAUDIO_ENABLE_WIND
|
|
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
if (region)
|
|
{
|
|
// Scale down the contribution of weather-simulation wind to the
|
|
// ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s
|
|
// whereas steady-state avatar walk velocity is only 3.2 m/s.
|
|
// Without this the world feels desolate on first login when you are
|
|
// standing still.
|
|
static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f);
|
|
LLVector3 scaled_wind_vec = gWindVec * wind_level;
|
|
|
|
// Mix in the avatar's motion, subtract because when you walk north,
|
|
// the apparent wind moves south.
|
|
LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity();
|
|
|
|
// rotate the wind vector to be listener (agent) relative
|
|
gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec );
|
|
|
|
// don't use the setter setMaxWindGain() because we don't
|
|
// want to screw up the fade-in on startup by setting actual source gain
|
|
// outside the fade-in.
|
|
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
|
//F32 master_volume = gSavedSettings.getBOOL("MuteAudio") ? 0.f : gSavedSettings.getF32("AudioLevelMaster");
|
|
//F32 ambient_volume = gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient");
|
|
|
|
static LLCachedControl<bool> muteAudio(gSavedSettings, "MuteAudio");
|
|
static LLCachedControl<bool> muteAmbient(gSavedSettings, "MuteAmbient");
|
|
static LLCachedControl<F32> audioLevelMaster(gSavedSettings, "AudioLevelMaster");
|
|
static LLCachedControl<F32> audioLevelAmbient(gSavedSettings, "AudioLevelAmbient");
|
|
|
|
F32 master_volume = muteAudio ? 0.f : (F32)audioLevelMaster;
|
|
F32 ambient_volume = muteAmbient ? 0.f : (F32)audioLevelAmbient;
|
|
// </FS:Ansariel>
|
|
F32 max_wind_volume = master_volume * ambient_volume;
|
|
|
|
const F32 WIND_SOUND_TRANSITION_TIME = 2.f;
|
|
// amount to change volume this frame
|
|
F32 volume_delta = (LLFrameTimer::getFrameDeltaTimeF32() / WIND_SOUND_TRANSITION_TIME) * max_wind_volume;
|
|
if (force_update)
|
|
{
|
|
// initialize wind volume (force_update) by using large volume_delta
|
|
// which is sufficient to completely turn off or turn on wind noise
|
|
volume_delta = 1.f;
|
|
}
|
|
|
|
if (!gAudiop)
|
|
{
|
|
LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
|
|
return;
|
|
}
|
|
|
|
// mute wind when not flying
|
|
// <FS:Ansarriel> FIRE-12819: Disable wind sounds while under water
|
|
//if (gAgent.getFlying())
|
|
if (gAgent.getFlying() && isAgentAvatarValid() && !gAgentAvatarp->mBelowWater)
|
|
// </FS:Ansariel>
|
|
{
|
|
// volume increases by volume_delta, up to no more than max_wind_volume
|
|
gAudiop->mMaxWindGain = llmin(gAudiop->mMaxWindGain + volume_delta, max_wind_volume);
|
|
}
|
|
else
|
|
{
|
|
// volume decreases by volume_delta, down to no less than 0
|
|
gAudiop->mMaxWindGain = llmax(gAudiop->mMaxWindGain - volume_delta, 0.f);
|
|
}
|
|
|
|
gAudiop->updateWind(gRelativeWindVec, gAgentCamera.getCameraPositionAgent()[VZ] - gAgent.getRegion()->getWaterHeight());
|
|
}
|
|
#endif
|
|
}
|