Mercurial > hg > aim92
diff tools/stats.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/stats.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,401 @@ +/* + stats.c calculate some statistics (min, max, mean etc.) + ------- + +*/ + +#include <stdio.h> +#include <math.h> +#include "options.h" +#include "units.h" +#include "strmatch.h" + +char applic[] = "print statistics of input files" ; + +static char *helpstr, *debugstr, *typestr, *statstr ; +static char *sampstr, *frstr, *widstr, *sizestr ; +static char *linestr, *precstr, *fieldstr ; + +static Options option[] = { + { "help" , "off" , &helpstr , "help" , DEBUG }, + { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, + { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL }, + { "frame" , "1" , &frstr , "select frames inclusively" , VAL }, + { "width" , "max" , &widstr , "frame width" , VAL }, + { "type" , "short" , &typestr , "data type" , VAL }, + { "stat" , "mean" , &statstr , "statistic list (comma separated)" , VAL }, + { "line" , "off" , &linestr , "force ascii output" , SETFLAG }, + { "fieldwidth", "10" , &fieldstr , "field width for ascii printing", SVAL }, + { "precision" , "3" , &precstr , "precision for ascii printing" , SVAL }, + { "SIZE" , "262144p" , &sizestr , "buffer size (s, ms, or p)" , SVAL }, + ( char * ) 0 } ; + + +typedef float (*PF)() ; /* pointer-to-function type returning float */ + +typedef struct { /* a struct to hold both function name and pointer */ + char *name ; /* string name of function */ + PF func ; /* pointer to function */ + char *help ; /* explanation of use */ +} Func ; + + +float num(), sum(), sumabs(), sumsq(), mean() ; +float rms(), variance(), stddev(), min(), max() ; +float absmax(), absrange(), pc() ; + +float call_by_name() ; + +Func statistic[] = { + { "n" , num , "sample size (ie. frame width)" } , + { "sum" , sum , "area" } , + { "sa" , sumabs , "sum of absolute values" } , + { "ss" , sumsq , "sum of squares" } , + { "mean" , mean , "sum/n" } , + { "rms" , rms , "root mean square: square root of ss/n" } , + { "variance" , variance , "computed with n-1 degrees of freedom" } , + { "stddev" , stddev , "standard deviation: square root of variance" } , + { "min" , min , "minimum value" } , + { "max" , max , "maximum value" } , + { "absmax" , absmax , "maximum absolute value, ie. max( |max|, |min| )" } , + { "range" , absrange , "max-min" } , + { "pc_1of2" , pc , "percentage correct, ie. greater first of each pair" } , + ( char * ) 0 } ; + + +int samplerate ; +int bytes ; +int type ; /* datatype index */ +int nstat ; /* number of statistics required */ +int width ; +int SIZE ; +int lineout ; /* flag for forcing ascii output */ + +float *buf ; /* args to every stat function */ +int n ; + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fp ; + char **list ; + float y ; + int i, j, k, a, b, helpstats() ; + + i = getopts( option, argc, argv ) ; + if ( !isoff( helpstr ) ) + helpopts1( helpstr, argv[0], applic, option, helpstats ) ; + + if ( ( type = typeindex( typestr ) ) < 0 ) { + fprintf( stderr, "stats: bad type [%s]\n", typestr ) ; + exit( 1 ) ; + } + bytes = typebytes( type ) ; + + if ( selector( frstr, &a, &b ) == 0 ) { + fprintf(stderr,"stats: bad frame selector [%s]\n", frstr ) ; + exit( 1 ) ; + } + + PRECISION = atoi( precstr ) ; + FIELDWIDTH = atoi( fieldstr ) ; + lineout = ison( linestr ) ; + samplerate = to_Hz( sampstr, 0) ; + SIZE = to_p( sizestr, samplerate ) ; + if ( ismax( widstr ) ) width = (-1) ; + else width = to_p( widstr, samplerate ) ; + + nstat = flistsize( statistic ) ; /* max number of statistics */ + list = (char **)malloc( nstat * sizeof( char *) ) ; + if ( ( nstat = tokens( statstr, list, nstat, ',' ) ) == 0 ) { + fprintf(stderr,"stats: incorrect stat list\n" ) ; + exit( 1 ) ; + } + + do { + + if ( i == 0 ) fp = stdin ; + else if ( ( fp = fopen( argv[argc-i], "r" ) ) == (FILE *)0 ) { + fprintf( stderr,"stats: can't open %s\n", argv[argc-i] ) ; + exit( 1 ) ; + } + + if ( width > 0 ) buf = (float *)malloc( width * sizeof(float) ) ; + else buf = (float *)malloc( SIZE * sizeof(float) ) ; + + if ( width > 0 && a > 1 ) + if ( seekstart( (a-1)*width, bytes, fp ) < (a-1)*width ) + fprintf( stderr, "stats warning: insufficient input\n" ) ; + + for ( j = a ; ( j <= b || b == 0 ) && ( n = Readitem( buf, type, width, fp, SIZE ) ) > 0 ; j++ ) { + + for ( k = 0 ; k < nstat ; k++ ) { + + y = call_by_name( list[k], statistic ) ; + + if ( lineout ) + printf( "%*.*f ", FIELDWIDTH, PRECISION, y ) ; + else + writeitem( &y, type, 1, stdout ) ; + } + } + + free( buf ) ; + fclose( fp ) ; + if ( lineout ) printf( "\n" ) ; + + } while ( --i > 0 ) ; + +} + + +/* +Return the number of structs in the null-terminated array of Func structs. +*/ + +flistsize( flist ) +Func *flist ; +{ + int i ; + + for ( i = 0 ; flist[i].name != (char *)0 ; i++ ) + ; + return i ; +} + + +/* +Call a function given its string name. The function's address is found against +the matching name in the given `flist'. +The function returns an float. +Rather than return at the first matching name, search all the list for names +which match the (possibly abbreviated) string name. Print a warning if +ambiguity found. +*/ + +float call_by_name( str, flist ) +char *str ; +Func *flist ; +{ + int i, j = (-1) ; + + for ( i=0 ; flist[i].name != (char *)0 ; i++ ) { + if ( iststr( str, flist[i].name ) ) { + if ( j >= 0 ) + fprintf( stderr,"warning: ambiguous stat names (%s and %s)\n", flist[j].name, flist[i].name ) ; + j = i ; + } + } + return ( (*flist[j].func)() ) ; +} + + +/* +Read items of given type up to max of SIZE items (when n=-1). +Return n or 0 if eof. +*/ + +Readitem( y, type, n, fp, SIZE ) +float *y ; +int type ; +int n ; +FILE *fp ; +int SIZE ; +{ + if ( n == (-1) ) { + for ( n = 0 ; n < SIZE && readitem( &y[n], type, 1, fp ) ; n++ ) + ; + if ( n == SIZE ) + fprintf( stderr, "stats warning: buffer full\n" ) ; + } + else if ( readitem( y, type, n, fp ) == 0 ) return 0 ; + + return n ; +} + + +/* +Print help on request +*/ + +helpstats() +{ + int i ; + + fprintf(stderr,"\nstatistics: \n"); + + for ( i = 0 ; statistic[i].name != (char *)0 ; i++ ) + fprintf(stderr," %-10s %s\n", statistic[i].name, statistic[i].help ) ; + + exit( 1 ) ; +} + + +/*************************** functions ************************************/ +/* The functions all take two args: char *buf; int n; */ +/* These are declared externally. */ + + +float num() +{ + return n ; +} + + +float sum() +{ + int i ; + float sum = 0 ; + + for ( i = 0 ; i < n ; i++ ) + sum += buf[i] ; + + return ( sum ) ; +} + + +float sumabs() +{ + int i ; + float sum = 0 ; + + for ( i = 0 ; i < n ; i++ ) + sum += fabs( (double)buf[i] ) ; + + return ( sum ) ; +} + + +float sumsq() +{ + int i ; + float sumsq = 0 ; + + for ( i = 0 ; i < n ; i++ ) + sumsq += ( buf[i] * buf[i] ) ; + + return ( sumsq ) ; +} + + +float mean() +{ + int i ; + float sum = 0 ; + + for ( i = 0 ; i < n ; i++ ) + sum += buf[i] ; + + return ( sum / n ) ; +} + + +float rms() +{ + int i ; + float sumsq = 0 ; + + for ( i = 0 ; i < n ; i++ ) + sumsq += ( buf[i] * buf[i] ) ; + + return ( sqrt( sumsq / n ) ) ; +} + + +float variance() /* computed with n-1 degrees of freedom */ +{ + int i ; + float sum = 0, sumsq = 0 ; + + for ( i = 0 ; i < n ; i++ ) { + sum += buf[i] ; + sumsq += ( buf[i] * buf[i] ) ; + } + + return ( ( sumsq - sum*sum/n ) / ( n - 1 ) ) ; /* replace n-1 by n for n degrees of freedom */ +} + + +float stddev() /* computed with n-1 degrees of freedom */ +{ + return ( sqrt( variance( buf, n ) ) ) ; +} + + +float min() +{ + int i ; + float min = 99999999999. ; + + for ( i = 0 ; i < n ; i++ ) + if ( buf[i] < min ) min = buf[i] ; + return ( min ) ; +} + + +float max() +{ + int i ; + float max = ( -99999999999. ) ; + + for ( i = 0 ; i < n ; i++ ) + if ( buf[i] > max ) max = buf[i] ; + + return ( max ) ; +} + + +float absmax() +{ + int i ; + float min = 99999999999. ; + float max = ( -99999999999. ) ; + + for ( i = 0 ; i < n ; i++ ) { + if ( buf[i] < min ) min = buf[i] ; + if ( buf[i] > max ) max = buf[i] ; + } + + if ( ( max = fabs( (double)max ) ) < ( min = fabs( (double)min ) ) ) + max = min ; + + return ( max ) ; +} + + +float absrange() +{ + int i ; + float min = 99999999999. ; + float max = ( -99999999999. ) ; + + for ( i = 0 ; i < n ; i++ ) { + if ( buf[i] < min ) min = buf[i] ; + if ( buf[i] > max ) max = buf[i] ; + } + + return ( max - min ) ; +} + + +/* +The buf contains n/2 pairs of numbers. Calculate how many of each pair have +the first number greater than the last, and return this as a "percentage +correct". +*/ + +float pc() +{ + int i ; + float p = 0 ; + + for ( i = 0 ; i < n ; i+=2 ) + if ( buf[i] > buf[i+1] ) + p++ ; + + return ( ( p / (n/2) ) * 100 ) ; +} + + +