diff options
| author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 | 
|---|---|---|
| committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 | 
| commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
| tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llvoicevisualizer.cpp | |
| parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
| parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (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/llvoicevisualizer.cpp')
| -rw-r--r-- | indra/newview/llvoicevisualizer.cpp | 1224 | 
1 files changed, 612 insertions, 612 deletions
diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 304b7adfb7..6e177fb1fb 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -1,612 +1,612 @@ -/**  - * @file llvoicevisualizer.cpp - * @brief Draws in-world speaking indicators. - * - * $LicenseInfo:firstyear=2000&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$ - */ - -//---------------------------------------------------------------------- -// Voice Visualizer -// author: JJ Ventrella -// (information about this stuff can be found in "llvoicevisualizer.h") -//---------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" -#include "llviewercontrol.h" -#include "llglheaders.h" -#include "llsphere.h" -#include "llvoicevisualizer.h" -#include "llviewercamera.h" -#include "llviewerobject.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llvoiceclient.h" -#include "llrender.h" -#include "llagent.h" - -//brent's wave image -//29de489d-0491-fb00-7dab-f9e686d31e83 - - -//-------------------------------------------------------------------------------------- -// sound symbol constants -//-------------------------------------------------------------------------------------- -const F32	HEIGHT_ABOVE_HEAD	= 0.3f;		// how many meters vertically above the av's head the voice symbol will appear -const F32	RED_THRESHOLD		= LLVoiceClient::OVERDRIVEN_POWER_LEVEL;		// value above which speaking amplitude causes the voice symbol to turn red -const F32	GREEN_THRESHOLD		= 0.2f;		// value above which speaking amplitude causes the voice symbol to turn green -const F32	FADE_OUT_DURATION	= 0.4f;		// how many seconds it takes for a pair of waves to fade away -const F32	EXPANSION_RATE		= 1.0f;		// how many seconds it takes for the waves to expand to twice their original size -const F32	EXPANSION_MAX		= 1.5f;		// maximum size scale to which the waves can expand before popping back to 1.0  -const F32	WAVE_WIDTH_SCALE	= 0.03f;	// base width of the waves  -const F32	WAVE_HEIGHT_SCALE	= 0.02f;	// base height of the waves  -const F32	BASE_BRIGHTNESS		= 0.7f;		// gray level of the voice indicator when quiet (below green threshold) -const F32	DOT_SIZE			= 0.05f;	// size of the dot billboard texture -const F32	DOT_OPACITY			= 0.7f;		// how opaque the dot is -const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a function of speaking amplitude - -//-------------------------------------------------------------------------------------- -// gesticulation constants -//-------------------------------------------------------------------------------------- -const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE	= 0.2f;  -const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE	= 1.0f; - -//-------------------------------------------------------------------------------------- -// other constants -//-------------------------------------------------------------------------------------- -const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL - -//------------------------------------------------------------------ -// Initialize the statics -//------------------------------------------------------------------ -bool LLVoiceVisualizer::sPrefsInitialized	= false; -bool LLVoiceVisualizer::sLipSyncEnabled		= false; -F32* LLVoiceVisualizer::sOoh				= NULL; -F32* LLVoiceVisualizer::sAah				= NULL; -U32	 LLVoiceVisualizer::sOohs				= 0; -U32	 LLVoiceVisualizer::sAahs				= 0; -F32	 LLVoiceVisualizer::sOohAahRate			= 0.0f; -F32* LLVoiceVisualizer::sOohPowerTransfer	= NULL; -U32	 LLVoiceVisualizer::sOohPowerTransfers	= 0; -F32	 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f; -F32* LLVoiceVisualizer::sAahPowerTransfer	= NULL; -U32	 LLVoiceVisualizer::sAahPowerTransfers	= 0; -F32	 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; - - -//----------------------------------------------- -// constructor -//----------------------------------------------- -LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) -	: LLHUDEffect(type) -{ -	mCurrentTime					= mTimer.getTotalSeconds(); -	mPreviousTime					= mCurrentTime; -	mStartTime						= mCurrentTime; -	mVoiceSourceWorldPosition		= LLVector3( 0.0f, 0.0f, 0.0f ); -	mSpeakingAmplitude				= 0.0f; -	mCurrentlySpeaking				= false; -	mVoiceEnabled					= false; -	mMinGesticulationAmplitude		= DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; -	mMaxGesticulationAmplitude		= DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; -	mSoundSymbol.mActive			= true; -	mSoundSymbol.mPosition			= LLVector3( 0.0f, 0.0f, 0.0f ); -	 -	mTimer.reset(); -	 -	const char* sound_level_img[] =  -	{ -		"voice_meter_dot.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c" -	}; - -	for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) -	{ -		mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime; -		mSoundSymbol.mTexture				[i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FTT_LOCAL_FILE, false, LLGLTexture::BOOST_UI); -		mSoundSymbol.mWaveActive			[i] = false; -		mSoundSymbol.mWaveOpacity			[i] = 1.0f; -		mSoundSymbol.mWaveExpansion			[i] = 1.0f; -	} - -	mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - -	// The first instance loads the initial state from prefs. -	if (!sPrefsInitialized) -	{ -		setPreferences(); -        -		// Set up our listener to get updates on all prefs values we care about. -		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2)); -		 -		sPrefsInitialized = true; -	} - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) -{ -	mMinGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m ) -{ -	mMaxGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceEnabled( bool v ) -{ -	mVoiceEnabled = v; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setStartSpeaking() -{ -	mStartTime				= mTimer.getTotalSeconds(); -	mCurrentlySpeaking		= true; -	mSoundSymbol.mActive	= true; -		 -}//--------------------------------------------------- - - -//--------------------------------------------------- -bool LLVoiceVisualizer::getCurrentlySpeaking() -{ -	return mCurrentlySpeaking; -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setStopSpeaking() -{ -	mCurrentlySpeaking = false; -	mSpeakingAmplitude = 0.0f; -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setSpeakingAmplitude( F32 a ) -{ -	mSpeakingAmplitude = a; -	 -}//--------------------------------------------------- - -//------------------------------------------------------------------ -// handles parameter updates -//------------------------------------------------------------------ -bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) -{ -	// Note: Ignore the specific event value, we look up the ones we want -	LLVoiceVisualizer::setPreferences(); -	return true; -} - -//--------------------------------------------------- -void LLVoiceVisualizer::setPreferences( ) -{ -	sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled"); -	sOohAahRate		= gSavedSettings.getF32("LipSyncOohAahRate"); - -	std::string oohString = gSavedSettings.getString("LipSyncOoh"); -	lipStringToF32s (oohString, sOoh, sOohs); - -	std::string aahString = gSavedSettings.getString("LipSyncAah"); -	lipStringToF32s (aahString, sAah, sAahs); - -	std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer"); -	lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers); -	sOohPowerTransfersf = (F32) sOohPowerTransfers; - -	std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer"); -	lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers); -	sAahPowerTransfersf = (F32) sAahPowerTransfers; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -// convert a string of digits to an array of floats. -// the result for each digit is the value of the -// digit multiplied by 0.11 -//--------------------------------------------------- -void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ) -{ -	delete[] out_F32s;	// get rid of the current array - -	count_F32s = in_string.length(); -	if (count_F32s == 0) -	{ -		// we don't like zero length arrays - -		count_F32s  = 1; -		out_F32s	   = new F32[1]; -		out_F32s[0] = 0.0f; -	} -	else -	{ -		out_F32s = new F32[count_F32s]; - -		for (U32 i=0; i<count_F32s; i++) -		{ -			// we convert the characters 0 to 9 to their numeric value -			// anything else we take the low order four bits with a ceiling of 9 - -		    U8 digit = in_string[i]; -			U8 four_bits = digit % 16; -			if (four_bits > 9) -			{ -				four_bits = 9; -			} -			out_F32s[i] = 0.11f * (F32) four_bits; -		}  -	} - -}//--------------------------------------------------- - - -//-------------------------------------------------------------------------- -// find the amount to blend the ooh and aah mouth morphs -//-------------------------------------------------------------------------- -void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) -{ -	if (sLipSyncEnabled && mCurrentlySpeaking) -	{ -		U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude); -		if (transfer_index >= sOohPowerTransfers) -		{ -		   transfer_index = sOohPowerTransfers - 1; -		} -		F32 transfer_ooh = sOohPowerTransfer[transfer_index]; - -		transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude); -		if (transfer_index >= sAahPowerTransfers) -		{ -		   transfer_index = sAahPowerTransfers - 1; -		} -		F32 transfer_aah = sAahPowerTransfer[transfer_index]; - -		F64 current_time   = mTimer.getTotalSeconds(); -		F64 elapsed_time   = current_time - mStartTime; -		U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); -		U32 elapsed_oohs   = elapsed_frames % sOohs; -		U32 elapsed_aahs   = elapsed_frames % sAahs; - -		ooh = transfer_ooh * sOoh[elapsed_oohs]; -		aah = transfer_aah * sAah[elapsed_aahs]; - -		/* -		LL_INFOS() << " elapsed frames " << elapsed_frames -				<< " ooh "            << ooh -				<< " aah "            << aah -				<< " transfer ooh"    << transfer_ooh -				<< " transfer aah"    << transfer_aah -				<< " start time "     << mStartTime -				<< " current time "   << current_time -				<< " elapsed time "   << elapsed_time -				<< " elapsed oohs "   << elapsed_oohs -				<< " elapsed aahs "   << elapsed_aahs -				<< LL_ENDL; -		*/ -	} -	else -	{ -		ooh = 0.0f; -		aah = 0.0f; -	} -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -// this method is inherited from HUD Effect -//--------------------------------------------------- -void LLVoiceVisualizer::render() -{ -	if ( ! mVoiceEnabled ) -	{ -		return; -	} -	 -	if ( mSoundSymbol.mActive )  -	{				 -		mPreviousTime = mCurrentTime; -		mCurrentTime = mTimer.getTotalSeconds(); -	 -		//--------------------------------------------------------------- -		// set the sound symbol position over the source (avatar's head) -		//--------------------------------------------------------------- -        mSoundSymbol.mPosition = gAgent.getPosAgentFromGlobal(mPositionGlobal) + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; -	 -		//--------------------------------------------------------------- -		// some gl state -		//--------------------------------------------------------------- -		LLGLSPipelineAlpha alpha_blend; -		LLGLDepthTest depth(GL_TRUE, GL_FALSE); -		//LLGLDisable gls_stencil(GL_STENCIL_TEST); -		 -		//------------------------------------------------------------- -		// create coordinates of the geometry for the dot -		//------------------------------------------------------------- -		LLViewerCamera* camera = LLViewerCamera::getInstance(); -		LLVector3 l	= camera->getLeftAxis() * DOT_SIZE; -		LLVector3 u	= camera->getUpAxis()   * DOT_SIZE; - -		LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u; -		LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u; -		LLVector3 topLeft		= mSoundSymbol.mPosition + l + u; -		LLVector3 topRight		= mSoundSymbol.mPosition - l + u; -		 -		//----------------------------- -		// bind texture 0 (the dot) -		//----------------------------- -		gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]); -		 -		//------------------------------------------------------------- -		// now render the dot -		//------------------------------------------------------------- -		gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );	 -		 -		gGL.begin( LLRender::TRIANGLE_STRIP ); -			gGL.texCoord2i( 0,	0	); gGL.vertex3fv( bottomLeft.mV ); -			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV ); -			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV ); -		gGL.end(); - -		gGL.begin( LLRender::TRIANGLE_STRIP ); -			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV ); -			gGL.texCoord2i( 1,	1	); gGL.vertex3fv( topRight.mV ); -			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV ); -		gGL.end(); -		 -		 -		 -		//-------------------------------------------------------------------------------------- -		// if currently speaking, trigger waves (1 through 6) based on speaking amplitude -		//-------------------------------------------------------------------------------------- -		if ( mCurrentlySpeaking ) -		{ -			F32 min = 0.2f; -			F32 max = 0.7f; -			F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); -		 -			// in case mSpeakingAmplitude > max.... -			if ( fraction > 1.0f ) -			{ -				fraction = 1.0f; -			} -														 -			S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); -																										 -			for (int i=0; i<level+1; i++) -			{ -				mSoundSymbol.mWaveActive			[i] = true; -				mSoundSymbol.mWaveOpacity			[i] = 1.0f; -				mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime; -			}			 -			 -		} // if currently speaking -								 -		//--------------------------------------------------- -		// determine color -		//--------------------------------------------------- -		F32 red		= 0.0f; -		F32 green	= 0.0f; -		F32 blue	= 0.0f; -        if ( mSpeakingAmplitude < RED_THRESHOLD ) -        { -			if ( mSpeakingAmplitude < GREEN_THRESHOLD ) -			{ -				red		= BASE_BRIGHTNESS; -				green	= BASE_BRIGHTNESS; -				blue	= BASE_BRIGHTNESS; -			} -			else -			{ -				//--------------------------------------------------- -				// fade from gray to bright green -				//--------------------------------------------------- -				F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD ); -				red		= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); -				green	= BASE_BRIGHTNESS +   fraction * ( 1.0f - BASE_BRIGHTNESS ); -				blue	= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); -			} -        } -        else -        { -			//--------------------------------------------------- -			// redish -			//--------------------------------------------------- -			red		= 1.0f; -			green	= 0.2f; -			blue	= 0.2f; -        } -														 -		for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) -		{ -			if ( mSoundSymbol.mWaveActive[i] )  -			{ -				F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION; - -				mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction; -				 -				if ( mSoundSymbol.mWaveOpacity[i] < 0.0f ) -				{ -					mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime; -					mSoundSymbol.mWaveOpacity			[i] = 0.0f; -					mSoundSymbol.mWaveActive			[i] = false; -				} -				 -				//---------------------------------------------------------------------------------- -				// This is where we calculate the expansion of the waves - that is, the -				// rate at which they are scaled greater than 1.0 so that they grow over time. -				//---------------------------------------------------------------------------------- -				F32 timeSlice = (F32)( mCurrentTime - mPreviousTime ); -				F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE; -				mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed ); -				 -				if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX ) -				{ -					mSoundSymbol.mWaveExpansion[i] = 1.0f; -				}			 -								 -				//---------------------------------------------------------------------------------- -				// create geometry for the wave billboard textures -				//---------------------------------------------------------------------------------- -				F32 width	= i * WAVE_WIDTH_SCALE  * mSoundSymbol.mWaveExpansion[i]; -				F32 height	= i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; - -				LLVector3 l	= camera->getLeftAxis() * width; -				LLVector3 u	= camera->getUpAxis()   * height; - -				LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u; -				LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u; -				LLVector3 topLeft		= mSoundSymbol.mPosition + l + u; -				LLVector3 topRight		= mSoundSymbol.mPosition - l + u; -							 -				gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );		 -				gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]); - -				 -				//--------------------------------------------------- -				// now, render the mofo -				//--------------------------------------------------- -				gGL.begin( LLRender::TRIANGLE_STRIP ); -					gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); -					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); -					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); -				gGL.end(); - -				gGL.begin( LLRender::TRIANGLE_STRIP ); -					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); -					gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); -					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); -				gGL.end(); -				 -			} //if ( mSoundSymbol.mWaveActive[i] )  -			 -		}// for loop -											 -	}//if ( mSoundSymbol.mActive )  - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) -{ -	mVoiceSourceWorldPosition	= p; - -}//--------------------------------------------------- - -//--------------------------------------------------- -VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() -{ -	VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default -	 -	//----------------------------------------------------------------------------------------- -	// Within the range of gesticulation amplitudes, the sound signal is split into -	// three equal amplitude regimes, each specifying one of three gesticulation levels. -	//----------------------------------------------------------------------------------------- -	F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; -	 -			if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH;		} -	else	if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM;	} -	else	if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW;		} - -	return gesticulationLevel; - -}//--------------------------------------------------- - - - -//------------------------------------ -// Destructor -//------------------------------------ -LLVoiceVisualizer::~LLVoiceVisualizer() -{ -}//---------------------------------------------- - - -//--------------------------------------------------- -// "packData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) -{ -	// Pack the default data -	LLHUDEffect::packData(mesgsys); - -	// TODO -- pack the relevant data for voice effects -	// we'll come up with some cool configurations....TBD -	//U8 packed_data[41]; -	//mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); -	U8 packed_data = 0; -	mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); -} - - -//--------------------------------------------------- -// "unpackData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) -{ -	// TODO -- find the speaker, unpack binary data, set the properties of this effect -	/* -	LLHUDEffect::unpackData(mesgsys, blocknum); -	LLUUID source_id; -	LLUUID target_id; -	S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); -	if (size != 1) -	{ -		LL_WARNS() << "Voice effect with bad size " << size << LL_ENDL; -		return; -	} -	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); -	*/ -} - - -//------------------------------------------------------------------ -// this method is inherited from HUD Effect -//------------------------------------------------------------------ -void LLVoiceVisualizer::markDead() -{ -	mCurrentlySpeaking		= false; -	mVoiceEnabled			= false; -	mSoundSymbol.mActive	= false; - -	LLHUDEffect::markDead(); -}//------------------------------------------------------------------ +/**
 + * @file llvoicevisualizer.cpp
 + * @brief Draws in-world speaking indicators.
 + *
 + * $LicenseInfo:firstyear=2000&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$
 + */
 +
 +//----------------------------------------------------------------------
 +// Voice Visualizer
 +// author: JJ Ventrella
 +// (information about this stuff can be found in "llvoicevisualizer.h")
 +//----------------------------------------------------------------------
 +#include "llviewerprecompiledheaders.h"
 +#include "llviewercontrol.h"
 +#include "llglheaders.h"
 +#include "llsphere.h"
 +#include "llvoicevisualizer.h"
 +#include "llviewercamera.h"
 +#include "llviewerobject.h"
 +#include "llviewertexture.h"
 +#include "llviewertexturelist.h"
 +#include "llvoiceclient.h"
 +#include "llrender.h"
 +#include "llagent.h"
 +
 +//brent's wave image
 +//29de489d-0491-fb00-7dab-f9e686d31e83
 +
 +
 +//--------------------------------------------------------------------------------------
 +// sound symbol constants
 +//--------------------------------------------------------------------------------------
 +const F32   HEIGHT_ABOVE_HEAD   = 0.3f;     // how many meters vertically above the av's head the voice symbol will appear
 +const F32   RED_THRESHOLD       = LLVoiceClient::OVERDRIVEN_POWER_LEVEL;        // value above which speaking amplitude causes the voice symbol to turn red
 +const F32   GREEN_THRESHOLD     = 0.2f;     // value above which speaking amplitude causes the voice symbol to turn green
 +const F32   FADE_OUT_DURATION   = 0.4f;     // how many seconds it takes for a pair of waves to fade away
 +const F32   EXPANSION_RATE      = 1.0f;     // how many seconds it takes for the waves to expand to twice their original size
 +const F32   EXPANSION_MAX       = 1.5f;     // maximum size scale to which the waves can expand before popping back to 1.0
 +const F32   WAVE_WIDTH_SCALE    = 0.03f;    // base width of the waves
 +const F32   WAVE_HEIGHT_SCALE   = 0.02f;    // base height of the waves
 +const F32   BASE_BRIGHTNESS     = 0.7f;     // gray level of the voice indicator when quiet (below green threshold)
 +const F32   DOT_SIZE            = 0.05f;    // size of the dot billboard texture
 +const F32   DOT_OPACITY         = 0.7f;     // how opaque the dot is
 +const F32   WAVE_MOTION_RATE    = 1.5f;     // scalar applied to consecutive waves as a function of speaking amplitude
 +
 +//--------------------------------------------------------------------------------------
 +// gesticulation constants
 +//--------------------------------------------------------------------------------------
 +const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE   = 0.2f;
 +const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE   = 1.0f;
 +
 +//--------------------------------------------------------------------------------------
 +// other constants
 +//--------------------------------------------------------------------------------------
 +const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL
 +
 +//------------------------------------------------------------------
 +// Initialize the statics
 +//------------------------------------------------------------------
 +bool LLVoiceVisualizer::sPrefsInitialized   = false;
 +bool LLVoiceVisualizer::sLipSyncEnabled     = false;
 +F32* LLVoiceVisualizer::sOoh                = NULL;
 +F32* LLVoiceVisualizer::sAah                = NULL;
 +U32  LLVoiceVisualizer::sOohs               = 0;
 +U32  LLVoiceVisualizer::sAahs               = 0;
 +F32  LLVoiceVisualizer::sOohAahRate         = 0.0f;
 +F32* LLVoiceVisualizer::sOohPowerTransfer   = NULL;
 +U32  LLVoiceVisualizer::sOohPowerTransfers  = 0;
 +F32  LLVoiceVisualizer::sOohPowerTransfersf = 0.0f;
 +F32* LLVoiceVisualizer::sAahPowerTransfer   = NULL;
 +U32  LLVoiceVisualizer::sAahPowerTransfers  = 0;
 +F32  LLVoiceVisualizer::sAahPowerTransfersf = 0.0f;
 +
 +
 +//-----------------------------------------------
 +// constructor
 +//-----------------------------------------------
 +LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
 +    : LLHUDEffect(type)
 +{
 +    mCurrentTime                    = mTimer.getTotalSeconds();
 +    mPreviousTime                   = mCurrentTime;
 +    mStartTime                      = mCurrentTime;
 +    mVoiceSourceWorldPosition       = LLVector3( 0.0f, 0.0f, 0.0f );
 +    mSpeakingAmplitude              = 0.0f;
 +    mCurrentlySpeaking              = false;
 +    mVoiceEnabled                   = false;
 +    mMinGesticulationAmplitude      = DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE;
 +    mMaxGesticulationAmplitude      = DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;
 +    mSoundSymbol.mActive            = true;
 +    mSoundSymbol.mPosition          = LLVector3( 0.0f, 0.0f, 0.0f );
 +
 +    mTimer.reset();
 +
 +    const char* sound_level_img[] =
 +    {
 +        "voice_meter_dot.j2c",
 +        "voice_meter_rings.j2c",
 +        "voice_meter_rings.j2c",
 +        "voice_meter_rings.j2c",
 +        "voice_meter_rings.j2c",
 +        "voice_meter_rings.j2c",
 +        "voice_meter_rings.j2c"
 +    };
 +
 +    for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
 +    {
 +        mSoundSymbol.mWaveFadeOutStartTime  [i] = mCurrentTime;
 +        mSoundSymbol.mTexture               [i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FTT_LOCAL_FILE, false, LLGLTexture::BOOST_UI);
 +        mSoundSymbol.mWaveActive            [i] = false;
 +        mSoundSymbol.mWaveOpacity           [i] = 1.0f;
 +        mSoundSymbol.mWaveExpansion         [i] = 1.0f;
 +    }
 +
 +    mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
 +
 +    // The first instance loads the initial state from prefs.
 +    if (!sPrefsInitialized)
 +    {
 +        setPreferences();
 +
 +        // Set up our listener to get updates on all prefs values we care about.
 +        gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +        gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +        gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +        gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +        gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +        gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +
 +        sPrefsInitialized = true;
 +    }
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )
 +{
 +    mMinGesticulationAmplitude = m;
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m )
 +{
 +    mMaxGesticulationAmplitude = m;
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setVoiceEnabled( bool v )
 +{
 +    mVoiceEnabled = v;
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setStartSpeaking()
 +{
 +    mStartTime              = mTimer.getTotalSeconds();
 +    mCurrentlySpeaking      = true;
 +    mSoundSymbol.mActive    = true;
 +
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +bool LLVoiceVisualizer::getCurrentlySpeaking()
 +{
 +    return mCurrentlySpeaking;
 +
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setStopSpeaking()
 +{
 +    mCurrentlySpeaking = false;
 +    mSpeakingAmplitude = 0.0f;
 +
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )
 +{
 +    mSpeakingAmplitude = a;
 +
 +}//---------------------------------------------------
 +
 +//------------------------------------------------------------------
 +// handles parameter updates
 +//------------------------------------------------------------------
 +bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue)
 +{
 +    // Note: Ignore the specific event value, we look up the ones we want
 +    LLVoiceVisualizer::setPreferences();
 +    return true;
 +}
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setPreferences( )
 +{
 +    sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled");
 +    sOohAahRate     = gSavedSettings.getF32("LipSyncOohAahRate");
 +
 +    std::string oohString = gSavedSettings.getString("LipSyncOoh");
 +    lipStringToF32s (oohString, sOoh, sOohs);
 +
 +    std::string aahString = gSavedSettings.getString("LipSyncAah");
 +    lipStringToF32s (aahString, sAah, sAahs);
 +
 +    std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer");
 +    lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers);
 +    sOohPowerTransfersf = (F32) sOohPowerTransfers;
 +
 +    std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer");
 +    lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers);
 +    sAahPowerTransfersf = (F32) sAahPowerTransfers;
 +
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +// convert a string of digits to an array of floats.
 +// the result for each digit is the value of the
 +// digit multiplied by 0.11
 +//---------------------------------------------------
 +void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s )
 +{
 +    delete[] out_F32s;  // get rid of the current array
 +
 +    count_F32s = in_string.length();
 +    if (count_F32s == 0)
 +    {
 +        // we don't like zero length arrays
 +
 +        count_F32s  = 1;
 +        out_F32s       = new F32[1];
 +        out_F32s[0] = 0.0f;
 +    }
 +    else
 +    {
 +        out_F32s = new F32[count_F32s];
 +
 +        for (U32 i=0; i<count_F32s; i++)
 +        {
 +            // we convert the characters 0 to 9 to their numeric value
 +            // anything else we take the low order four bits with a ceiling of 9
 +
 +            U8 digit = in_string[i];
 +            U8 four_bits = digit % 16;
 +            if (four_bits > 9)
 +            {
 +                four_bits = 9;
 +            }
 +            out_F32s[i] = 0.11f * (F32) four_bits;
 +        }
 +    }
 +
 +}//---------------------------------------------------
 +
 +
 +//--------------------------------------------------------------------------
 +// find the amount to blend the ooh and aah mouth morphs
 +//--------------------------------------------------------------------------
 +void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah )
 +{
 +    if (sLipSyncEnabled && mCurrentlySpeaking)
 +    {
 +        U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude);
 +        if (transfer_index >= sOohPowerTransfers)
 +        {
 +           transfer_index = sOohPowerTransfers - 1;
 +        }
 +        F32 transfer_ooh = sOohPowerTransfer[transfer_index];
 +
 +        transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude);
 +        if (transfer_index >= sAahPowerTransfers)
 +        {
 +           transfer_index = sAahPowerTransfers - 1;
 +        }
 +        F32 transfer_aah = sAahPowerTransfer[transfer_index];
 +
 +        F64 current_time   = mTimer.getTotalSeconds();
 +        F64 elapsed_time   = current_time - mStartTime;
 +        U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate);
 +        U32 elapsed_oohs   = elapsed_frames % sOohs;
 +        U32 elapsed_aahs   = elapsed_frames % sAahs;
 +
 +        ooh = transfer_ooh * sOoh[elapsed_oohs];
 +        aah = transfer_aah * sAah[elapsed_aahs];
 +
 +        /*
 +        LL_INFOS() << " elapsed frames " << elapsed_frames
 +                << " ooh "            << ooh
 +                << " aah "            << aah
 +                << " transfer ooh"    << transfer_ooh
 +                << " transfer aah"    << transfer_aah
 +                << " start time "     << mStartTime
 +                << " current time "   << current_time
 +                << " elapsed time "   << elapsed_time
 +                << " elapsed oohs "   << elapsed_oohs
 +                << " elapsed aahs "   << elapsed_aahs
 +                << LL_ENDL;
 +        */
 +    }
 +    else
 +    {
 +        ooh = 0.0f;
 +        aah = 0.0f;
 +    }
 +
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +// this method is inherited from HUD Effect
 +//---------------------------------------------------
 +void LLVoiceVisualizer::render()
 +{
 +    if ( ! mVoiceEnabled )
 +    {
 +        return;
 +    }
 +
 +    if ( mSoundSymbol.mActive )
 +    {
 +        mPreviousTime = mCurrentTime;
 +        mCurrentTime = mTimer.getTotalSeconds();
 +
 +        //---------------------------------------------------------------
 +        // set the sound symbol position over the source (avatar's head)
 +        //---------------------------------------------------------------
 +        mSoundSymbol.mPosition = gAgent.getPosAgentFromGlobal(mPositionGlobal) + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD;
 +
 +        //---------------------------------------------------------------
 +        // some gl state
 +        //---------------------------------------------------------------
 +        LLGLSPipelineAlpha alpha_blend;
 +        LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 +        //LLGLDisable gls_stencil(GL_STENCIL_TEST);
 +
 +        //-------------------------------------------------------------
 +        // create coordinates of the geometry for the dot
 +        //-------------------------------------------------------------
 +        LLViewerCamera* camera = LLViewerCamera::getInstance();
 +        LLVector3 l = camera->getLeftAxis() * DOT_SIZE;
 +        LLVector3 u = camera->getUpAxis()   * DOT_SIZE;
 +
 +        LLVector3 bottomLeft    = mSoundSymbol.mPosition + l - u;
 +        LLVector3 bottomRight   = mSoundSymbol.mPosition - l - u;
 +        LLVector3 topLeft       = mSoundSymbol.mPosition + l + u;
 +        LLVector3 topRight      = mSoundSymbol.mPosition - l + u;
 +
 +        //-----------------------------
 +        // bind texture 0 (the dot)
 +        //-----------------------------
 +        gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]);
 +
 +        //-------------------------------------------------------------
 +        // now render the dot
 +        //-------------------------------------------------------------
 +        gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );
 +
 +        gGL.begin( LLRender::TRIANGLE_STRIP );
 +            gGL.texCoord2i( 0,  0   ); gGL.vertex3fv( bottomLeft.mV );
 +            gGL.texCoord2i( 1,  0   ); gGL.vertex3fv( bottomRight.mV );
 +            gGL.texCoord2i( 0,  1   ); gGL.vertex3fv( topLeft.mV );
 +        gGL.end();
 +
 +        gGL.begin( LLRender::TRIANGLE_STRIP );
 +            gGL.texCoord2i( 1,  0   ); gGL.vertex3fv( bottomRight.mV );
 +            gGL.texCoord2i( 1,  1   ); gGL.vertex3fv( topRight.mV );
 +            gGL.texCoord2i( 0,  1   ); gGL.vertex3fv( topLeft.mV );
 +        gGL.end();
 +
 +
 +
 +        //--------------------------------------------------------------------------------------
 +        // if currently speaking, trigger waves (1 through 6) based on speaking amplitude
 +        //--------------------------------------------------------------------------------------
 +        if ( mCurrentlySpeaking )
 +        {
 +            F32 min = 0.2f;
 +            F32 max = 0.7f;
 +            F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min );
 +
 +            // in case mSpeakingAmplitude > max....
 +            if ( fraction > 1.0f )
 +            {
 +                fraction = 1.0f;
 +            }
 +
 +            S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) );
 +
 +            for (int i=0; i<level+1; i++)
 +            {
 +                mSoundSymbol.mWaveActive            [i] = true;
 +                mSoundSymbol.mWaveOpacity           [i] = 1.0f;
 +                mSoundSymbol.mWaveFadeOutStartTime  [i] = mCurrentTime;
 +            }
 +
 +        } // if currently speaking
 +
 +        //---------------------------------------------------
 +        // determine color
 +        //---------------------------------------------------
 +        F32 red     = 0.0f;
 +        F32 green   = 0.0f;
 +        F32 blue    = 0.0f;
 +        if ( mSpeakingAmplitude < RED_THRESHOLD )
 +        {
 +            if ( mSpeakingAmplitude < GREEN_THRESHOLD )
 +            {
 +                red     = BASE_BRIGHTNESS;
 +                green   = BASE_BRIGHTNESS;
 +                blue    = BASE_BRIGHTNESS;
 +            }
 +            else
 +            {
 +                //---------------------------------------------------
 +                // fade from gray to bright green
 +                //---------------------------------------------------
 +                F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD );
 +                red     = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
 +                green   = BASE_BRIGHTNESS +   fraction * ( 1.0f - BASE_BRIGHTNESS );
 +                blue    = BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
 +            }
 +        }
 +        else
 +        {
 +            //---------------------------------------------------
 +            // redish
 +            //---------------------------------------------------
 +            red     = 1.0f;
 +            green   = 0.2f;
 +            blue    = 0.2f;
 +        }
 +
 +        for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
 +        {
 +            if ( mSoundSymbol.mWaveActive[i] )
 +            {
 +                F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION;
 +
 +                mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction;
 +
 +                if ( mSoundSymbol.mWaveOpacity[i] < 0.0f )
 +                {
 +                    mSoundSymbol.mWaveFadeOutStartTime  [i] = mCurrentTime;
 +                    mSoundSymbol.mWaveOpacity           [i] = 0.0f;
 +                    mSoundSymbol.mWaveActive            [i] = false;
 +                }
 +
 +                //----------------------------------------------------------------------------------
 +                // This is where we calculate the expansion of the waves - that is, the
 +                // rate at which they are scaled greater than 1.0 so that they grow over time.
 +                //----------------------------------------------------------------------------------
 +                F32 timeSlice = (F32)( mCurrentTime - mPreviousTime );
 +                F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE;
 +                mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed );
 +
 +                if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX )
 +                {
 +                    mSoundSymbol.mWaveExpansion[i] = 1.0f;
 +                }
 +
 +                //----------------------------------------------------------------------------------
 +                // create geometry for the wave billboard textures
 +                //----------------------------------------------------------------------------------
 +                F32 width   = i * WAVE_WIDTH_SCALE  * mSoundSymbol.mWaveExpansion[i];
 +                F32 height  = i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];
 +
 +                LLVector3 l = camera->getLeftAxis() * width;
 +                LLVector3 u = camera->getUpAxis()   * height;
 +
 +                LLVector3 bottomLeft    = mSoundSymbol.mPosition + l - u;
 +                LLVector3 bottomRight   = mSoundSymbol.mPosition - l - u;
 +                LLVector3 topLeft       = mSoundSymbol.mPosition + l + u;
 +                LLVector3 topRight      = mSoundSymbol.mPosition - l + u;
 +
 +                gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );
 +                gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]);
 +
 +
 +                //---------------------------------------------------
 +                // now, render the mofo
 +                //---------------------------------------------------
 +                gGL.begin( LLRender::TRIANGLE_STRIP );
 +                    gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV );
 +                    gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
 +                    gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
 +                gGL.end();
 +
 +                gGL.begin( LLRender::TRIANGLE_STRIP );
 +                    gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
 +                    gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV );
 +                    gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
 +                gGL.end();
 +
 +            } //if ( mSoundSymbol.mWaveActive[i] )
 +
 +        }// for loop
 +
 +    }//if ( mSoundSymbol.mActive )
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )
 +{
 +    mVoiceSourceWorldPosition   = p;
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel()
 +{
 +    VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default
 +
 +    //-----------------------------------------------------------------------------------------
 +    // Within the range of gesticulation amplitudes, the sound signal is split into
 +    // three equal amplitude regimes, each specifying one of three gesticulation levels.
 +    //-----------------------------------------------------------------------------------------
 +    F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude;
 +
 +            if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f )   { gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH;      }
 +    else    if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f    )   { gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM;    }
 +    else    if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f )   { gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW;       }
 +
 +    return gesticulationLevel;
 +
 +}//---------------------------------------------------
 +
 +
 +
 +//------------------------------------
 +// Destructor
 +//------------------------------------
 +LLVoiceVisualizer::~LLVoiceVisualizer()
 +{
 +}//----------------------------------------------
 +
 +
 +//---------------------------------------------------
 +// "packData" is inherited from HUDEffect
 +//---------------------------------------------------
 +void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys)
 +{
 +    // Pack the default data
 +    LLHUDEffect::packData(mesgsys);
 +
 +    // TODO -- pack the relevant data for voice effects
 +    // we'll come up with some cool configurations....TBD
 +    //U8 packed_data[41];
 +    //mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
 +    U8 packed_data = 0;
 +    mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1);
 +}
 +
 +
 +//---------------------------------------------------
 +// "unpackData" is inherited from HUDEffect
 +//---------------------------------------------------
 +void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 +{
 +    // TODO -- find the speaker, unpack binary data, set the properties of this effect
 +    /*
 +    LLHUDEffect::unpackData(mesgsys, blocknum);
 +    LLUUID source_id;
 +    LLUUID target_id;
 +    S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
 +    if (size != 1)
 +    {
 +        LL_WARNS() << "Voice effect with bad size " << size << LL_ENDL;
 +        return;
 +    }
 +    mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum);
 +    */
 +}
 +
 +
 +//------------------------------------------------------------------
 +// this method is inherited from HUD Effect
 +//------------------------------------------------------------------
 +void LLVoiceVisualizer::markDead()
 +{
 +    mCurrentlySpeaking      = false;
 +    mVoiceEnabled           = false;
 +    mSoundSymbol.mActive    = false;
 +
 +    LLHUDEffect::markDead();
 +}//------------------------------------------------------------------
  | 
