Adding more tests and style

parent dfe6c563
......@@ -41,20 +41,15 @@ class ITADatasource;
* \param uiNumberOfSamples Anzahl der Samples
* \param dGain Verstärkungsfaktor (optional)
* \param bOnline Echtzeit-Modus verwenden? (d.h. reale Dauern zwischen den
* Datenanforderungen verwenden). Falls false, werden die
* Datenanforderungen verwenden). Falls false, werden die
* Daten direkt hintereinander angefordert (Maximaler Datendurchsatz)
* \param bDisplayProgress Fortschritt auf der Konsole ausgeben? (Optional, Standard: Nein)
*
* \note Gibt die Datenquelle den Nullzeiger zurück, wird für
* \note Gibt die Datenquelle den Nullzeiger zurück, wird für
* den betreffenden Block Stille in den Puffer geschrieben
* \note Ausnahmebehandlung mittels der Klasse ITAException
*/
ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer(ITADatasource* pSource,
float** ppfDest,
unsigned int uiNumberOfSamples,
double dGain=1.0,
bool bOnline=true,
bool bDisplayProgress=false);
ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer( ITADatasource* pSource, float** ppfDest, unsigned int uiNumberOfSamples, double dGain = 1.0, bool bOnline = true, bool bDisplayProgress = false );
//! Daten einer Datenquelle in eine Datei schreiben
/**
......@@ -66,20 +61,14 @@ ITA_DATA_SOURCES_API void WriteFromDatasourceToBuffer(ITADatasource* pSource,
* \param uiNumberOfSamples Anzahl der Samples
* \param dGain Verstärkungsfaktor (optional)
* \param bOnline Echtzeit-Modus verwenden? (d.h. reale Dauern zwischen den
* Datenanforderungen verwenden). Falls false, werden die
* Datenanforderungen verwenden). Falls false, werden die
* Daten direkt hintereinander angefordert (Maximaler Datendurchsatz)
* \param bDisplayProgress Fortschritt auf der Konsole ausgeben? (Optional, Standard: Nein)
*
* \note Gibt die Datenquelle den Nullzeiger zurück, wird für
* \note Gibt die Datenquelle den Nullzeiger zurück, wird für
* den betreffenden Block Stille in die Datei geschrieben
* \note Ausnahmebehandlung mittels der Klasse ITAException
*/
ITA_DATA_SOURCES_API void WriteFromDatasourceToFile(ITADatasource* pSource,
std::string sFilename,
unsigned int uiNumberOfSamples,
double dGain=1.0,
bool bOnline=true,
bool bDisplayProgress=false);
ITA_DATA_SOURCES_API void WriteFromDatasourceToFile( ITADatasource* pSource, std::string sFilename, unsigned int uiNumberOfSamples, double dGain = 1.0, bool bOnline = true, bool bDisplayProgress = false );
#endif // INCLUDE_WATCHER_ITA_DATA_SOURCES_UTILS
......@@ -24,59 +24,62 @@
#include <unistd.h>
#endif
void WriteFromDatasourceToBuffer(ITADatasource* pSource,
float** ppfDest,
unsigned int uiNumberOfSamples,
double dGain,
bool bOnline,
bool bDisplayProgress) {
void WriteFromDatasourceToBuffer( ITADatasource* pSource, float** ppfDest, unsigned int uiNumberOfSamples, double dGain, bool bOnline, bool bDisplayProgress )
{
// Nullzeiger ausschlieen
// TODO: Fehlerbehandlung
if (!pSource) return;
if( !pSource )
return;
unsigned int uiChannels = pSource->GetNumberOfChannels();
double dSamplerate = pSource->GetSampleRate();
unsigned int uiBlocklength = pSource->GetBlocklength();
ITAStreamInfo siState;
long periodMs = (long)ceil(uiBlocklength / dSamplerate * 1000);
long periodMs = ( long ) ceil( uiBlocklength / dSamplerate * 1000 );
#ifdef _WIN32
HANDLE hTimer=0;
if (bOnline) {
HANDLE hTimer = 0;
if( bOnline )
{
// Timer erzeugen
if (FAILED(hTimer = CreateWaitableTimer(NULL, false, NULL)))
ITA_EXCEPT1(UNKNOWN, "Timer konnte nicht erzeugt werden");
if( FAILED( hTimer = CreateWaitableTimer( NULL, false, NULL ) ) )
ITA_EXCEPT1( UNKNOWN, "Timer konnte nicht erzeugt werden" );
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = 0;
SetWaitableTimer(hTimer, &liDueTime, periodMs, NULL, NULL, true);
SetWaitableTimer( hTimer, &liDueTime, periodMs, NULL, NULL, true );
}
#endif
try {
unsigned int n=0;
unsigned int n = 0;
float fProgress = 0.0f;
while (n < uiNumberOfSamples)
while( n < uiNumberOfSamples )
{
#ifdef _WIN32
// Warten
if (bOnline) WaitForSingleObject(hTimer, INFINITE);
if( bOnline )
WaitForSingleObject( hTimer, INFINITE );
#else
if (bOnline) usleep(periodMs * 1000);
if( bOnline )
usleep( periodMs * 1000 );
#endif
// Daten von der Quelle holen
for (unsigned int i=0; i<uiChannels; i++) {
const float* pfData = pSource->GetBlockPointer(i, &siState);
for( unsigned int i = 0; i < uiChannels; i++ )
{
const float* pfData = pSource->GetBlockPointer( i, &siState );
unsigned int k = (uiNumberOfSamples - n);
if (k > uiBlocklength) k = uiBlocklength;
unsigned int k = ( uiNumberOfSamples - n );
if( k > uiBlocklength )
k = uiBlocklength;
if( !pfData )
{ // Stille einfgen
{
// Stille einfgen
for( unsigned int j = 0; j < uiBlocklength; j++ )
ppfDest[ i ][ n + j ] = 0;
}
......@@ -94,52 +97,52 @@ void WriteFromDatasourceToBuffer(ITADatasource* pSource,
n += uiBlocklength;
siState.nSamples += uiBlocklength;
siState.dStreamTimeCode = (double) (siState.nSamples) / dSamplerate;
siState.dStreamTimeCode = ( double ) ( siState.nSamples ) / dSamplerate;
siState.dSysTimeCode = ITAClock::getDefaultClock()->getTime();
if (bDisplayProgress)
if( bDisplayProgress )
{
float p = 100 * (float) n / uiNumberOfSamples;
if(p > fProgress + 5.0f)
float p = 100 * ( float ) n / uiNumberOfSamples;
if( p > fProgress + 5.0f )
{
fProgress = p;
printf("WriteFromDatasourceToBuffer: %0.2f%% geschrieben", p);
printf( "WriteFromDatasourceToBuffer: %0.2f%% geschrieben", p );
}
}
}
} catch (...) {
}
catch( ... )
{
#ifdef _WIN32
if (bOnline) CloseHandle(hTimer);
if( bOnline )
CloseHandle( hTimer );
#endif
throw;
}
if (bDisplayProgress)
printf("WriteFromDatasourceToBuffer: 100,00%% geschrieben");
if( bDisplayProgress )
printf( "WriteFromDatasourceToBuffer: 100,00%% geschrieben" );
#ifdef _WIN32
if (bOnline)
CloseHandle(hTimer);
if( bOnline )
CloseHandle( hTimer );
#endif
}
void WriteFromDatasourceToFile(ITADatasource* pSource,
std::string sFilename,
unsigned int uiNumberOfSamples,
double dGain,
bool bOnline,
bool bDisplayProgress) {
void WriteFromDatasourceToFile( ITADatasource* pSource, std::string sFilename, unsigned int uiNumberOfSamples, double dGain, bool bOnline, bool bDisplayProgress )
{
// Nullzeiger ausschlieen
// TODO: Fehlerbehandlung
if (!pSource) return;
if( !pSource )
return;
unsigned int uiChannels = pSource->GetNumberOfChannels();
unsigned int uiBlocklength = pSource->GetBlocklength();
double dSamplerate = pSource->GetSampleRate();
std::vector<float*> vpfData;
for (unsigned int i=0; i<uiChannels; i++)
vpfData.push_back(new float[uiBlocklength]);
for( unsigned int i = 0; i < uiChannels; i++ )
vpfData.push_back( new float[ uiBlocklength ] );
ITAAudiofileProperties props;
props.iChannels = uiChannels;
......@@ -147,91 +150,103 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
props.eQuantization = ITAQuantization::ITA_FLOAT;
props.eDomain = ITADomain::ITA_TIME_DOMAIN;
props.iLength = uiNumberOfSamples;
ITAAudiofileWriter* writer = ITAAudiofileWriter::create(sFilename, props);
ITAAudiofileWriter* writer = ITAAudiofileWriter::create( sFilename, props );
ITAStreamInfo siState;
long periodMs = (long)ceil(uiBlocklength / dSamplerate * 1000);
long periodMs = ( long ) ceil( uiBlocklength / dSamplerate * 1000 );
#ifdef _WIN32
HANDLE hTimer=0;
HANDLE hTimer = 0;
if (bOnline) {
if( bOnline )
{
// Timer erzeugen
if (FAILED(hTimer = CreateWaitableTimer(NULL, false, NULL))) {
if( FAILED( hTimer = CreateWaitableTimer( NULL, false, NULL ) ) )
{
delete writer;
ITA_EXCEPT1(UNKNOWN, "Timer konnte nicht erzeugt werden");
ITA_EXCEPT1( UNKNOWN, "Timer konnte nicht erzeugt werden" );
}
LARGE_INTEGER liDueTime;
liDueTime.QuadPart=0;
SetWaitableTimer(hTimer, &liDueTime, periodMs, NULL, NULL, true);
liDueTime.QuadPart = 0;
SetWaitableTimer( hTimer, &liDueTime, periodMs, NULL, NULL, true );
}
#endif
try {
unsigned int n=0;
unsigned int n = 0;
float fProgress = 0.0;
while (n < uiNumberOfSamples) {
while( n < uiNumberOfSamples )
{
#ifdef _WIN32
// Warten
if (bOnline) WaitForSingleObject(hTimer, INFINITE);
if( bOnline )
WaitForSingleObject( hTimer, INFINITE );
#else
if (bOnline) usleep(periodMs * 1000);
if( bOnline )
usleep( periodMs * 1000 );
#endif
// Daten von der Quelle holen
for (unsigned int i=0; i<uiChannels; i++) {
const float* pfSource = pSource->GetBlockPointer(i, &siState);
float* pfDest = vpfData[i];
if (!pfSource)
for( unsigned int i = 0; i < uiChannels; i++ )
{
const float* pfSource = pSource->GetBlockPointer( i, &siState );
float* pfDest = vpfData[ i ];
if( !pfSource )
{
// Stille einfgen
for (unsigned int j=0; j<uiBlocklength; j++) pfDest[j] = 0;
else {
if (dGain == 1)
memcpy(pfDest, pfSource, uiBlocklength*sizeof(float));
else
for (unsigned int j=0; j<uiBlocklength; j++)
pfDest[j] = pfSource[j] * (float) dGain;
for( unsigned int j = 0; j < uiBlocklength; j++ )
pfDest[ j ] = 0;
}
else
{
if( dGain == 1 )
memcpy( pfDest, pfSource, uiBlocklength*sizeof( float ) );
else
for( unsigned int j = 0; j < uiBlocklength; j++ )
pfDest[ j ] = pfSource[ j ] * ( float ) dGain;
}
}
pSource->IncrementBlockPointer();
siState.nSamples += uiBlocklength;
siState.dStreamTimeCode = (double) (siState.nSamples) / dSamplerate;
siState.dStreamTimeCode = ( double ) ( siState.nSamples ) / dSamplerate;
siState.dSysTimeCode = ITAClock::getDefaultClock()->getTime();
// Daten schreiben
writer->write((std::min)(uiBlocklength, (uiNumberOfSamples - n)), vpfData);
writer->write( ( std::min )( uiBlocklength, ( uiNumberOfSamples - n ) ), vpfData );
n += uiBlocklength;
if (bDisplayProgress)
if( bDisplayProgress )
{
float p = 100 * (float) n / uiNumberOfSamples;
if(p > fProgress + 5.0f)
float p = 100 * ( float ) n / uiNumberOfSamples;
if( p > fProgress + 5.0f )
{
fProgress = p;
printf("WriteFromDatasourceToFile: %0.2f%% geschrieben\r", p);
printf( "WriteFromDatasourceToFile: %0.2f%% written\r", p );
}
}
}
} catch (...) {
}
catch( ... )
{
#ifdef _WIN32
if (bOnline) CloseHandle(hTimer);
if( bOnline )
CloseHandle( hTimer );
#endif
delete writer;
throw;
}
if (bDisplayProgress)
printf("WriteFromDatasourceToFile: 100,00%% geschrieben\r");
if( bDisplayProgress )
printf( "WriteFromDatasourceToFile: 100,00%% written\r" );
#ifdef _WIN32
if (bOnline)
CloseHandle(hTimer);
if( bOnline )
CloseHandle( hTimer );
#endif
delete writer;
}
......@@ -41,7 +41,7 @@ set_property( TARGET ITAPortaudioMeasurementTest PROPERTY FOLDER "ITACoreLibs/Te
add_executable( ReciprocalDAADLatencyMeasurement ReciprocalDAADLatencyMeasurement.cpp )
target_link_libraries( ReciprocalDAADLatencyMeasurement ${VISTA_USE_PACKAGE_LIBRARIES} )
vista_set_target_msvc_arguments( ReciprocalDAADLatencyMeasurement 1 1 "${CMAKE_CURRENT_SOURCE_DIR}/sweep.wav ${CMAKE_CURRENT_SOURCE_DIR}/recordA.wav ${CMAKE_CURRENT_SOURCE_DIR}/recordB.wav 44100 2048" )
vista_set_target_msvc_arguments( ReciprocalDAADLatencyMeasurement "1 1 ${CMAKE_CURRENT_SOURCE_DIR}/sweep.wav ${CMAKE_CURRENT_SOURCE_DIR}/recordA.wav ${CMAKE_CURRENT_SOURCE_DIR}/recordB.wav 44100 2048" )
vista_configure_app( ReciprocalDAADLatencyMeasurement )
vista_install( ReciprocalDAADLatencyMeasurement )
......
// ITADataSources
#include <ITADataSourceUtils.h>
#include <ITAPortaudioInterface.h>
#include <ITAStreamProbe.h>
#include <ITAFileDataSource.h>
#include <ITAStreamMultiplier1N.h>
// ITABase
#include <ITAException.h>
#include <ITAStringUtils.h>
// STL
#include <iostream>
#include <string>
using namespace std;
void list_portaudio_devices();
int main( int argc, char *argv[] )
{
......@@ -18,13 +24,13 @@ int main( int argc, char *argv[] )
try
{
// Arguments
int iDeviceA = StringToInt( string( argv[ 1 ] ) );
int iDeviceB = StringToInt( string( argv[ 2 ] ) );
const int iDeviceA = StringToInt( string( argv[ 1 ] ) ) - 1;
const int iDeviceB = StringToInt( string( argv[ 2 ] ) ) - 1;
string sExcitationSignalPath = string( argv[ 3 ] );
string sRecordingSignalPathA = string( argv[ 4 ] );
string sRecordingSignalPathB = string( argv[ 5 ] );
double dSampleRate = StringToDouble( string( argv[ 6 ] ) );
int iBlockLength = StringToInt( string( argv[ 7 ] ) );
const double dSampleRate = StringToDouble( string( argv[ 6 ] ) );
const int iBlockLength = StringToInt( string( argv[ 7 ] ) );
// --- Device A ---
......@@ -35,16 +41,25 @@ int main( int argc, char *argv[] )
ITA_EXCEPT1( INVALID_PARAMETER, "Could not initialize device A: " + ITAPortaudioInterface::GetErrorCodeString( err ) );
string sDeviceA = oPADeviceA.GetDeviceName( iDeviceA );
cout << "Input device identifier: " << sDeviceA << endl;
cout << "Device A device identifier: " << sDeviceA << endl;
int iNumInputChannelsA, iNumOutputChannelsA;
oPADeviceA.GetNumChannels( iDeviceA, iNumInputChannelsA, iNumOutputChannelsA );
if( iNumInputChannelsA == 0 || iNumOutputChannelsA == 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "Not enough I/O channels for device A: " + sDeviceA );
cout << "Using " << iNumOutputChannelsA << " outputs and " << iNumInputChannelsA << " inputs for device A" << endl;
ITAFileDatasource oPlaybackA( sExcitationSignalPath, iBlockLength );
if( oPlaybackA.GetNumberOfChannels() != 1 )
ITA_EXCEPT_INVALID_PARAMETER( "Excitation signal must be single channel" );
ITAStreamMultiplier1N oMultiplierA( &oPlaybackA, iNumOutputChannelsA );
oPADeviceA.SetPlaybackEnabled( true );
oPADeviceA.SetPlaybackDatasource( &oPlaybackA );
oPADeviceA.SetPlaybackDatasource( &oMultiplierA );
oPADeviceA.SetRecordEnabled( true );
ITAStreamProbe oRecordStreamProbeA( oPADeviceA.GetRecordDatasource(), sRecordingSignalPathA );
......@@ -55,13 +70,23 @@ int main( int argc, char *argv[] )
ITAPortaudioInterface oPADeviceB( dSampleRate, iBlockLength );
oPADeviceB.Initialize( iDeviceB );
string sDeviceB = oPADeviceB.GetDeviceName( iDeviceB );
cout << "Input device identifier: " << sDeviceB << endl;
cout << "Device B device identifier: " << sDeviceB << endl;
int iNumInputChannelsB, iNumOutputChannelsB;
oPADeviceB.GetNumChannels( iDeviceB, iNumInputChannelsB, iNumOutputChannelsB );
if( iNumInputChannelsB == 0 || iNumOutputChannelsB == 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "Not enough I/O channels for device B: " + sDeviceB );
cout << "Using " << iNumOutputChannelsB << " outputs and " << iNumInputChannelsB << " inputs for device B" << endl;
ITAFileDatasource oPlaybackB( sExcitationSignalPath, iBlockLength );
if( oPlaybackB.GetNumberOfChannels() != 1 )
ITA_EXCEPT_INVALID_PARAMETER( "Excitation signal must be single channel" );
ITAStreamMultiplier1N oMultiplierB( &oPlaybackB, iNumOutputChannelsB );
oPADeviceB.SetPlaybackEnabled( true );
oPADeviceB.SetPlaybackDatasource( &oPlaybackB );
oPADeviceB.SetPlaybackDatasource( &oMultiplierB );
oPADeviceB.SetRecordEnabled( true );
ITAStreamProbe oRecordStreamProbeB( oPADeviceB.GetRecordDatasource(), sRecordingSignalPathB );
......@@ -71,15 +96,26 @@ int main( int argc, char *argv[] )
// Open
oPADeviceA.Open();
oPADeviceA.Open();
oPADeviceB.Open();
// Start streaming
oPADeviceA.Start();
oPADeviceB.Start();
// Measurement
WriteFromDatasourceToFile( &oRecordStreamProbeA, sRecordingSignalPathA, oPlaybackA.GetFileCapacity(), 1.0, true, true );
WriteFromDatasourceToFile( &oRecordStreamProbeB, sRecordingSignalPathA, oPlaybackB.GetFileCapacity(), 1.0, true, true );
std::vector< float* > vpfSamples;
std::vector< std::vector< float >* > vpfSamplesVector;
for( unsigned int i = 0; i < oRecordStreamProbeB.GetNumberOfChannels(); i++ )
{
std::vector< float >* pvfData = new std::vector< float >( oPlaybackA.GetFileCapacity() );
vpfSamplesVector.push_back( pvfData );
vpfSamples.push_back( &( *pvfData )[ 0 ] );
}
//WriteFromDatasourceToBuffer( &oRecordStreamProbeA, &vpfSamples[ 0 ], oPlaybackA.GetFileCapacity(), 1.0, true, true );
WriteFromDatasourceToBuffer( &oRecordStreamProbeB, &vpfSamples[ 0 ], oPlaybackB.GetFileCapacity(), 1.0, true, true );
for( size_t i = 0; i < vpfSamplesVector.size(); i++ )
delete vpfSamplesVector[ i ];
// Stop streaming
oPADeviceA.Stop();
......@@ -96,7 +132,20 @@ int main( int argc, char *argv[] )
catch( const ITAException& e )
{
cerr << e << endl;
cout << "Listing all available Portaudio devices: " << endl;
list_portaudio_devices();
}
return 0;
}
\ No newline at end of file
}
void list_portaudio_devices()
{
ITAPortaudioInterface oITAPA( 44.1e3, 1024 );
oITAPA.Initialize();
int iPANumDevices = oITAPA.GetNumDevices();
for( int i = 0; i < iPANumDevices; i++ )
cout << "[" << i + 1 << "] \"" << oITAPA.GetDeviceName( i ) << "\"" << endl;
cout << endl;
oITAPA.Finalize();
}
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