summaryrefslogtreecommitdiff
path: root/indra/newview/llvieweraudio.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llvieweraudio.cpp
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (diff)
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/cmake/CMakeLists.txt # indra/cmake/GoogleMock.cmake # indra/llaudio/llaudioengine_fmodstudio.cpp # indra/llaudio/llaudioengine_fmodstudio.h # indra/llaudio/lllistener_fmodstudio.cpp # indra/llaudio/lllistener_fmodstudio.h # indra/llaudio/llstreamingaudio_fmodstudio.cpp # indra/llaudio/llstreamingaudio_fmodstudio.h # indra/llcharacter/llmultigesture.cpp # indra/llcharacter/llmultigesture.h # indra/llimage/llimage.cpp # indra/llimage/llimagepng.cpp # indra/llimage/llimageworker.cpp # indra/llimage/tests/llimageworker_test.cpp # indra/llmessage/tests/llmockhttpclient.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llfontfreetype.cpp # indra/llui/llcombobox.cpp # indra/llui/llfolderview.cpp # indra/llui/llfolderviewmodel.h # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltextvalidate.cpp # indra/llui/lltextvalidate.h # indra/llui/lluictrl.h # indra/llui/llview.cpp # indra/llwindow/llwindowmacosx.cpp # indra/newview/app_settings/settings.xml # indra/newview/llappearancemgr.cpp # indra/newview/llappearancemgr.h # indra/newview/llavatarpropertiesprocessor.cpp # indra/newview/llavatarpropertiesprocessor.h # indra/newview/llbreadcrumbview.cpp # indra/newview/llbreadcrumbview.h # indra/newview/llbreastmotion.cpp # indra/newview/llbreastmotion.h # indra/newview/llconversationmodel.h # indra/newview/lldensityctrl.cpp # indra/newview/lldensityctrl.h # indra/newview/llface.inl # indra/newview/llfloatereditsky.cpp # indra/newview/llfloatereditwater.cpp # indra/newview/llfloateremojipicker.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterprofiletexture.cpp # indra/newview/llfloaterprofiletexture.h # indra/newview/llgesturemgr.cpp # indra/newview/llgesturemgr.h # indra/newview/llimpanel.cpp # indra/newview/llimpanel.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryclipboard.cpp # indra/newview/llinventoryclipboard.h # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventoryfunctions.h # indra/newview/llinventorygallery.cpp # indra/newview/lllistbrowser.cpp # indra/newview/lllistbrowser.h # indra/newview/llpanelobjectinventory.cpp # indra/newview/llpanelprofile.cpp # indra/newview/llpanelprofile.h # indra/newview/llpreviewgesture.cpp # indra/newview/llsavedsettingsglue.cpp # indra/newview/llsavedsettingsglue.h # indra/newview/lltooldraganddrop.cpp # indra/newview/llurllineeditorctrl.cpp # indra/newview/llvectorperfoptions.cpp # indra/newview/llvectorperfoptions.h # indra/newview/llviewerparceloverlay.cpp # indra/newview/llviewertexlayer.cpp # indra/newview/llviewertexturelist.cpp # indra/newview/macmain.h # indra/test/test.cpp
Diffstat (limited to 'indra/newview/llvieweraudio.cpp')
-rw-r--r--indra/newview/llvieweraudio.cpp1185
1 files changed, 597 insertions, 588 deletions
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index 318cf199c0..9d17898b5e 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -1,588 +1,597 @@
-/**
- * @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"
-
-/////////////////////////////////////////////////////////
-
-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)
- {
- mIdleListnerActive = true;
- doOnIdleRepeating(boost::bind(boost::bind(&LLViewerAudio::onIdleUpdate, this)));
- }
-}
-
-void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI)
-{
- LL_DEBUGS("AudioEngine") << "Start with outo fade: " << streamURI << LL_ENDL;
-
- // Old and new stream are identical
- if (mNextStreamURI == streamURI)
- {
- return;
- }
-
- if (!gAudiop)
- {
- LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
- return;
- }
-
- // Record the URI we are going to be switching to
- mNextStreamURI = streamURI;
-
- switch (mFadeState)
- {
- case FADE_IDLE:
- // 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("FMODExStreamBufferSize"), gSavedSettings.getU32("FMODExDecodeBufferSize"));
-
- gAudiop->startInternetStream(mNextStreamURI);
- }
-
- startFading();
- break;
-
- case FADE_OUT:
- startFading();
- break;
-
- case FADE_IN:
- break;
-
- default:
- LL_WARNS() << "Unknown fading state: " << mFadeState << LL_ENDL;
- return;
- }
-
- registerIdleListener();
-}
-
-// 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
- LL_DEBUGS("AudioEngine") << "Done with audio fade" << LL_ENDL;
- gAudiop->startInternetStream(LLStringUtil::null);
- gAudiop->stopInternetStream();
- }
-
- if (!mNextStreamURI.empty())
- {
- mFadeState = FADE_IN;
-
- if (gAudiop)
- {
- LL_DEBUGS("AudioEngine") << "Audio fade in: " << mNextStreamURI << LL_ENDL;
- LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
- if(stream && stream->supportsAdjustableBufferSizes())
- stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
-
- 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()
-{
- mFadeState = FADE_IDLE;
- mNextStreamURI = LLStringUtil::null;
- mDone = true;
-
- if (gAudiop)
- {
- LL_DEBUGS("AudioEngine") << "Stop audio fade" << LL_ENDL;
- gAudiop->startInternetStream(LLStringUtil::null);
- gAudiop->stopInternetStream();
- }
-}
-
-void LLViewerAudio::startFading()
-{
- const F32 AUDIO_MUSIC_FADE_IN_TIME = 3.0f;
- const F32 AUDIO_MUSIC_FADE_OUT_TIME = 2.0f;
- // 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 = LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT ?
- AUDIO_MUSIC_FADE_OUT_TIME : AUDIO_MUSIC_FADE_IN_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());
- 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")));
- }
-
- audio_update_volume(true);
-}
-
-void audio_update_volume(bool force_update)
-{
- F32 master_volume = gSavedSettings.getF32("AudioLevelMaster");
- bool mute_audio = gSavedSettings.getBOOL("MuteAudio");
-
- 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 );
-
- gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
-
- if(!LLViewerCamera::getInstance()->cameraUnderWater())
- gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
- else
- gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelUnderwaterRolloff"));
-
- 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
- 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"));
-
- // Streaming Music
-
- if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade())
- {
- LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty());
- LLViewerAudio::getInstance()->setForcedTeleportFade(false);
- }
-
- F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");
- bool music_muted = gSavedSettings.getBOOL("MuteMusic");
- 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
- F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");
- bool media_muted = gSavedSettings.getBOOL("MuteMedia");
- 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())
- {
- F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
- voice_volume = mute_volume * master_volume * voice_volume;
- bool voice_mute = gSavedSettings.getBOOL("MuteVoice");
- LLVoiceClient *voice_inst = LLVoiceClient::getInstance();
- voice_inst->setVoiceVolume(voice_mute ? 0.f : voice_volume);
- voice_inst->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
-
- if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
- {
- voice_inst->setMuteMic(true);
- }
- else
- {
- voice_inst->setMuteMic(false);
- }
- }
-}
-
-void audio_update_listener()
-{
- if (gAudiop)
- {
- // update listener position because agent has moved
- static LLUICachedControl<S32> mEarLocation("MediaSoundsEarLocation", 0);
- LLVector3d ear_position;
- switch(mEarLocation)
- {
- case 0:
- default:
- ear_position = gAgentCamera.getCameraPositionGlobal();
- break;
-
- case 1:
- ear_position = gAgent.getPositionGlobal();
- break;
- }
- LLVector3d lpos_global = ear_position;
- 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.
- static LLCachedControl<bool> mute_audio(gSavedSettings, "MuteAudio");
- static LLCachedControl<bool> mute_ambient(gSavedSettings, "MuteAmbient");
- static LLCachedControl<F32> level_master(gSavedSettings, "AudioLevelMaster");
- static LLCachedControl<F32> level_ambient(gSavedSettings, "AudioLevelAmbient");
-
- F32 master_volume = mute_audio() ? 0.f : level_master();
- F32 ambient_volume = mute_ambient() ? 0.f : level_ambient();
- 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
- if (gAgent.getFlying())
- {
- // 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
-}
+/**
+ * @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"
+
+/////////////////////////////////////////////////////////
+const U32 FMODEX_DECODE_BUFFER_SIZE = 1000; // in milliseconds
+const U32 FMODEX_STREAM_BUFFER_SIZE = 7000; // in milliseconds
+
+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)
+ {
+ mIdleListnerActive = true;
+ doOnIdleRepeating(boost::bind(boost::bind(&LLViewerAudio::onIdleUpdate, this)));
+ }
+}
+
+void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI)
+{
+ LL_DEBUGS("AudioEngine") << "Start with outo fade: " << streamURI << LL_ENDL;
+
+ // Old and new stream are identical
+ if (mNextStreamURI == streamURI)
+ {
+ return;
+ }
+
+ if (!gAudiop)
+ {
+ LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL;
+ return;
+ }
+
+ // Record the URI we are going to be switching to
+ mNextStreamURI = streamURI;
+
+ switch (mFadeState)
+ {
+ case FADE_IDLE:
+ // 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(FMODEX_STREAM_BUFFER_SIZE, FMODEX_DECODE_BUFFER_SIZE);
+
+ gAudiop->startInternetStream(mNextStreamURI);
+ }
+
+ startFading();
+ break;
+
+ case FADE_OUT:
+ startFading();
+ break;
+
+ case FADE_IN:
+ break;
+
+ default:
+ LL_WARNS() << "Unknown fading state: " << mFadeState << LL_ENDL;
+ return;
+ }
+
+ registerIdleListener();
+}
+
+// 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
+ LL_DEBUGS("AudioEngine") << "Done with audio fade" << LL_ENDL;
+ gAudiop->startInternetStream(LLStringUtil::null);
+ gAudiop->stopInternetStream();
+ }
+
+ if (!mNextStreamURI.empty())
+ {
+ mFadeState = FADE_IN;
+
+ if (gAudiop)
+ {
+ LL_DEBUGS("AudioEngine") << "Audio fade in: " << mNextStreamURI << LL_ENDL;
+ LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
+ if(stream && stream->supportsAdjustableBufferSizes())
+ stream->setBufferSizes(FMODEX_STREAM_BUFFER_SIZE, FMODEX_DECODE_BUFFER_SIZE);
+
+ 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()
+{
+ mFadeState = FADE_IDLE;
+ mNextStreamURI = LLStringUtil::null;
+ mDone = true;
+
+ if (gAudiop)
+ {
+ LL_DEBUGS("AudioEngine") << "Stop audio fade" << LL_ENDL;
+ gAudiop->startInternetStream(LLStringUtil::null);
+ gAudiop->stopInternetStream();
+ }
+}
+
+void LLViewerAudio::startFading()
+{
+ const F32 AUDIO_MUSIC_FADE_IN_TIME = 3.0f;
+ const F32 AUDIO_MUSIC_FADE_OUT_TIME = 2.0f;
+ // 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 = LLViewerAudio::getInstance()->getFadeState() == LLViewerAudio::FADE_OUT ?
+ AUDIO_MUSIC_FADE_OUT_TIME : AUDIO_MUSIC_FADE_IN_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());
+ 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")));
+ }
+
+ audio_update_volume(true);
+}
+
+void audio_update_volume(bool force_update)
+{
+ F32 master_volume = gSavedSettings.getF32("AudioLevelMaster");
+ bool mute_audio = gSavedSettings.getBOOL("MuteAudio");
+
+ 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 );
+
+ const F32 AUDIO_LEVEL_DOPPLER = 1.f;
+ gAudiop->setDopplerFactor(AUDIO_LEVEL_DOPPLER);
+
+ if(!LLViewerCamera::getInstance()->cameraUnderWater())
+ {
+ const F32 AUDIO_LEVEL_ROLLOFF = 1.f;
+ gAudiop->setRolloffFactor(AUDIO_LEVEL_ROLLOFF);
+ }
+ else
+ {
+ const F32 AUDIO_LEVEL_UNDERWATER_ROLLOFF = 5.f;
+ gAudiop->setRolloffFactor(AUDIO_LEVEL_UNDERWATER_ROLLOFF);
+ }
+
+ 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
+ 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"));
+
+ // Streaming Music
+
+ if (!progress_view_visible && LLViewerAudio::getInstance()->getForcedTeleportFade())
+ {
+ LLViewerAudio::getInstance()->setWasPlaying(!gAudiop->getInternetStreamURL().empty());
+ LLViewerAudio::getInstance()->setForcedTeleportFade(false);
+ }
+
+ F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");
+ bool music_muted = gSavedSettings.getBOOL("MuteMusic");
+ 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
+ F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");
+ bool media_muted = gSavedSettings.getBOOL("MuteMedia");
+ 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())
+ {
+ F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
+ voice_volume = mute_volume * master_volume * voice_volume;
+ bool voice_mute = gSavedSettings.getBOOL("MuteVoice");
+ LLVoiceClient *voice_inst = LLVoiceClient::getInstance();
+ voice_inst->setVoiceVolume(voice_mute ? 0.f : voice_volume);
+ voice_inst->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic"));
+
+ if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
+ {
+ voice_inst->setMuteMic(true);
+ }
+ else
+ {
+ voice_inst->setMuteMic(false);
+ }
+ }
+}
+
+void audio_update_listener()
+{
+ if (gAudiop)
+ {
+ // update listener position because agent has moved
+ static LLUICachedControl<S32> mEarLocation("MediaSoundsEarLocation", 0);
+ LLVector3d ear_position;
+ switch(mEarLocation)
+ {
+ case 0:
+ default:
+ ear_position = gAgentCamera.getCameraPositionGlobal();
+ break;
+
+ case 1:
+ ear_position = gAgent.getPositionGlobal();
+ break;
+ }
+ LLVector3d lpos_global = ear_position;
+ 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.
+ const F32 WIND_LEVEL = 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.
+ static LLCachedControl<bool> mute_audio(gSavedSettings, "MuteAudio");
+ static LLCachedControl<bool> mute_ambient(gSavedSettings, "MuteAmbient");
+ static LLCachedControl<F32> level_master(gSavedSettings, "AudioLevelMaster");
+ static LLCachedControl<F32> level_ambient(gSavedSettings, "AudioLevelAmbient");
+
+ F32 master_volume = mute_audio() ? 0.f : level_master();
+ F32 ambient_volume = mute_ambient() ? 0.f : level_ambient();
+ 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
+ if (gAgent.getFlying())
+ {
+ // 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
+}