Mercurial > hg > aim92
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 |