diff tools/loudness.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/loudness.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,147 @@
+/***************************************************************************
+ loudness.c     Loudness measure from spiral sector-weights contour.
+ ----------
+			Michael Allerhand, 1992.
+
+	Read m binary shorts (default m=SECTORS) for each specified frame.
+	Compute the loudness as the mean value of the sector-weights.
+
+****************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[] = "Loudness measure from spiral sector-weights contour.\n           (Input and output in binary shorts)." ;
+
+static char *helpstr, *debugstr, *fstr, *sstr, *mstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                        , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"            , DEBUG   },
+    {   "frames"    ,   "1-max"     ,  &fstr        ,   "select frames inclusively"   , VAL     },
+    {   "scale"     ,   "1.848"     ,  &sstr        ,   "scale factor"                , SVAL    },
+    {   "nsectors"  ,   "64"        ,  &mstr        ,   "number of sectors"           , SVAL    },
+   ( char * ) 0 } ;
+
+
+main (argc, argv)
+int    argc;
+char **argv;
+{
+    FILE   *fp;
+    int     m;                  /* Number of sectors around spiral.     */
+    short  *sector;             /* Sector-weights contour.              */
+    float   scalar;             /* Scale factor for loudness.           */
+    int     i, a, b;
+    char   *val1, *val2 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    m = atoi( mstr ) ;
+    scalar = atof( sstr ) ;
+
+    /* parse bounds on number of frames */
+
+    if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"loudness: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+    a = atoi( val1 ) ;
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismax( val2 ) ) b = 0 ;
+    else                      b = atoi( val2 ) ;
+
+    if (b<a && b>0) fprintf(stderr,"loudness: warning, bad frame specifiers\n");
+
+    if ( ison( debugstr ) ) {
+	printf("a=%d b=%d m=%d scalar=%.3f\n",
+		a, b, m, scalar );
+	exit(0);
+    }
+
+
+    /* Allocate space for sector-weights contour */
+
+    if (( sector = (short *)malloc(m*sizeof(short))) == NULL)
+	    fprintf(stderr,"loudness: malloc out of space\n");
+
+    /* Seek past a-1 frames, then read the next b-a+1 frames, or all    */
+    /* remaining frames if b==0.                                        */
+
+    if (a>0) {
+
+	for (i=1 ; i<a  && fread(sector,sizeof(short),m,fp) ; i++)
+	    ;
+	if (b > 0)
+	    for (  ; i<=b && fread(sector,sizeof(short),m,fp) ; i++)
+		loudness(sector,m,scalar);
+	else
+	    while ( fread(sector,sizeof(short),m,fp) )
+		loudness(sector,m,scalar);
+    }
+
+    fclose(fp);
+}
+
+
+loudness(sector,m,scalar)
+short  *sector;         /* Sector-weights contour.                  */
+int     m;              /* Number of sectors around spiral.         */
+float   scalar;         /* Scale factor for loudness measure.       */
+{
+    short   scale;      /* Mean weights.                            */
+
+    scale = (short)( normalize_scale(sector,m) * scalar );
+    fwrite(&scale,sizeof(short),1,stdout);
+
+}
+
+
+/****************************************************************************
+    Normalize Scale.
+****************************************************************************/
+
+/*
+Normalize for unit variance and zero mean, and then scale for MEAN and STDDEV.
+In general the stddev is scaled down to STDDEV, but if the stddev is already
+less than the target STDDEV, than it is left alone.
+*/
+
+#define MEAN    100
+#define STDDEV  32       /* Resulting variance will be this squared */
+
+normalize_scale(V,m)
+short *V;
+int    m;
+{
+    int   i;
+    float mean, var;
+    float sum, sumsq, stddev, norm;
+
+    sum=0; sumsq=0;
+    for (i=0 ; i<m ; i++) {
+	sum   += V[i];
+	sumsq += V[i] * V[i];
+    }
+    mean = sum/m;
+    var  = sumsq/m - mean*mean;
+
+    if ((stddev = sqrt(var)) >= STDDEV)
+	for (i=0 ; i<m ; i++) {
+	    norm = ( (float)V[i] - mean ) / stddev;
+	    V[i] = norm * STDDEV + MEAN;
+	}
+    else
+	for (i=0 ;  i<m ; i++) {
+	    norm = (float)V[i]-mean;
+	    V[i] = norm + MEAN;
+	}
+
+    return (int)mean;
+}
+