Mercurial > hg > aim92
view tools/noise.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line source
/* noise.c generate samples of a normally distributed deviate (white noise) ------- in binary shorts or floats. The routine gasdev returns normally distributed numbers with zero mean and unit variance, using the Box-Muller method described in Numerical recipes [p203]. It is based upon a random number generator ran1 which generates uniformly distributed numbers in the range [0,1]. The period of the random sequences is claimed to be infinite, [Numerical recipes, p196]. Random sequences which repeat can be heard as periodic if the sequence repeats every 4secs or less. Therefore the period of a random sequence should be greater than 5secs, or 100000 samples (at 20kHz samplerate). The seed of each random sequence is the variable "seed", which should be set to any negative value to initialize or re-initialize the sequence, [Numerical recipes, p196]. The same seed gives the same random sequence. Otherwise, (and by default when seed=off or seed=0), the system call getpid() supplies a new seed each run. Each sample is scaled using the given mean and variance parameters so that samples are drawn from a normal distribution of given mean and variance. */ #include <stdio.h> #include <math.h> #include "options.h" #include "units.h" #include "strmatch.h" char applic[] = "generate white noise. " ; char usage[] = "noise [options]" ; static char *helpstr, *debugstr, *sampstr, *durstr, *meanstr, *varstr, *seedstr, *datastr ; static Options option[] = { { "help" , "off" , &helpstr , "help" , DEBUG }, { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL }, { "duration" , "500ms" , &durstr , "duration of waveform" , VAL }, { "mean" , "0" , &meanstr , "mean value of waveform" , VAL }, { "variance" , "500" , &varstr , "variance of values" , VAL }, { "seed" , "off" , &seedstr , "seed for random sequence" , VAL }, { "type" , "short" , &datastr , "o/p datatype (short/float)", VAL }, ( char * ) 0 } ; int samplerate ; int duration ; float mean ; float variance ; int seed ; main (argc,argv) int argc; char **argv; { float gasdev(); float n2 ; short n1 ; getopts( option,argc,argv ) ; if ( !isoff( helpstr ) ) helpopts3( helpstr, argv[0], applic, usage, option ) ; samplerate = to_Hz( sampstr, 0 ) ; duration = to_p( durstr, samplerate ) ; mean = atof( meanstr ) ; variance = atof( varstr ) ; if ( isoff( seedstr ) ) seed = ( -getpid() ) ; else seed = atoi( seedstr ) ; if ( iststr( datastr, "short" ) ) while ( duration-- ) { n1 = (short)( gasdev( &seed ) * variance + mean ) ; fwrite( &n1, sizeof(short), 1, stdout ) ; } else if ( iststr( datastr, "float" ) ) while ( duration-- ) { n2 = gasdev( &seed ) * variance + mean ; fwrite( &n2, sizeof(float), 1, stdout ) ; } else fprintf(stderr,"noise: unknown datatype [%s]\n", datastr) ; } float gasdev( idum ) int *idum; { static int iset=0; static float gset; float fac,r,v1,v2; float ran1(); if ( iset == 0 ) { do { v1 = 2.0 * ran1( idum ) - 1.0 ; v2 = 2.0 * ran1( idum ) - 1.0 ; r = v1*v1+v2*v2; } while (r >= 1.0); fac = sqrt(-2.0*log(r)/r); gset = v1*fac; iset = 1; return v2*fac; } else { iset = 0; return gset; } } #define M1 259200 #define IA1 7141 #define IC1 54773 #define RM1 (1.0/M1) #define M2 134456 #define IA2 8121 #define IC2 28411 #define RM2 (1.0/M2) #define M3 243000 #define IA3 4561 #define IC3 51349 float ran1( idum ) int *idum; { static long ix1,ix2,ix3; static float r[98]; float temp; static int iff=0; int j; if ( *idum < 0 || iff == 0 ) { iff=1; ix1=(IC1-(*idum)) % M1; ix1=(IA1*ix1+IC1) % M1; ix2=ix1 % M2; ix1=(IA1*ix1+IC1) % M1; ix3=ix1 % M3; for (j=1;j<=97;j++) { ix1=(IA1*ix1+IC1) % M1; ix2=(IA2*ix2+IC2) % M2; r[j]=(ix1+ix2*RM2)*RM1; } *idum=1; } ix1=(IA1*ix1+IC1) % M1; ix2=(IA2*ix2+IC2) % M2; ix3=(IA3*ix3+IC3) % M3; j=1 + ((97*ix3)/M3); if (j > 97 || j < 1) { fprintf(stderr, "noise: This cannot happen\n"); exit(1); } temp=r[j]; r[j]=(ix1+ix2*RM2)*RM1; return temp; }