QAR-468 "Babble Lipsync MergeMe"
svn merge -c85508 svn+ssh://svn.lindenlab.com/svn/linden/branches/babble-merge1-r85500master
parent
06e8af59a9
commit
c01edec021
|
|
@ -189,6 +189,7 @@ Michelle2 Zenovka
|
|||
VWR-3749
|
||||
Mm Alder
|
||||
VWR-3777
|
||||
VWR-4794
|
||||
Mr Greggan
|
||||
VWR-445
|
||||
Nicholaz Beresford
|
||||
|
|
|
|||
|
|
@ -3918,6 +3918,72 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>LipSyncAah</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Aah (jaw opening) babble loop</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>257998776531013446642343</string>
|
||||
</map>
|
||||
<key>LipSyncAahPowerTransfer</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Transfer curve for Voice Interface power to aah lip sync amplitude</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>0000123456789</string>
|
||||
</map>
|
||||
<key>LipSyncEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>0 disable lip-sync, 1 enable babble loop</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>LipSyncOoh</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Ooh (mouth width) babble loop</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>1247898743223344444443200000</string>
|
||||
</map>
|
||||
<key>LipSyncOohAahRate</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rate to babble Ooh and Aah (/sec)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>24.0</real>
|
||||
</map>
|
||||
<key>LipSyncOohPowerTransfer</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Transfer curve for Voice Interface power to ooh lip sync amplitude</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>0012345566778899</string>
|
||||
</map>
|
||||
<key>LocalCacheVersion</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -426,6 +426,7 @@ bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
|
|||
gVoiceClient->setCaptureDevice(inputDevice);
|
||||
std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
|
||||
gVoiceClient->setRenderDevice(outputDevice);
|
||||
gVoiceClient->setLipSyncEnabled(gSavedSettings.getU32("LipSyncEnabled"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -555,5 +556,6 @@ void settings_setup_listeners()
|
|||
gSavedSettings.getControl("VivoxDebugServerName")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
|
||||
gSavedSettings.getControl("VoiceInputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
|
||||
gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
|
||||
gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@
|
|||
#include "llstatusbar.h"
|
||||
#include "lltargetingmotion.h"
|
||||
#include "lltexlayer.h"
|
||||
#include "lltoolbar.h"
|
||||
#include "lltoolgrab.h" // for needsRenderBeam
|
||||
#include "lltoolmgr.h" // for needsRenderBeam
|
||||
#include "lltoolmorph.h"
|
||||
|
|
@ -117,20 +116,13 @@
|
|||
#include "llspatialpartition.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llappviewer.h"
|
||||
#include "lscript_byteformat.h"
|
||||
#include "llsky.h"
|
||||
|
||||
//#include "vtune/vtuneapi.h"
|
||||
|
||||
//Ventrella
|
||||
#include "llgesturemgr.h" //needed to trigger the voice gestculations
|
||||
#include "llgesturemgr.h" //needed to trigger the voice gesticulations
|
||||
#include "llvoicevisualizer.h"
|
||||
#include "llvoiceclient.h"
|
||||
//end Ventrella
|
||||
|
||||
// Direct imports, evil
|
||||
extern LLSky gSky;
|
||||
extern void set_avatar_character(void* charNameArg);
|
||||
extern BOOL gRenderForSelect;
|
||||
|
||||
LLXmlTree LLVOAvatar::sXMLTree;
|
||||
LLXmlTree LLVOAvatar::sSkeletonXMLTree;
|
||||
|
|
@ -766,6 +758,10 @@ LLVOAvatar::LLVOAvatar(
|
|||
mStepOnLand = TRUE;
|
||||
mStepMaterial = 0;
|
||||
|
||||
mLipSyncActive = false;
|
||||
mOohMorph = NULL;
|
||||
mAahMorph = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// initialize joint, mesh and shape members
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
@ -950,10 +946,8 @@ LLVOAvatar::LLVOAvatar(
|
|||
|
||||
//VTPause(); // VTune
|
||||
|
||||
//Ventrella
|
||||
mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
|
||||
mCurrentGesticulationLevel = 0;
|
||||
//END Ventrella
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -1886,6 +1880,26 @@ void LLVOAvatar::buildCharacter()
|
|||
//-------------------------------------------------------------------------
|
||||
updateHeadOffset();
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// initialize lip sync morph pointers
|
||||
//-------------------------------------------------------------------------
|
||||
mOohMorph = getVisualParam( "Lipsync_Ooh" );
|
||||
mAahMorph = getVisualParam( "Lipsync_Aah" );
|
||||
|
||||
// If we don't have the Ooh morph, use the Kiss morph
|
||||
if (!mOohMorph)
|
||||
{
|
||||
llwarns << "Missing 'Ooh' morph for lipsync, using fallback." << llendl;
|
||||
mOohMorph = getVisualParam( "Express_Kiss" );
|
||||
}
|
||||
|
||||
// If we don't have the Aah morph, use the Open Mouth morph
|
||||
if (!mAahMorph)
|
||||
{
|
||||
llwarns << "Missing 'Aah' morph for lipsync, using fallback." << llendl;
|
||||
mAahMorph = getVisualParam( "Express_Open_Mouth" );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// start default motions
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
@ -2449,88 +2463,93 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||
// animate the character
|
||||
// store off last frame's root position to be consistent with camera position
|
||||
LLVector3 root_pos_last = mRoot.getWorldPosition();
|
||||
|
||||
BOOL detailed_update = updateCharacter(agent);
|
||||
bool voiceEnabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
|
||||
|
||||
{
|
||||
//Ventrella
|
||||
bool voiceEnabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
|
||||
// disable voice visualizer when in mouselook
|
||||
mVoiceVisualizer->setVoiceEnabled( voiceEnabled && !(mIsSelf && gAgent.cameraMouselook()) );
|
||||
if ( voiceEnabled )
|
||||
// disable voice visualizer when in mouselook
|
||||
mVoiceVisualizer->setVoiceEnabled( voiceEnabled && !(mIsSelf && gAgent.cameraMouselook()) );
|
||||
if ( voiceEnabled )
|
||||
{
|
||||
//----------------------------------------------------------------
|
||||
// Only do gesture triggering for your own avatar, and only when you're in a proximal channel.
|
||||
//----------------------------------------------------------------
|
||||
if( mIsSelf )
|
||||
{
|
||||
//----------------------------------------------------------------------------------------
|
||||
// The following takes the voice signal and uses that to trigger gesticulations.
|
||||
//----------------------------------------------------------------------------------------
|
||||
int lastGesticulationLevel = mCurrentGesticulationLevel;
|
||||
mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel();
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// If "current gesticulation level" changes, we catch this, and trigger the new gesture
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
if ( lastGesticulationLevel != mCurrentGesticulationLevel )
|
||||
{
|
||||
if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF )
|
||||
{
|
||||
LLString gestureString = "unInitialized";
|
||||
if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; }
|
||||
else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; }
|
||||
else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; }
|
||||
else { llinfos << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << llendl; }
|
||||
|
||||
// this is the call that Karl S. created for triggering gestures from within the code.
|
||||
gGestureManager.triggerAndReviseString( gestureString );
|
||||
}
|
||||
}
|
||||
|
||||
} //if( mIsSelf )
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
// If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer.
|
||||
// Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol.
|
||||
//
|
||||
// Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
|
||||
// "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking.
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
if ( gVoiceClient->getIsSpeaking( mID ) )
|
||||
{
|
||||
//----------------------------------------------------------------
|
||||
// Only do gesture triggering for your own avatar, and only when you're in a proximal channel.
|
||||
//----------------------------------------------------------------
|
||||
if ( ! mVoiceVisualizer->getCurrentlySpeaking() )
|
||||
{
|
||||
mVoiceVisualizer->setStartSpeaking();
|
||||
|
||||
//printf( "gAwayTimer.reset();\n" );
|
||||
}
|
||||
|
||||
mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
|
||||
|
||||
if( mIsSelf )
|
||||
{
|
||||
//----------------------------------------------------------------------------------------
|
||||
// The following takes the voice signal and uses that to trigger gesticulations.
|
||||
//----------------------------------------------------------------------------------------
|
||||
int lastGesticulationLevel = mCurrentGesticulationLevel;
|
||||
mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel();
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// If "current gesticulation level" changes, we catch this, and trigger the new gesture
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
if ( lastGesticulationLevel != mCurrentGesticulationLevel )
|
||||
{
|
||||
if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF )
|
||||
{
|
||||
LLString gestureString = "unInitialized";
|
||||
if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; }
|
||||
else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; }
|
||||
else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; }
|
||||
else { llinfos << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << llendl; }
|
||||
|
||||
// this is the call that Karl S. created for triggering gestures from within the code.
|
||||
gGestureManager.triggerAndReviseString( gestureString );
|
||||
}
|
||||
}
|
||||
|
||||
} //if( mIsSelf )
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
// If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer.
|
||||
// Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol.
|
||||
//
|
||||
// Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
|
||||
// "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking.
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
if ( gVoiceClient->getIsSpeaking( mID ) )
|
||||
gAgent.clearAFK();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mVoiceVisualizer->getCurrentlySpeaking() )
|
||||
{
|
||||
if ( ! mVoiceVisualizer->getCurrentlySpeaking() )
|
||||
mVoiceVisualizer->setStopSpeaking();
|
||||
|
||||
if ( mLipSyncActive )
|
||||
{
|
||||
mVoiceVisualizer->setStartSpeaking();
|
||||
if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight(), FALSE);
|
||||
if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight(), FALSE);
|
||||
|
||||
//printf( "gAwayTimer.reset();\n" );
|
||||
}
|
||||
|
||||
mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
|
||||
|
||||
if( mIsSelf )
|
||||
{
|
||||
gAgent.clearAFK();
|
||||
mLipSyncActive = false;
|
||||
LLCharacter::updateVisualParams();
|
||||
dirtyMesh();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mVoiceVisualizer->getCurrentlySpeaking() )
|
||||
{
|
||||
mVoiceVisualizer->setStopSpeaking();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// here we get the approximate head position and set as sound source for the voice symbol
|
||||
// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)
|
||||
//--------------------------------------------------------------------------------------------
|
||||
LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] );
|
||||
mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset );
|
||||
|
||||
}//if ( voiceEnabled )
|
||||
}
|
||||
//End Ventrella
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// here we get the approximate head position and set as sound source for the voice symbol
|
||||
// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)
|
||||
//--------------------------------------------------------------------------------------------
|
||||
LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] );
|
||||
mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset );
|
||||
|
||||
}//if ( voiceEnabled )
|
||||
|
||||
if (LLVOAvatar::sJointDebug)
|
||||
{
|
||||
|
|
@ -2704,6 +2723,35 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||
dirtyMesh();
|
||||
}
|
||||
|
||||
// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
|
||||
if ( voiceEnabled && (gVoiceClient->lipSyncEnabled() > 0) && gVoiceClient->getIsSpeaking( mID ) )
|
||||
{
|
||||
F32 ooh_morph_amount = 0.0f;
|
||||
F32 aah_morph_amount = 0.0f;
|
||||
|
||||
mVoiceVisualizer->lipSyncOohAah( ooh_morph_amount, aah_morph_amount );
|
||||
|
||||
if( mOohMorph )
|
||||
{
|
||||
F32 ooh_weight = mOohMorph->getMinWeight()
|
||||
+ ooh_morph_amount * (mOohMorph->getMaxWeight() - mOohMorph->getMinWeight());
|
||||
|
||||
mOohMorph->setWeight( ooh_weight, FALSE );
|
||||
}
|
||||
|
||||
if( mAahMorph )
|
||||
{
|
||||
F32 aah_weight = mAahMorph->getMinWeight()
|
||||
+ aah_morph_amount * (mAahMorph->getMaxWeight() - mAahMorph->getMinWeight());
|
||||
|
||||
mAahMorph->setWeight( aah_weight, FALSE );
|
||||
}
|
||||
|
||||
mLipSyncActive = true;
|
||||
LLCharacter::updateVisualParams();
|
||||
dirtyMesh();
|
||||
}
|
||||
|
||||
// update wind effect
|
||||
if ((LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
|
||||
{
|
||||
|
|
@ -3883,7 +3931,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
|
|||
if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
|
||||
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
|
||||
updateMeshData();
|
||||
mDirtyMesh = FALSE;
|
||||
mDirtyMesh = FALSE;
|
||||
mNeedsSkin = TRUE;
|
||||
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
|
||||
}
|
||||
|
|
@ -9507,7 +9555,7 @@ BOOL LLVOAvatar::updateLOD()
|
|||
if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
|
||||
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
|
||||
updateMeshData();
|
||||
mDirtyMesh = FALSE;
|
||||
mDirtyMesh = FALSE;
|
||||
mNeedsSkin = TRUE;
|
||||
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -831,6 +831,17 @@ public:
|
|||
F32 mLastAppearanceBlendTime;
|
||||
BOOL mAppearanceAnimating;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// we're morphing for lip sync
|
||||
//--------------------------------------------------------------------
|
||||
bool mLipSyncActive;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// cached pointers morphs for lip sync
|
||||
//--------------------------------------------------------------------
|
||||
LLVisualParam *mOohMorph;
|
||||
LLVisualParam *mAahMorph;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// static members
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -833,6 +833,7 @@ LLVoiceClient::LLVoiceClient()
|
|||
setCaptureDevice(captureDevice);
|
||||
std::string renderDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
|
||||
setRenderDevice(renderDevice);
|
||||
mLipSyncEnabled = gSavedSettings.getU32("LipSyncEnabled");
|
||||
|
||||
mTuningMode = false;
|
||||
mTuningEnergy = 0.0f;
|
||||
|
|
@ -3607,6 +3608,24 @@ bool LLVoiceClient::voiceEnabled()
|
|||
return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice");
|
||||
}
|
||||
|
||||
void LLVoiceClient::setLipSyncEnabled(U32 enabled)
|
||||
{
|
||||
mLipSyncEnabled = enabled;
|
||||
}
|
||||
|
||||
U32 LLVoiceClient::lipSyncEnabled()
|
||||
{
|
||||
|
||||
if ( mVoiceEnabled && stateDisabled != getState() )
|
||||
{
|
||||
return mLipSyncEnabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LLVoiceClient::setUsePTT(bool usePTT)
|
||||
{
|
||||
if(usePTT && !mUsePTT)
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
|
|||
void setMicGain(F32 volume);
|
||||
void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
|
||||
void setVivoxDebugServerName(std::string &serverName);
|
||||
void setLipSyncEnabled(U32 enabled);
|
||||
U32 lipSyncEnabled();
|
||||
|
||||
// PTT key triggering
|
||||
void keyDown(KEY key, MASK mask);
|
||||
|
|
@ -516,6 +518,8 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
|
|||
|
||||
LLTimer mUpdateTimer;
|
||||
|
||||
U32 mLipSyncEnabled;
|
||||
|
||||
typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
|
||||
observer_set_t mObservers;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,35 @@ const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE = 1.0f;
|
|||
const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.
|
||||
const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// handles parameter updates
|
||||
//------------------------------------------------------------------
|
||||
static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue)
|
||||
{
|
||||
// Note: Ignore the specific event value, we look up the ones we want
|
||||
LLVoiceVisualizer::setPreferences();
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Initialize the statics
|
||||
//------------------------------------------------------------------
|
||||
bool LLVoiceVisualizer::sPrefsInitialized = false;
|
||||
U32 LLVoiceVisualizer::sLipSyncEnabled = 0;
|
||||
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
|
||||
//-----------------------------------------------
|
||||
|
|
@ -87,6 +116,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
|
|||
{
|
||||
mCurrentTime = mTimer.getTotalSeconds();
|
||||
mPreviousTime = mCurrentTime;
|
||||
mStartTime = mCurrentTime;
|
||||
mVoiceSourceWorldPosition = LLVector3( 0.0f, 0.0f, 0.0f );
|
||||
mSpeakingAmplitude = 0.0f;
|
||||
mCurrentlySpeaking = false;
|
||||
|
|
@ -105,7 +135,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
|
|||
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
||||
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
||||
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
||||
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
||||
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c",
|
||||
"29de489d-0491-fb00-7dab-f9e686d31e83.j2c"
|
||||
};
|
||||
|
||||
|
|
@ -117,7 +147,23 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
|
|||
mSoundSymbol.mWaveOpacity [i] = 1.0f;
|
||||
mSoundSymbol.mWaveExpansion [i] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
// 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(&handleVoiceVisualizerPrefsChanged, _1));
|
||||
gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
||||
gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
||||
gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
||||
gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
||||
gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _1));
|
||||
|
||||
sPrefsInitialized = true;
|
||||
}
|
||||
|
||||
}//---------------------------------------------------
|
||||
|
||||
//---------------------------------------------------
|
||||
|
|
@ -144,6 +190,7 @@ void LLVoiceVisualizer::setVoiceEnabled( bool v )
|
|||
//---------------------------------------------------
|
||||
void LLVoiceVisualizer::setStartSpeaking()
|
||||
{
|
||||
mStartTime = mTimer.getTotalSeconds();
|
||||
mCurrentlySpeaking = true;
|
||||
mSoundSymbol.mActive = true;
|
||||
|
||||
|
|
@ -175,6 +222,130 @@ void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )
|
|||
}//---------------------------------------------------
|
||||
|
||||
|
||||
//---------------------------------------------------
|
||||
void LLVoiceVisualizer::setPreferences( )
|
||||
{
|
||||
sLipSyncEnabled = gSavedSettings.getU32("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 == 1 ) && mCurrentlySpeaking )
|
||||
{
|
||||
U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude);
|
||||
if (transfer_index < 0)
|
||||
{
|
||||
transfer_index = 0;
|
||||
}
|
||||
if (transfer_index >= sOohPowerTransfers)
|
||||
{
|
||||
transfer_index = sOohPowerTransfers - 1;
|
||||
}
|
||||
F32 transfer_ooh = sOohPowerTransfer[transfer_index];
|
||||
|
||||
transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude);
|
||||
if (transfer_index < 0)
|
||||
{
|
||||
transfer_index = 0;
|
||||
}
|
||||
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];
|
||||
|
||||
/*
|
||||
llinfos << " 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
|
||||
<< llendl;
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
ooh = 0.0f;
|
||||
aah = 0.0f;
|
||||
}
|
||||
|
||||
}//---------------------------------------------------
|
||||
|
||||
|
||||
//---------------------------------------------------
|
||||
// this method is inherited from HUD Effect
|
||||
//---------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -90,7 +90,9 @@ class LLVoiceVisualizer : public LLHUDEffect
|
|||
void setStopSpeaking(); // tell me when the av stops speaking
|
||||
bool getCurrentlySpeaking(); // the get for the above set
|
||||
VoiceGesticulationLevel getCurrentGesticulationLevel(); // based on voice amplitude, I'll give you the current "energy level" of avatar speech
|
||||
|
||||
static void setPreferences( );
|
||||
static void lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats
|
||||
void lipSyncOohAah( F32& ooh, F32& aah );
|
||||
void render(); // inherited from HUD Effect
|
||||
void packData(LLMessageSystem *mesgsys); // inherited from HUD Effect
|
||||
void unpackData(LLMessageSystem *mesgsys, S32 blocknum); // inherited from HUD Effect
|
||||
|
|
@ -124,6 +126,7 @@ class LLVoiceVisualizer : public LLHUDEffect
|
|||
};
|
||||
|
||||
LLFrameTimer mTimer; // so I can ask the current time in seconds
|
||||
F64 mStartTime; // time in seconds when speaking started
|
||||
F64 mCurrentTime; // current time in seconds, captured every step
|
||||
F64 mPreviousTime; // copy of "current time" from last frame
|
||||
SoundSymbol mSoundSymbol; // the sound symbol that appears over the avatar's head
|
||||
|
|
@ -134,6 +137,24 @@ class LLVoiceVisualizer : public LLHUDEffect
|
|||
F32 mMaxGesticulationAmplitude; // this is the upper-limit of the envelope of detectable gesticulation leves
|
||||
F32 mMinGesticulationAmplitude; // this is the lower-limit of the envelope of detectable gesticulation leves
|
||||
|
||||
//---------------------------------------------------
|
||||
// private static members
|
||||
//---------------------------------------------------
|
||||
|
||||
static U32 sLipSyncEnabled; // 0 disabled, 1 babble loop
|
||||
static bool sPrefsInitialized; // the first instance will initialize the static members
|
||||
static F32* sOoh; // the babble loop of amplitudes for the ooh morph
|
||||
static F32* sAah; // the babble loop of amplitudes for the ooh morph
|
||||
static U32 sOohs; // the number of entries in the ooh loop
|
||||
static U32 sAahs; // the number of entries in the aah loop
|
||||
static F32 sOohAahRate; // frames per second for the babble loop
|
||||
static F32* sOohPowerTransfer; // the power transfer characteristics for the ooh amplitude
|
||||
static U32 sOohPowerTransfers; // the number of entries in the ooh transfer characteristics
|
||||
static F32 sOohPowerTransfersf; // the number of entries in the ooh transfer characteristics as a float
|
||||
static F32* sAahPowerTransfer; // the power transfer characteristics for the aah amplitude
|
||||
static U32 sAahPowerTransfers; // the number of entries in the aah transfer characteristics
|
||||
static F32 sAahPowerTransfersf; // the number of entries in the aah transfer characteristics as a float
|
||||
|
||||
};//-----------------------------------------------------------------
|
||||
// end of LLVoiceVisualizer class
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue