/** @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
*/
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <math.h>
#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
{
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,
} \
} 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
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; i<framesPerBuffer; i++ )
+ for( frameIndex = 0; frameIndex < framesPerBuffer; frameIndex++ )
{
- phase += 0x123;
- *out++ = (float) (phase * (1.0 / 32768.0));
- if( data->numChannels == 2 )
+ sample = NextSineSample( data );
+ for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ )
{
- *out++ = (float) (phase * (1.0 / 32768.0));
+ *out++ = sample;
}
}
}
case paInt32:
{
int *out = (int *) outputBuffer;
- for( i=0; i<framesPerBuffer; i++ )
+ for( frameIndex = 0; frameIndex < framesPerBuffer; frameIndex++ )
{
- phase += 0x123;
- *out++ = ((int) phase ) << 16;
- if( data->numChannels == 2 )
+ sample = NextSineSample( data );
+ for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ )
{
- *out++ = ((int) phase ) << 16;
+ *out++ = ((int)(sample * 0x00800000)) << 8;
}
}
}
case paInt16:
{
short *out = (short *) outputBuffer;
- for( i=0; i<framesPerBuffer; i++ )
+ for( frameIndex = 0; frameIndex < framesPerBuffer; frameIndex++ )
{
- phase += 0x123;
- *out++ = phase;
- if( data->numChannels == 2 )
+ sample = NextSineSample( data );
+ for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ )
{
- *out++ = phase;
+ *out++ = (short)(sample * 32767);
}
}
}
{
unsigned char *out = (unsigned char *) outputBuffer;
unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample;
- for( i=0; i<numBytes; i++ )
- {
- *out++ = 0;
- }
+ memset(out, 0, numBytes);
}
break;
}
- data->sawPhase = phase;
}
/* Are we through yet? */
if( data->framesLeft > framesPerBuffer )
}
/*******************************************************************/
-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( i<argc )
+ {
+ char *arg = argv[i];
+ if( arg[0] == '-' )
+ {
+ switch(arg[1])
+ {
+ case 'a':
+ allDevices = 1;
+ break;
+ case 'i':
+ testOutput = 0;
+ break;
+ case 'o':
+ testInput = 0;
+ break;
+
+ default:
+ printf("Illegal option: %s\n", arg);
+ case '?':
+ usage( executableName );
+ exit(1);
+ break;
+ }
+ }
+ else
+ {
+ printf("Illegal argument: %s\n", arg);
+ usage( executableName );
+ return 1;
+
+ }
+ i += 1;
+ }
+
+ EXPECT(sizeof(short) == 2); /* The callback assumes we have 16-bit shorts. */
+ EXPECT(sizeof(int) == 4); /* The callback assumes we have 32-bit ints. */
EXPECT( ((result=Pa_Initialize()) == 0) );
- printf("Test OUTPUT ---------------\n");
- TestDevices( MODE_OUTPUT );
- printf("Test INPUT ---------------\n");
- TestDevices( MODE_INPUT );
+
+ if( testOutput )
+ {
+ printf("\n---- Test OUTPUT ---------------\n");
+ TestDevices( MODE_OUTPUT, allDevices );
+ }
+ if( testInput )
+ {
+ printf("\n---- Test INPUT ---------------\n");
+ TestDevices( MODE_INPUT, allDevices );
+ }
+
error:
Pa_Terminate();
printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed );
/*******************************************************************
* Try each output device, through its full range of capabilities. */
-static void TestDevices( int mode )
+static void TestDevices( int mode, int allDevices )
{
int id, jc, i;
int maxChannels;
+ int isDefault;
const PaDeviceInfo *pdi;
static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0,
16000.0, 22050.0, 24000.0,
for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
{
pdi = Pa_GetDeviceInfo( id );
- /* Try 1 to maxChannels on each device. */
- maxChannels = (( mode == MODE_INPUT ) ? pdi->maxInputChannels : 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++ )
{
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,
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;