diff --git a/tests/AsioTests/CMakeLists.txt b/tests/AsioTests/CMakeLists.txt
index 84d328a0bb2090b820167e6cde40392769e1b486..99b49c8dbe57c900fe08b85d483155b3c2be3029 100644
--- a/tests/AsioTests/CMakeLists.txt
+++ b/tests/AsioTests/CMakeLists.txt
@@ -26,3 +26,12 @@ vista_install( NativeAsioThreadedMultiInstanceTest )
 vista_create_default_info_file( NativeAsioThreadedMultiInstanceTest )
 
 set_property( TARGET NativeAsioThreadedMultiInstanceTest PROPERTY FOLDER "ITACoreLibs/Tests/ITADataSources/Asio" )
+
+add_executable( ReciprocalDAADLatencyMeasurement ReciprocalDAADLatencyMeasurement.cpp )
+target_link_libraries( ReciprocalDAADLatencyMeasurement ${VISTA_USE_PACKAGE_LIBRARIES} )
+
+vista_configure_app( ReciprocalDAADLatencyMeasurement )
+vista_install( ReciprocalDAADLatencyMeasurement )
+vista_create_default_info_file( ReciprocalDAADLatencyMeasurement )
+
+set_property( TARGET ReciprocalDAADLatencyMeasurement PROPERTY FOLDER "ITACoreLibs/Tests/ITADataSources/Asio" )
diff --git a/tests/AsioTests/NativeAsioThreadedMultiInstanceTest.cpp b/tests/AsioTests/NativeAsioThreadedMultiInstanceTest.cpp
index 9f06baab90f203348093d7239f938b8007083d4c..79c365de6e2df80a77662d916f906c80dde5d8d5 100644
--- a/tests/AsioTests/NativeAsioThreadedMultiInstanceTest.cpp
+++ b/tests/AsioTests/NativeAsioThreadedMultiInstanceTest.cpp
@@ -28,22 +28,28 @@ public:
 	inline CThreadedASIO( const int iDriverIndex )
 		: m_iDriverIndex( iDriverIndex )
 	{
-		assert( iDriverIndex < g_oAsioDriverList.asioGetNumDev() && iDriverIndex > 0 );
+		ASIOError ae;
+
+		assert( m_iDriverIndex < g_oAsioDriverList.asioGetNumDev() && m_iDriverIndex >= 0 );
 		m_sDriverName.resize( 256 );
-		m_oDriver.asioGetDriverName( iDriverIndex, &m_sDriverName[ 0 ], int( m_sDriverName.size() ) );
+		m_oDriver.asioGetDriverName( m_iDriverIndex, &m_sDriverName[ 0 ], int( m_sDriverName.size() ) );
 		m_sDriverName = std::string( m_sDriverName.c_str() ); // Strip
-		cout << "New threaded ASIO instance with driver name: " << m_sDriverName << endl;
+
+		cout << "[" << m_sDriverName << "] Initializing ASIO from thread " << VistaThread::GetThreadIdentity() << endl;
+
+		VistaTimeUtils::Sleep( 1000 );
 
 		bool bLoadSuccess = m_oDriver.loadDriver( &m_sDriverName[ 0 ] );
+		assert( bLoadSuccess );
+
+		VistaTimeUtils::Sleep( 1000 );
 
 		ASIODriverInfo oDriverInfo;
 		oDriverInfo.asioVersion = 2;
-		assert( ASIOInit( &oDriverInfo ) == ASE_OK );
+		assert( ( ae = ASIOInit( &oDriverInfo ) ) == ASE_OK );
 
 		ASIOCallbacks oAsioCallback;
-		//long AsioMessages( long selector, long value, void*, double* )
-		
-		oAsioCallback.asioMessage = long( CThreadedASIO::* )( long, long, void*, double* );
+		oAsioCallback.asioMessage = &( CThreadedASIO::AsioMessages );
 		oAsioCallback.bufferSwitch = &( CThreadedASIO::AsioBufferSwitch );
 		oAsioCallback.bufferSwitchTimeInfo = &( CThreadedASIO::AsioBufferSwitchTimeInfo );
 		oAsioCallback.sampleRateDidChange = &( CThreadedASIO::AsioSampleRateChanged );
@@ -72,22 +78,15 @@ public:
 		assert( ASE_OK == ASIOCreateBuffers( &voBufferInfos.front(), 4, preferredSize, &oAsioCallback ) );
 
 		g_oRegistry[ VistaThread::GetThreadIdentity() ] = this;
-	};
 
-	inline void StartStreaming()
-	{
 		assert( ASE_OK == ASIOStart() );
+		cout << "[" << m_sDriverName << "] Started ASIO from thread " << VistaThread::GetThreadIdentity() << endl;
+		VistaTimeUtils::Sleep( 10000 );
+		assert( ASE_OK == ASIOStop() );
 	};
-
+	
 	inline void ThreadBody()
 	{
-		cout << "[" << m_sDriverName << "] Tic Toc" << endl;
-		VistaTimeUtils::Sleep( 1000 );
-	};
-
-	inline void StopStreaming()
-	{
-		assert( ASE_OK == ASIOStop() );
 	};
 
 	inline static ASIOTime* AsioBufferSwitchTimeInfo( ASIOTime *timeInfo, long index, ASIOBool processNow )
@@ -104,9 +103,10 @@ public:
 			timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
 
 		AsioBufferSwitchTimeInfo( &timeInfo, index, processNow );
-
-		long iThreadID = VistaThread::GetThreadIdentity();
-		g_oRegistry[ iThreadID ];
+		
+		long iThreadID = VistaThread::GetCallingThreadIdentity();
+		cout << "Buffer switch called from thread " << iThreadID << endl;
+		//g_oRegistry[ iThreadID ];
 	};
 
 	inline static void AsioSampleRateChanged( ASIOSampleRate fs )
@@ -115,7 +115,7 @@ public:
 		return;
 	};
 	
-	inline long AsioMessages( long selector, long value, void*, double* )
+	inline static long AsioMessages( long selector, long value, void*, double* )
 	{
 		return 0;
 	};
@@ -129,16 +129,14 @@ private:
 
 int main( int, char[] )
 {
-	CThreadedASIO oAsio1( 2 );
-	CThreadedASIO oAsio2( 2 );
-
-	oAsio1.StartStreaming();
-	oAsio2.StartStreaming();
+	cout << "Main thread is called by " << VistaThread::GetCallingThreadIdentity() << endl;
+	CThreadedASIO oAsio1( 1 );
+	//CThreadedASIO oAsio2( 1 );
 
-	VistaTimeUtils::Sleep( 3000 );
+	oAsio1.Run();
+	//oAsio2.Run();
 
-	oAsio1.StopStreaming();
-	oAsio2.StopStreaming();
+	VistaTimeUtils::Sleep( 10000 );
 
 	return 0;
 }
diff --git a/tests/AsioTests/ReciprocalDAADLatencyMeasurement.cpp b/tests/AsioTests/ReciprocalDAADLatencyMeasurement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d9dba855ee5bd301521b8dcf27aed310c6fe81fa
--- /dev/null
+++ b/tests/AsioTests/ReciprocalDAADLatencyMeasurement.cpp
@@ -0,0 +1,207 @@
+#include <cassert>
+#include <conio.h>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include <host/asiodrivers.h>
+#include <common/asio.h>
+
+#include <VistaBase/VistaTimeUtils.h>
+
+using namespace std;
+
+ASIOTime* AsioBufferSwitchTimeInfoA( ASIOTime *timeInfo, long, ASIOBool )
+{
+	return timeInfo;
+};
+
+void AsioBufferSwitchA( long nIndex, ASIOBool processNow )
+{
+	ASIOTime timeInfo;
+	memset( &timeInfo, 0, sizeof( timeInfo ) );
+
+	if( ASIOGetSamplePosition( &timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime ) == ASE_OK )
+		timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
+
+	AsioBufferSwitchTimeInfoA( &timeInfo, nIndex, processNow );
+};
+
+void AsioSampleRateChangedA( ASIOSampleRate fs )
+{
+	cout << "Sample rate changed to " << fs << endl;
+	return;
+};
+
+long AsioMessagesA( long, long, void*, double* )
+{
+	return 0;
+};
+
+ASIOTime* AsioBufferSwitchTimeInfoB( ASIOTime *timeInfo, long, ASIOBool )
+{
+	return timeInfo;
+};
+
+void AsioBufferSwitchB( long nIndex, ASIOBool processNow )
+{
+	ASIOTime timeInfo;
+	memset( &timeInfo, 0, sizeof( timeInfo ) );
+
+	if( ASIOGetSamplePosition( &timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime ) == ASE_OK )
+		timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
+
+	AsioBufferSwitchTimeInfoB( &timeInfo, nIndex, processNow );
+};
+
+void AsioSampleRateChangedB( ASIOSampleRate fs )
+{
+	cout << "Sample rate changed to " << fs << endl;
+	return;
+};
+
+long AsioMessagesB( long, long, void*, double* )
+{
+	return 0;
+};
+
+
+int main( int, char[] )
+{
+	ASIOError ae;
+	AsioDriverList* pDrivers = new AsioDriverList();
+	long nNumDrivers = pDrivers->asioGetNumDev();
+	cout << "Number of ASIO drivers: " << nNumDrivers << endl;
+	delete pDrivers;
+
+	// Driver A
+
+	int iDriverIndexA = 1;
+	AsioDrivers* pDriverA = new AsioDrivers();
+
+	string sDriverNameA;
+	sDriverNameA.resize( 256 );
+	pDriverA->asioGetDriverName( iDriverIndexA, &sDriverNameA[ 0 ], int( sDriverNameA.size() ) );
+	sDriverNameA = std::string( sDriverNameA.c_str() ); // Strip
+	cout << "Driver name: " << sDriverNameA << "." << endl;
+
+
+	int iDriverIndexB = 1;
+	//AsioDrivers* pDriverB = new AsioDrivers();
+	string sDriverNameB;
+	sDriverNameB.resize( 256 );
+	pDriverA->asioGetDriverName( iDriverIndexB, &sDriverNameB[ 0 ], int( sDriverNameB.size() ) );
+	sDriverNameB = std::string( sDriverNameB.c_str() ); // Strip
+	cout << "Driver name: " << sDriverNameB << "." << endl;
+
+	bool bLoadSuccessA = pDriverA->loadDriver( &sDriverNameA[ 0 ] );
+	assert( bLoadSuccessA );
+
+	bool bLoadSuccessB = pDriverA->loadDriver( &sDriverNameB[ 0 ] );
+	assert( bLoadSuccessB );
+				
+	ASIODriverInfo oDriverInfo;
+	oDriverInfo.asioVersion = 2;
+	if( ASIOInit( &oDriverInfo ) != ASE_OK )
+	{
+		cout << "Could not initialize " << sDriverNameA << ", skipping." << endl;
+		return 255;
+	}
+
+	ASIOCallbacks oAsioCallbackA;
+	oAsioCallbackA.asioMessage = &AsioMessagesA;
+	oAsioCallbackA.bufferSwitch = &AsioBufferSwitchA;
+	oAsioCallbackA.bufferSwitchTimeInfo = &AsioBufferSwitchTimeInfoA;
+	oAsioCallbackA.sampleRateDidChange = &AsioSampleRateChangedA;
+
+	vector< ASIOBufferInfo > voBufferInfosA( 4 );
+	voBufferInfosA[ 0 ].buffers;
+	voBufferInfosA[ 0 ].channelNum = 0;
+	voBufferInfosA[ 0 ].isInput = ASIOTrue;
+	voBufferInfosA[ 1 ].buffers;
+	voBufferInfosA[ 1 ].channelNum = 1;
+	voBufferInfosA[ 1 ].isInput = ASIOTrue;
+	voBufferInfosA[ 2 ].buffers;
+	voBufferInfosA[ 2 ].channelNum = 0;
+	voBufferInfosA[ 2 ].isInput = ASIOFalse;
+	voBufferInfosA[ 3 ].buffers;
+	voBufferInfosA[ 3 ].channelNum = 1;
+	voBufferInfosA[ 3 ].isInput = ASIOFalse;
+
+	ASIOSampleRate fs;
+	if( ASIOGetSampleRate( &fs ) == ASE_NotPresent )
+		return 255;
+
+	long minSize, maxSize, preferredSize, granularity;
+	ae = ASIOGetBufferSize( &minSize, &maxSize, &preferredSize, &granularity );
+	preferredSize = ( preferredSize == 0 ? min( 1024, maxSize ) : preferredSize );
+
+	ae = ASIOCreateBuffers( &voBufferInfosA.front(), 4, preferredSize, &oAsioCallbackA );
+	assert( ae == ASE_OK );
+						
+	ae = ASIOStart();
+	assert( ae == ASE_OK );
+
+	VistaTimeUtils::Sleep( int( 2e3 ) );
+
+	ae = ASIOStop();
+	assert( ae == ASE_OK );
+
+	
+	// Driver B
+
+	ASIODriverInfo oDriverInfoB;
+	oDriverInfoB.asioVersion = 2;
+	if( ASIOInit( &oDriverInfoB ) != ASE_OK )
+	{
+		cout << "Could not initialize " << sDriverNameB << ", skipping." << endl;
+		return 255;
+	}
+
+	ASIOCallbacks oAsioCallbackB;
+	oAsioCallbackB.asioMessage = &AsioMessagesB;
+	oAsioCallbackB.bufferSwitch = &AsioBufferSwitchB;
+	oAsioCallbackB.bufferSwitchTimeInfo = &AsioBufferSwitchTimeInfoB;
+	oAsioCallbackB.sampleRateDidChange = &AsioSampleRateChangedB;
+
+	vector< ASIOBufferInfo > voBufferInfosB( 4 );
+	voBufferInfosB[ 0 ].buffers;
+	voBufferInfosB[ 0 ].channelNum = 0;
+	voBufferInfosB[ 0 ].isInput = ASIOTrue;
+	voBufferInfosB[ 1 ].buffers;
+	voBufferInfosB[ 1 ].channelNum = 1;
+	voBufferInfosB[ 1 ].isInput = ASIOTrue;
+	voBufferInfosB[ 2 ].buffers;
+	voBufferInfosB[ 2 ].channelNum = 0;
+	voBufferInfosB[ 2 ].isInput = ASIOFalse;
+	voBufferInfosB[ 3 ].buffers;
+	voBufferInfosB[ 3 ].channelNum = 1;
+	voBufferInfosB[ 3 ].isInput = ASIOFalse;
+
+	if( ASIOGetSampleRate( &fs ) == ASE_NotPresent )
+		return 255;
+
+	ae = ASIOGetBufferSize( &minSize, &maxSize, &preferredSize, &granularity );
+	preferredSize = ( preferredSize == 0 ? min( 1024, maxSize ) : preferredSize );
+
+
+	ae = ASIOCreateBuffers( &voBufferInfosB.front(), 4, preferredSize, &oAsioCallbackB );
+	assert( ae == ASE_OK );
+
+	ae = ASIOStart();
+	assert( ae == ASE_OK );
+	
+	VistaTimeUtils::Sleep( int( 2e3 ) );
+
+	ae = ASIOStop();
+	assert( ae == ASE_OK );
+
+	pDriverA->removeCurrentDriver();
+	delete pDriverA;
+
+//	pDriverB->removeCurrentDriver();
+	//delete pDriverB;
+	
+	return 0;
+}