From: Phil Burk Date: Sat, 19 Dec 2020 23:59:23 +0000 (-0800) Subject: paqa_devs: test default device X-Git-Tag: v19.7.0~79 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=5f869e787e2127d9ddd640df9af7be610d03dd08;p=portaudio paqa_devs: test default device Use sine wave instead of sawtooth because it is easier to hear glitches. Add some options: -a - Test ALL devices, otherwise just the default devices. -i - Test INPUT only. -o - Test OUTPUT only. --- diff --git a/qa/paqa_devs.c b/qa/paqa_devs.c index 721b07f..fae9f25 100644 --- a/qa/paqa_devs.c +++ b/qa/paqa_devs.c @@ -1,13 +1,13 @@ /** @file paqa_devs.c - @ingroup qa_src + @ingroup qa_src @brief Self Testing Quality Assurance app for PortAudio - Try to open each device and run through all the - possible configurations. This test does not verify + Try to open the default devices and run through all the + possible configurations. This test does not verify that the configuration works well. It just verifies that it does not crash. It requires a human to listen to - the outputs. + the sine wave outputs. - @author Phil Burk http://www.softsynth.com + @author Phil Burk http://www.softsynth.com Pieter adapted to V19 API. Test now relies heavily on Pa_IsFormatSupported(). Uses same 'standard' sample rates @@ -52,14 +52,20 @@ */ #include +#include +#include #include #include "portaudio.h" #include "pa_trace.h" /****************************************** Definitions ***********/ -#define MODE_INPUT (0) -#define MODE_OUTPUT (1) -#define MAX_TEST_CHANNELS 4 +#define MODE_INPUT (0) +#define MODE_OUTPUT (1) +#define MAX_TEST_CHANNELS (4) +#define LOWEST_FREQUENCY (300.0) +#define LOWEST_SAMPLE_RATE (8000.0) +#define PHASE_INCREMENT (2.0 * M_PI * LOWEST_FREQUENCY / LOWEST_SAMPLE_RATE) +#define SINE_AMPLITUDE (0.2) typedef struct PaQaData { @@ -67,13 +73,13 @@ typedef struct PaQaData int numChannels; int bytesPerSample; int mode; - short sawPhase; + float phase; PaSampleFormat format; } PaQaData; /****************************************** Prototypes ***********/ -static void TestDevices( int mode ); +static void TestDevices( int mode, int allDevices ); static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate, int numChannels ); static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, @@ -107,6 +113,14 @@ static int gNumFailed = 0; } \ } while(0) +static float NextSineSample( PaQaData *data ) +{ + float phase = data->phase + PHASE_INCREMENT; + if( phase > M_PI ) phase -= 2.0 * M_PI; + data->phase = phase; + return sinf(phase) * SINE_AMPLITUDE; +} + /*******************************************************************/ /* This routine will be called by the PortAudio engine when audio is needed. ** It may be called at interrupt level on some machines so don't do anything @@ -118,27 +132,26 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, PaStreamCallbackFlags statusFlags, void *userData ) { - unsigned long i; - short phase; + unsigned long frameIndex; + unsigned long channelIndex; + float sample; PaQaData *data = (PaQaData *) userData; (void) inputBuffer; - /* Play simple sawtooth wave. */ + /* Play simple sine wave. */ if( data->mode == MODE_OUTPUT ) { - phase = data->sawPhase; switch( data->format ) { case paFloat32: { float *out = (float *) outputBuffer; - for( i=0; inumChannels == 2 ) + sample = NextSineSample( data ); + for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ ) { - *out++ = (float) (phase * (1.0 / 32768.0)); + *out++ = sample; } } } @@ -147,13 +160,12 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, case paInt32: { int *out = (int *) outputBuffer; - for( i=0; inumChannels == 2 ) + sample = NextSineSample( data ); + for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ ) { - *out++ = ((int) phase ) << 16; + *out++ = ((int)(sample * 0x00800000)) << 8; } } } @@ -162,13 +174,12 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, case paInt16: { short *out = (short *) outputBuffer; - for( i=0; inumChannels == 2 ) + sample = NextSineSample( data ); + for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ ) { - *out++ = phase; + *out++ = (short)(sample * 32767); } } } @@ -178,14 +189,10 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, { unsigned char *out = (unsigned char *) outputBuffer; unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample; - for( i=0; isawPhase = phase; } /* Are we through yet? */ if( data->framesLeft > framesPerBuffer ) @@ -203,15 +210,78 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, } /*******************************************************************/ -int main(void); -int main(void) +static void usage( const char *name ) +{ + printf("%s [-a]\n", name); + printf(" -a - Test ALL devices, otherwise just the default devices.\n"); + printf(" -i - Test INPUT only.\n"); + printf(" -o - Test OUTPUT only.\n"); + printf(" -? - Help\n"); +} + +/*******************************************************************/ +int main( int argc, char **argv ); +int main( int argc, char **argv ) { + int i; PaError result; + int allDevices = 0; + int testOutput = 1; + int testInput = 1; + char *executableName = argv[0]; + + /* Parse command line parameters. */ + i = 1; + while( imaxInputChannels : pdi->maxOutputChannels); + + if( mode == MODE_INPUT ) { + maxChannels = pdi->maxInputChannels; + isDefault = ( id == Pa_GetDefaultInputDevice()); + } else { + maxChannels = pdi->maxOutputChannels; + isDefault = ( id == Pa_GetDefaultOutputDevice()); + } if( maxChannels > MAX_TEST_CHANNELS ) maxChannels = MAX_TEST_CHANNELS; + + if (!allDevices && !isDefault) continue; // skip this device for( jc=1; jc<=maxChannels; jc++ ) { - printf("\n========================================================================\n"); + printf("\n===========================================================\n"); printf(" Device = %s\n", pdi->name ); - printf("========================================================================\n"); + printf("===========================================================\n"); /* Try each standard sample rate. */ for( i=0; standardSampleRates[i] > 0; i++ ) { @@ -299,32 +378,35 @@ static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, inputParameters.device = deviceID; inputParameters.channelCount = numChannels; inputParameters.sampleFormat = format; - inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; + inputParameters.suggestedLatency = + Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; ipp = &inputParameters; } else { - ipp = NULL; - } - + ipp = NULL; + } + if( mode == MODE_OUTPUT ) { outputParameters.device = deviceID; outputParameters.channelCount = numChannels; outputParameters.sampleFormat = format; - outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; + outputParameters.suggestedLatency = + Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; opp = &outputParameters; } else { - opp = NULL; - } - + opp = NULL; + } + if(paFormatIsSupported == Pa_IsFormatSupported( ipp, opp, sampleRate )) { - printf("------ TestAdvance: %s, device = %d, rate = %g, numChannels = %d, format = %lu -------\n", + printf("------ TestAdvance: %s, device = %d, rate = %g" + ", numChannels = %d, format = %lu -------\n", ( mode == MODE_INPUT ) ? "INPUT" : "OUTPUT", deviceID, sampleRate, numChannels, (unsigned long)format); EXPECT( ((result = Pa_OpenStream( &stream, @@ -353,7 +435,7 @@ static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, oldStamp = Pa_GetStreamTime(stream); Pa_Sleep(msec); newStamp = Pa_GetStreamTime(stream); - printf("oldStamp = %9.6f, newStamp = %9.6f\n", oldStamp, newStamp ); /**/ + printf("oldStamp = %9.6f, newStamp = %9.6f\n", oldStamp, newStamp ); /**/ EXPECT( (oldStamp < newStamp) ); /* Check to make sure callback is decrementing framesLeft. */ oldFrames = myData.framesLeft;