annotate src/portaudio_20140130/qa/paqa_devs.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 7ddb4fc30dac
children
rev   line source
Chris@39 1 /** @file paqa_devs.c
Chris@39 2 @ingroup qa_src
Chris@39 3 @brief Self Testing Quality Assurance app for PortAudio
Chris@39 4 Try to open each device and run through all the
Chris@39 5 possible configurations. This test does not verify
Chris@39 6 that the configuration works well. It just verifies
Chris@39 7 that it does not crash. It requires a human to listen to
Chris@39 8 the outputs.
Chris@39 9
Chris@39 10 @author Phil Burk http://www.softsynth.com
Chris@39 11
Chris@39 12 Pieter adapted to V19 API. Test now relies heavily on
Chris@39 13 Pa_IsFormatSupported(). Uses same 'standard' sample rates
Chris@39 14 as in test pa_devs.c.
Chris@39 15 */
Chris@39 16 /*
Chris@39 17 * $Id: paqa_devs.c 1910 2013-09-07 10:14:52Z gineera $
Chris@39 18 *
Chris@39 19 * This program uses the PortAudio Portable Audio Library.
Chris@39 20 * For more information see: http://www.portaudio.com
Chris@39 21 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
Chris@39 22 *
Chris@39 23 * Permission is hereby granted, free of charge, to any person obtaining
Chris@39 24 * a copy of this software and associated documentation files
Chris@39 25 * (the "Software"), to deal in the Software without restriction,
Chris@39 26 * including without limitation the rights to use, copy, modify, merge,
Chris@39 27 * publish, distribute, sublicense, and/or sell copies of the Software,
Chris@39 28 * and to permit persons to whom the Software is furnished to do so,
Chris@39 29 * subject to the following conditions:
Chris@39 30 *
Chris@39 31 * The above copyright notice and this permission notice shall be
Chris@39 32 * included in all copies or substantial portions of the Software.
Chris@39 33 *
Chris@39 34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@39 35 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@39 36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Chris@39 37 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
Chris@39 38 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@39 39 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@39 40 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@39 41 */
Chris@39 42
Chris@39 43 /*
Chris@39 44 * The text above constitutes the entire PortAudio license; however,
Chris@39 45 * the PortAudio community also makes the following non-binding requests:
Chris@39 46 *
Chris@39 47 * Any person wishing to distribute modifications to the Software is
Chris@39 48 * requested to send the modifications to the original developer so that
Chris@39 49 * they can be incorporated into the canonical version. It is also
Chris@39 50 * requested that these non-binding requests be included along with the
Chris@39 51 * license above.
Chris@39 52 */
Chris@39 53
Chris@39 54 #include <stdio.h>
Chris@39 55 #include <math.h>
Chris@39 56 #include "portaudio.h"
Chris@39 57 #include "pa_trace.h"
Chris@39 58
Chris@39 59 /****************************************** Definitions ***********/
Chris@39 60 #define MODE_INPUT (0)
Chris@39 61 #define MODE_OUTPUT (1)
Chris@39 62 #define MAX_TEST_CHANNELS 4
Chris@39 63
Chris@39 64 typedef struct PaQaData
Chris@39 65 {
Chris@39 66 unsigned long framesLeft;
Chris@39 67 int numChannels;
Chris@39 68 int bytesPerSample;
Chris@39 69 int mode;
Chris@39 70 short sawPhase;
Chris@39 71 PaSampleFormat format;
Chris@39 72 }
Chris@39 73 PaQaData;
Chris@39 74
Chris@39 75 /****************************************** Prototypes ***********/
Chris@39 76 static void TestDevices( int mode );
Chris@39 77 static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate,
Chris@39 78 int numChannels );
Chris@39 79 static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate,
Chris@39 80 int numChannels, PaSampleFormat format );
Chris@39 81 static int QaCallback( const void *inputBuffer, void *outputBuffer,
Chris@39 82 unsigned long framesPerBuffer,
Chris@39 83 const PaStreamCallbackTimeInfo* timeInfo,
Chris@39 84 PaStreamCallbackFlags statusFlags,
Chris@39 85 void *userData );
Chris@39 86
Chris@39 87 /****************************************** Globals ***********/
Chris@39 88 static int gNumPassed = 0;
Chris@39 89 static int gNumFailed = 0;
Chris@39 90
Chris@39 91 /****************************************** Macros ***********/
Chris@39 92 /* Print ERROR if it fails. Tally success or failure. */
Chris@39 93 /* Odd do-while wrapper seems to be needed for some compilers. */
Chris@39 94 #define EXPECT(_exp) \
Chris@39 95 do \
Chris@39 96 { \
Chris@39 97 if ((_exp)) {\
Chris@39 98 /* printf("SUCCESS for %s\n", #_exp ); */ \
Chris@39 99 gNumPassed++; \
Chris@39 100 } \
Chris@39 101 else { \
Chris@39 102 printf("ERROR - 0x%x - %s for %s\n", result, \
Chris@39 103 ((result == 0) ? "-" : Pa_GetErrorText(result)), \
Chris@39 104 #_exp ); \
Chris@39 105 gNumFailed++; \
Chris@39 106 goto error; \
Chris@39 107 } \
Chris@39 108 } while(0)
Chris@39 109
Chris@39 110 /*******************************************************************/
Chris@39 111 /* This routine will be called by the PortAudio engine when audio is needed.
Chris@39 112 ** It may be called at interrupt level on some machines so don't do anything
Chris@39 113 ** that could mess up the system like calling malloc() or free().
Chris@39 114 */
Chris@39 115 static int QaCallback( const void *inputBuffer, void *outputBuffer,
Chris@39 116 unsigned long framesPerBuffer,
Chris@39 117 const PaStreamCallbackTimeInfo* timeInfo,
Chris@39 118 PaStreamCallbackFlags statusFlags,
Chris@39 119 void *userData )
Chris@39 120 {
Chris@39 121 unsigned long i;
Chris@39 122 short phase;
Chris@39 123 PaQaData *data = (PaQaData *) userData;
Chris@39 124 (void) inputBuffer;
Chris@39 125
Chris@39 126 /* Play simple sawtooth wave. */
Chris@39 127 if( data->mode == MODE_OUTPUT )
Chris@39 128 {
Chris@39 129 phase = data->sawPhase;
Chris@39 130 switch( data->format )
Chris@39 131 {
Chris@39 132 case paFloat32:
Chris@39 133 {
Chris@39 134 float *out = (float *) outputBuffer;
Chris@39 135 for( i=0; i<framesPerBuffer; i++ )
Chris@39 136 {
Chris@39 137 phase += 0x123;
Chris@39 138 *out++ = (float) (phase * (1.0 / 32768.0));
Chris@39 139 if( data->numChannels == 2 )
Chris@39 140 {
Chris@39 141 *out++ = (float) (phase * (1.0 / 32768.0));
Chris@39 142 }
Chris@39 143 }
Chris@39 144 }
Chris@39 145 break;
Chris@39 146
Chris@39 147 case paInt32:
Chris@39 148 {
Chris@39 149 int *out = (int *) outputBuffer;
Chris@39 150 for( i=0; i<framesPerBuffer; i++ )
Chris@39 151 {
Chris@39 152 phase += 0x123;
Chris@39 153 *out++ = ((int) phase ) << 16;
Chris@39 154 if( data->numChannels == 2 )
Chris@39 155 {
Chris@39 156 *out++ = ((int) phase ) << 16;
Chris@39 157 }
Chris@39 158 }
Chris@39 159 }
Chris@39 160 break;
Chris@39 161
Chris@39 162 case paInt16:
Chris@39 163 {
Chris@39 164 short *out = (short *) outputBuffer;
Chris@39 165 for( i=0; i<framesPerBuffer; i++ )
Chris@39 166 {
Chris@39 167 phase += 0x123;
Chris@39 168 *out++ = phase;
Chris@39 169 if( data->numChannels == 2 )
Chris@39 170 {
Chris@39 171 *out++ = phase;
Chris@39 172 }
Chris@39 173 }
Chris@39 174 }
Chris@39 175 break;
Chris@39 176
Chris@39 177 default:
Chris@39 178 {
Chris@39 179 unsigned char *out = (unsigned char *) outputBuffer;
Chris@39 180 unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample;
Chris@39 181 for( i=0; i<numBytes; i++ )
Chris@39 182 {
Chris@39 183 *out++ = 0;
Chris@39 184 }
Chris@39 185 }
Chris@39 186 break;
Chris@39 187 }
Chris@39 188 data->sawPhase = phase;
Chris@39 189 }
Chris@39 190 /* Are we through yet? */
Chris@39 191 if( data->framesLeft > framesPerBuffer )
Chris@39 192 {
Chris@39 193 PaUtil_AddTraceMessage("QaCallback: running. framesLeft", data->framesLeft );
Chris@39 194 data->framesLeft -= framesPerBuffer;
Chris@39 195 return 0;
Chris@39 196 }
Chris@39 197 else
Chris@39 198 {
Chris@39 199 PaUtil_AddTraceMessage("QaCallback: DONE! framesLeft", data->framesLeft );
Chris@39 200 data->framesLeft = 0;
Chris@39 201 return 1;
Chris@39 202 }
Chris@39 203 }
Chris@39 204
Chris@39 205 /*******************************************************************/
Chris@39 206 int main(void);
Chris@39 207 int main(void)
Chris@39 208 {
Chris@39 209 PaError result;
Chris@39 210 EXPECT( ((result=Pa_Initialize()) == 0) );
Chris@39 211 printf("Test OUTPUT ---------------\n");
Chris@39 212 TestDevices( MODE_OUTPUT );
Chris@39 213 printf("Test INPUT ---------------\n");
Chris@39 214 TestDevices( MODE_INPUT );
Chris@39 215 error:
Chris@39 216 Pa_Terminate();
Chris@39 217 printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed );
Chris@39 218 return (gNumFailed > 0) ? 1 : 0;
Chris@39 219 }
Chris@39 220
Chris@39 221 /*******************************************************************
Chris@39 222 * Try each output device, through its full range of capabilities. */
Chris@39 223 static void TestDevices( int mode )
Chris@39 224 {
Chris@39 225 int id, jc, i;
Chris@39 226 int maxChannels;
Chris@39 227 const PaDeviceInfo *pdi;
Chris@39 228 static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0,
Chris@39 229 16000.0, 22050.0, 24000.0,
Chris@39 230 32000.0, 44100.0, 48000.0,
Chris@39 231 88200.0, 96000.0,
Chris@39 232 -1.0 }; /* Negative terminated list. */
Chris@39 233 int numDevices = Pa_GetDeviceCount();
Chris@39 234 for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
Chris@39 235 {
Chris@39 236 pdi = Pa_GetDeviceInfo( id );
Chris@39 237 /* Try 1 to maxChannels on each device. */
Chris@39 238 maxChannels = (( mode == MODE_INPUT ) ? pdi->maxInputChannels : pdi->maxOutputChannels);
Chris@39 239 if( maxChannels > MAX_TEST_CHANNELS )
Chris@39 240 maxChannels = MAX_TEST_CHANNELS;
Chris@39 241
Chris@39 242 for( jc=1; jc<=maxChannels; jc++ )
Chris@39 243 {
Chris@39 244 printf("\n========================================================================\n");
Chris@39 245 printf(" Device = %s\n", pdi->name );
Chris@39 246 printf("========================================================================\n");
Chris@39 247 /* Try each standard sample rate. */
Chris@39 248 for( i=0; standardSampleRates[i] > 0; i++ )
Chris@39 249 {
Chris@39 250 TestFormats( mode, (PaDeviceIndex)id, standardSampleRates[i], jc );
Chris@39 251 }
Chris@39 252 }
Chris@39 253 }
Chris@39 254 }
Chris@39 255
Chris@39 256 /*******************************************************************/
Chris@39 257 static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate,
Chris@39 258 int numChannels )
Chris@39 259 {
Chris@39 260 TestAdvance( mode, deviceID, sampleRate, numChannels, paFloat32 );
Chris@39 261 TestAdvance( mode, deviceID, sampleRate, numChannels, paInt16 );
Chris@39 262 TestAdvance( mode, deviceID, sampleRate, numChannels, paInt32 );
Chris@39 263 /* TestAdvance( mode, deviceID, sampleRate, numChannels, paInt24 ); */
Chris@39 264 }
Chris@39 265
Chris@39 266 /*******************************************************************/
Chris@39 267 static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate,
Chris@39 268 int numChannels, PaSampleFormat format )
Chris@39 269 {
Chris@39 270 PaStreamParameters inputParameters, outputParameters, *ipp, *opp;
Chris@39 271 PaStream *stream = NULL;
Chris@39 272 PaError result = paNoError;
Chris@39 273 PaQaData myData;
Chris@39 274 #define FRAMES_PER_BUFFER (64)
Chris@39 275 const int kNumSeconds = 100;
Chris@39 276
Chris@39 277 /* Setup data for synthesis thread. */
Chris@39 278 myData.framesLeft = (unsigned long) (sampleRate * kNumSeconds);
Chris@39 279 myData.numChannels = numChannels;
Chris@39 280 myData.mode = mode;
Chris@39 281 myData.format = format;
Chris@39 282 switch( format )
Chris@39 283 {
Chris@39 284 case paFloat32:
Chris@39 285 case paInt32:
Chris@39 286 case paInt24:
Chris@39 287 myData.bytesPerSample = 4;
Chris@39 288 break;
Chris@39 289 /* case paPackedInt24:
Chris@39 290 myData.bytesPerSample = 3;
Chris@39 291 break; */
Chris@39 292 default:
Chris@39 293 myData.bytesPerSample = 2;
Chris@39 294 break;
Chris@39 295 }
Chris@39 296
Chris@39 297 if( mode == MODE_INPUT )
Chris@39 298 {
Chris@39 299 inputParameters.device = deviceID;
Chris@39 300 inputParameters.channelCount = numChannels;
Chris@39 301 inputParameters.sampleFormat = format;
Chris@39 302 inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
Chris@39 303 inputParameters.hostApiSpecificStreamInfo = NULL;
Chris@39 304 ipp = &inputParameters;
Chris@39 305 }
Chris@39 306 else
Chris@39 307 {
Chris@39 308 ipp = NULL;
Chris@39 309 }
Chris@39 310
Chris@39 311 if( mode == MODE_OUTPUT )
Chris@39 312 {
Chris@39 313 outputParameters.device = deviceID;
Chris@39 314 outputParameters.channelCount = numChannels;
Chris@39 315 outputParameters.sampleFormat = format;
Chris@39 316 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
Chris@39 317 outputParameters.hostApiSpecificStreamInfo = NULL;
Chris@39 318 opp = &outputParameters;
Chris@39 319 }
Chris@39 320 else
Chris@39 321 {
Chris@39 322 opp = NULL;
Chris@39 323 }
Chris@39 324
Chris@39 325 if(paFormatIsSupported == Pa_IsFormatSupported( ipp, opp, sampleRate ))
Chris@39 326 {
Chris@39 327 printf("------ TestAdvance: %s, device = %d, rate = %g, numChannels = %d, format = %lu -------\n",
Chris@39 328 ( mode == MODE_INPUT ) ? "INPUT" : "OUTPUT",
Chris@39 329 deviceID, sampleRate, numChannels, (unsigned long)format);
Chris@39 330 EXPECT( ((result = Pa_OpenStream( &stream,
Chris@39 331 ipp,
Chris@39 332 opp,
Chris@39 333 sampleRate,
Chris@39 334 FRAMES_PER_BUFFER,
Chris@39 335 paClipOff, /* we won't output out of range samples so don't bother clipping them */
Chris@39 336 QaCallback,
Chris@39 337 &myData ) ) == 0) );
Chris@39 338 if( stream )
Chris@39 339 {
Chris@39 340 PaTime oldStamp, newStamp;
Chris@39 341 unsigned long oldFrames;
Chris@39 342 int minDelay = ( mode == MODE_INPUT ) ? 1000 : 400;
Chris@39 343 /* Was:
Chris@39 344 int minNumBuffers = Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate );
Chris@39 345 int msec = (int) ((minNumBuffers * 3 * 1000.0 * FRAMES_PER_BUFFER) / sampleRate);
Chris@39 346 */
Chris@39 347 int msec = (int)( 3.0 *
Chris@39 348 (( mode == MODE_INPUT ) ? inputParameters.suggestedLatency : outputParameters.suggestedLatency ));
Chris@39 349 if( msec < minDelay ) msec = minDelay;
Chris@39 350 printf("msec = %d\n", msec); /**/
Chris@39 351 EXPECT( ((result=Pa_StartStream( stream )) == 0) );
Chris@39 352 /* Check to make sure PortAudio is advancing timeStamp. */
Chris@39 353 oldStamp = Pa_GetStreamTime(stream);
Chris@39 354 Pa_Sleep(msec);
Chris@39 355 newStamp = Pa_GetStreamTime(stream);
Chris@39 356 printf("oldStamp = %9.6f, newStamp = %9.6f\n", oldStamp, newStamp ); /**/
Chris@39 357 EXPECT( (oldStamp < newStamp) );
Chris@39 358 /* Check to make sure callback is decrementing framesLeft. */
Chris@39 359 oldFrames = myData.framesLeft;
Chris@39 360 Pa_Sleep(msec);
Chris@39 361 printf("oldFrames = %lu, myData.framesLeft = %lu\n", oldFrames, myData.framesLeft ); /**/
Chris@39 362 EXPECT( (oldFrames > myData.framesLeft) );
Chris@39 363 EXPECT( ((result=Pa_CloseStream( stream )) == 0) );
Chris@39 364 stream = NULL;
Chris@39 365 }
Chris@39 366 }
Chris@39 367 return 0;
Chris@39 368 error:
Chris@39 369 if( stream != NULL ) Pa_CloseStream( stream );
Chris@39 370 return -1;
Chris@39 371 }