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 |
