view 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 source
/***************************************************************************
 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;
}