Mercurial > hg > aim92
comparison tools/smooth.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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:5242703e91d3 |
---|---|
1 /* | |
2 smooth.c Low-pass filter by windowing in the time or frequency domain. | |
3 -------- | |
4 | |
5 In the time domain the input is convolved with a unit area Gaussian window. | |
6 In the frequency domain the spectrum is multiplied by a Gaussian mask which | |
7 zeroes higher frequency components. The transform between domains uses the FFT. | |
8 | |
9 One parameter controls the amount of smoothing. This parameter controls the | |
10 size of the window. | |
11 | |
12 Caveats for the frequency-domain approach are descibed in NR p436 (such as | |
13 the damped ringing effect which results when when sharp edges are smoothed). | |
14 | |
15 */ | |
16 | |
17 #include <stdio.h> | |
18 #include <math.h> | |
19 #include "options.h" | |
20 #include "units.h" | |
21 #include "strmatch.h" | |
22 #include "sigproc.h" | |
23 | |
24 char applic[] = "Data smoothing by convolution with Gaussian window." ; | |
25 | |
26 static char *helpstr, *debugstr, *sampstr, *lenstr, *varstr, *domstr ; | |
27 static char *ranstr, *typestr, *sizestr ; | |
28 | |
29 static Options option[] = { | |
30 { "help" , "off" , &helpstr , "help" , DEBUG }, | |
31 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, | |
32 { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL }, | |
33 { "length" , "max" , &lenstr , "Size of input." , VAL }, | |
34 { "variance" , "20" , &varstr , "Variance of Gaussian window" , VAL }, | |
35 { "range" , "4" , &ranstr , "Range in standard deviations about mean", VAL }, | |
36 { "domain" , "time" , &domstr , "Convolve in time or frequency domain" , VAL }, | |
37 { "type" , "short" , &typestr , "Data type input and output" , VAL }, | |
38 { "SIZE" , "262144" , &sizestr , "buffer size (s, ms, samples)" , SVAL }, | |
39 ( char * ) 0 } ; | |
40 | |
41 | |
42 int samplerate ; | |
43 int length ; | |
44 | |
45 float *window ; | |
46 int points ; | |
47 | |
48 short *buf1 ; | |
49 float *buf2 ; | |
50 float *out ; | |
51 FILE *fp ; | |
52 | |
53 | |
54 | |
55 main (argc, argv) | |
56 int argc; | |
57 char **argv; | |
58 { | |
59 int maxlen, i ; | |
60 | |
61 fp = openopts( option,argc,argv ) ; | |
62 if ( !isoff( helpstr ) ) | |
63 helpopts( helpstr, argv[0], applic, option ) ; | |
64 | |
65 samplerate = to_Hz( sampstr ) ; | |
66 | |
67 if ( ismax( lenstr ) ) maxlen = to_p( sizestr, samplerate ) ; | |
68 else maxlen = to_p( lenstr, samplerate ) ; | |
69 | |
70 out = (float *)malloc( maxlen * sizeof(float) ) ; | |
71 window = gauss_window( to_p( sqrt_units( varstr ), samplerate ), atof( ranstr ), &points ) ; | |
72 normalize_area( window, points ) ; | |
73 | |
74 if ( isstr( typestr, "short" ) ) { | |
75 buf1 = (short *)malloc( maxlen * sizeof(short) ) ; | |
76 length = fread( buf1, sizeof(short), maxlen, fp ) ; | |
77 } | |
78 else if ( isstr( typestr, "float" ) ) { | |
79 buf2 = (float *)malloc( maxlen * sizeof(float) ) ; | |
80 length = fread( buf2, sizeof(float), maxlen, fp ) ; | |
81 } | |
82 else { | |
83 fprintf( stderr,"smooth: unknown data type [%s]\n", typestr ) ; | |
84 exit( 1 ) ; | |
85 } | |
86 | |
87 | |
88 if ( length < maxlen ) { | |
89 if ( length == 0 ) { | |
90 fprintf( stderr,"smooth: missing input data\n"); | |
91 exit( 1 ) ; | |
92 } | |
93 if ( !ismax( lenstr ) ) | |
94 fprintf( stderr,"smooth: warning: %d samples found\n", length ) ; | |
95 } | |
96 fclose( fp ) ; | |
97 | |
98 if ( points <= 0 ) { | |
99 fprintf( stderr,"smooth: window size = %d\n", points ) ; | |
100 exit( 1 ) ; | |
101 } | |
102 | |
103 if ( isstr( typestr, "short" ) ) { | |
104 | |
105 if ( points == 1 ) /* no smoothing */ | |
106 fwrite( buf1, sizeof(short), length, stdout ) ; | |
107 | |
108 else if ( iststr( domstr, "time" ) ) | |
109 convolve_time( buf1, length, window, points, out ) ; | |
110 | |
111 else if ( iststr( domstr, "frequency" ) ) | |
112 convolve_freq( buf1, length, window, points, out ) ; | |
113 | |
114 else { | |
115 fprintf( stderr,"smooth: unknown domain [%s]\n", domstr ) ; | |
116 exit( 1 ) ; | |
117 } | |
118 | |
119 ftos( out, buf1, length, 1. ) ; | |
120 fwrite( buf1, sizeof(short), length, stdout ) ; | |
121 } | |
122 | |
123 else { | |
124 | |
125 if ( points == 1 ) /* no smoothing */ | |
126 fwrite( buf2, sizeof(float), length, stdout ) ; | |
127 | |
128 else if ( iststr( domstr, "time" ) ) | |
129 convolve_time2( buf2, length, window, points, out ) ; | |
130 | |
131 else if ( iststr( domstr, "frequency" ) ) | |
132 convolve_freq2( buf2, length, window, points, out ) ; | |
133 | |
134 else { | |
135 fprintf( stderr,"smooth: unknown domain [%s]\n", domstr ) ; | |
136 exit( 1 ) ; | |
137 } | |
138 | |
139 fwrite( out, sizeof(float), length, stdout ) ; | |
140 } | |
141 | |
142 | |
143 } | |
144 | |
145 | |
146 convolve_time2( y, n, x, m, z ) | |
147 float *y ; /* input signal */ | |
148 int n ; /* length of array y */ | |
149 float *x ; /* convolution window or filter impulse response */ | |
150 int m ; /* length of array x */ | |
151 float *z ; /* output signal of length n (same as input) */ | |
152 { | |
153 register int i, j, k, lim1, lim2 ; | |
154 register float sum ; | |
155 | |
156 for ( i = 0 ; i < n ; i++ ) { | |
157 | |
158 k = m - 1 ; | |
159 if ( ( lim1 = i - (m-1)/2 ) < 0 ) { | |
160 k += lim1 ; | |
161 lim1 = 0 ; | |
162 } | |
163 if ( ( lim2 = i + (m-1)/2 ) > n ) | |
164 lim2 = n - 1 ; | |
165 | |
166 sum = 0 ; | |
167 for ( j = lim1 ; j <= lim2 ; j++, --k ) | |
168 sum += x[k] * y[j] ; | |
169 | |
170 z[i] = sum ; | |
171 } | |
172 } | |
173 | |
174 | |
175 /* | |
176 Frequency-domain convolution. | |
177 */ | |
178 | |
179 convolve_freq2( y, n, x, m, z ) | |
180 float *y ; /* input signal */ | |
181 int n ; /* length of array y */ | |
182 float *x ; /* convolution window or filter impulse response */ | |
183 int m ; /* length of array x */ | |
184 float *z ; /* output signal of length n (same as input) */ | |
185 { | |
186 int i, j, n1 ; | |
187 float *data, *respns, *ans ; | |
188 | |
189 n1 = getpower( n + m ) ; /* padded length of input signal */ | |
190 | |
191 data = (float *)malloc( ( n1 + 1 ) * sizeof(float) ) ; | |
192 respns = (float *)malloc( ( n1 + 1 ) * sizeof(float) ) ; | |
193 ans = (float *)malloc( ( n1 * 2 + 1 ) * sizeof(float) ) ; | |
194 | |
195 /* copy and pad signal */ | |
196 | |
197 for ( i = 0 ; i < n ; i++ ) | |
198 data[i] = y[i] ; | |
199 for ( ; i < n1 ; i++ ) | |
200 data[i] = (float)0 ; | |
201 | |
202 /* copy window into wrap-around order */ | |
203 | |
204 for ( i = m/2, j = 0 ; i < m ; i++, j++ ) | |
205 respns[i] = x[j] ; | |
206 for ( i = 0 ; i < m/2 ; i++, j++ ) | |
207 respns[i] = x[j] ; | |
208 | |
209 /* Convolve and copy output */ | |
210 | |
211 convlv( data-1, n1, respns-1, m, 1, ans-1 ) ; | |
212 | |
213 for ( i = 0 ; i < n ; i++ ) | |
214 z[i] = ans[i] ; | |
215 | |
216 free( data ) ; | |
217 free( respns ) ; | |
218 free( ans ) ; | |
219 } | |
220 | |
221 |