Add self tests to paqa_latency.c
This commit is contained in:
parent
7a78469780
commit
a08b3b1856
1 changed files with 174 additions and 5 deletions
|
|
@ -44,6 +44,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "portaudio.h"
|
#include "portaudio.h"
|
||||||
|
#include "loopback/src/qa_tools.h"
|
||||||
|
|
||||||
#define NUM_SECONDS (5)
|
#define NUM_SECONDS (5)
|
||||||
#define SAMPLE_RATE (44100)
|
#define SAMPLE_RATE (44100)
|
||||||
|
|
@ -69,6 +70,10 @@ typedef struct
|
||||||
}
|
}
|
||||||
paTestData;
|
paTestData;
|
||||||
|
|
||||||
|
/* Used to tally the results of the QA tests. */
|
||||||
|
int g_testsPassed = 0;
|
||||||
|
int g_testsFailed = 0;
|
||||||
|
|
||||||
/* This routine will be called by the PortAudio engine when audio is needed.
|
/* This routine will be called by the PortAudio engine when audio is needed.
|
||||||
** It may called at interrupt level on some machines so don't do anything
|
** It may called at interrupt level on some machines so don't do anything
|
||||||
** that could mess up the system like calling malloc() or free().
|
** that could mess up the system like calling malloc() or free().
|
||||||
|
|
@ -96,7 +101,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
||||||
data->maxFramesPerBuffer = framesPerBuffer;
|
data->maxFramesPerBuffer = framesPerBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure min and max output time stamp delta.
|
/* Measure min and max output time stamp delta. */
|
||||||
if( data->callbackCount > 0 )
|
if( data->callbackCount > 0 )
|
||||||
{
|
{
|
||||||
PaTime delta = timeInfo->outputBufferDacTime - data->previousTimeInfo.outputBufferDacTime;
|
PaTime delta = timeInfo->outputBufferDacTime - data->previousTimeInfo.outputBufferDacTime;
|
||||||
|
|
@ -187,6 +192,167 @@ error1:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
static int paqaNoopCallback( const void *inputBuffer, void *outputBuffer,
|
||||||
|
unsigned long framesPerBuffer,
|
||||||
|
const PaStreamCallbackTimeInfo* timeInfo,
|
||||||
|
PaStreamCallbackFlags statusFlags,
|
||||||
|
void *userData )
|
||||||
|
{
|
||||||
|
(void)inputBuffer;
|
||||||
|
(void)outputBuffer;
|
||||||
|
(void)framesPerBuffer;
|
||||||
|
(void)timeInfo;
|
||||||
|
(void)statusFlags;
|
||||||
|
(void)userData;
|
||||||
|
return paContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
static int paqaCheckMultipleSuggested( PaDeviceIndex deviceIndex, int isInput )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int numLoops = 10;
|
||||||
|
PaError err;
|
||||||
|
PaStream *stream;
|
||||||
|
PaStreamParameters streamParameters;
|
||||||
|
const PaStreamInfo* streamInfo;
|
||||||
|
double lowLatency;
|
||||||
|
double highLatency;
|
||||||
|
double finalLatency;
|
||||||
|
double sampleRate = 44100.0;
|
||||||
|
const PaDeviceInfo *pdi = Pa_GetDeviceInfo( deviceIndex );
|
||||||
|
double previousLatency = 0.0;
|
||||||
|
int numChannels = 1;
|
||||||
|
|
||||||
|
printf("------------------------ paqaCheckMultipleSuggested - %s\n",
|
||||||
|
(isInput ? "INPUT" : "OUTPUT") );
|
||||||
|
if( isInput )
|
||||||
|
{
|
||||||
|
lowLatency = pdi->defaultLowInputLatency;
|
||||||
|
highLatency = pdi->defaultHighInputLatency;
|
||||||
|
numChannels = (pdi->maxInputChannels < 2) ? 1 : 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lowLatency = pdi->defaultLowOutputLatency;
|
||||||
|
highLatency = pdi->defaultHighOutputLatency;
|
||||||
|
numChannels = (pdi->maxOutputChannels < 2) ? 1 : 2;
|
||||||
|
}
|
||||||
|
streamParameters.channelCount = numChannels;
|
||||||
|
streamParameters.device = deviceIndex;
|
||||||
|
streamParameters.hostApiSpecificStreamInfo = NULL;
|
||||||
|
streamParameters.sampleFormat = paFloat32;
|
||||||
|
|
||||||
|
printf(" lowLatency = %g\n", lowLatency );
|
||||||
|
printf(" highLatency = %g\n", highLatency );
|
||||||
|
printf(" numChannels = %d\n", numChannels );
|
||||||
|
|
||||||
|
for( i=0; i<numLoops; i++ )
|
||||||
|
{
|
||||||
|
streamParameters.suggestedLatency = lowLatency + ((highLatency - lowLatency) * i /(numLoops - 1.0));
|
||||||
|
|
||||||
|
printf(" suggestedLatency[%d] = %6.4f\n", i, streamParameters.suggestedLatency );
|
||||||
|
|
||||||
|
err = Pa_OpenStream(
|
||||||
|
&stream,
|
||||||
|
(isInput ? &streamParameters : NULL),
|
||||||
|
(isInput ? NULL : &streamParameters),
|
||||||
|
sampleRate,
|
||||||
|
paFramesPerBufferUnspecified,
|
||||||
|
paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
||||||
|
paqaNoopCallback,
|
||||||
|
NULL );
|
||||||
|
if( err != paNoError ) goto error;
|
||||||
|
|
||||||
|
streamInfo = Pa_GetStreamInfo( stream );
|
||||||
|
|
||||||
|
err = Pa_CloseStream( stream );
|
||||||
|
|
||||||
|
if( isInput )
|
||||||
|
{
|
||||||
|
finalLatency = streamInfo->inputLatency;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
finalLatency = streamInfo->outputLatency;
|
||||||
|
}
|
||||||
|
printf(" finalLatency = %6.4f\n", finalLatency );
|
||||||
|
QA_ASSERT_CLOSE( "final latency should be close to suggested latency",
|
||||||
|
streamParameters.suggestedLatency, finalLatency, (streamParameters.suggestedLatency * 0.3) );
|
||||||
|
|
||||||
|
QA_ASSERT_TRUE( " final latency should increase with suggested latency", (finalLatency > previousLatency) );
|
||||||
|
previousLatency = finalLatency;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
static int paqaVerifySuggestedLatency( void )
|
||||||
|
{
|
||||||
|
PaDeviceIndex id;
|
||||||
|
int result = 0;
|
||||||
|
const PaDeviceInfo *pdi;
|
||||||
|
int numDevices = Pa_GetDeviceCount();
|
||||||
|
|
||||||
|
printf("\n ------------------------ paqaVerifySuggestedLatency\n");
|
||||||
|
for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
|
||||||
|
{
|
||||||
|
pdi = Pa_GetDeviceInfo( id );
|
||||||
|
printf("Using device #%d: '%s' (%s)\n", id, pdi->name, Pa_GetHostApiInfo(pdi->hostApi)->name);
|
||||||
|
if( pdi->maxOutputChannels > 0 )
|
||||||
|
{
|
||||||
|
if( (result = paqaCheckMultipleSuggested( id, 0 )) != 0 ) goto error;
|
||||||
|
}
|
||||||
|
if( pdi->maxInputChannels > 0 )
|
||||||
|
{
|
||||||
|
if( (result = paqaCheckMultipleSuggested( id, 1 )) != 0 ) goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
static int paqaVerifyDeviceInfoLatency( void )
|
||||||
|
{
|
||||||
|
PaDeviceIndex id;
|
||||||
|
const PaDeviceInfo *pdi;
|
||||||
|
int numDevices = Pa_GetDeviceCount();
|
||||||
|
|
||||||
|
printf("\n ------------------------ paqaVerifyDeviceInfoLatency\n");
|
||||||
|
for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
|
||||||
|
{
|
||||||
|
pdi = Pa_GetDeviceInfo( id );
|
||||||
|
printf("Using device #%d: '%s' (%s)\n", id, pdi->name, Pa_GetHostApiInfo(pdi->hostApi)->name);
|
||||||
|
if( pdi->maxOutputChannels > 0 )
|
||||||
|
{
|
||||||
|
printf(" Output defaultLowOutputLatency = %f seconds\n", pdi->defaultLowOutputLatency);
|
||||||
|
printf(" Output info: defaultHighOutputLatency = %f seconds\n", pdi->defaultHighOutputLatency);
|
||||||
|
QA_ASSERT_TRUE( "defaultLowOutputLatency should be > 0", (pdi->defaultLowOutputLatency > 0.0) );
|
||||||
|
QA_ASSERT_TRUE( "defaultHighOutputLatency should be > 0", (pdi->defaultHighOutputLatency > 0.0) );
|
||||||
|
QA_ASSERT_TRUE( "defaultHighOutputLatency should be > Low", (pdi->defaultHighOutputLatency > pdi->defaultLowOutputLatency) );
|
||||||
|
}
|
||||||
|
if( pdi->maxInputChannels > 0 )
|
||||||
|
{
|
||||||
|
printf(" Input defaultLowOutputLatency = %f seconds\n", pdi->defaultLowInputLatency);
|
||||||
|
printf(" Input defaultHighOutputLatency = %f seconds\n", pdi->defaultHighInputLatency);
|
||||||
|
QA_ASSERT_TRUE( "defaultLowOutputLatency should be > 0", (pdi->defaultLowInputLatency > 0.0) );
|
||||||
|
QA_ASSERT_TRUE( "defaultHighOutputLatency should be > 0", (pdi->defaultHighInputLatency > 0.0) );
|
||||||
|
QA_ASSERT_TRUE( "defaultHighOutputLatency should be > Low", (pdi->defaultHighInputLatency > pdi->defaultLowInputLatency) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
int main(void);
|
int main(void);
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|
@ -198,7 +364,6 @@ int main(void)
|
||||||
int i;
|
int i;
|
||||||
int framesPerBuffer;
|
int framesPerBuffer;
|
||||||
double sampleRate = 44100;
|
double sampleRate = 44100;
|
||||||
|
|
||||||
|
|
||||||
printf("PortAudio QA: investigate output latency. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
printf("PortAudio QA: investigate output latency. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
||||||
|
|
||||||
|
|
@ -211,7 +376,12 @@ int main(void)
|
||||||
|
|
||||||
err = Pa_Initialize();
|
err = Pa_Initialize();
|
||||||
if( err != paNoError ) goto error;
|
if( err != paNoError ) goto error;
|
||||||
|
|
||||||
|
/* Run self tests. */
|
||||||
|
if( paqaVerifyDeviceInfoLatency() < 0 ) goto error;
|
||||||
|
|
||||||
|
if( paqaVerifySuggestedLatency() < 0 ) goto error;
|
||||||
|
|
||||||
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
||||||
if (outputParameters.device == paNoDevice) {
|
if (outputParameters.device == paNoDevice) {
|
||||||
fprintf(stderr,"Error: No default output device.\n");
|
fprintf(stderr,"Error: No default output device.\n");
|
||||||
|
|
@ -226,7 +396,6 @@ int main(void)
|
||||||
printf("Device info: defaultHighOutputLatency = %f seconds\n", deviceInfo->defaultHighOutputLatency);
|
printf("Device info: defaultHighOutputLatency = %f seconds\n", deviceInfo->defaultHighOutputLatency);
|
||||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||||
|
|
||||||
|
|
||||||
// Try to use a small buffer that is smaller than we think the device can handle.
|
// Try to use a small buffer that is smaller than we think the device can handle.
|
||||||
// Try to force combining multiple user buffers into a host buffer.
|
// Try to force combining multiple user buffers into a host buffer.
|
||||||
printf("------------- Try a very small buffer.\n");
|
printf("------------- Try a very small buffer.\n");
|
||||||
|
|
@ -240,7 +409,7 @@ int main(void)
|
||||||
outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency * 1.1;
|
outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency * 1.1;
|
||||||
err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer );
|
err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer );
|
||||||
if( err != paNoError ) goto error;
|
if( err != paNoError ) goto error;
|
||||||
|
|
||||||
// Try to create a huge buffer that is bigger than the allowed device maximum.
|
// Try to create a huge buffer that is bigger than the allowed device maximum.
|
||||||
printf("------------- Try a huge buffer.\n");
|
printf("------------- Try a huge buffer.\n");
|
||||||
framesPerBuffer = 16*1024;
|
framesPerBuffer = 16*1024;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue