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