tomwalters@0
|
1 /*
|
tomwalters@0
|
2 noise.c generate samples of a normally distributed deviate (white noise)
|
tomwalters@0
|
3 ------- in binary shorts or floats.
|
tomwalters@0
|
4
|
tomwalters@0
|
5
|
tomwalters@0
|
6 The routine gasdev returns normally distributed numbers with zero mean
|
tomwalters@0
|
7 and unit variance, using the Box-Muller method described in Numerical
|
tomwalters@0
|
8 recipes [p203]. It is based upon a random number generator ran1 which
|
tomwalters@0
|
9 generates uniformly distributed numbers in the range [0,1].
|
tomwalters@0
|
10
|
tomwalters@0
|
11 The period of the random sequences is claimed to be infinite,
|
tomwalters@0
|
12 [Numerical recipes, p196].
|
tomwalters@0
|
13 Random sequences which repeat can be heard as periodic if the sequence
|
tomwalters@0
|
14 repeats every 4secs or less. Therefore the period of a random sequence
|
tomwalters@0
|
15 should be greater than 5secs, or 100000 samples (at 20kHz samplerate).
|
tomwalters@0
|
16
|
tomwalters@0
|
17 The seed of each random sequence is the variable "seed", which should be
|
tomwalters@0
|
18 set to any negative value to initialize or re-initialize the sequence,
|
tomwalters@0
|
19 [Numerical recipes, p196]. The same seed gives the same random sequence.
|
tomwalters@0
|
20 Otherwise, (and by default when seed=off or seed=0), the system call
|
tomwalters@0
|
21 getpid() supplies a new seed each run.
|
tomwalters@0
|
22
|
tomwalters@0
|
23 Each sample is scaled using the given mean and variance parameters so that
|
tomwalters@0
|
24 samples are drawn from a normal distribution of given mean and variance.
|
tomwalters@0
|
25 */
|
tomwalters@0
|
26
|
tomwalters@0
|
27
|
tomwalters@0
|
28 #include <stdio.h>
|
tomwalters@0
|
29 #include <math.h>
|
tomwalters@0
|
30 #include "options.h"
|
tomwalters@0
|
31 #include "units.h"
|
tomwalters@0
|
32 #include "strmatch.h"
|
tomwalters@0
|
33
|
tomwalters@0
|
34 char applic[] = "generate white noise. " ;
|
tomwalters@0
|
35 char usage[] = "noise [options]" ;
|
tomwalters@0
|
36
|
tomwalters@0
|
37 static char *helpstr, *debugstr, *sampstr, *durstr, *meanstr, *varstr, *seedstr, *datastr ;
|
tomwalters@0
|
38
|
tomwalters@0
|
39 static Options option[] = {
|
tomwalters@0
|
40 { "help" , "off" , &helpstr , "help" , DEBUG },
|
tomwalters@0
|
41 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
|
tomwalters@0
|
42 { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL },
|
tomwalters@0
|
43 { "duration" , "500ms" , &durstr , "duration of waveform" , VAL },
|
tomwalters@0
|
44 { "mean" , "0" , &meanstr , "mean value of waveform" , VAL },
|
tomwalters@0
|
45 { "variance" , "500" , &varstr , "variance of values" , VAL },
|
tomwalters@0
|
46 { "seed" , "off" , &seedstr , "seed for random sequence" , VAL },
|
tomwalters@0
|
47 { "type" , "short" , &datastr , "o/p datatype (short/float)", VAL },
|
tomwalters@0
|
48 ( char * ) 0 } ;
|
tomwalters@0
|
49
|
tomwalters@0
|
50
|
tomwalters@0
|
51 int samplerate ;
|
tomwalters@0
|
52 int duration ;
|
tomwalters@0
|
53 float mean ;
|
tomwalters@0
|
54 float variance ;
|
tomwalters@0
|
55 int seed ;
|
tomwalters@0
|
56
|
tomwalters@0
|
57
|
tomwalters@0
|
58 main (argc,argv)
|
tomwalters@0
|
59 int argc;
|
tomwalters@0
|
60 char **argv;
|
tomwalters@0
|
61 {
|
tomwalters@0
|
62 float gasdev();
|
tomwalters@0
|
63 float n2 ;
|
tomwalters@0
|
64 short n1 ;
|
tomwalters@0
|
65
|
tomwalters@0
|
66 getopts( option,argc,argv ) ;
|
tomwalters@0
|
67 if ( !isoff( helpstr ) )
|
tomwalters@0
|
68 helpopts3( helpstr, argv[0], applic, usage, option ) ;
|
tomwalters@0
|
69
|
tomwalters@0
|
70 samplerate = to_Hz( sampstr, 0 ) ;
|
tomwalters@0
|
71 duration = to_p( durstr, samplerate ) ;
|
tomwalters@0
|
72 mean = atof( meanstr ) ;
|
tomwalters@0
|
73 variance = atof( varstr ) ;
|
tomwalters@0
|
74
|
tomwalters@0
|
75 if ( isoff( seedstr ) )
|
tomwalters@0
|
76 seed = ( -getpid() ) ;
|
tomwalters@0
|
77 else
|
tomwalters@0
|
78 seed = atoi( seedstr ) ;
|
tomwalters@0
|
79
|
tomwalters@0
|
80
|
tomwalters@0
|
81 if ( iststr( datastr, "short" ) )
|
tomwalters@0
|
82 while ( duration-- ) {
|
tomwalters@0
|
83 n1 = (short)( gasdev( &seed ) * variance + mean ) ;
|
tomwalters@0
|
84 fwrite( &n1, sizeof(short), 1, stdout ) ;
|
tomwalters@0
|
85 }
|
tomwalters@0
|
86
|
tomwalters@0
|
87 else if ( iststr( datastr, "float" ) )
|
tomwalters@0
|
88 while ( duration-- ) {
|
tomwalters@0
|
89 n2 = gasdev( &seed ) * variance + mean ;
|
tomwalters@0
|
90 fwrite( &n2, sizeof(float), 1, stdout ) ;
|
tomwalters@0
|
91 }
|
tomwalters@0
|
92
|
tomwalters@0
|
93 else
|
tomwalters@0
|
94 fprintf(stderr,"noise: unknown datatype [%s]\n", datastr) ;
|
tomwalters@0
|
95 }
|
tomwalters@0
|
96
|
tomwalters@0
|
97
|
tomwalters@0
|
98 float gasdev( idum )
|
tomwalters@0
|
99 int *idum;
|
tomwalters@0
|
100 {
|
tomwalters@0
|
101 static int iset=0;
|
tomwalters@0
|
102 static float gset;
|
tomwalters@0
|
103 float fac,r,v1,v2;
|
tomwalters@0
|
104 float ran1();
|
tomwalters@0
|
105
|
tomwalters@0
|
106 if ( iset == 0 ) {
|
tomwalters@0
|
107 do {
|
tomwalters@0
|
108 v1 = 2.0 * ran1( idum ) - 1.0 ;
|
tomwalters@0
|
109 v2 = 2.0 * ran1( idum ) - 1.0 ;
|
tomwalters@0
|
110 r = v1*v1+v2*v2;
|
tomwalters@0
|
111 } while (r >= 1.0);
|
tomwalters@0
|
112 fac = sqrt(-2.0*log(r)/r);
|
tomwalters@0
|
113 gset = v1*fac;
|
tomwalters@0
|
114 iset = 1;
|
tomwalters@0
|
115 return v2*fac;
|
tomwalters@0
|
116 }
|
tomwalters@0
|
117 else {
|
tomwalters@0
|
118 iset = 0;
|
tomwalters@0
|
119 return gset;
|
tomwalters@0
|
120 }
|
tomwalters@0
|
121 }
|
tomwalters@0
|
122
|
tomwalters@0
|
123
|
tomwalters@0
|
124 #define M1 259200
|
tomwalters@0
|
125 #define IA1 7141
|
tomwalters@0
|
126 #define IC1 54773
|
tomwalters@0
|
127 #define RM1 (1.0/M1)
|
tomwalters@0
|
128 #define M2 134456
|
tomwalters@0
|
129 #define IA2 8121
|
tomwalters@0
|
130 #define IC2 28411
|
tomwalters@0
|
131 #define RM2 (1.0/M2)
|
tomwalters@0
|
132 #define M3 243000
|
tomwalters@0
|
133 #define IA3 4561
|
tomwalters@0
|
134 #define IC3 51349
|
tomwalters@0
|
135
|
tomwalters@0
|
136 float ran1( idum )
|
tomwalters@0
|
137 int *idum;
|
tomwalters@0
|
138 {
|
tomwalters@0
|
139 static long ix1,ix2,ix3;
|
tomwalters@0
|
140 static float r[98];
|
tomwalters@0
|
141 float temp;
|
tomwalters@0
|
142 static int iff=0;
|
tomwalters@0
|
143 int j;
|
tomwalters@0
|
144
|
tomwalters@0
|
145 if ( *idum < 0 || iff == 0 ) {
|
tomwalters@0
|
146 iff=1;
|
tomwalters@0
|
147 ix1=(IC1-(*idum)) % M1;
|
tomwalters@0
|
148 ix1=(IA1*ix1+IC1) % M1;
|
tomwalters@0
|
149 ix2=ix1 % M2;
|
tomwalters@0
|
150 ix1=(IA1*ix1+IC1) % M1;
|
tomwalters@0
|
151 ix3=ix1 % M3;
|
tomwalters@0
|
152 for (j=1;j<=97;j++) {
|
tomwalters@0
|
153 ix1=(IA1*ix1+IC1) % M1;
|
tomwalters@0
|
154 ix2=(IA2*ix2+IC2) % M2;
|
tomwalters@0
|
155 r[j]=(ix1+ix2*RM2)*RM1;
|
tomwalters@0
|
156 }
|
tomwalters@0
|
157 *idum=1;
|
tomwalters@0
|
158 }
|
tomwalters@0
|
159 ix1=(IA1*ix1+IC1) % M1;
|
tomwalters@0
|
160 ix2=(IA2*ix2+IC2) % M2;
|
tomwalters@0
|
161 ix3=(IA3*ix3+IC3) % M3;
|
tomwalters@0
|
162 j=1 + ((97*ix3)/M3);
|
tomwalters@0
|
163 if (j > 97 || j < 1) {
|
tomwalters@0
|
164 fprintf(stderr, "noise: This cannot happen\n");
|
tomwalters@0
|
165 exit(1);
|
tomwalters@0
|
166 }
|
tomwalters@0
|
167 temp=r[j];
|
tomwalters@0
|
168 r[j]=(ix1+ix2*RM2)*RM1;
|
tomwalters@0
|
169 return temp;
|
tomwalters@0
|
170 }
|
tomwalters@0
|
171
|