annotate src/portaudio_20161030_catalina_patch/test/patest_out_underflow.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 4edcd14160a5
children
rev   line source
Chris@4 1 /** @file patest_out_underflow.c
Chris@4 2 @ingroup test_src
Chris@4 3 @brief Count output underflows (using paOutputUnderflow flag)
Chris@4 4 under overloaded and normal conditions.
Chris@4 5 @author Ross Bencina <rossb@audiomulch.com>
Chris@4 6 @author Phil Burk <philburk@softsynth.com>
Chris@4 7 */
Chris@4 8 /*
Chris@55 9 * $Id$
Chris@4 10 *
Chris@4 11 * This program uses the PortAudio Portable Audio Library.
Chris@4 12 * For more information see: http://www.portaudio.com
Chris@4 13 * Copyright (c) 1999-2004 Ross Bencina and Phil Burk
Chris@4 14 *
Chris@4 15 * Permission is hereby granted, free of charge, to any person obtaining
Chris@4 16 * a copy of this software and associated documentation files
Chris@4 17 * (the "Software"), to deal in the Software without restriction,
Chris@4 18 * including without limitation the rights to use, copy, modify, merge,
Chris@4 19 * publish, distribute, sublicense, and/or sell copies of the Software,
Chris@4 20 * and to permit persons to whom the Software is furnished to do so,
Chris@4 21 * subject to the following conditions:
Chris@4 22 *
Chris@4 23 * The above copyright notice and this permission notice shall be
Chris@4 24 * included in all copies or substantial portions of the Software.
Chris@4 25 *
Chris@4 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@4 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@4 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Chris@4 29 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
Chris@4 30 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@4 31 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@4 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@4 33 */
Chris@4 34
Chris@4 35 /*
Chris@4 36 * The text above constitutes the entire PortAudio license; however,
Chris@4 37 * the PortAudio community also makes the following non-binding requests:
Chris@4 38 *
Chris@4 39 * Any person wishing to distribute modifications to the Software is
Chris@4 40 * requested to send the modifications to the original developer so that
Chris@4 41 * they can be incorporated into the canonical version. It is also
Chris@4 42 * requested that these non-binding requests be included along with the
Chris@4 43 * license above.
Chris@4 44 */
Chris@4 45
Chris@4 46 #include <stdio.h>
Chris@4 47 #include <math.h>
Chris@4 48 #include "portaudio.h"
Chris@4 49
Chris@4 50 #define MAX_SINES (1000)
Chris@4 51 #define MAX_LOAD (1.2)
Chris@4 52 #define SAMPLE_RATE (44100)
Chris@4 53 #define FRAMES_PER_BUFFER (512)
Chris@4 54 #ifndef M_PI
Chris@4 55 #define M_PI (3.14159265)
Chris@4 56 #endif
Chris@4 57 #define TWOPI (M_PI * 2.0)
Chris@4 58
Chris@4 59 typedef struct paTestData
Chris@4 60 {
Chris@4 61 int sineCount;
Chris@4 62 double phases[MAX_SINES];
Chris@4 63 int countUnderflows;
Chris@4 64 int outputUnderflowCount;
Chris@4 65 }
Chris@4 66 paTestData;
Chris@4 67
Chris@4 68 /* This routine will be called by the PortAudio engine when audio is needed.
Chris@4 69 ** It may called at interrupt level on some machines so don't do anything
Chris@4 70 ** that could mess up the system like calling malloc() or free().
Chris@4 71 */
Chris@4 72 static int patestCallback( const void *inputBuffer, void *outputBuffer,
Chris@4 73 unsigned long framesPerBuffer,
Chris@4 74 const PaStreamCallbackTimeInfo* timeInfo,
Chris@4 75 PaStreamCallbackFlags statusFlags,
Chris@4 76 void *userData )
Chris@4 77 {
Chris@4 78 paTestData *data = (paTestData*)userData;
Chris@4 79 float *out = (float*)outputBuffer;
Chris@4 80 unsigned long i;
Chris@4 81 int j;
Chris@4 82 int finished = paContinue;
Chris@4 83 (void) timeInfo; /* Prevent unused variable warning. */
Chris@4 84 (void) inputBuffer; /* Prevent unused variable warning. */
Chris@4 85
Chris@4 86
Chris@4 87 if( data->countUnderflows && (statusFlags & paOutputUnderflow) )
Chris@55 88 {
Chris@4 89 data->outputUnderflowCount++;
Chris@55 90 }
Chris@4 91 for( i=0; i<framesPerBuffer; i++ )
Chris@4 92 {
Chris@4 93 float output = 0.0;
Chris@4 94 double phaseInc = 0.02;
Chris@4 95 double phase;
Chris@4 96
Chris@4 97 for( j=0; j<data->sineCount; j++ )
Chris@4 98 {
Chris@4 99 /* Advance phase of next oscillator. */
Chris@4 100 phase = data->phases[j];
Chris@4 101 phase += phaseInc;
Chris@4 102 if( phase > TWOPI ) phase -= TWOPI;
Chris@4 103
Chris@4 104 phaseInc *= 1.02;
Chris@4 105 if( phaseInc > 0.5 ) phaseInc *= 0.5;
Chris@4 106
Chris@4 107 /* This is not a very efficient way to calc sines. */
Chris@4 108 output += (float) sin( phase );
Chris@4 109 data->phases[j] = phase;
Chris@4 110 }
Chris@4 111 *out++ = (float) (output / data->sineCount);
Chris@4 112 }
Chris@4 113
Chris@4 114 return finished;
Chris@4 115 }
Chris@4 116
Chris@4 117 /*******************************************************************/
Chris@4 118 int main(void);
Chris@4 119 int main(void)
Chris@4 120 {
Chris@4 121 PaStreamParameters outputParameters;
Chris@4 122 PaStream *stream;
Chris@4 123 PaError err;
Chris@4 124 int safeSineCount, stressedSineCount;
Chris@55 125 int sineCount;
Chris@4 126 int safeUnderflowCount, stressedUnderflowCount;
Chris@4 127 paTestData data = {0};
Chris@4 128 double load;
Chris@55 129 double suggestedLatency;
Chris@4 130
Chris@4 131
Chris@4 132 printf("PortAudio Test: output sine waves, count underflows. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
Chris@4 133 SAMPLE_RATE, FRAMES_PER_BUFFER, (float)MAX_LOAD );
Chris@4 134
Chris@4 135 err = Pa_Initialize();
Chris@4 136 if( err != paNoError ) goto error;
Chris@4 137
Chris@4 138 outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
Chris@4 139 if (outputParameters.device == paNoDevice) {
Chris@4 140 fprintf(stderr,"Error: No default output device.\n");
Chris@4 141 goto error;
Chris@4 142 }
Chris@4 143 outputParameters.channelCount = 1; /* mono output */
Chris@4 144 outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
Chris@55 145 suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
Chris@55 146 outputParameters.suggestedLatency = suggestedLatency;
Chris@4 147 outputParameters.hostApiSpecificStreamInfo = NULL;
Chris@4 148
Chris@4 149 err = Pa_OpenStream(
Chris@4 150 &stream,
Chris@4 151 NULL, /* no input */
Chris@4 152 &outputParameters,
Chris@4 153 SAMPLE_RATE,
Chris@4 154 FRAMES_PER_BUFFER,
Chris@4 155 paClipOff, /* we won't output out of range samples so don't bother clipping them */
Chris@4 156 patestCallback,
Chris@4 157 &data );
Chris@4 158 if( err != paNoError ) goto error;
Chris@4 159 err = Pa_StartStream( stream );
Chris@4 160 if( err != paNoError ) goto error;
Chris@4 161
Chris@4 162 printf("Establishing load conditions...\n" );
Chris@4 163
Chris@4 164 /* Determine number of sines required to get to 50% */
Chris@4 165 do
Chris@4 166 {
Chris@55 167 Pa_Sleep( 100 );
Chris@4 168
Chris@4 169 load = Pa_GetStreamCpuLoad( stream );
Chris@4 170 printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
Chris@4 171
Chris@55 172 if( load < 0.3 )
Chris@55 173 {
Chris@55 174 data.sineCount += 10;
Chris@55 175 }
Chris@55 176 else if( load < 0.4 )
Chris@55 177 {
Chris@55 178 data.sineCount += 2;
Chris@55 179 }
Chris@55 180 else
Chris@55 181 {
Chris@55 182 data.sineCount += 1;
Chris@55 183 }
Chris@4 184 }
Chris@4 185 while( load < 0.5 && data.sineCount < (MAX_SINES-1));
Chris@4 186
Chris@4 187 safeSineCount = data.sineCount;
Chris@4 188
Chris@4 189 /* Calculate target stress value then ramp up to that level*/
Chris@4 190 stressedSineCount = (int) (2.0 * data.sineCount * MAX_LOAD );
Chris@4 191 if( stressedSineCount > MAX_SINES )
Chris@4 192 stressedSineCount = MAX_SINES;
Chris@55 193 sineCount = data.sineCount;
Chris@55 194 for( ; sineCount < stressedSineCount; sineCount+=4 )
Chris@4 195 {
Chris@55 196 data.sineCount = sineCount;
Chris@4 197 Pa_Sleep( 100 );
Chris@4 198 load = Pa_GetStreamCpuLoad( stream );
Chris@55 199 printf("STRESSING: sineCount = %d, CPU load = %f\n", sineCount, load );
Chris@4 200 }
Chris@4 201
Chris@55 202 printf("Counting underflows for 2 seconds.\n");
Chris@4 203 data.countUnderflows = 1;
Chris@55 204 Pa_Sleep( 2000 );
Chris@4 205
Chris@4 206 stressedUnderflowCount = data.outputUnderflowCount;
Chris@4 207
Chris@4 208 data.countUnderflows = 0;
Chris@4 209 data.sineCount = safeSineCount;
Chris@4 210
Chris@4 211 printf("Resuming safe load...\n");
Chris@4 212 Pa_Sleep( 1500 );
Chris@4 213 data.outputUnderflowCount = 0;
Chris@4 214 Pa_Sleep( 1500 );
Chris@4 215 load = Pa_GetStreamCpuLoad( stream );
Chris@4 216 printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
Chris@4 217
Chris@4 218 printf("Counting underflows for 5 seconds.\n");
Chris@4 219 data.countUnderflows = 1;
Chris@4 220 Pa_Sleep( 5000 );
Chris@4 221
Chris@4 222 safeUnderflowCount = data.outputUnderflowCount;
Chris@4 223
Chris@4 224 printf("Stop stream.\n");
Chris@4 225 err = Pa_StopStream( stream );
Chris@4 226 if( err != paNoError ) goto error;
Chris@4 227
Chris@4 228 err = Pa_CloseStream( stream );
Chris@4 229 if( err != paNoError ) goto error;
Chris@4 230
Chris@4 231 Pa_Terminate();
Chris@4 232
Chris@55 233 printf("suggestedLatency = %f\n", suggestedLatency);
Chris@55 234
Chris@55 235 // Report pass or fail
Chris@4 236 if( stressedUnderflowCount == 0 )
Chris@55 237 printf("Test FAILED, no output underflows detected under stress.\n");
Chris@4 238 else
Chris@55 239 printf("Test %s, %d expected output underflows detected under stress, "
Chris@55 240 "%d unexpected underflows detected under safe load.\n",
Chris@55 241 (safeUnderflowCount == 0) ? "PASSED" : "FAILED",
Chris@55 242 stressedUnderflowCount, safeUnderflowCount );
Chris@4 243
Chris@4 244 return err;
Chris@4 245 error:
Chris@4 246 Pa_Terminate();
Chris@4 247 fprintf( stderr, "An error occured while using the portaudio stream\n" );
Chris@4 248 fprintf( stderr, "Error number: %d\n", err );
Chris@4 249 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
Chris@4 250 return err;
Chris@4 251 }