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