00001
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
00058
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <string.h>
00062 #include <math.h>
00063 #include <time.h>
00064
00065 #include "portaudio.h"
00066 #include "pa_ringbuffer.h"
00067 #include "pa_util.h"
00068
00069 #define PINK_MAX_RANDOM_ROWS (30)
00070 #define PINK_RANDOM_BITS (24)
00071 #define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS)
00072
00073 typedef struct
00074 {
00075 long pink_Rows[PINK_MAX_RANDOM_ROWS];
00076 long pink_RunningSum;
00077 int pink_Index;
00078 int pink_IndexMask;
00079 float pink_Scalar;
00080 }
00081 PinkNoise;
00082
00083 typedef struct
00084 {
00085 float bq_b0;
00086 float bq_b1;
00087 float bq_b2;
00088 float bq_a1;
00089 float bq_a2;
00090 } BiQuad;
00091
00092 typedef enum
00093 {
00094 State_kAttack,
00095 State_kPreDecay,
00096 State_kDecay,
00097 State_kCnt,
00098 } EnvState;
00099
00100 typedef struct
00101 {
00102 PinkNoise wave_left;
00103 PinkNoise wave_right;
00104
00105 BiQuad wave_bq_coeffs;
00106 float wave_bq_left[2];
00107 float wave_bq_right[2];
00108
00109 EnvState wave_envelope_state;
00110 float wave_envelope_level;
00111 float wave_envelope_max_level;
00112 float wave_pan_left;
00113 float wave_pan_right;
00114 float wave_attack_incr;
00115 float wave_decay_incr;
00116
00117 } OceanWave;
00118
00119
00120 static unsigned long GenerateRandomNumber( void );
00121 void InitializePinkNoise( PinkNoise *pink, int numRows );
00122 float GeneratePinkNoise( PinkNoise *pink );
00123 unsigned GenerateWave( OceanWave* wave, float* output, unsigned noOfFrames);
00124
00125
00126
00127 static unsigned long GenerateRandomNumber( void )
00128 {
00129
00130 static unsigned long randSeed = 22222;
00131 randSeed = (randSeed * 196314165) + 907633515;
00132 return randSeed;
00133 }
00134
00135
00136
00137 void InitializePinkNoise( PinkNoise *pink, int numRows )
00138 {
00139 int i;
00140 long pmax;
00141 pink->pink_Index = 0;
00142 pink->pink_IndexMask = (1<<numRows) - 1;
00143
00144 pmax = (numRows + 1) * (1<<(PINK_RANDOM_BITS-1));
00145 pink->pink_Scalar = 1.0f / pmax;
00146
00147 for( i=0; i<numRows; i++ ) pink->pink_Rows[i] = 0;
00148 pink->pink_RunningSum = 0;
00149 }
00150
00151
00152 float GeneratePinkNoise( PinkNoise *pink )
00153 {
00154 long newRandom;
00155 long sum;
00156 float output;
00157
00158 pink->pink_Index = (pink->pink_Index + 1) & pink->pink_IndexMask;
00159
00160 if( pink->pink_Index != 0 )
00161 {
00162
00163
00164 int numZeros = 0;
00165 int n = pink->pink_Index;
00166 while( (n & 1) == 0 )
00167 {
00168 n = n >> 1;
00169 numZeros++;
00170 }
00171
00172
00173
00174
00175 pink->pink_RunningSum -= pink->pink_Rows[numZeros];
00176 newRandom = ((long)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
00177 pink->pink_RunningSum += newRandom;
00178 pink->pink_Rows[numZeros] = newRandom;
00179 }
00180
00181
00182 newRandom = ((long)GenerateRandomNumber()) >> PINK_RANDOM_SHIFT;
00183 sum = pink->pink_RunningSum + newRandom;
00184
00185 output = pink->pink_Scalar * sum;
00186 return output;
00187 }
00188
00189 float ProcessBiquad(const BiQuad* coeffs, float* memory, float input)
00190 {
00191 float w = input - coeffs->bq_a1 * memory[0] - coeffs->bq_a2 * memory[1];
00192 float out = coeffs->bq_b1 * memory[0] + coeffs->bq_b2 * memory[1] + coeffs->bq_b0 * w;
00193 memory[1] = memory[0];
00194 memory[0] = w;
00195 return out;
00196 }
00197
00198 static const float one_over_2Q_LP = 0.3f;
00199 static const float one_over_2Q_HP = 1.0f;
00200
00201 unsigned GenerateWave( OceanWave* wave, float* output, unsigned noOfFrames )
00202 {
00203 unsigned retval=0,i;
00204 float targetLevel, levelIncr, currentLevel;
00205 switch (wave->wave_envelope_state)
00206 {
00207 case State_kAttack:
00208 targetLevel = noOfFrames * wave->wave_attack_incr + wave->wave_envelope_level;
00209 if (targetLevel >= wave->wave_envelope_max_level)
00210 {
00211
00212 wave->wave_envelope_state = State_kPreDecay;
00213 targetLevel = wave->wave_envelope_max_level;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 {
00229 const float w0 = 3.141592654f * targetLevel / wave->wave_envelope_max_level;
00230 const float alpha = sinf(w0) * one_over_2Q_LP;
00231 const float cosw0 = cosf(w0);
00232 const float a0_fact = 1.0f / (1.0f + alpha);
00233 wave->wave_bq_coeffs.bq_b1 = (1.0f - cosw0) * a0_fact;
00234 wave->wave_bq_coeffs.bq_b0 = wave->wave_bq_coeffs.bq_b1 * 0.5f;
00235 wave->wave_bq_coeffs.bq_b2 = wave->wave_bq_coeffs.bq_b0;
00236 wave->wave_bq_coeffs.bq_a2 = (1.0f - alpha) * a0_fact;
00237 wave->wave_bq_coeffs.bq_a1 = -2.0f * cosw0 * a0_fact;
00238 }
00239 break;
00240
00241 case State_kPreDecay:
00242
00243 memset(wave->wave_bq_left, 0, 2 * sizeof(float));
00244 memset(wave->wave_bq_right, 0, 2 * sizeof(float));
00245 wave->wave_envelope_state = State_kDecay;
00246
00247
00248
00249 case State_kDecay:
00250 targetLevel = noOfFrames * wave->wave_decay_incr + wave->wave_envelope_level;
00251 if (targetLevel < 0.001f)
00252 {
00253
00254 wave->wave_envelope_state = 3;
00255 retval = 1;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 {
00271 const float v = targetLevel / wave->wave_envelope_max_level;
00272 const float w0 = 1.5707963f * (1.0f - (v*v));
00273 const float alpha = sinf(w0) * one_over_2Q_HP;
00274 const float cosw0 = cosf(w0);
00275 const float a0_fact = 1.0f / (1.0f + alpha);
00276 wave->wave_bq_coeffs.bq_b1 = (float)(- (1 + cosw0) * a0_fact);
00277 wave->wave_bq_coeffs.bq_b0 = -wave->wave_bq_coeffs.bq_b1 * 0.5f;
00278 wave->wave_bq_coeffs.bq_b2 = wave->wave_bq_coeffs.bq_b0;
00279 wave->wave_bq_coeffs.bq_a2 = (float)((1.0 - alpha) * a0_fact);
00280 wave->wave_bq_coeffs.bq_a1 = (float)(-2.0 * cosw0 * a0_fact);
00281 }
00282 break;
00283
00284 default:
00285 break;
00286 }
00287
00288 currentLevel = wave->wave_envelope_level;
00289 wave->wave_envelope_level = targetLevel;
00290 levelIncr = (targetLevel - currentLevel) / noOfFrames;
00291
00292 for (i = 0; i < noOfFrames; ++i, currentLevel += levelIncr)
00293 {
00294 (*output++) += ProcessBiquad(&wave->wave_bq_coeffs, wave->wave_bq_left, (GeneratePinkNoise(&wave->wave_left))) * currentLevel * wave->wave_pan_left;
00295 (*output++) += ProcessBiquad(&wave->wave_bq_coeffs, wave->wave_bq_right, (GeneratePinkNoise(&wave->wave_right))) * currentLevel * wave->wave_pan_right;
00296 }
00297
00298 return retval;
00299 }
00300
00301
00302
00303
00304
00305 typedef struct
00306 {
00307 OceanWave* waves[16];
00308 unsigned noOfActiveWaves;
00309
00310
00311 PaUtilRingBuffer rBufToRT;
00312 void* rBufToRTData;
00313
00314
00315 PaUtilRingBuffer rBufFromRT;
00316 void* rBufFromRTData;
00317 }
00318 paTestData;
00319
00320
00321
00322
00323
00324 static int patestCallback(const void* inputBuffer,
00325 void* outputBuffer,
00326 unsigned long framesPerBuffer,
00327 const PaStreamCallbackTimeInfo* timeInfo,
00328 PaStreamCallbackFlags statusFlags,
00329 void* userData)
00330 {
00331 int i;
00332 paTestData *data = (paTestData*)userData;
00333 float *out = (float*)outputBuffer;
00334 (void) inputBuffer;
00335
00336
00337 memset(out, 0, framesPerBuffer * 2 * sizeof(float));
00338
00339 for (i = 0; i < 16; ++i)
00340 {
00341
00342 if (data->waves[i] == 0 && PaUtil_GetRingBufferReadAvailable(&data->rBufToRT))
00343 {
00344 OceanWave* ptr = 0;
00345 PaUtil_ReadRingBuffer(&data->rBufToRT, &ptr, 1);
00346 data->waves[i] = ptr;
00347 }
00348
00349 if (data->waves[i] != 0)
00350 {
00351 if (GenerateWave(data->waves[i], out, framesPerBuffer))
00352 {
00353
00354 PaUtil_WriteRingBuffer(&data->rBufFromRT, &data->waves[i], 1);
00355 data->waves[i] = 0;
00356 }
00357 }
00358 }
00359 return paContinue;
00360 }
00361
00362 #define NEW_ROW_SIZE (12 + (8*rand())/RAND_MAX)
00363
00364 OceanWave* InitializeWave(double SR, float attackInSeconds, float maxLevel, float positionLeftRight)
00365 {
00366 OceanWave* wave = NULL;
00367 static unsigned lastNoOfRows = 12;
00368 unsigned newNoOfRows;
00369
00370 wave = (OceanWave*)PaUtil_AllocateMemory(sizeof(OceanWave));
00371 if (wave != NULL)
00372 {
00373 InitializePinkNoise(&wave->wave_left, lastNoOfRows);
00374 while ((newNoOfRows = NEW_ROW_SIZE) == lastNoOfRows);
00375 InitializePinkNoise(&wave->wave_right, newNoOfRows);
00376 lastNoOfRows = newNoOfRows;
00377
00378 wave->wave_envelope_state = State_kAttack;
00379 wave->wave_envelope_level = 0.f;
00380 wave->wave_envelope_max_level = maxLevel;
00381 wave->wave_attack_incr = wave->wave_envelope_max_level / (attackInSeconds * (float)SR);
00382 wave->wave_decay_incr = - wave->wave_envelope_max_level / (attackInSeconds * 4 * (float)SR);
00383
00384 wave->wave_pan_left = sqrtf(1.0 - positionLeftRight);
00385 wave->wave_pan_right = sqrtf(positionLeftRight);
00386 }
00387 return wave;
00388 }
00389
00390 static float GenerateFloatRandom(float minValue, float maxValue)
00391 {
00392 return minValue + ((maxValue - minValue) * rand()) / RAND_MAX;
00393 }
00394
00395
00396 int main(void);
00397 int main(void)
00398 {
00399 PaStream* stream;
00400 PaError err;
00401 paTestData data = {0};
00402 PaStreamParameters outputParameters;
00403 double tstamp;
00404 double tstart;
00405 double tdelta = 0;
00406 static const double SR = 44100.0;
00407 static const int FPB = 128;
00408
00409
00410 data.rBufToRTData = PaUtil_AllocateMemory(sizeof(OceanWave*) * 256);
00411 if (data.rBufToRTData == NULL)
00412 {
00413 return 1;
00414 }
00415 PaUtil_InitializeRingBuffer(&data.rBufToRT, sizeof(OceanWave*), 256, data.rBufToRTData);
00416
00417 data.rBufFromRTData = PaUtil_AllocateMemory(sizeof(OceanWave*) * 256);
00418 if (data.rBufFromRTData == NULL)
00419 {
00420 return 1;
00421 }
00422 PaUtil_InitializeRingBuffer(&data.rBufFromRT, sizeof(OceanWave*), 256, data.rBufFromRTData);
00423
00424 err = Pa_Initialize();
00425 if( err != paNoError ) goto error;
00426
00427
00428 outputParameters.device = Pa_GetDefaultOutputDevice();
00429 if (outputParameters.device == paNoDevice) {
00430 fprintf(stderr,"Error: No default output device.\n");
00431 goto error;
00432 }
00433 outputParameters.channelCount = 2;
00434 outputParameters.hostApiSpecificStreamInfo = NULL;
00435 outputParameters.sampleFormat = paFloat32;
00436 outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
00437 err = Pa_OpenStream(&stream,
00438 NULL,
00439 &outputParameters,
00440 SR,
00441 FPB,
00442 paDitherOff,
00443 patestCallback,
00444 &data);
00445 if( err != paNoError ) goto error;
00446
00447 err = Pa_StartStream( stream );
00448 if( err != paNoError ) goto error;
00449
00450 printf("Stereo \"ocean waves\" for one minute...\n");
00451
00452 tstart = PaUtil_GetTime();
00453 tstamp = tstart;
00454 srand( (unsigned)time(NULL) );
00455
00456 while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
00457 {
00458 const double tcurrent = PaUtil_GetTime();
00459
00460
00461 while (PaUtil_GetRingBufferReadAvailable(&data.rBufFromRT) > 0)
00462 {
00463 OceanWave* ptr = 0;
00464 PaUtil_ReadRingBuffer(&data.rBufFromRT, &ptr, 1);
00465 if (ptr != 0)
00466 {
00467 printf("Wave is deleted...\n");
00468 PaUtil_FreeMemory(ptr);
00469 --data.noOfActiveWaves;
00470 }
00471 }
00472
00473 if (tcurrent - tstart < 60.0)
00474 {
00475 if (tcurrent >= tstamp)
00476 {
00477 double tdelta = GenerateFloatRandom(1.0f, 4.0f);
00478 tstamp += tdelta;
00479
00480 if (data.noOfActiveWaves<16)
00481 {
00482 const float attackTime = GenerateFloatRandom(2.0f, 6.0f);
00483 const float level = GenerateFloatRandom(0.1f, 1.0f);
00484 const float pos = GenerateFloatRandom(0.0f, 1.0f);
00485 OceanWave* p = InitializeWave(SR, attackTime, level, pos);
00486 if (p != NULL)
00487 {
00488
00489 PaUtil_WriteRingBuffer(&data.rBufToRT, &p, 1);
00490 ++data.noOfActiveWaves;
00491
00492 printf("Starting wave at level = %.2f, attack = %.2lf, pos = %.2lf\n", level, attackTime, pos);
00493 }
00494 }
00495 }
00496 }
00497 else
00498 {
00499 if (data.noOfActiveWaves == 0)
00500 {
00501 printf("All waves finished!\n");
00502 break;
00503 }
00504 }
00505
00506 Pa_Sleep(100);
00507 }
00508 if( err < 0 ) goto error;
00509
00510 err = Pa_CloseStream( stream );
00511 if( err != paNoError ) goto error;
00512
00513 if (data.rBufToRTData)
00514 {
00515 PaUtil_FreeMemory(data.rBufToRTData);
00516 }
00517 if (data.rBufFromRTData)
00518 {
00519 PaUtil_FreeMemory(data.rBufFromRTData);
00520 }
00521
00522 Pa_Sleep(1000);
00523
00524 Pa_Terminate();
00525 return 0;
00526
00527 error:
00528 Pa_Terminate();
00529 fprintf( stderr, "An error occured while using the portaudio stream\n" );
00530 fprintf( stderr, "Error number: %d\n", err );
00531 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
00532 return 0;
00533 }