annotate 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
rev   line source
tomwalters@0 1 /*
tomwalters@0 2 stats.c calculate some statistics (min, max, mean etc.)
tomwalters@0 3 -------
tomwalters@0 4
tomwalters@0 5 */
tomwalters@0 6
tomwalters@0 7 #include <stdio.h>
tomwalters@0 8 #include <math.h>
tomwalters@0 9 #include "options.h"
tomwalters@0 10 #include "units.h"
tomwalters@0 11 #include "strmatch.h"
tomwalters@0 12
tomwalters@0 13 char applic[] = "print statistics of input files" ;
tomwalters@0 14
tomwalters@0 15 static char *helpstr, *debugstr, *typestr, *statstr ;
tomwalters@0 16 static char *sampstr, *frstr, *widstr, *sizestr ;
tomwalters@0 17 static char *linestr, *precstr, *fieldstr ;
tomwalters@0 18
tomwalters@0 19 static Options option[] = {
tomwalters@0 20 { "help" , "off" , &helpstr , "help" , DEBUG },
tomwalters@0 21 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
tomwalters@0 22 { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL },
tomwalters@0 23 { "frame" , "1" , &frstr , "select frames inclusively" , VAL },
tomwalters@0 24 { "width" , "max" , &widstr , "frame width" , VAL },
tomwalters@0 25 { "type" , "short" , &typestr , "data type" , VAL },
tomwalters@0 26 { "stat" , "mean" , &statstr , "statistic list (comma separated)" , VAL },
tomwalters@0 27 { "line" , "off" , &linestr , "force ascii output" , SETFLAG },
tomwalters@0 28 { "fieldwidth", "10" , &fieldstr , "field width for ascii printing", SVAL },
tomwalters@0 29 { "precision" , "3" , &precstr , "precision for ascii printing" , SVAL },
tomwalters@0 30 { "SIZE" , "262144p" , &sizestr , "buffer size (s, ms, or p)" , SVAL },
tomwalters@0 31 ( char * ) 0 } ;
tomwalters@0 32
tomwalters@0 33
tomwalters@0 34 typedef float (*PF)() ; /* pointer-to-function type returning float */
tomwalters@0 35
tomwalters@0 36 typedef struct { /* a struct to hold both function name and pointer */
tomwalters@0 37 char *name ; /* string name of function */
tomwalters@0 38 PF func ; /* pointer to function */
tomwalters@0 39 char *help ; /* explanation of use */
tomwalters@0 40 } Func ;
tomwalters@0 41
tomwalters@0 42
tomwalters@0 43 float num(), sum(), sumabs(), sumsq(), mean() ;
tomwalters@0 44 float rms(), variance(), stddev(), min(), max() ;
tomwalters@0 45 float absmax(), absrange(), pc() ;
tomwalters@0 46
tomwalters@0 47 float call_by_name() ;
tomwalters@0 48
tomwalters@0 49 Func statistic[] = {
tomwalters@0 50 { "n" , num , "sample size (ie. frame width)" } ,
tomwalters@0 51 { "sum" , sum , "area" } ,
tomwalters@0 52 { "sa" , sumabs , "sum of absolute values" } ,
tomwalters@0 53 { "ss" , sumsq , "sum of squares" } ,
tomwalters@0 54 { "mean" , mean , "sum/n" } ,
tomwalters@0 55 { "rms" , rms , "root mean square: square root of ss/n" } ,
tomwalters@0 56 { "variance" , variance , "computed with n-1 degrees of freedom" } ,
tomwalters@0 57 { "stddev" , stddev , "standard deviation: square root of variance" } ,
tomwalters@0 58 { "min" , min , "minimum value" } ,
tomwalters@0 59 { "max" , max , "maximum value" } ,
tomwalters@0 60 { "absmax" , absmax , "maximum absolute value, ie. max( |max|, |min| )" } ,
tomwalters@0 61 { "range" , absrange , "max-min" } ,
tomwalters@0 62 { "pc_1of2" , pc , "percentage correct, ie. greater first of each pair" } ,
tomwalters@0 63 ( char * ) 0 } ;
tomwalters@0 64
tomwalters@0 65
tomwalters@0 66 int samplerate ;
tomwalters@0 67 int bytes ;
tomwalters@0 68 int type ; /* datatype index */
tomwalters@0 69 int nstat ; /* number of statistics required */
tomwalters@0 70 int width ;
tomwalters@0 71 int SIZE ;
tomwalters@0 72 int lineout ; /* flag for forcing ascii output */
tomwalters@0 73
tomwalters@0 74 float *buf ; /* args to every stat function */
tomwalters@0 75 int n ;
tomwalters@0 76
tomwalters@0 77 main (argc, argv)
tomwalters@0 78 int argc;
tomwalters@0 79 char **argv;
tomwalters@0 80 {
tomwalters@0 81 FILE *fp ;
tomwalters@0 82 char **list ;
tomwalters@0 83 float y ;
tomwalters@0 84 int i, j, k, a, b, helpstats() ;
tomwalters@0 85
tomwalters@0 86 i = getopts( option, argc, argv ) ;
tomwalters@0 87 if ( !isoff( helpstr ) )
tomwalters@0 88 helpopts1( helpstr, argv[0], applic, option, helpstats ) ;
tomwalters@0 89
tomwalters@0 90 if ( ( type = typeindex( typestr ) ) < 0 ) {
tomwalters@0 91 fprintf( stderr, "stats: bad type [%s]\n", typestr ) ;
tomwalters@0 92 exit( 1 ) ;
tomwalters@0 93 }
tomwalters@0 94 bytes = typebytes( type ) ;
tomwalters@0 95
tomwalters@0 96 if ( selector( frstr, &a, &b ) == 0 ) {
tomwalters@0 97 fprintf(stderr,"stats: bad frame selector [%s]\n", frstr ) ;
tomwalters@0 98 exit( 1 ) ;
tomwalters@0 99 }
tomwalters@0 100
tomwalters@0 101 PRECISION = atoi( precstr ) ;
tomwalters@0 102 FIELDWIDTH = atoi( fieldstr ) ;
tomwalters@0 103 lineout = ison( linestr ) ;
tomwalters@0 104 samplerate = to_Hz( sampstr, 0) ;
tomwalters@0 105 SIZE = to_p( sizestr, samplerate ) ;
tomwalters@0 106 if ( ismax( widstr ) ) width = (-1) ;
tomwalters@0 107 else width = to_p( widstr, samplerate ) ;
tomwalters@0 108
tomwalters@0 109 nstat = flistsize( statistic ) ; /* max number of statistics */
tomwalters@0 110 list = (char **)malloc( nstat * sizeof( char *) ) ;
tomwalters@0 111 if ( ( nstat = tokens( statstr, list, nstat, ',' ) ) == 0 ) {
tomwalters@0 112 fprintf(stderr,"stats: incorrect stat list\n" ) ;
tomwalters@0 113 exit( 1 ) ;
tomwalters@0 114 }
tomwalters@0 115
tomwalters@0 116 do {
tomwalters@0 117
tomwalters@0 118 if ( i == 0 ) fp = stdin ;
tomwalters@0 119 else if ( ( fp = fopen( argv[argc-i], "r" ) ) == (FILE *)0 ) {
tomwalters@0 120 fprintf( stderr,"stats: can't open %s\n", argv[argc-i] ) ;
tomwalters@0 121 exit( 1 ) ;
tomwalters@0 122 }
tomwalters@0 123
tomwalters@0 124 if ( width > 0 ) buf = (float *)malloc( width * sizeof(float) ) ;
tomwalters@0 125 else buf = (float *)malloc( SIZE * sizeof(float) ) ;
tomwalters@0 126
tomwalters@0 127 if ( width > 0 && a > 1 )
tomwalters@0 128 if ( seekstart( (a-1)*width, bytes, fp ) < (a-1)*width )
tomwalters@0 129 fprintf( stderr, "stats warning: insufficient input\n" ) ;
tomwalters@0 130
tomwalters@0 131 for ( j = a ; ( j <= b || b == 0 ) && ( n = Readitem( buf, type, width, fp, SIZE ) ) > 0 ; j++ ) {
tomwalters@0 132
tomwalters@0 133 for ( k = 0 ; k < nstat ; k++ ) {
tomwalters@0 134
tomwalters@0 135 y = call_by_name( list[k], statistic ) ;
tomwalters@0 136
tomwalters@0 137 if ( lineout )
tomwalters@0 138 printf( "%*.*f ", FIELDWIDTH, PRECISION, y ) ;
tomwalters@0 139 else
tomwalters@0 140 writeitem( &y, type, 1, stdout ) ;
tomwalters@0 141 }
tomwalters@0 142 }
tomwalters@0 143
tomwalters@0 144 free( buf ) ;
tomwalters@0 145 fclose( fp ) ;
tomwalters@0 146 if ( lineout ) printf( "\n" ) ;
tomwalters@0 147
tomwalters@0 148 } while ( --i > 0 ) ;
tomwalters@0 149
tomwalters@0 150 }
tomwalters@0 151
tomwalters@0 152
tomwalters@0 153 /*
tomwalters@0 154 Return the number of structs in the null-terminated array of Func structs.
tomwalters@0 155 */
tomwalters@0 156
tomwalters@0 157 flistsize( flist )
tomwalters@0 158 Func *flist ;
tomwalters@0 159 {
tomwalters@0 160 int i ;
tomwalters@0 161
tomwalters@0 162 for ( i = 0 ; flist[i].name != (char *)0 ; i++ )
tomwalters@0 163 ;
tomwalters@0 164 return i ;
tomwalters@0 165 }
tomwalters@0 166
tomwalters@0 167
tomwalters@0 168 /*
tomwalters@0 169 Call a function given its string name. The function's address is found against
tomwalters@0 170 the matching name in the given `flist'.
tomwalters@0 171 The function returns an float.
tomwalters@0 172 Rather than return at the first matching name, search all the list for names
tomwalters@0 173 which match the (possibly abbreviated) string name. Print a warning if
tomwalters@0 174 ambiguity found.
tomwalters@0 175 */
tomwalters@0 176
tomwalters@0 177 float call_by_name( str, flist )
tomwalters@0 178 char *str ;
tomwalters@0 179 Func *flist ;
tomwalters@0 180 {
tomwalters@0 181 int i, j = (-1) ;
tomwalters@0 182
tomwalters@0 183 for ( i=0 ; flist[i].name != (char *)0 ; i++ ) {
tomwalters@0 184 if ( iststr( str, flist[i].name ) ) {
tomwalters@0 185 if ( j >= 0 )
tomwalters@0 186 fprintf( stderr,"warning: ambiguous stat names (%s and %s)\n", flist[j].name, flist[i].name ) ;
tomwalters@0 187 j = i ;
tomwalters@0 188 }
tomwalters@0 189 }
tomwalters@0 190 return ( (*flist[j].func)() ) ;
tomwalters@0 191 }
tomwalters@0 192
tomwalters@0 193
tomwalters@0 194 /*
tomwalters@0 195 Read items of given type up to max of SIZE items (when n=-1).
tomwalters@0 196 Return n or 0 if eof.
tomwalters@0 197 */
tomwalters@0 198
tomwalters@0 199 Readitem( y, type, n, fp, SIZE )
tomwalters@0 200 float *y ;
tomwalters@0 201 int type ;
tomwalters@0 202 int n ;
tomwalters@0 203 FILE *fp ;
tomwalters@0 204 int SIZE ;
tomwalters@0 205 {
tomwalters@0 206 if ( n == (-1) ) {
tomwalters@0 207 for ( n = 0 ; n < SIZE && readitem( &y[n], type, 1, fp ) ; n++ )
tomwalters@0 208 ;
tomwalters@0 209 if ( n == SIZE )
tomwalters@0 210 fprintf( stderr, "stats warning: buffer full\n" ) ;
tomwalters@0 211 }
tomwalters@0 212 else if ( readitem( y, type, n, fp ) == 0 ) return 0 ;
tomwalters@0 213
tomwalters@0 214 return n ;
tomwalters@0 215 }
tomwalters@0 216
tomwalters@0 217
tomwalters@0 218 /*
tomwalters@0 219 Print help on request
tomwalters@0 220 */
tomwalters@0 221
tomwalters@0 222 helpstats()
tomwalters@0 223 {
tomwalters@0 224 int i ;
tomwalters@0 225
tomwalters@0 226 fprintf(stderr,"\nstatistics: \n");
tomwalters@0 227
tomwalters@0 228 for ( i = 0 ; statistic[i].name != (char *)0 ; i++ )
tomwalters@0 229 fprintf(stderr," %-10s %s\n", statistic[i].name, statistic[i].help ) ;
tomwalters@0 230
tomwalters@0 231 exit( 1 ) ;
tomwalters@0 232 }
tomwalters@0 233
tomwalters@0 234
tomwalters@0 235 /*************************** functions ************************************/
tomwalters@0 236 /* The functions all take two args: char *buf; int n; */
tomwalters@0 237 /* These are declared externally. */
tomwalters@0 238
tomwalters@0 239
tomwalters@0 240 float num()
tomwalters@0 241 {
tomwalters@0 242 return n ;
tomwalters@0 243 }
tomwalters@0 244
tomwalters@0 245
tomwalters@0 246 float sum()
tomwalters@0 247 {
tomwalters@0 248 int i ;
tomwalters@0 249 float sum = 0 ;
tomwalters@0 250
tomwalters@0 251 for ( i = 0 ; i < n ; i++ )
tomwalters@0 252 sum += buf[i] ;
tomwalters@0 253
tomwalters@0 254 return ( sum ) ;
tomwalters@0 255 }
tomwalters@0 256
tomwalters@0 257
tomwalters@0 258 float sumabs()
tomwalters@0 259 {
tomwalters@0 260 int i ;
tomwalters@0 261 float sum = 0 ;
tomwalters@0 262
tomwalters@0 263 for ( i = 0 ; i < n ; i++ )
tomwalters@0 264 sum += fabs( (double)buf[i] ) ;
tomwalters@0 265
tomwalters@0 266 return ( sum ) ;
tomwalters@0 267 }
tomwalters@0 268
tomwalters@0 269
tomwalters@0 270 float sumsq()
tomwalters@0 271 {
tomwalters@0 272 int i ;
tomwalters@0 273 float sumsq = 0 ;
tomwalters@0 274
tomwalters@0 275 for ( i = 0 ; i < n ; i++ )
tomwalters@0 276 sumsq += ( buf[i] * buf[i] ) ;
tomwalters@0 277
tomwalters@0 278 return ( sumsq ) ;
tomwalters@0 279 }
tomwalters@0 280
tomwalters@0 281
tomwalters@0 282 float mean()
tomwalters@0 283 {
tomwalters@0 284 int i ;
tomwalters@0 285 float sum = 0 ;
tomwalters@0 286
tomwalters@0 287 for ( i = 0 ; i < n ; i++ )
tomwalters@0 288 sum += buf[i] ;
tomwalters@0 289
tomwalters@0 290 return ( sum / n ) ;
tomwalters@0 291 }
tomwalters@0 292
tomwalters@0 293
tomwalters@0 294 float rms()
tomwalters@0 295 {
tomwalters@0 296 int i ;
tomwalters@0 297 float sumsq = 0 ;
tomwalters@0 298
tomwalters@0 299 for ( i = 0 ; i < n ; i++ )
tomwalters@0 300 sumsq += ( buf[i] * buf[i] ) ;
tomwalters@0 301
tomwalters@0 302 return ( sqrt( sumsq / n ) ) ;
tomwalters@0 303 }
tomwalters@0 304
tomwalters@0 305
tomwalters@0 306 float variance() /* computed with n-1 degrees of freedom */
tomwalters@0 307 {
tomwalters@0 308 int i ;
tomwalters@0 309 float sum = 0, sumsq = 0 ;
tomwalters@0 310
tomwalters@0 311 for ( i = 0 ; i < n ; i++ ) {
tomwalters@0 312 sum += buf[i] ;
tomwalters@0 313 sumsq += ( buf[i] * buf[i] ) ;
tomwalters@0 314 }
tomwalters@0 315
tomwalters@0 316 return ( ( sumsq - sum*sum/n ) / ( n - 1 ) ) ; /* replace n-1 by n for n degrees of freedom */
tomwalters@0 317 }
tomwalters@0 318
tomwalters@0 319
tomwalters@0 320 float stddev() /* computed with n-1 degrees of freedom */
tomwalters@0 321 {
tomwalters@0 322 return ( sqrt( variance( buf, n ) ) ) ;
tomwalters@0 323 }
tomwalters@0 324
tomwalters@0 325
tomwalters@0 326 float min()
tomwalters@0 327 {
tomwalters@0 328 int i ;
tomwalters@0 329 float min = 99999999999. ;
tomwalters@0 330
tomwalters@0 331 for ( i = 0 ; i < n ; i++ )
tomwalters@0 332 if ( buf[i] < min ) min = buf[i] ;
tomwalters@0 333 return ( min ) ;
tomwalters@0 334 }
tomwalters@0 335
tomwalters@0 336
tomwalters@0 337 float max()
tomwalters@0 338 {
tomwalters@0 339 int i ;
tomwalters@0 340 float max = ( -99999999999. ) ;
tomwalters@0 341
tomwalters@0 342 for ( i = 0 ; i < n ; i++ )
tomwalters@0 343 if ( buf[i] > max ) max = buf[i] ;
tomwalters@0 344
tomwalters@0 345 return ( max ) ;
tomwalters@0 346 }
tomwalters@0 347
tomwalters@0 348
tomwalters@0 349 float absmax()
tomwalters@0 350 {
tomwalters@0 351 int i ;
tomwalters@0 352 float min = 99999999999. ;
tomwalters@0 353 float max = ( -99999999999. ) ;
tomwalters@0 354
tomwalters@0 355 for ( i = 0 ; i < n ; i++ ) {
tomwalters@0 356 if ( buf[i] < min ) min = buf[i] ;
tomwalters@0 357 if ( buf[i] > max ) max = buf[i] ;
tomwalters@0 358 }
tomwalters@0 359
tomwalters@0 360 if ( ( max = fabs( (double)max ) ) < ( min = fabs( (double)min ) ) )
tomwalters@0 361 max = min ;
tomwalters@0 362
tomwalters@0 363 return ( max ) ;
tomwalters@0 364 }
tomwalters@0 365
tomwalters@0 366
tomwalters@0 367 float absrange()
tomwalters@0 368 {
tomwalters@0 369 int i ;
tomwalters@0 370 float min = 99999999999. ;
tomwalters@0 371 float max = ( -99999999999. ) ;
tomwalters@0 372
tomwalters@0 373 for ( i = 0 ; i < n ; i++ ) {
tomwalters@0 374 if ( buf[i] < min ) min = buf[i] ;
tomwalters@0 375 if ( buf[i] > max ) max = buf[i] ;
tomwalters@0 376 }
tomwalters@0 377
tomwalters@0 378 return ( max - min ) ;
tomwalters@0 379 }
tomwalters@0 380
tomwalters@0 381
tomwalters@0 382 /*
tomwalters@0 383 The buf contains n/2 pairs of numbers. Calculate how many of each pair have
tomwalters@0 384 the first number greater than the last, and return this as a "percentage
tomwalters@0 385 correct".
tomwalters@0 386 */
tomwalters@0 387
tomwalters@0 388 float pc()
tomwalters@0 389 {
tomwalters@0 390 int i ;
tomwalters@0 391 float p = 0 ;
tomwalters@0 392
tomwalters@0 393 for ( i = 0 ; i < n ; i+=2 )
tomwalters@0 394 if ( buf[i] > buf[i+1] )
tomwalters@0 395 p++ ;
tomwalters@0 396
tomwalters@0 397 return ( ( p / (n/2) ) * 100 ) ;
tomwalters@0 398 }
tomwalters@0 399
tomwalters@0 400
tomwalters@0 401