Commit 14618eec authored by Dipl.-Ing. Jonas Stienen's avatar Dipl.-Ing. Jonas Stienen
Browse files

upd: feature for binaural renderer: additional static delay can be passed.

upd: fix in generic path renderer when sound source volume is anything else than 1. also added a channel-specific update routinge to load a filter for a dedicated channel.
upd: core config now reads input and output dum files with macro substitution
parent bb164ca7
......@@ -42,6 +42,7 @@
#include <VistaInterProcComm/Concurrency/VistaThreadEvent.h>
// STL includes
#include <algorithm>
#include <assert.h>
#include <fstream>
#include <iomanip>
......@@ -141,7 +142,7 @@ public:
};
void UpdateDir( bool bDIRAuraModeEnabled );
void UpdateMediumPropagation( double dSpeedOfSound );
void UpdateMediumPropagation( double dSpeedOfSound, double dAdditionalDelaySeconds = 0.0f );
double CalculateInverseDistanceDecrease() const;
void UpdateHRIR(const CVAListenerState::CVAAnthropometricParameter& );
......@@ -243,6 +244,7 @@ CVABinauralFreeFieldAudioRenderer::CVABinauralFreeFieldAudioRenderer( const CVAA
, m_bDumpListeners( false )
, m_dDumpListenersGain( 1.0 )
, m_iHRIRFilterLength( -1 )
, m_dAdditionalStaticDelaySeconds( 0.0f )
, m_oParams( oParams )
{
// read config
......@@ -302,6 +304,8 @@ void CVABinauralFreeFieldAudioRenderer::Init( const CVAStruct& oArgs )
conf.OptInteger( "HRIRFilterLength", m_iHRIRFilterLength, 256 );
conf.OptNumber( "AdditionalStaticDelaySeconds", m_dAdditionalStaticDelaySeconds, 0.0f );
// Motion model Listener
conf.OptInteger( "MotionModelNumHistoryKeys", m_oDefaultListenerConf.iMotionModelNumHistoryKeys, 1000 );
......@@ -674,7 +678,7 @@ void CVABinauralFreeFieldAudioRenderer::ProcessStream( const ITAStreamInfo* pStr
pPath->pVariableDelayLineChL->SetAlgorithm( !bDPEnabledCurrent ? m_iDefaultVDLSwitchingAlgorithm : CVAVariableDelayLine::SWITCH );
pPath->pVariableDelayLineChR->SetAlgorithm( !bDPEnabledCurrent ? m_iDefaultVDLSwitchingAlgorithm : CVAVariableDelayLine::SWITCH );
}
pPath->UpdateMediumPropagation( m_dSpeedOfSound );
pPath->UpdateMediumPropagation( m_dSpeedOfSound, m_dAdditionalStaticDelaySeconds );
// Spherical spreading loss
bool bSSLEnabledSource = ( pSourceState->GetAuralizationMode() & IVACore::VA_AURAMODE_SPREADING_LOSS ) > 0;
......@@ -715,8 +719,8 @@ void CVABinauralFreeFieldAudioRenderer::ProcessStream( const ITAStreamInfo* pStr
pPath->pThirdOctaveFilterBank->Process( psbInput->data(), ctxAudio.m_sbTempL.data() );
pPath->pVariableDelayLineChR->Process( &( ctxAudio.m_sbTempL ), &( ctxAudio.m_sbTempR ) );
pPath->pVariableDelayLineChL->Process( &( ctxAudio.m_sbTempL ), &( ctxAudio.m_sbTempL ) ); // inplace
pPath->pFIRConvolverChL->process( psbInput->data(), ( *pPath->pListener->psfOutput )[ 0 ].data(), DSMBCConvolver::OUTPUT_MIX );
pPath->pFIRConvolverChR->process( psbInput->data(), ( *pPath->pListener->psfOutput )[ 1 ].data(), DSMBCConvolver::OUTPUT_MIX );
pPath->pFIRConvolverChL->process( ctxAudio.m_sbTempL.data(), ( *pPath->pListener->psfOutput )[ 0 ].data(), DSMBCConvolver::OUTPUT_MIX );
pPath->pFIRConvolverChR->process( ctxAudio.m_sbTempR.data(), ( *pPath->pListener->psfOutput )[ 1 ].data(), DSMBCConvolver::OUTPUT_MIX );
spit++;
}
......@@ -1193,11 +1197,12 @@ void CVABFFSoundPath::UpdateDir( bool bDIRAuraModeEnabled )
return;
}
void CVABFFSoundPath::UpdateMediumPropagation( double dSpeedOfSound )
void CVABFFSoundPath::UpdateMediumPropagation( double dSpeedOfSound, double dAdditionalStaticDelaySeconds )
{
assert( dSpeedOfSound > 0 );
double dDelay = oRelations.dDistance / dSpeedOfSound;
double dDistanceDelay = oRelations.dDistance / dSpeedOfSound;
double dDelay = max( 0, dDistanceDelay + dAdditionalStaticDelaySeconds );
pVariableDelayLineChL->SetDelayTime( float( dDelay ) );
pVariableDelayLineChR->SetDelayTime( float( dDelay ) );
}
......@@ -1278,8 +1283,8 @@ void CVABFFSoundPath::UpdateHRIR(const CVAListenerState::CVAAnthropometricParame
float fAktDelayTimeChL=pVariableDelayLineChL->GetNewDelayTime();
float fAktDelayTimeChR=pVariableDelayLineChR->GetNewDelayTime();
float fITDDifference = 0;// 3.0 / 340.0*sinf( oRelations.dAzimuthL2S*ITAConstants::PI_F / 180.0 )*( oAnthroParameters.dHeadWidth / 2.0 - pHRIRDataNew->GetProperties()->oAnthroParams.dHeadWidth / 2.0 );
pVariableDelayLineChL->SetDelayTime(fAktDelayTimeChL-fITDDifference);
pVariableDelayLineChR->SetDelayTime(fAktDelayTimeChR+fITDDifference);
//pVariableDelayLineChL->SetDelayTime(fAktDelayTimeChL-fITDDifference);
//pVariableDelayLineChR->SetDelayTime(fAktDelayTimeChR+fITDDifference);
//oAnthroParameters.dHeadWidth;//Virtueller Hrer
//pHRIRDataNew->GetProperties()->oAntrhoParams.dHeadWidth;//Datenbank(Kunstkopf)
return;
......@@ -1289,7 +1294,19 @@ int CVABinauralFreeFieldAudioRenderer::CallObject( const CVAStruct& oArgs, CVASt
{
oReturn.Clear();
const CVAStructValue* pStruct;
if( ( pStruct = oArgs.GetValue( "AdditionalDelaySeconds" ) ) != nullptr )
{
if( pStruct->GetDatatype() != CVAStructValue::DOUBLE )
VA_EXCEPT2( INVALID_PARAMETER, "Additional delay must be a double" );
oReturn[ "CurrentAdditionalDelaySeconds" ] = m_dAdditionalStaticDelaySeconds;
m_dAdditionalStaticDelaySeconds = *pStruct;
oReturn[ "NewAdditionalDelaySeconds" ] = m_dAdditionalStaticDelaySeconds;
return 1;
}
if( ( pStruct = oArgs.GetValue( "DIFFRACTION" ) ) != nullptr )
{
if( pStruct->GetDatatype() != CVAStructValue::STRING )
......
......@@ -309,6 +309,7 @@ private:
int m_iHRIRFilterLength; //!< Length of the HRIR filter DSP module
int m_iDefaultVDLSwitchingAlgorithm;
double m_dAdditionalStaticDelaySeconds; //!< Additional delay in seconds for delay compensation
CVABFFListener::Config m_oDefaultListenerConf; //!< Default listener config for factory object creation
CVABFFSource::Config m_oDefaultSourceConf; //!< Default source config for factory object creation
......
......@@ -196,6 +196,9 @@ void CVAPTGenericPathAudioRenderer::Init( const CVAStruct& oArgs )
if( m_iIRFilterLengthSamples < 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "IR filter size must be positive" );
if( m_iFilterDelaySamples >= m_iIRFilterLengthSamples )
ITA_EXCEPT1( INVALID_PARAMETER, "IR filter delay samples must be smaller than IR filter length" );
return;
}
......@@ -637,12 +640,38 @@ void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int
UpdateGenericSoundPath( iListenerID, iSourceID, sfIR );
}
void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int iSourceID, int iChannelIndex, const std::string& sIRFilePath )
{
if( iChannelIndex >= m_iNumChannels || iChannelIndex < 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "Requested filter channel greater than output channels or smaller than 1, can not update." );
ITASampleFrame sfIR( sIRFilePath );
if( sfIR.channels() != 1 )
{
if( sfIR.channels() != m_iNumChannels )
{
VA_ERROR( "CVAPTGenericPathAudioRenderer", "Filter has mismatching and more than one channel. Don't know what to do - refusing this update." );
}
else
{
VA_WARN( "CVAPTGenericPathAudioRenderer", "Filter has more than one channel, updating only requested channel index." );
UpdateGenericSoundPath( iListenerID, iSourceID, iChannelIndex, sfIR[ iChannelIndex ] );
}
}
else
{
UpdateGenericSoundPath( iListenerID, iSourceID, iChannelIndex, sfIR[ 0 ] );
}
}
void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int iSourceID, ITASampleFrame& sfIR )
{
if( sfIR.length() > m_iIRFilterLengthSamples )
VA_WARN( "CVAPTGenericPathAudioRenderer", "Filter length for generic sound path too long, cropping." );
sfIR.CyclicShift( m_iFilterDelaySamples );
if( m_iFilterDelaySamples != 0 )
sfIR.CyclicShift( m_iFilterDelaySamples );
std::list< CVAPTGenericSoundPath* >::const_iterator spcit = m_lSoundPaths.begin();
while( spcit != m_lSoundPaths.end() )
......@@ -657,6 +686,7 @@ void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int
pFilter->zeros();
int iLength = (std::min)( m_iIRFilterLengthSamples, sfIR.length() );
pFilter->load( sfIR[n].data(), iLength );
pConvolver->exchangeFilter( pFilter );
pFilter->release();
}
......@@ -668,15 +698,16 @@ void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int
}
void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int iSourceID, int iChannel, ITASampleBuffer& sbIR )
void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int iSourceID, int iChannelIndex, ITASampleBuffer& sbIR )
{
if( iChannel >= m_iNumChannels )
if( iChannelIndex >= m_iNumChannels || iChannelIndex < 0 )
VA_EXCEPT2( INVALID_PARAMETER, "Requested filter channel index of generic sound path out of bounds" );
if( sbIR.length() > m_iIRFilterLengthSamples )
VA_WARN( "CVAPTGenericPathAudioRenderer", "Filter length for generic sound path channel too long, cropping." );
sbIR.CyclicShift( m_iFilterDelaySamples );
if( m_iFilterDelaySamples != 0 )
sbIR.CyclicShift( m_iFilterDelaySamples );
std::list< CVAPTGenericSoundPath* >::const_iterator spcit = m_lSoundPaths.begin();
while( spcit != m_lSoundPaths.end() )
......@@ -684,7 +715,7 @@ void CVAPTGenericPathAudioRenderer::UpdateGenericSoundPath( int iListenerID, int
CVAPTGenericSoundPath* pPath( *spcit++ );
if( pPath->pListener->pData->iID == iListenerID && pPath->pSource->pData->iID == iSourceID )
{
DSMBCConvolver* pConvolver( pPath->vpFIRConvolver[iChannel] );
DSMBCConvolver* pConvolver( pPath->vpFIRConvolver[iChannelIndex] );
DSMBCFilter* pFilter = pConvolver->requestFilter();
pFilter->zeros();
int iLength = (std::min)( m_iIRFilterLengthSamples, sbIR.length() );
......@@ -754,12 +785,12 @@ void CVAPTGenericPathAudioRenderer::HandleProcessStream( ITADatasourceRealizatio
CVASoundSourceDesc* pSourceData = pPath->pSource->pData;
ITASampleBuffer* psbInput = pSourceData->pSignalSourceInputBuf;
float fSoundSourceGain = float(pSourceState->GetVolume() );
psbInput->mul_scalar(fSoundSourceGain);
float fSoundSourceGain = float( pSourceState->GetVolume() );
for( int n=0; n < m_iNumChannels; n++ )
{
DSMBCConvolver* pConvolver = pPath->vpFIRConvolver[n];
pConvolver->setGain( fSoundSourceGain );
pConvolver->process( psbInput->data(), ( *pPath->pListener->psfOutput )[n].data(), DSMBCConvolver::OUTPUT_MIX );
}
......@@ -827,9 +858,10 @@ int CVAPTGenericPathAudioRenderer::CallObject( const CVAStruct& oArgs, CVAStruct
}
else if( oArgs.HasKey( "info" ) )
{
oReturn["numchannels"] = m_iNumChannels;
oReturn["irfilterlengthsamples"] = m_iIRFilterLengthSamples;
oReturn["numpaths"] = int( m_lSoundPaths.size() );
oReturn[ "numchannels" ] = m_iNumChannels;
oReturn[ "irfilterlengthsamples" ] = m_iIRFilterLengthSamples;
oReturn[ "numpaths" ] = int( m_lSoundPaths.size() );
oReturn[ "filterdelaysamples" ] = m_iFilterDelaySamples;
return 1;
}
else
......@@ -848,8 +880,18 @@ int CVAPTGenericPathAudioRenderer::CallObject( const CVAStruct& oArgs, CVAStruct
if( oArgs.HasKey( "filepath" ) )
{
const std::string& sFilePathRaw( oArgs[ "filepath" ] );
std::string sFilePath = m_pCore->SubstituteMacros( sFilePathRaw );
UpdateGenericSoundPath( iListenerID, iSourceID, sFilePath );
std::string sFilePath = m_pCore->FindFilePath( sFilePathRaw );
if( oArgs.HasKey( "channel" ) )
{
int iChannelNumber = oArgs[ "channel" ];
UpdateGenericSoundPath( iListenerID, iSourceID, iChannelNumber - 1, sFilePath );
}
else
{
UpdateGenericSoundPath( iListenerID, iSourceID, sFilePath );
}
std::stringstream ssVerboseText;
if( bVerbose )
......
......@@ -186,6 +186,7 @@ private:
void ResetInternalData();
void UpdateGenericSoundPath( int iListenerID, int iSourceID, const std::string& sIRFilePath );
void UpdateGenericSoundPath( int iListenerID, int iSourceID, int iChannel, const std::string& sIRFilePath );
void UpdateGenericSoundPath( int iListenerID, int iSourceID, ITASampleFrame& sfIR );
void UpdateGenericSoundPath( int iListenerID, int iSourceID, int iChannel, ITASampleBuffer& sbIR );
......
......@@ -111,8 +111,10 @@ void CVACoreConfig::Init( const CVAStruct& oData )
// --= Debug =--
conf.OptString("Debug/DumpDeviceInput", sDumpDeviceInputFilename);
conf.OptString("Debug/DumpFinalOutput", sDumpFinalOutputFilename);
conf.OptString( "Debug/DumpDeviceInput", sDumpDeviceInputFilename );
sDumpDeviceInputFilename = mMacros.SubstituteMacros( sDumpDeviceInputFilename );
conf.OptString( "Debug/DumpFinalOutput", sDumpFinalOutputFilename );
sDumpFinalOutputFilename = mMacros.SubstituteMacros( sDumpFinalOutputFilename );
// --= Substitute Macros =--
......
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