Aufgrund von Umarbeiten des s3 Storage wird es in GitLab, in nächster Zeit, mögliche Performance-Einbußen geben. Näheres dazu unter: https://maintenance.itc.rwth-aachen.de/ticket/status/messages/43/show_ticket/6670

WIP on HATO test and implementation in BFF renderer, still jumpy for...

WIP on HATO test and implementation in BFF renderer, still jumpy for near-range-limit HATO HRTFs, problem with index layout or input data?
parent 4791e51d
......@@ -736,8 +736,8 @@ void CVABinauralFreeFieldAudioRenderer::ProcessStream( const ITAStreamInfo* pStr
// HATO
const VAQuat qHATO = pListenerState->GetMotionState()->GetHeadAboveTorsoOrientation();
const double dHATODeg = 0.0f;
// @todo daniel: calculate HAT rotation based on HATO quaternion
const double dHATODenominator = sqrt( 1 - qHATO.w * qHATO.w );
const double dHATODeg = rad2grad( dHATODenominator == 0.0f ? 0.0f : qHATO.y / dHATODenominator );
pPath->UpdateHRIR( pListenerState->GetAnthropometricData(), dHATODeg );
// Sound source gain / direct sound audibility via AuraMode flags
......@@ -1093,7 +1093,7 @@ void CVABinauralFreeFieldAudioRenderer::ResetInternalData()
void CVABinauralFreeFieldAudioRenderer::UpdateSoundPaths()
{
int iGlobalAuralisationMode = m_iCurGlobalAuralizationMode;
const int iGlobalAuralisationMode = m_iCurGlobalAuralizationMode;
// Check for new data
std::list< CVABFFSoundPath* >::iterator it = m_lSoundPaths.begin();
......@@ -1274,65 +1274,80 @@ double CVABFFSoundPath::CalculateInverseDistanceDecrease() const
void CVABFFSoundPath::UpdateHRIR( const CVAReceiverState::CVAAnthropometricParameter& oAnthroParameters, const double dHATODeg )
{
double dITDCorrectionShift = .0f;
IVADirectivity* pCurHRIR = oHRIRStateCur.pData;
IVADirectivity* pNewHRIR = oHRIRStateNew.pData;
switch( oHRIRStateNew.pData->GetType() )
// No new directivity
if( pNewHRIR == nullptr )
{
if( pCurHRIR )
{
// Directivity has been removed, set zero filters once
ITAUPFilter* pHRIRFilterChL = pFIRConvolverChL->GetFilterPool()->RequestFilter();
ITAUPFilter* pHRIRFilterChR = pFIRConvolverChR->GetFilterPool()->RequestFilter();
pHRIRFilterChL->Zeros();
pHRIRFilterChR->Zeros();
pFIRConvolverChL->ExchangeFilter( pHRIRFilterChL );
pFIRConvolverChR->ExchangeFilter( pHRIRFilterChR );
pFIRConvolverChL->ReleaseFilter( pHRIRFilterChL );
pFIRConvolverChR->ReleaseFilter( pHRIRFilterChR );
}
return;
}
switch( pNewHRIR->GetType() )
{
case IVADirectivity::DAFF_HATO_HRIR:
{
CVADirectivityDAFFHATOHRIR* pHRIRDataNew = ( CVADirectivityDAFFHATOHRIR * ) oHRIRStateNew.pData;
CVADirectivityDAFFHATOHRIR* pHATOHRIR = ( CVADirectivityDAFFHATOHRIR * ) pNewHRIR;
oHRIRStateNew.dHATODeg = dHATODeg; // Overwrite current HATO
// Quick check if nearest neighbour is equal
bool bForceUpdate = false;
if( pHRIRDataNew != nullptr )
{
// Quick check if nearest neighbour is equal
if( pHRIRDataNew->GetProperties()->bSpaceDiscrete )
pHRIRDataNew->GetNearestSpatialNeighbourIndex( float( oRelations.dAzimuthL2S ), float( oRelations.dElevationL2S ), &oHRIRStateNew.iRecord );
else
bForceUpdate = true; // Update always required, if non-discrete data
}
if( pHATOHRIR->GetProperties()->bSpaceDiscrete )
pHATOHRIR->GetNearestSpatialNeighbourIndex( float( oRelations.dAzimuthL2S ), float( oRelations.dElevationL2S ), &oHRIRStateNew.iRecord );
else
bForceUpdate = true; // Update always required, if non-discrete data
if( ( oHRIRStateCur != oHRIRStateNew ) || bForceUpdate )
{
ITAUPFilter* pHRIRFilterChL = pFIRConvolverChL->GetFilterPool()->RequestFilter();
ITAUPFilter* pHRIRFilterChR = pFIRConvolverChR->GetFilterPool()->RequestFilter();
if( pHRIRDataNew == nullptr )
int iNewFilterLength = pHATOHRIR->GetProperties()->iFilterLength;
if( m_sfHRIRTemp.length() != iNewFilterLength )
{
pHRIRFilterChL->Zeros();
pHRIRFilterChR->Zeros();
m_sfHRIRTemp.init( 2, iNewFilterLength, false );
}
if( iNewFilterLength > pFIRConvolverChL->GetMaxFilterlength() )
{
VA_WARN( "BFFSoundPath", "HRIR too long for convolver, cropping. Increase HRIR filter length in BinauralFreefieldAudioRenderer configuration." );
iNewFilterLength = pFIRConvolverChL->GetMaxFilterlength();
}
if( pHATOHRIR->GetProperties()->bSpaceDiscrete )
{
pHATOHRIR->GetHRIRByIndexAndHATO( &m_sfHRIRTemp, oHRIRStateNew.iRecord, float( dHATODeg ) );
oHRIRStateNew.fDistance = float( oRelations.dDistance );
}
else
{
int iNewFilterLength = pHRIRDataNew->GetProperties()->iFilterLength;
if( m_sfHRIRTemp.length() != iNewFilterLength )
{
m_sfHRIRTemp.init( 2, iNewFilterLength, false );
}
int iRecordIndex = -1;
pHATOHRIR->GetNearestSpatialNeighbourIndex( float( oRelations.dAzimuthL2S ), float( oRelations.dElevationL2S ), &iRecordIndex );
pHATOHRIR->GetHRIRByIndexAndHATO( &m_sfHRIRTemp, iRecordIndex, dHATODeg );
}
if( iNewFilterLength > pFIRConvolverChL->GetMaxFilterlength() )
{
VA_WARN( "BFFSoundPath", "HRIR too long for convolver, cropping. Increase HRIR filter length in BinauralFreefieldAudioRenderer configuration." );
iNewFilterLength = pFIRConvolverChL->GetMaxFilterlength();
}
if( pHRIRDataNew->GetProperties()->bSpaceDiscrete )
{
pHRIRDataNew->GetHRIRByIndexAndHATO( &m_sfHRIRTemp, oHRIRStateNew.iRecord, float( dHATODeg ) );
oHRIRStateNew.fDistance = float( oRelations.dDistance );
}
else
{
int iRecordIndex = -1;
pHRIRDataNew->GetNearestSpatialNeighbourIndex( float( oRelations.dAzimuthL2S ), float( oRelations.dElevationL2S ), &iRecordIndex );
pHRIRDataNew->GetHRIRByIndexAndHATO( &m_sfHRIRTemp, iRecordIndex, dHATODeg );
}
// Update DSP element
pHRIRFilterChL->Load( m_sfHRIRTemp[ 0 ].data(), iNewFilterLength );
pHRIRFilterChR->Load( m_sfHRIRTemp[ 1 ].data(), iNewFilterLength );
}
ITAUPFilter* pHRIRFilterChL = pFIRConvolverChL->GetFilterPool()->RequestFilter();
ITAUPFilter* pHRIRFilterChR = pFIRConvolverChR->GetFilterPool()->RequestFilter();
pHRIRFilterChL->Load( m_sfHRIRTemp[ 0 ].data(), iNewFilterLength );
pHRIRFilterChR->Load( m_sfHRIRTemp[ 1 ].data(), iNewFilterLength );
pFIRConvolverChL->ExchangeFilter( pHRIRFilterChL );
pFIRConvolverChR->ExchangeFilter( pHRIRFilterChR );
......@@ -1343,29 +1358,27 @@ void CVABFFSoundPath::UpdateHRIR( const CVAReceiverState::CVAAnthropometricParam
oHRIRStateCur = oHRIRStateNew;
}
if( pHRIRDataNew )
{
// Calculate individualized ITD based on anthropometric data
// Source: ???
double daw = -8.7231e-4;
double dbw = 0.0029;
double dah = -3.942e-4;
double dbh = 6.0476e-4;
double dad = 4.2308e-4;
double dbd = oAnthroParameters.GetHeadDepthParameterFromLUT( oAnthroParameters.dHeadDepth );
double dDeltaWidth = oAnthroParameters.dHeadWidth - pHRIRDataNew->GetProperties()->oAnthroParams.dHeadWidth;
double dDeltaHeight = oAnthroParameters.dHeadHeight - pHRIRDataNew->GetProperties()->oAnthroParams.dHeadHeight;
double dDeltaDepth = oAnthroParameters.dHeadDepth - pHRIRDataNew->GetProperties()->oAnthroParams.dHeadDepth;
double dPhiRad = oRelations.dAzimuthL2S * ITAConstants::PI_F / 180.0;
double dThetaRad = -( oRelations.dElevationL2S * ITAConstants::PI_F / 180.0 - ITAConstants::PI_F / 2.0f );
double dAmplitude = dPhiRad * ( dDeltaWidth * ( dThetaRad * dThetaRad * daw + dThetaRad * dbw ) + dDeltaHeight * ( dThetaRad * dThetaRad * dah + dThetaRad * dbh ) + dDeltaDepth * ( dThetaRad * dThetaRad * dad + dThetaRad * dbd ) );
dITDCorrectionShift = std::sin( dPhiRad ) * dAmplitude;
}
// Calculate individualized ITD based on anthropometric data
// Source: ???
double daw = -8.7231e-4;
double dbw = 0.0029;
double dah = -3.942e-4;
double dbh = 6.0476e-4;
double dad = 4.2308e-4;
double dbd = oAnthroParameters.GetHeadDepthParameterFromLUT( oAnthroParameters.dHeadDepth );
double dDeltaWidth = oAnthroParameters.dHeadWidth - pHATOHRIR->GetProperties()->oAnthroParams.dHeadWidth;
double dDeltaHeight = oAnthroParameters.dHeadHeight - pHATOHRIR->GetProperties()->oAnthroParams.dHeadHeight;
double dDeltaDepth = oAnthroParameters.dHeadDepth - pHATOHRIR->GetProperties()->oAnthroParams.dHeadDepth;
double dPhiRad = oRelations.dAzimuthL2S * ITAConstants::PI_F / 180.0;
double dThetaRad = -( oRelations.dElevationL2S * ITAConstants::PI_F / 180.0 - ITAConstants::PI_F / 2.0f );
double dAmplitude = dPhiRad * ( dDeltaWidth * ( dThetaRad * dThetaRad * daw + dThetaRad * dbw ) + dDeltaHeight * ( dThetaRad * dThetaRad * dah + dThetaRad * dbh ) + dDeltaDepth * ( dThetaRad * dThetaRad * dad + dThetaRad * dbd ) );
dITDCorrectionShift = std::sin( dPhiRad ) * dAmplitude;
}
case IVADirectivity::DAFF_HRIR:
{
CVADirectivityDAFFHRIR* pHRIRDataNew = ( CVADirectivityDAFFHRIR * ) oHRIRStateNew.pData;
CVADirectivityDAFFHRIR* pHRIRDataNew = ( CVADirectivityDAFFHRIR * ) pNewHRIR;
bool bForeUpdate = false;
if( pHRIRDataNew != nullptr )
{
......@@ -1445,7 +1458,6 @@ void CVABFFSoundPath::UpdateHRIR( const CVAReceiverState::CVAAnthropometricParam
}
}
// Apply individualized delay
const float fPreviousDelayTimeL = pVariableDelayLineChL->GetNewDelayTime();
const float fPreviousDelayTimeR = pVariableDelayLineChR->GetNewDelayTime();
......
......@@ -161,6 +161,9 @@ void CVADirectivityDAFFHATOHRIR::GetNearestSpatialNeighbourIndex( const float fA
int iDAFFIndex;
m_pContent->getNearestNeighbour( DAFF_OBJECT_VIEW, fAzimuthDeg, fElevationDeg, iDAFFIndex, bOutOfBounds );
if( piIndex )
*piIndex = iDAFFIndex;
if( pbOutOfBounds )
*pbOutOfBounds = bOutOfBounds;
}
......@@ -168,39 +171,38 @@ void CVADirectivityDAFFHATOHRIR::GetNearestSpatialNeighbourIndex( const float fA
int CVADirectivityDAFFHATOHRIR::GetHATOChannelIndexLeft( const double dHATODeg ) const
{
// Convert index to artificial HATO index, @todo daniel
double dHATODegProjected = dHATODeg > 180.0f ? dHATODeg - 360.0f : dHATODeg;
assert( dHATODeg <= m_dHATOEndDeg && dHATODeg >= m_dHATOStartDeg );
if( dHATODegProjected > m_dHATOEndDeg )
dHATODegProjected = m_dHATOEndDeg;
if( dHATODegProjected < m_dHATOStartDeg )
dHATODegProjected = m_dHATOStartDeg;
if ( !dHATODeg )
return 1;
if( dHATODegProjected == 0.0f )
return 0;
int iNumHATODirections = m_pContent->getProperties()->getNumberOfChannels() / 2;
if (iNumHATODirections == 1)
return 1;
assert( iNumHATODirections >= 3 ); // laut Kommentar mindestens 6 HATO Channels. Falls vorher schon geprft, berflssig.
assert( iNumHATODirections > 2 ); // laut Kommentar mindestens 6 HATO Channels. Falls vorher schon geprft, berflssig.
double dHATORes = ( m_dHATOEndDeg - m_dHATOStartDeg ) / ( iNumHATODirections - 1 );
double dDeviation = fmod( dHATODeg, dHATORes ); // bin nicht sicher ob math.h (fr fmod) bereits includiert, daher habe ich das oben hinzugefgt.
double dNearestHATODeg;
double dDeviation = fmod( dHATODegProjected, dHATORes ); // bin nicht sicher ob math.h (fr fmod) bereits includiert, daher habe ich das oben hinzugefgt.
if ( dDeviation < ( dHATORes / 2 ) )
dNearestHATODeg = dHATODeg - dDeviation;
double dNearestHATODeg = .0f;
if( dDeviation < ( dHATORes / 2 ) )
dNearestHATODeg = dHATODegProjected - dDeviation;
else
dNearestHATODeg = dHATODeg + dHATORes - dDeviation;
if ( !dNearestHATODeg )
return 1;
int iResult
if (dNearestHATODeg > 0)
iResult = (int)( ( m_dHATOEndDeg + dNearestHATODeg ) / dHATORes );
dNearestHATODeg = dHATODegProjected + dHATORes - dDeviation;
if( dNearestHATODeg == 0.0f )
return 0;
int iResult;
if( dNearestHATODeg > 0 )
iResult = ( int ) ( ( m_dHATOEndDeg + dNearestHATODeg ) / dHATORes );
else
iResult = (int)( ( m_dHATOEndDeg + dNearestHATODeg ) / dHATORes ) + 1;
iResult = ( int ) ( ( m_dHATOEndDeg + dNearestHATODeg ) / dHATORes ) + 1;
return 2 * iResult + 1; // odd! index
return 2 * iResult; // odd! index
}
int CVADirectivityDAFFHATOHRIR::GetHATOChannelIndexRight( const double dHATODeg ) const
......@@ -215,13 +217,15 @@ void CVADirectivityDAFFHATOHRIR::GetHRIRByIndexAndHATO( ITASampleFrame* psfDest,
if( psfDest->channels() > m_pReader->getProperties()->getNumberOfChannels() )
VA_EXCEPT1( std::string( "CVADirectivityDAFFHATOHRIR::GetHRIRByIndex - Target SampleFrame contains more channels than HRIR database" ) );
int iResult;
const int iHATOChannelIndexL = GetHATOChannelIndexLeft( dHATODeg );
int iResult = -1;
iResult = m_pContent->getFilterCoeffs( iIndex, GetHATOChannelIndexLeft( dHATODeg ), ( *psfDest )[ 0 ].data() );
iResult = m_pContent->getFilterCoeffs( iIndex, iHATOChannelIndexL, ( *psfDest )[ 0 ].data() );
if( iResult != DAFF_NO_ERROR )
VA_EXCEPT1( DAFFUtils::StrError( iResult ) );
iResult = m_pContent->getFilterCoeffs( iIndex, GetHATOChannelIndexRight( dHATODeg ), ( *psfDest )[ 1 ].data() );
const int iHATOChannelIndexR = GetHATOChannelIndexRight( dHATODeg );
iResult = m_pContent->getFilterCoeffs( iIndex, iHATOChannelIndexR, ( *psfDest )[ 1 ].data() );
if( iResult != DAFF_NO_ERROR )
VA_EXCEPT1( DAFFUtils::StrError( iResult ) );
......
......@@ -12,42 +12,43 @@ IVAInterface* core = NULL;
void TestHATO()
{
// Load input data
string sFileSignalID = core->CreateSignalSourceBufferFromFile( "$(DemoSound)" );
core->SetSignalSourceBufferPlaybackAction( sFileSignalID, IVAInterface::VA_PLAYBACK_ACTION_PLAY );
core->SetSignalSourceBufferLooping( sFileSignalID, true );
int iHATOHRTFID = core->CreateDirectivityFromFile( "$(DefaultHRIR)" );
//int iHATOHRTFID = core->CreateDirectivityFromFile( "Fabian_HATO.v17.ir.daff" );
// Load directivity / HATO-compatible HRTF
//int iHATOHRTFID = core->CreateDirectivityFromFile( "$(DefaultHRIR)" );
int iHATOHRTFID = core->CreateDirectivityFromFile( "FABIAN_HATO_5x5x5_256_44100Hz.v17.ir.daff" );
// Set up scene
int iSourceID = core->CreateSoundSource( "Source" );
core->SetSoundSourcePose( iSourceID, VAVec3( 0, 1.7, -3 ), VAQuat( 0, 0, 0, 1 ) );
core->SetSoundSourceSignalSource( iSourceID, sFileSignalID );
int iListenerID = core->CreateSoundReceiver( "Listener with HATO HRTF" );
core->SetSoundReceiverPosition( iListenerID, VAVec3( 0, 1.7, 0 ) );
core->SetActiveSoundReceiver( iListenerID );
core->SetSoundReceiverDirectivity( iListenerID, iHATOHRTFID );
int iSourceID = core->CreateSoundSource( "Source" );
core->SetSoundSourcePosition( iSourceID, VAVec3( 3, 1.7, 0 ) ); // from right direction on horizontal plane
// Load input data & start playback
string sFileSignalID = core->CreateSignalSourceBufferFromFile( "$(DemoSound)" );
core->SetSignalSourceBufferPlaybackAction( sFileSignalID, IVAInterface::VA_PLAYBACK_ACTION_PLAY );
core->SetSignalSourceBufferLooping( sFileSignalID, true );
core->SetSoundSourceSignalSource( iSourceID, sFileSignalID );
// Rotate head (above torso)
for( float fAngleDeg=-40.0f; fAngleDeg < 40.0f; fAngleDeg+=0.5f )
for( float fAngleDeg = -60.0f; fAngleDeg <= 60.0f; fAngleDeg += 5.0f )
{
VistaTimeUtils::Sleep( 20 ); // ~20ms timeout
VistaTimeUtils::Sleep( 0.5e3 ); // timeout
cout << "HATO angle is now " << fAngleDeg << " degree" << endl;
// @todo: quaternions verstehen und entsprechend rotation der HAT orientierung setzen ... ab hier steht potenzieller quatsch!
const double dAngleQuaternionValue = sin( fAngleDeg / 180.0f * 2.0f * ITAConstants::PI_D );
// Set pose for rendering modules
core->SetSoundReceiverOrientation( iListenerID, VAQuat( 0, 1, 0, dAngleQuaternionValue ) );
core->SetSoundReceiverHeadAboveTorsoOrientation( iListenerID, VAQuat( 0, 1, 0, -dAngleQuaternionValue ) );
core->SetSoundReceiverOrientation( iListenerID, VAQuat( 0, 1, 0, 0 ) );
core->SetSoundReceiverHeadAboveTorsoOrientation( iListenerID, VAQuat( 0, 1, 0, dAngleQuaternionValue ) );
// Set pose for reproduction modules
core->SetSoundReceiverRealWorldPose( iListenerID, VAVec3( 0, 1.7, 0 ), VAQuat( 0, 1, 0, 0 ) );
core->SetSoundReceiverRealWorldHeadAboveTorsoOrientation( iListenerID, VAQuat( 0, 1, 0, dAngleQuaternionValue ) );
}
}
}
int main()
......@@ -56,10 +57,10 @@ int main()
{
core = VACore::CreateCoreInstance( "../conf/VACore.ini" );
core->Initialize();
core->AddSearchPath( "../data" );
TestHATO();
core->Finalize();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment