VABinauralFreefieldAudioRenderer.h 11.7 KB
Newer Older
Jonas Stienen's avatar
Jonas Stienen committed
1
/*
2
 *  --------------------------------------------------------------------------------------------
Jonas Stienen's avatar
Jonas Stienen committed
3
 *
4 5 6
 *    VVV        VVV A           Virtual Acoustics (VA) | http://www.virtualacoustics.org
 *     VVV      VVV AAA          Licensed under the Apache License, Version 2.0
 *      VVV    VVV   AAA
7
 *       VVV  VVV     AAA        Copyright 2015-2018
8 9
 *        VVVVVV       AAA       Institute of Technical Acoustics (ITA)
 *         VVVV         AAA      RWTH Aachen University
Jonas Stienen's avatar
Jonas Stienen committed
10
 *
11
 *  --------------------------------------------------------------------------------------------
Jonas Stienen's avatar
Jonas Stienen committed
12
 */
13

Jonas Stienen's avatar
Jonas Stienen committed
14

15 16
#ifndef IW_VACORE_BINAURALFREEFIELDAUDIORENDERER
#define IW_VACORE_BINAURALFREEFIELDAUDIORENDERER
Jonas Stienen's avatar
Jonas Stienen committed
17

18
#ifdef VACORE_WITH_RENDERER_BINAURAL_FREE_FIELD
Jonas Stienen's avatar
Jonas Stienen committed
19

20 21
#include <VA.h>

Jonas Stienen's avatar
Jonas Stienen committed
22 23 24 25 26 27 28 29 30 31
// VA includes
#include "../../../Motion/VAMotionModelBase.h"
#include "../../../Motion/VASharedMotionModel.h"
#include "../../VAAudioRenderer.h"
#include "../../VAAudioRendererRegistry.h"
#include "../../../Scene/VAScene.h"
#include "../../../VASourceListenerMetrics.h"
#include "../../../VACoreImpl.h"

// ITA includes
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
32 33
#include <ITABufferedAudioFileWriter.h>
#include <ITADataSourceRealization.h>
34
#include <ITAVariableDelayLine.h>
Jonas Stienen's avatar
Jonas Stienen committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
#include <ITASampleFrame.h>
#include <ITAStringUtils.h>

// 3rdParty includes
#include <tbb/concurrent_queue.h>

// STL Includes
#include <list>
#include <set>

// VA forwards
class CVASceneState;
class CVASceneStateDiff;
class CVASignalSourceManager;
class CVASoundSourceDesc;

// Internal forwards
class CVABFFSoundPath;
class CVABFFSoundPathFactory;

//! Binaural Freefield Audio Renderer
/**
  * The binaural freefield audio renderer implements sound propagation with
58
  * no propagation disturbance in the medium (for eample no reflecting surfaces).
Jonas Stienen's avatar
Jonas Stienen committed
59
  *
60
  * It accounts for
Jonas Stienen's avatar
Jonas Stienen committed
61 62 63 64 65 66 67 68
  *		- source directivity
  *		- medium propagation delay
  *		- medium absorption over distance
  *		- distance gain / 1-by-r law / spherical spreading attenuation
  *		- two channel binaural receiver directivity (HRTF)
  *		- Doppler shifts (source and listener movement in medium of finite speed of sound)
  *
  */
69
class CVABinauralFreeFieldAudioRenderer : public IVAAudioRenderer, public ITADatasourceRealization, public CVAObject
Jonas Stienen's avatar
Jonas Stienen committed
70 71 72 73 74 75 76 77 78 79 80 81
{
public:
	CVABinauralFreeFieldAudioRenderer( const CVAAudioRendererInitParams& oParams );
	virtual ~CVABinauralFreeFieldAudioRenderer();

	//! Handle a user requested reset
	/**
	  * This method resets the entire scene by removing all entities. The
	  * modules have to reset their internal state and return to a clean
	  * scene. This call should be blocking until reset is done.
	  */
	void Reset();
82

Jonas Stienen's avatar
Jonas Stienen committed
83 84 85 86
	//! Load a user requested scene
	/**
	  * This method loads a scene, usually a file path to geometry data.
	  */
87
	inline void LoadScene( const std::string& ) {};
88

Jonas Stienen's avatar
Jonas Stienen committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	//! Handle a scene state change
	/**
	  * This method updates the internal representation of the VA Scene
	  * by setting up or deleting the sound path entities as well as
	  * modifying existing ones that have changed their state, i.e.
	  * pose or dataset
	  */
	void UpdateScene( CVASceneState* pNewSceneState );

	//! Handle a state change in global auralisation mode
	/**
	  * This method updates internal settings for the global auralisation
	  * mode affecting the activation/deactivation of certain components
	  * of the sound path entities
	  */
	void UpdateGlobalAuralizationMode( int iGlobalAuralizationMode );
105

Jonas Stienen's avatar
Jonas Stienen committed
106 107 108 109 110 111 112 113 114 115 116 117 118 119
	//! Render output sample blocks
	/**
	  * This method renders the sound propagation based on the binaural approach
	  * by evaluating motion and events that are retarded in time, i.e. it switches
	  * filter parts and magnitudes of the HRIR or Directivity. It also considers
	  * the effective auralisation mode.
	  */
	void ProcessStream( const ITAStreamInfo* pStreamInfo );

	//! Returns the renderers output stream datasource
	ITADatasource* GetOutputDatasource();

	// --= Module interface =--

120
	CVAStruct CallObject( const CVAStruct& oArgs );
121
	void SetParameters( const CVAStruct& oParams );
122
	CVAStruct GetParameters( const CVAStruct& );
Jonas Stienen's avatar
Jonas Stienen committed
123

124
	void onStartDumpListeners( const std::string& sFilenameFormat );
Jonas Stienen's avatar
Jonas Stienen committed
125 126 127 128 129
	void onStopDumpListeners();

protected:

	//! Internal source representation
130
	class CVABFFSource : public CVAPoolObject
Jonas Stienen's avatar
Jonas Stienen committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144
	{
	public:
		class Config
		{
		public:
			bool bMotionModelLogInputEnabled;
			bool bMotionModelLogEstimatedEnabled;

			double dMotionModelWindowSize;
			double dMotionModelWindowDelay;

			int iMotionModelNumHistoryKeys;
		};

145
		inline CVABFFSource( const Config& oConf_ )
Jonas Stienen's avatar
Jonas Stienen committed
146 147 148 149 150 151 152 153 154 155 156 157 158
			: oConf( oConf_ )
		{};

		const Config oConf;
		CVASoundSourceDesc* pData;			//!< (Unversioned) Source description
		CVASharedMotionModel* pMotionModel;
		bool bDeleted;
		VAVec3 vPredPos;				//!< Estimated position
		VAVec3 vPredView;				//!< Estimated Orientation (View-Vektor)
		VAVec3 vPredUp;					//!< Estimated Orientation (Up-Vektor)
		bool bValidTrajectoryPresent;	//!< Estimation possible -> valid trajectory present

		//! Pool-Konstruktor
159
		inline void PreRequest()
Jonas Stienen's avatar
Jonas Stienen committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173
		{
			pData = nullptr;

			CVABasicMotionModel::Config oDefaultConfig;
			oDefaultConfig.bLogEstimatedOutputEnabled = oConf.bMotionModelLogEstimatedEnabled;;
			oDefaultConfig.bLogInputEnabled = oConf.bMotionModelLogInputEnabled;
			oDefaultConfig.dWindowDelay = oConf.dMotionModelWindowDelay;
			oDefaultConfig.dWindowSize = oConf.dMotionModelWindowSize;
			oDefaultConfig.iNumHistoryKeys = oConf.iMotionModelNumHistoryKeys;
			pMotionModel = new CVASharedMotionModel( new CVABasicMotionModel( oDefaultConfig ), true );

			bValidTrajectoryPresent = false;
		};

174
		inline void PreRelease()
Jonas Stienen's avatar
Jonas Stienen committed
175 176 177 178 179
		{
			delete pMotionModel;
			pMotionModel = nullptr;
		};

180 181 182
		inline double GetCreationTimestamp() const
		{
			return m_dCreationTimeStamp;
Jonas Stienen's avatar
Jonas Stienen committed
183 184 185 186 187 188 189 190
		};

	private:
		double m_dCreationTimeStamp;  //!< Date of creation within streaming context
	};


	//! Internal listener representation
191
	class CVABFFListener : public CVAPoolObject
Jonas Stienen's avatar
Jonas Stienen committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205
	{
	public:
		class Config
		{
		public:
			bool bMotionModelLogInputEnabled;
			bool bMotionModelLogEstimatedEnabled;

			double dMotionModelWindowSize;
			double dMotionModelWindowDelay;

			int iMotionModelNumHistoryKeys;
		};

206 207 208
		inline CVABFFListener( CVACoreImpl* pCore, const Config& oConf )
			: pCore( pCore )
			, oConf( oConf )
Jonas Stienen's avatar
Jonas Stienen committed
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
		{};

		CVACoreImpl* pCore;
		const Config oConf;

		CVAListenerDesc* pData;				//!< (Unversioned) Listener description
		CVASharedMotionModel* pMotionModel;
		bool bDeleted;
		VAVec3 vPredPos;				//!< Estimated position
		VAVec3 vPredView;				//!< Estimated Orientation (View-Vektor)
		VAVec3 vPredUp;					//!< Estimated Orientation (Up-Vektor)
		bool bValidTrajectoryPresent;	//!< Estimation possible -> valid trajectory present

		ITASampleFrame* psfOutput;			//!< Accumulated listener output signals
		ITAAudiofileWriter* pListenerOutputAudioFileWriter;	//!< File writer used for dumping the listener signals
224 225 226

		inline void PreRequest()
		{
Jonas Stienen's avatar
Jonas Stienen committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
			pData = nullptr;

			CVABasicMotionModel::Config oListenerMotionConfig;
			oListenerMotionConfig.bLogEstimatedOutputEnabled = oConf.bMotionModelLogEstimatedEnabled;
			oListenerMotionConfig.bLogInputEnabled = oConf.bMotionModelLogInputEnabled;
			oListenerMotionConfig.dWindowDelay = oConf.dMotionModelWindowDelay;
			oListenerMotionConfig.dWindowSize = oConf.dMotionModelWindowSize;
			oListenerMotionConfig.iNumHistoryKeys = oConf.iMotionModelNumHistoryKeys;
			pMotionModel = new CVASharedMotionModel( new CVABasicMotionModel( oListenerMotionConfig ), true );

			bValidTrajectoryPresent = false;

			pListenerOutputAudioFileWriter = nullptr;
			psfOutput = nullptr;
		};

243
		inline void PreRelease()
Jonas Stienen's avatar
Jonas Stienen committed
244 245 246 247 248 249 250 251
		{
			delete pMotionModel;
			pMotionModel = nullptr;
			delete psfOutput;

			FinalizeDump();
		};

252 253 254 255 256 257
		inline void InitDump( const std::string& sFilename )
		{
			std::string sOutput( sFilename );
			sOutput = SubstituteMacro( sOutput, "ListenerName", pData->sName );
			sOutput = SubstituteMacro( sOutput, "ListenerID", IntToString( pData->iID ) );

Jonas Stienen's avatar
Jonas Stienen committed
258
			ITAAudiofileProperties props;
259 260 261 262 263
			props.dSampleRate = pCore->GetCoreConfig()->oAudioDriverConfig.dSampleRate;
			props.eDomain = ITADomain::ITA_TIME_DOMAIN;
			props.eQuantization = ITAQuantization::ITA_FLOAT;
			props.iChannels = 2;
			props.iLength = 0;
264 265
			pListenerOutputAudioFileWriter = ITABufferedAudiofileWriter::create( sOutput, props );
		};
Jonas Stienen's avatar
Jonas Stienen committed
266

267
		inline void FinalizeDump()
Jonas Stienen's avatar
Jonas Stienen committed
268 269 270
		{
			delete pListenerOutputAudioFileWriter;
			pListenerOutputAudioFileWriter = nullptr;
271
		};
Jonas Stienen's avatar
Jonas Stienen committed
272 273 274 275 276 277 278 279 280 281 282 283
	};

private:

	const CVAAudioRendererInitParams m_oParams; //!< Create a const copy of the init params

	CVACoreImpl* m_pCore;					//!< Pointer to VACore

	CVASceneState* m_pCurSceneState;
	CVASceneState* m_pNewSceneState;

	int m_iCurGlobalAuralizationMode;
284

Jonas Stienen's avatar
Jonas Stienen committed
285 286 287 288 289 290 291 292 293 294 295 296 297
	IVAObjectPool* m_pSoundPathPool;
	CVABFFSoundPathFactory* m_pSoundPathFactory;
	std::list< CVABFFSoundPath* > m_lSoundPaths;	//!< List of sound paths in user context (VACore calls)	

	IVAObjectPool* m_pSourcePool;
	IVAObjectPool* m_pListenerPool;

	std::map< int, CVABFFSource* > m_mSources;	//!< Internal list of sources
	std::map< int, CVABFFListener* > m_mListeners;	//!< Internal list of listener

	bool m_bDumpListeners;
	double m_dDumpListenersGain;
	ITAAtomicInt m_iDumpListenersFlag;
298

Jonas Stienen's avatar
Jonas Stienen committed
299 300 301
	int m_iHRIRFilterLength;				//!< Length of the HRIR filter DSP module

	int m_iDefaultVDLSwitchingAlgorithm;
302
	double m_dAdditionalStaticDelaySeconds;        //!< Additional delay in seconds for delay compensation
Jonas Stienen's avatar
Jonas Stienen committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

	CVABFFListener::Config m_oDefaultListenerConf; //!< Default listener config for factory object creation
	CVABFFSource::Config m_oDefaultSourceConf; //!< Default source config for factory object creation

	class CVABFFUpdateMessage : public CVAPoolObject
	{
	public:
		std::list< CVABFFSource* > vNewSources;
		std::list< CVABFFSource* > vDelSources;
		std::list< CVABFFListener* > vNewListeners;
		std::list< CVABFFListener* > vDelListeners;
		std::list< CVABFFSoundPath* > vNewPaths;
		std::list< CVABFFSoundPath* > vDelPaths;

		void PreRequest()
		{
			vNewSources.clear();
			vDelSources.clear();
			vNewListeners.clear();
			vDelListeners.clear();
			vNewPaths.clear();
			vDelPaths.clear();
		}
	};

	IVAObjectPool* m_pUpdateMessagePool; // really necessary?
	CVABFFUpdateMessage* m_pUpdateMessage;

	//! Data in context of audio process
	struct
	{
		tbb::concurrent_queue< CVABFFUpdateMessage* > m_qpUpdateMessages;	//!< Update messages list
		std::list< CVABFFSoundPath* > m_lSoundPaths;	//!< List of sound paths
		std::list< CVABFFSource* > m_lSources;			//!< List of sources
337
		std::list< CVABFFListener* > m_lListeners;		//!< List of listeners
338 339
		ITASampleBuffer m_sbTempL;	//!< Temporally used buffer to store a block of samples during processing (left ear)
		ITASampleBuffer m_sbTempR;	//!< Temporally used buffer to store a block of samples during processing (right ear)
Jonas Stienen's avatar
Jonas Stienen committed
340 341 342 343 344 345
		ITAAtomicInt m_iResetFlag;	//!< Reset status flag: 0=normal_op, 1=reset_request, 2=reset_ack
		ITAAtomicInt m_iStatus;		//!< Current status flag: 0=stopped, 1=running
	} ctxAudio;

	void Init( const CVAStruct& oArgs );

346
	void ManageSoundPaths( const CVASceneState* pCurScene, const CVASceneState* pNewScene, const CVASceneStateDiff* pDiff );
Jonas Stienen's avatar
Jonas Stienen committed
347
	void UpdateSources();
348
	CVABFFListener* CreateListener( int iID, const CVAReceiverState* );
Jonas Stienen's avatar
Jonas Stienen committed
349 350 351 352 353
	void DeleteListener( int iID );
	CVABFFSource* CreateSource( int iID, const CVASoundSourceState* );
	void DeleteSource( int iID );
	CVABFFSoundPath* CreateSoundPath( CVABFFSource*, CVABFFListener* );
	void DeleteSoundPath( CVABFFSoundPath* );
354

Jonas Stienen's avatar
Jonas Stienen committed
355 356 357 358 359 360 361 362 363 364 365
	void UpdateTrajectories();
	void UpdateSoundPaths();

	void SampleTrajectoriesInternal( double dTime );

	void SyncInternalData();
	void ResetInternalData();

	friend class CVABFFSoundPath;
	friend class CVABFFListenerPoolFactory;
	friend class CVABFFSourcePoolFactory;
366 367

	//! Not for use, avoid C4512
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
368
	inline CVABinauralFreeFieldAudioRenderer operator=( const CVABinauralFreeFieldAudioRenderer & ) { VA_EXCEPT_NOT_IMPLEMENTED; };
Jonas Stienen's avatar
Jonas Stienen committed
369 370
};

371
#endif // ( VACORE_WITH_RENDERER_BINAURAL_FREE_FIELD
Jonas Stienen's avatar
Jonas Stienen committed
372

373
#endif // IW_VACORE_BINAURALFREEFIELDAUDIORENDERER