Mercurial > hg > aim92
view 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 source
/* 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 ) ; }