ITANCTC.h 10.4 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1
/*
2
3
4
5
 * ----------------------------------------------------------------
 *
 *		ITA core libs
 *		(c) Copyright Institute of Technical Acoustics (ITA)
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
6
 *		RWTH Aachen University, Germany, 2015-2020
7
8
9
10
11
12
13
14
15
16
17
 *
 * ----------------------------------------------------------------
 *				    ____  __________  _______
 *				   //  / //__   ___/ //  _   |
 *				  //  /    //  /    //  /_|  |
 *				 //  /    //  /    //  ___   |
 *				//__/    //__/    //__/   |__|
 *
 * ----------------------------------------------------------------
 *
 */
Jonas Stienen's avatar
Jonas Stienen committed
18
19
20
21
22
23

#ifndef INCLUDE_WATCHER_ITA_N_CTC
#define INCLUDE_WATCHER_ITA_N_CTC

#include <ITACTCDefinitions.h>

24
#include <atomic>
Jonas Stienen's avatar
Jonas Stienen committed
25
26
27
28
29
#include <string>
#include <vector>

#include <ITAFFT.h>
#include <ITASampleFrame.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
30
#include <ITAStopWatch.h>
Jonas Stienen's avatar
Jonas Stienen committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <ITAHDFTSpectra.h>

#include <VistaBase/VistaVector3D.h>
#include <VistaMath/VistaGeometries.h>
//#include <VistaBase/VistaQuaternion.h>

class ITANCTCStreamFilter;
class DAFFContentIR;
class DAFFContentDFT;
class ITADatasource;

//! ITANCTC - Crosstalk-Cancellation framework
/**
  *
  * See dissertation of Bruno Masiero
  *
  * non-reentrant
  *
  * Crosstalk-Cancellation-Engine for arbitrary loudspeaker
  *					configurations using pseudo-inverse matrix solution with
  *					all channels active
52
  *
Jonas Stienen's avatar
Jonas Stienen committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  */
class ITA_CTC_API ITANCTC
{
public:

	//! CTC filter algorithms
	enum CTCFilterAlgorithms
	{
		CTC_REGULARIZED = 0, //!< Regularized algorithm
		CTC_WIENER_REG,		 //!< Regularized Wiener algorithm
		CTC_WIENER_REG_MIN,	 //!< Regularized Wiener algorithm with minimum phase filter
	};

	//! Data class that encapsules the pose of an object
	/**
	  * The pose of an object such as a loudspeaker or head
	  * stores the position as well as orientation. While
	  * view and up vectors are used to determine the orientation
	  * of the object, they can also be set in yaw, pitch and
	  * roll convention.
	  */
	class ITA_CTC_API Pose
	{
	public:
		inline Pose() {};

		VistaVector3D vPos;			//!< Position vector
		//VistaQuaternion qOrient;	//!< Orientation
		VistaVector3D vView;		//!< View direction (OpenGL convention)
		VistaVector3D vUp;			//!< Up direction (OpenGL convention)

		Pose& operator=( const Pose& );

		//! Set the orientation using yaw-pitch-roll (YPR) convention [degrees]
		/**
		  * \note All angles in degrees [°]
		  */
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
90
		void SetOrientationYPRdeg( const float fYaw, const float fPitch, const float fRoll );
Jonas Stienen's avatar
Jonas Stienen committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

		//! Get YPR angles
		void GetOrientationYPRdeg( float& fYaw, float& fPitch, float& fRoll ) const;
	};


	//! NCTC configuration data class
	/**
	  * This static configuration data has to be passed
	  * for each instance if the CircularNCTC class. Changes
	  * cannot be made afterwards.
	  * For dynamic parameters like Beta oder Delay have a look at
	  * the corresponding setters/getters
	  *
	  */
	class ITA_CTC_API Config
	{
	public:

110
111
112
113
		enum
		{
			OPTIMIZATION_NONE = 0, //!< No optimization in filter design
		};
Jonas Stienen's avatar
Jonas Stienen committed
114

115
116
		Config();

Jonas Stienen's avatar
Jonas Stienen committed
117
118
		int N;					//!< Number of loudspeakers
		int iCTCFilterLength;	//!< CTC filter taps, i.e. 4096
119
120
		float fSampleRate;		//!< Sampling rate
		float fSpeedOfSound;	//!< Speed of sound, m/s
121
		int iOptimization;		//!< Optimization algorithm (future work, see features/room_compensation)
122
123
		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)
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
124
		float fRegularizationFactor; //!< Regularization factor (beta)
Jonas Stienen's avatar
Jonas Stienen committed
125
126
127
128

		class ITA_CTC_API Loudspeaker
		{
		public:
129
130
			enum
			{
131
132
133
				SIDE_NOT_SPECIFIED = 0, //!@ Side of the loudspeaker not specified
				LEFT_SIDE = 1,          //!@ Loudspeaker is left from listener viewpoint
				RIGHT_SIDE = 2,         //!@ Loudspeaker is right from listener viewpoint
134
			};
Jonas Stienen's avatar
Jonas Stienen committed
135
136
137
138
			Loudspeaker();
			Loudspeaker( const Pose& oStaticPose );
			Pose oPose;							//!< Pose of loudspeaker
			const DAFFContentDFT* pDirectivity;	//!< Directivity data
139
			int iSide;
Jonas Stienen's avatar
Jonas Stienen committed
140
141
142
143
144
145
146
		};
		std::vector< Loudspeaker > voLoudspeaker; //!< Loudspeaker of this setup

	};

	//! Constructor
	/**
147
148
	  * 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
Jonas Stienen's avatar
Jonas Stienen committed
149
150
151
	  * through the configuration's SelectedSpeakers list. The configuration may have more
	  * loudspeakers defined than are selected in the end.
	  *
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
152
	  * @note Throws ITAException errors
Jonas Stienen's avatar
Jonas Stienen committed
153
	  *
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
154
	  * @param[in] oNCTCConfig The configuration, see @Config
Jonas Stienen's avatar
Jonas Stienen committed
155
156
157
158
159
160
161
	  *
	  */
	ITANCTC( const Config& oNCTCConfig );

	//! Destructor
	~ITANCTC();

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
162
	//! Get the number of loudspeakers/channels for this CTC engine
Jonas Stienen's avatar
Jonas Stienen committed
163
	/**
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
164
	  * @return Number of channels (N)
Jonas Stienen's avatar
Jonas Stienen committed
165
166
	  *
	  */
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
167
	int GetNumChannels() const;
Jonas Stienen's avatar
Jonas Stienen committed
168
169
170
171
172

	//! Configuration getter
	/**
	  * \return Static configuration parameters
	  */
173

Jonas Stienen's avatar
Jonas Stienen committed
174
175
	const Config& GetConfig() const;

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
176
	//! Get regularization factor (beta)
Jonas Stienen's avatar
Jonas Stienen committed
177
	/**
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
178
179
180
	  * @return Regularization factor
	  */
	float GetRegularizationFactor() const;
Jonas Stienen's avatar
Jonas Stienen committed
181

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
182
	//! Set regularization factor
Jonas Stienen's avatar
Jonas Stienen committed
183
	/**
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
184
185
186
	  * @param fRegularizationFator Set the regularization factor (beta)
	  */
	void SetRegularizationFactor( const float fRegularizationFator );
Jonas Stienen's avatar
Jonas Stienen committed
187

188
	//! Get cross-talk cancellation factor
189
190
191
	/**
	* \return Factor [0..1]
	*/
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
192
	float GetCrossTalkCancellationFactor() const;
193

194
	//! Set cross-talk cancellation factor
195
196
197
	/**
	* \param fFactor number between [0..1] (none: 0, max range = 1.0)
	*/
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
198
	void SetCrossTalkCancellationFactor( const float fFactor );
199
200
201
202
203

	//! Get cross-talk cancellation factor
	/**
	* \return Factor [0..1]
	*/
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
204
	float GetWaveIncidenceAngleCompensation() const;
205
206
207
208
209

	//! Set cross-talk cancellation factor
	/**
	* \param fFactor number between [0..1] (none: 0, max range = 1.0)
	*/
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
210
	void SetWaveIncidenceAngleCompensationFactor( const float fFactor );
211

Jonas Stienen's avatar
Jonas Stienen committed
212
213
214
215
	//! Get additional delay parameter
	/**
	  * \return Delay in seconds
	  */
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
216
	std::vector< float > GetDelayTime() const;
Jonas Stienen's avatar
Jonas Stienen committed
217

218
	//! Set additional delay parameter in seconds (affects all channels)
Jonas Stienen's avatar
Jonas Stienen committed
219
	/**
220
221
222
	  * The default value is half of the filter length.
	  *
	  * @note Will overwrite existing individual values.
223
224
225
	  *
	  * @param fDelayTime Set the time delay (all channels)
	  */
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
226
	void SetDelayTime( const float fDelayTime );
227
228
229
230
231
232

	//! 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.
	  *
233
234
	  * The default value is half of the filter length.
	  *
235
	  * \param vfDelayTime Set the time delay (each channel/loudspeaker individually)
Jonas Stienen's avatar
Jonas Stienen committed
236
	  */
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
237
	void SetDelayTime( const std::vector< float >& vfDelayTime );
238

Jonas Stienen's avatar
Jonas Stienen committed
239
240
241
242
	//! Sets the optimization
	/**
	  * Optimization setter, i.e. early reflection compensation for aixCAVE (see enum of Config)
	  */
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
243
	void SetOptimization( const int iOptimization );
Jonas Stienen's avatar
Jonas Stienen committed
244
245
246
247
248
249
250
251
252
253
254
255
256

	//! Optimization getter
	/**
	  * Optimization getter, i.e. early reflection compensation for aixCAVE (see enum of Config)
	  */
	int GetOptimization() const;

	//! Get loudspeaker pose
	/**
	  * \param	iLoudspeakerID Identifier of loudspeaker (begins with 0, max N-1)
	  * \return	Returns the pose of a loudspeaker
	  */

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
257
	const Pose& GetLoudspeakerPose( const int iLoudspeakerID ) const;
Jonas Stienen's avatar
Jonas Stienen committed
258
259
260
261
262
263
264

	//! Set HRIR dataset
	/**
	  * \param pHRIRDatabase The DAFF impulse response file with the head-related information
	  *
	  */
	void SetHRIR( const DAFFContentIR* pHRIR );
265

Jonas Stienen's avatar
Jonas Stienen committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
	//! Update the head position and orientation (combination = pose)
	/**
	  * Use this method to update the head pose (position and/or orientation). This is
	  * usually data that your tracking device provides. The CircularNCTC will then update
	  * for the new sweet spot.
	  *
	  * \param oHead	Pose of head (from tracking device)
	  */
	void UpdateHeadPose( const Pose& oHead );

	//! Returns the pointer to the currently used HRIR dataset
	/**
	  * \important	Not thread safe
	  */
280
	bool GetHRTF( std::vector< ITABase::CHDFTSpectra* >& vpHRTF ) const;
Jonas Stienen's avatar
Jonas Stienen committed
281
282
283
284
285
286

	//! Returns the currently used head pose
	/**
	  * \important	Not thread safe
	  */
	Pose GetHeadPose() const;
287
288
289
290
291
292
293

	//! Returns the minimum distance of head to all loudspeakers
	/**
	  *
	  */
	float GetMinimumDistanceHead2LS() const;

Jonas Stienen's avatar
Jonas Stienen committed
294
295
	//! Calculate the CTC filters
	/**
296
297
298
299
300
	  * 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
Jonas Stienen's avatar
Jonas Stienen committed
301
	  */
302
	void CalculateFilter( std::vector< ITABase::CHDFTSpectra* >& vpSpectra ) const;
Jonas Stienen's avatar
Jonas Stienen committed
303
304

	//! Calculate the Wiener-Hopf factorization
305
	void WienerHopfFactorization( const ITABase::CHDFTSpectrum* voSpecIn, ITABase::CHDFTSpectrum* voSpecOutPlus, ITABase::CHDFTSpectrum* voSpecOutMinus );
Jonas Stienen's avatar
Jonas Stienen committed
306
307
308
309
310
311

protected:

private:
	const Config m_oConfig;			//!< CTC Configuration

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
312
313
314
315
316
	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)
Jonas Stienen's avatar
Jonas Stienen committed
317
	const DAFFContentIR* m_pHRIR;	//!< HRIR dataset pointer
318

Jonas Stienen's avatar
Jonas Stienen committed
319
320
	Pose m_oHeadPose;				//!< Current head Pose data

321
322
	mutable ITAFFT m_fft, m_ifft;			//!< Internal FFT and IFFT transformations
	mutable ITASampleFrame m_sfCTC_temp;	//!< Internal CTC helper
Jonas Stienen's avatar
Jonas Stienen committed
323

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
324
	std::vector< float > m_vfWeights;				//!< Diagonal values for the weighting matrix (W or Z), only non-zero entries allowed
325
326
327
328
	std::vector< ITABase::CHDFTSpectra* > m_vpHRTFs;		//!< N-dim vector with two-channel HRTF sets for each LS direction
	std::vector< ITABase::CHDFTSpectra* > m_vpHelper2x2;	//!< Two-by-two helper matrix
	ITABase::CHDFTSpectrum* t;		//!< Helper
	ITABase::CHDFTSpectrum* det;	//!< Helper
329

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
330
	int GetLoudspeakerSide( const int ) const;
331

Jonas Stienen's avatar
Jonas Stienen committed
332
333
	//! Adds a HRIR into the target filter
	/**
334
335
336
337
338
	* @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
	*
	*/
339
	void AddHRIR( const Pose& oLoudspeakerPose, ITASampleFrame& sfTargetIR, bool& bOutOfRange, const double dGain = 1.0f, const int iDistanceCompensationSamples = 0 ) const;
Jonas Stienen's avatar
Jonas Stienen committed
340
341
342
343
344

	friend class ITACTCStreamFilter;
};

#endif // INCLUDE_WATCHER_ITA_N_CTC