......@@ -50,7 +50,7 @@ class ITADatasource;
* Crosstalk-Cancellation-Engine for arbitrary loudspeaker
* configurations using pseudo-inverse matrix solution with
* all channels active
*
*
*/
class ITA_CTC_API ITANCTC
{
......@@ -88,7 +88,7 @@ public:
/**
* \note All angles in degrees [°]
*/
void SetOrientationYPRdeg( double fYaw, double fPitch, double fRoll );
void SetOrientationYPRdeg( const float fYaw, const float fPitch, const float fRoll );
//! Get YPR angles
void GetOrientationYPRdeg( float& fYaw, float& fPitch, float& fRoll ) const;
......@@ -117,11 +117,12 @@ public:
int N; //!< Number of loudspeakers
int iCTCFilterLength; //!< CTC filter taps, i.e. 4096
double dSampleRate; //!< Sampling rate
float fSampleRate; //!< Sampling rate
float fSpeedOfSound; //!< Speed of sound, m/s
int iOptimization; //!< Optimization algorithm (future work, see features/room_compensation)
float fCrossTalkCancellationFactor; //!< Factor for cross-talk cancellation (none = 0.0, full = 1.0)
float fWaveIncidenceAngleCompensationFactor; //!< Factor for cross-talk cancellation (none = 0.0, full = 1.0)
float fRegularizationFactor; //!< Regularization factor (beta)
class ITA_CTC_API Loudspeaker
{
......@@ -144,14 +145,14 @@ public:
//! Constructor
/**
* Creates the NCTC module for N selected loudspeakers using the poses (position & orientation)
* given by the specified configuration file. The number of loudspeakers is defined
* Creates the NCTC module for N selected loudspeakers using the poses (position & orientation)
* given by the specified configuration file. The number of loudspeakers is defined
* through the configuration's SelectedSpeakers list. The configuration may have more
* loudspeakers defined than are selected in the end.
*
* \note Throws ITAException errors
* @note Throws ITAException errors
*
* \param oNCTCConfig The configuration, see \Config
* @param[in] oNCTCConfig The configuration, see @Config
*
*/
ITANCTC( const Config& oNCTCConfig );
......@@ -159,12 +160,12 @@ public:
//! Destructor
~ITANCTC();
//! Get the number of loudspeaker for this CTC enginge
//! Get the number of loudspeakers/channels for this CTC engine
/**
* \return number of channels (N)
* @return Number of channels (N)
*
*/
int GetN() const;
int GetNumChannels() const;
//! Configuration getter
/**
......@@ -173,74 +174,74 @@ public:
const Config& GetConfig() const;
//! Get beta parameter
//! Get regularization factor (beta)
/**
* \return Beta parameter
*/
float GetBeta();
* @return Regularization factor
*/
float GetRegularizationFactor() const;
//! Set beta parameter
//! Set regularization factor
/**
* \param fBeta Set the beta regularization parameter
*/
void SetBeta( float fBeta );
* @param fRegularizationFator Set the regularization factor (beta)
*/
void SetRegularizationFactor( const float fRegularizationFator );
//! Get cross-talk cancellation factor
/**
* \return Factor [0..1]
*/
float GetCrossTalkCancellationFactor();
float GetCrossTalkCancellationFactor() const;
//! Set cross-talk cancellation factor
/**
* \param fFactor number between [0..1] (none: 0, max range = 1.0)
*/
void SetCrossTalkCancellationFactor( float fFactor );
void SetCrossTalkCancellationFactor( const float fFactor );
//! Get cross-talk cancellation factor
/**
* \return Factor [0..1]
*/
float GetWaveIncidenceAngleCompensation();
float GetWaveIncidenceAngleCompensation() const;
//! Set cross-talk cancellation factor
/**
* \param fFactor number between [0..1] (none: 0, max range = 1.0)
*/
void SetWaveIncidenceAngleCompensationFactor( float fFactor );
void SetWaveIncidenceAngleCompensationFactor( const float fFactor );
//! Get additional delay parameter
/**
* \return Delay in seconds
*/
std::vector< float > GetDelayTime();
std::vector< float > GetDelayTime() const;
//! Set additional delay parameter in seconds (affects all channels)
/**
* The default value is half of the filter length.
*
* @note Will overwrite existing individual values.
* The default value is half of the filter length.
*
* @note Will overwrite existing individual values.
*
* @param fDelayTime Set the time delay (all channels)
*/
void SetDelayTime( float fDelayTime );
void SetDelayTime( const float fDelayTime );
//! Set delay parameter in seconds for each loudspeaker channel individually
/**
* The CTC filter set for each channel (loudspeaker) will be delayd by given time. This is
* helpful to overcome latency issues with different types of loudspeakers.
*
* The default value is half of the filter length.
*
* The default value is half of the filter length.
*
* \param vfDelayTime Set the time delay (each channel/loudspeaker individually)
*/
void SetDelayTime( std::vector< float > vfDelayTime );
void SetDelayTime( const std::vector< float >& vfDelayTime );
//! Sets the optimization
/**
* Optimization setter, i.e. early reflection compensation for aixCAVE (see enum of Config)
*/
void SetOptimization( int iOptimization );
void SetOptimization( const int iOptimization );
//! Optimization getter
/**
......@@ -254,7 +255,7 @@ public:
* \return Returns the pose of a loudspeaker
*/
const Pose& GetLoudspeakerPose( int iLoudspeakerID ) const;
const Pose& GetLoudspeakerPose( const int iLoudspeakerID ) const;
//! Set HRIR dataset
/**
......@@ -262,7 +263,7 @@ public:
*
*/
void SetHRIR( const DAFFContentIR* pHRIR );
//! Update the head position and orientation (combination = pose)
/**
* Use this method to update the head pose (position and/or orientation). This is
......@@ -284,50 +285,59 @@ public:
* \important Not thread safe
*/
Pose GetHeadPose() const;
//! Returns the minimum distance of head to all loudspeakers
/**
*
*/
float GetMinimumDistanceHead2LS() const;
//! Calculate the CTC filters
/**
* Starts calculation
* \param vpSpectra vector of two-channel CTC filter spectra for each loudspeaker (call-by-ref), will update filter in vector if possible
* \return True, if calculation was possible
* Designs CTC filters
*
* @param[out] vpSpectra Target vector of two-channel CTC filter spectra for each loudspeaker (call-by-ref)
*
* @note Will raise ITAException on error
*/
bool CalculateFilter( std::vector< ITAHDFTSpectra* >& vpSpectra );
void CalculateFilter( std::vector< ITAHDFTSpectra* >& vpSpectra ) const;
//! Calculate the Wiener-Hopf factorization
void WienerHopfFactorization( ITAHDFTSpectrum* voSpecIn, ITAHDFTSpectrum* voSpecOutPlus, ITAHDFTSpectrum* voSpecOutMinus );
void WienerHopfFactorization( const ITAHDFTSpectrum* voSpecIn, ITAHDFTSpectrum* voSpecOutPlus, ITAHDFTSpectrum* voSpecOutMinus );
protected:
private:
const Config m_oConfig; //!< CTC Configuration
std::atomic< float > m_fBeta; //!< Beta parameter (regularization)
std::vector< float > m_vfDelayTime; //!< Add a delay [seconds] to the resulting CTC filter (individual channels)
std::atomic <int > m_iOptimization; //!< Optimization (see Config enum)
std::atomic< float > m_fCrossTalkCancellationFactor; //!< Factor for cross-talk cancellation (none = 0.0, full = 1.0)
std::atomic< float > m_fWaveIncidenceAngleCompensationFactor; //!< Factor for cross-talk cancellation (none = 0.0, full = 1.0)
mutable std::atomic< float > m_fRegularizationFactor; //!< Beta parameter (regularization)
mutable std::vector< float > m_vfDelayTime; //!< Add a delay [seconds] to the resulting CTC filter (individual channels)
std::atomic< int > m_iOptimization; //!< Optimization (see Config enum)
mutable std::atomic< float > m_fCrossTalkCancellationFactor; //!< Factor for cross-talk cancellation (none = 0.0, full = 1.0)
mutable std::atomic< float > m_fWaveIncidenceAngleCompensationFactor; //!< Factor for cross-talk cancellation (none = 0.0, full = 1.0)
const DAFFContentIR* m_pHRIR; //!< HRIR dataset pointer
Pose m_oHeadPose; //!< Current head Pose data
ITAFFT m_fft, m_ifft; //!< Internal FFT and IFFT transformations
ITASampleFrame m_sfCTC_temp; //!< Internal CTC helper
mutable ITAFFT m_fft, m_ifft; //!< Internal FFT and IFFT transformations
mutable ITASampleFrame m_sfCTC_temp; //!< Internal CTC helper
std::vector< double > m_vdWeights; //!< Diagonal values for the weighting matrix (W or Z), only non-zero entries allowed
std::vector< float > m_vfWeights; //!< Diagonal values for the weighting matrix (W or Z), only non-zero entries allowed
std::vector< ITAHDFTSpectra* > m_vpHRTFs; //!< N-dim vector with two-channel HRTF sets for each LS direction
std::vector< ITAHDFTSpectra* > m_vpHelper2x2; //!< Two-by-two helper matrix
ITAHDFTSpectrum* t; //!< Helper
ITAHDFTSpectrum* det; //!< Helper
int GetLoudspeakerSide(int);
int GetLoudspeakerSide( const int ) const;
//! Adds a HRIR into the target filter
/**
* @param oLoudspeakerPose Pose of loudspeaker (or virtual source)
* @param bOutOfRange Indicator if the HRIR data for the required position is out of range
* @param sfTargetIR Target impulse response, where the HRIR will be placed by mul-adding with given gain
*
* @return True, if samples from HRIR could be copied into target filter, false, if target filter is too short
*/
bool AddHRIR( const Pose& oLoudspeakerPose, ITASampleFrame& sfTargetIR, bool& bOutOfRange, double dGain = 1.0f ) const;
void AddHRIR( const Pose& oLoudspeakerPose, ITASampleFrame& sfTargetIR, bool& bOutOfRange, const double dGain = 1.0f, const int iDistanceCompensationSamples = 0 ) const;
friend class ITACTCStreamFilter;
};
......
......@@ -88,4 +88,4 @@ private:
std::vector< ITAUPConvolution* > m_vpConvolvers; //!< 2*N individual block convolver for each CTC filter, even number = left binaural signal
};
#endif // INCLUDE_WATCHER_ITA_N_CTC_STREAMING_FILTER
\ No newline at end of file
#endif // INCLUDE_WATCHER_ITA_N_CTC_STREAMING_FILTER
This diff is collapsed.
......@@ -99,7 +99,7 @@ void ITANCTCStreamFilter::ExchangeFilters( const std::vector< ITAHDFTSpectra* >&
// Left binaural signal
ITAUPConvolution* pConvolverL( m_vpConvolvers[iIdxLeft] );
ITAUPFilter* pNewFilterL = m_pFilterPool->RequestFilter();
sbSpectrum.write( oCTCFilterL.data(), sbSpectrum.length() );
sbSpectrum.write( oCTCFilterL.GetData(), sbSpectrum.length() );
fIn = sbSpectrum.data();
fOut = sbImpulseResponse.data();
ifft.execute( fIn, fOut );
......@@ -111,7 +111,7 @@ void ITANCTCStreamFilter::ExchangeFilters( const std::vector< ITAHDFTSpectra* >&
// Right binaural signal
ITAUPConvolution* pConvolverR( m_vpConvolvers[iIdxRight] );
ITAUPFilter* pNewFilterR = m_pFilterPool->RequestFilter();
sbSpectrum.write( oCTCFilterR.data(), sbSpectrum.length() );
sbSpectrum.write( oCTCFilterR.GetData(), sbSpectrum.length() );
fIn = sbSpectrum.data();
fOut = sbImpulseResponse.data();
ifft.execute( fIn, fOut );
......
......@@ -18,7 +18,7 @@ int main( int, char** )
ITANCTC::Config oNCTCConfig;
oNCTCConfig.iCTCFilterLength = 10000;//2048;
oNCTCConfig.dSampleRate = 44.1e3;
oNCTCConfig.fSampleRate = 44.1e3;
oNCTCConfig.fSpeedOfSound = 344.0f;
//oNCTCConfig.iOptimization = ITANCTC::Config::OPTIMIZATION_NONE;
//oNCTCConfig.iOptimization = ITANCTC::Config::OPTIMIZATION_AIXCAVE_FULLY_CLOSED;
......@@ -90,15 +90,15 @@ int main( int, char** )
ITANCTC ctc( oNCTCConfig );
// Settings
ctc.SetBeta( 0.001f );
ctc.SetRegularizationFactor( 0.001f );
// Update and calculate filter
ctc.SetHRIR( pHRIR );
ctc.UpdateHeadPose( oHead );
std::vector< ITAHDFTSpectra* > vpCTCFilter;
for( int n=0; n<ctc.GetN(); n++ )
vpCTCFilter.push_back( new ITAHDFTSpectra( oNCTCConfig.dSampleRate, 2, oNCTCConfig.iCTCFilterLength+1, true ) );
for( int n=0; n<ctc.GetNumChannels(); n++ )
vpCTCFilter.push_back( new ITAHDFTSpectra( oNCTCConfig.fSampleRate, 2, oNCTCConfig.iCTCFilterLength+1, true ) );
try
{
......@@ -109,7 +109,7 @@ int main( int, char** )
std::cout << e << std::endl;
}
for( int i=0; i<ctc.GetN(); i++ )
for( int i=0; i<ctc.GetNumChannels(); i++ )
ITAFFTUtils::Export( vpCTCFilter[i], "CTCFilter_" + IntToString( i ) );
ITAStopWatch sw;
......@@ -133,7 +133,7 @@ int main( int, char** )
// Export resulting filter set to WAV file
for( int n=0; n<ctc.GetN(); n++ )
for( int n=0; n<ctc.GetNumChannels(); n++ )
{
ITAFFTUtils::Export( vpCTCFilter[ n ], "CTCFilter_LS" + IntToString( int( n + 1 ) ) );
ITAFFTUtils::Export( vpHRTF[ n ], "HRTFs_LS" + IntToString( int( n + 1 ) ) );
......