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