paex_pink.c
Go to the documentation of this file.00001
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <stdio.h>
00058 #include <math.h>
00059 #include "portaudio.h"
00060
00061 #define PINK_MAX_RANDOM_ROWS (30)
00062 #define PINK_RANDOM_BITS (24)
00063 #define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS)
00064
00065 typedef struct
00066 {
00067 long pink_Rows[PINK_MAX_RANDOM_ROWS];
00068 long pink_RunningSum;
00069 int pink_Index;
00070 int pink_IndexMask;
00071 float pink_Scalar;
00072 }
00073 PinkNoise;
00074
00075
00076 static unsigned long GenerateRandomNumber( void );
00077 void InitializePinkNoise( PinkNoise *pink, int numRows );
00078 float GeneratePinkNoise( PinkNoise *pink );
00079
00080
00081
00082 static unsigned long GenerateRandomNumber( void )
00083 {
00084
00085 static unsigned long randSeed = 22222;
00086 randSeed = (randSeed * 196314165) + 907633515;
00087 return randSeed;
00088 }
00089
00090
00091
00092 void InitializePinkNoise( PinkNoise *pink, int numRows )
00093 {
00094 int i;
00095 long pmax;
00096 pink->pink_Index = 0;
00097 pink->pink_IndexMask = (1<<numRows) - 1;
00098
00099 pmax = (numRows + 1) * (1<<(PINK_RANDOM_BITS-1));
00100 pink->pink_Scalar = 1.0f / pmax;
00101
00102 for( i=0; i<numRows; i++ ) pink->pink_Rows[i] = 0;
00103 pink->pink_RunningSum = 0;
00104 }
00105
00106 #define PINK_MEASURE
00107 #ifdef PINK_MEASURE
00108 float pinkMax = -999.0;
00109 float pinkMin = 999.0;
00110 #endif
00111
00112
00113 float GeneratePinkNoise( PinkNoise *pink )
00114 {
00115 long newRandom;
00116 long sum;
00117 float output;
00118
00119 pink->pink_Index = (pink->pink_Index + 1) & pink->pink_IndexMask;
00120
00121 if( pink->pink_Index != 0 )
00122 {
00123
00124
00125 int numZeros = 0;
00126 int n = pink->pink_Index;
00127 while( (n & 1) == 0 )
00128 {
00129 n = n >> 1;
00130 numZeros++;
00131 }
00132
00133
00134
00135
00136 pink->pink_RunningSum -= pink->pink_Rows[numZeros];
00137 newRandom = ((long)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
00138 pink->pink_RunningSum += newRandom;
00139 pink->pink_Rows[numZeros] = newRandom;
00140 }
00141
00142
00143 newRandom = ((long)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
00144 sum = pink->pink_RunningSum + newRandom;
00145
00146 output = pink->pink_Scalar * sum;
00147 #ifdef PINK_MEASURE
00148
00149 if( output > pinkMax ) pinkMax = output;
00150 else if( output < pinkMin ) pinkMin = output;
00151 #endif
00152 return output;
00153 }
00154
00155
00156 #define PINK_TEST
00157 #ifdef PINK_TEST
00158
00159
00160 typedef struct
00161 {
00162 PinkNoise leftPink;
00163 PinkNoise rightPink;
00164 unsigned int sampsToGo;
00165 }
00166 paTestData;
00167
00168
00169
00170
00171
00172 static int patestCallback(const void* inputBuffer,
00173 void* outputBuffer,
00174 unsigned long framesPerBuffer,
00175 const PaStreamCallbackTimeInfo* timeInfo,
00176 PaStreamCallbackFlags statusFlags,
00177 void* userData)
00178 {
00179 int finished;
00180 int i;
00181 int numFrames;
00182 paTestData *data = (paTestData*)userData;
00183 float *out = (float*)outputBuffer;
00184 (void) inputBuffer;
00185
00186
00187 if( data->sampsToGo < framesPerBuffer )
00188 {
00189 numFrames = data->sampsToGo;
00190 finished = 1;
00191 }
00192 else
00193 {
00194 numFrames = framesPerBuffer;
00195 finished = 0;
00196 }
00197 for( i=0; i<numFrames; i++ )
00198 {
00199 *out++ = GeneratePinkNoise( &data->leftPink );
00200 *out++ = GeneratePinkNoise( &data->rightPink );
00201 }
00202 data->sampsToGo -= numFrames;
00203 return finished;
00204 }
00205
00206
00207 int main(void);
00208 int main(void)
00209 {
00210 PaStream* stream;
00211 PaError err;
00212 paTestData data;
00213 PaStreamParameters outputParameters;
00214 int totalSamps;
00215 static const double SR = 44100.0;
00216 static const int FPB = 2048;
00217
00218
00219 InitializePinkNoise( &data.leftPink, 12 );
00220 InitializePinkNoise( &data.rightPink, 16 );
00221
00222
00223 {
00224 int i;
00225 float pink;
00226 for( i=0; i<20; i++ )
00227 {
00228 pink = GeneratePinkNoise( &data.leftPink );
00229 printf("Pink = %f\n", pink );
00230 }
00231 }
00232
00233 data.sampsToGo = totalSamps = (int)(60.0 * SR);
00234 err = Pa_Initialize();
00235 if( err != paNoError ) goto error;
00236
00237
00238 outputParameters.device = Pa_GetDefaultOutputDevice();
00239 if (outputParameters.device == paNoDevice) {
00240 fprintf(stderr,"Error: No default output device.\n");
00241 goto error;
00242 }
00243 outputParameters.channelCount = 2;
00244 outputParameters.hostApiSpecificStreamInfo = NULL;
00245 outputParameters.sampleFormat = paFloat32;
00246 outputParameters.suggestedLatency =
00247 Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
00248 err = Pa_OpenStream(&stream,
00249 NULL,
00250 &outputParameters,
00251 SR,
00252 FPB,
00253 paClipOff,
00254 patestCallback,
00255 &data);
00256 if( err != paNoError ) goto error;
00257
00258 err = Pa_StartStream( stream );
00259 if( err != paNoError ) goto error;
00260
00261 printf("Stereo pink noise for one minute...\n");
00262
00263 while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
00264 if( err < 0 ) goto error;
00265
00266 err = Pa_CloseStream( stream );
00267 if( err != paNoError ) goto error;
00268 #ifdef PINK_MEASURE
00269 printf("Pink min = %f, max = %f\n", pinkMin, pinkMax );
00270 #endif
00271 Pa_Terminate();
00272 return 0;
00273 error:
00274 Pa_Terminate();
00275 fprintf( stderr, "An error occured while using the portaudio stream\n" );
00276 fprintf( stderr, "Error number: %d\n", err );
00277 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
00278 return 0;
00279 }
00280 #endif