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