Mercurial > hg > aim92
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/filt1.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,118 @@ +/* + filt1.c 1st order LP filter using an exponential smoother + (recursive "leaky integrator" filter) + + The n'th recursive update is: + + a) y[n] = a.y[n-1] + x[n] recursive sum + b) y[n] = a.y[n-1] + (1-a).x[n] recursive mean + + where decay constant a = exp(-Ts/T) + and Ts is sample interval in seconds + T is decay time-constant in seconds + + The 1st order LP filter is an exponential window which decays into the past. + With decay constant a=1 there is infinite memory because it does not decay. + The result is either a steadily accumulating sum or mean. + (A zero mean is assumed). + With 0 < a < 1 there is a finite decaying memory. + The smaller `a', the smaller the memory (it decays faster). + With a = 0 the filter output is identical with its input. + + The window width parameter is the time-constant parameter. + The half life of the exponential window is given by -T.ln(0.5) = 0.693T + ie. for a given time constant, T secs, the window decays to half of its + current value in a period of 0.693T secs. + (Thus T can be set to accomodate an expected period). + + When the time-constant parameter is given with time units (s or ms) then + it is converted to a decay constant using a = exp(-Ts/T). + Otherwise it is taken to be the decay constant directly. + +*/ + +#include <stdio.h> +#include <math.h> +#include "options.h" +#include "units.h" +#include "strmatch.h" + +char applic[] = "1st order low-pass filter using exponential smoother." ; + +static char *helpstr, *debugstr, *sampstr, *tcstr, *destr ; + +static Options option[] = { + { "help" , "off" , &helpstr , "help" , DEBUG }, + { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, + { "samplerate", "20kHz" , &sampstr , "Samplerate " , VAL }, + { "tc" , "3ms" , &tcstr , "Decay time constant" , VAL }, + { "de" , "mean" , &destr , "Difference equation" , VAL }, + ( char * ) 0 } ; + + +int samplerate ; +double a ; /* decay constant */ + + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fp ; + short x, y ; + int morehelp() ; + + fp = openopts( option,argc,argv ) ; + if ( !isoff( helpstr ) ) + helpopts1( helpstr, argv[0], applic, option, morehelp ) ; + + samplerate = to_Hz( sampstr ) ; + + if ( Units( tcstr ) ) + a = exp( -(double)( 1. / ( samplerate * to_s( tcstr, samplerate ) ) ) ) ; + else + a = (double)atof( tcstr ) ; + + y = 0 ; /* initialization */ + + if ( iststr( destr, "mean" ) ) + while ( fread( &x, sizeof(short), 1, fp ) ) { + y = a * y + ( 1 - a ) * x ; + fwrite( &y, sizeof(short), 1, stdout ) ; + } + + else if ( iststr( destr, "sum" ) ) + while ( fread( &x, sizeof(short), 1, fp ) ) { + y = a * y + x ; + fwrite( &y, sizeof(short), 1, stdout ) ; + } + + else { + fprintf( stderr,"unknown de [%s]\n", destr ) ; + exit( 1 ) ; + } + + fclose( fp ); +} + + +/* Return 1 if the str has appended units. Otherwise return 0. */ + +Units(str) +char *str ; +{ + char *eptr = str + strlen( str ) ; + + if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */ + else return 1 ; +} + + + +morehelp() +{ + fprintf(stderr,"\nde: \n"); + fprintf(stderr," sum y[n] = a.y[n-1] + x[n] \n"); + fprintf(stderr," mean y[n] = a.y[n-1] + (1-a).x[n] (unity steady-state gain)\n"); + exit( 1 ) ; +}