annotate tools/filt1.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 filt1.c 1st order LP filter using an exponential smoother
tomwalters@0 3 (recursive "leaky integrator" filter)
tomwalters@0 4
tomwalters@0 5 The n'th recursive update is:
tomwalters@0 6
tomwalters@0 7 a) y[n] = a.y[n-1] + x[n] recursive sum
tomwalters@0 8 b) y[n] = a.y[n-1] + (1-a).x[n] recursive mean
tomwalters@0 9
tomwalters@0 10 where decay constant a = exp(-Ts/T)
tomwalters@0 11 and Ts is sample interval in seconds
tomwalters@0 12 T is decay time-constant in seconds
tomwalters@0 13
tomwalters@0 14 The 1st order LP filter is an exponential window which decays into the past.
tomwalters@0 15 With decay constant a=1 there is infinite memory because it does not decay.
tomwalters@0 16 The result is either a steadily accumulating sum or mean.
tomwalters@0 17 (A zero mean is assumed).
tomwalters@0 18 With 0 < a < 1 there is a finite decaying memory.
tomwalters@0 19 The smaller `a', the smaller the memory (it decays faster).
tomwalters@0 20 With a = 0 the filter output is identical with its input.
tomwalters@0 21
tomwalters@0 22 The window width parameter is the time-constant parameter.
tomwalters@0 23 The half life of the exponential window is given by -T.ln(0.5) = 0.693T
tomwalters@0 24 ie. for a given time constant, T secs, the window decays to half of its
tomwalters@0 25 current value in a period of 0.693T secs.
tomwalters@0 26 (Thus T can be set to accomodate an expected period).
tomwalters@0 27
tomwalters@0 28 When the time-constant parameter is given with time units (s or ms) then
tomwalters@0 29 it is converted to a decay constant using a = exp(-Ts/T).
tomwalters@0 30 Otherwise it is taken to be the decay constant directly.
tomwalters@0 31
tomwalters@0 32 */
tomwalters@0 33
tomwalters@0 34 #include <stdio.h>
tomwalters@0 35 #include <math.h>
tomwalters@0 36 #include "options.h"
tomwalters@0 37 #include "units.h"
tomwalters@0 38 #include "strmatch.h"
tomwalters@0 39
tomwalters@0 40 char applic[] = "1st order low-pass filter using exponential smoother." ;
tomwalters@0 41
tomwalters@0 42 static char *helpstr, *debugstr, *sampstr, *tcstr, *destr ;
tomwalters@0 43
tomwalters@0 44 static Options option[] = {
tomwalters@0 45 { "help" , "off" , &helpstr , "help" , DEBUG },
tomwalters@0 46 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
tomwalters@0 47 { "samplerate", "20kHz" , &sampstr , "Samplerate " , VAL },
tomwalters@0 48 { "tc" , "3ms" , &tcstr , "Decay time constant" , VAL },
tomwalters@0 49 { "de" , "mean" , &destr , "Difference equation" , VAL },
tomwalters@0 50 ( char * ) 0 } ;
tomwalters@0 51
tomwalters@0 52
tomwalters@0 53 int samplerate ;
tomwalters@0 54 double a ; /* decay constant */
tomwalters@0 55
tomwalters@0 56
tomwalters@0 57 main (argc, argv)
tomwalters@0 58 int argc;
tomwalters@0 59 char **argv;
tomwalters@0 60 {
tomwalters@0 61 FILE *fp ;
tomwalters@0 62 short x, y ;
tomwalters@0 63 int morehelp() ;
tomwalters@0 64
tomwalters@0 65 fp = openopts( option,argc,argv ) ;
tomwalters@0 66 if ( !isoff( helpstr ) )
tomwalters@0 67 helpopts1( helpstr, argv[0], applic, option, morehelp ) ;
tomwalters@0 68
tomwalters@0 69 samplerate = to_Hz( sampstr ) ;
tomwalters@0 70
tomwalters@0 71 if ( Units( tcstr ) )
tomwalters@0 72 a = exp( -(double)( 1. / ( samplerate * to_s( tcstr, samplerate ) ) ) ) ;
tomwalters@0 73 else
tomwalters@0 74 a = (double)atof( tcstr ) ;
tomwalters@0 75
tomwalters@0 76 y = 0 ; /* initialization */
tomwalters@0 77
tomwalters@0 78 if ( iststr( destr, "mean" ) )
tomwalters@0 79 while ( fread( &x, sizeof(short), 1, fp ) ) {
tomwalters@0 80 y = a * y + ( 1 - a ) * x ;
tomwalters@0 81 fwrite( &y, sizeof(short), 1, stdout ) ;
tomwalters@0 82 }
tomwalters@0 83
tomwalters@0 84 else if ( iststr( destr, "sum" ) )
tomwalters@0 85 while ( fread( &x, sizeof(short), 1, fp ) ) {
tomwalters@0 86 y = a * y + x ;
tomwalters@0 87 fwrite( &y, sizeof(short), 1, stdout ) ;
tomwalters@0 88 }
tomwalters@0 89
tomwalters@0 90 else {
tomwalters@0 91 fprintf( stderr,"unknown de [%s]\n", destr ) ;
tomwalters@0 92 exit( 1 ) ;
tomwalters@0 93 }
tomwalters@0 94
tomwalters@0 95 fclose( fp );
tomwalters@0 96 }
tomwalters@0 97
tomwalters@0 98
tomwalters@0 99 /* Return 1 if the str has appended units. Otherwise return 0. */
tomwalters@0 100
tomwalters@0 101 Units(str)
tomwalters@0 102 char *str ;
tomwalters@0 103 {
tomwalters@0 104 char *eptr = str + strlen( str ) ;
tomwalters@0 105
tomwalters@0 106 if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
tomwalters@0 107 else return 1 ;
tomwalters@0 108 }
tomwalters@0 109
tomwalters@0 110
tomwalters@0 111
tomwalters@0 112 morehelp()
tomwalters@0 113 {
tomwalters@0 114 fprintf(stderr,"\nde: \n");
tomwalters@0 115 fprintf(stderr," sum y[n] = a.y[n-1] + x[n] \n");
tomwalters@0 116 fprintf(stderr," mean y[n] = a.y[n-1] + (1-a).x[n] (unity steady-state gain)\n");
tomwalters@0 117 exit( 1 ) ;
tomwalters@0 118 }