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