QAR-468 "Babble Lipsync MergeMe"

svn merge -c85508
svn+ssh://svn.lindenlab.com/svn/linden/branches/babble-merge1-r85500
master
Adam Moss 2008-04-22 16:17:22 +00:00
parent 06e8af59a9
commit c01edec021
9 changed files with 432 additions and 89 deletions

View File

@ -189,6 +189,7 @@ Michelle2 Zenovka
VWR-3749
Mm Alder
VWR-3777
VWR-4794
Mr Greggan
VWR-445
Nicholaz Beresford

View File

@ -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>

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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
//--------------------------------------------------------------------

View File

@ -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)

View File

@ -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;

View File

@ -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
//---------------------------------------------------

View File

@ -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
//------------------------------------------------------------------