tomwalters@0: /*************************************************************************** tomwalters@0: pitch_strength.c Pitch strength measure from spiral sector-weights contour. tomwalters@0: ---------------- tomwalters@0: Michael Allerhand, 1992. tomwalters@0: tomwalters@0: Read m binary shorts (default m=SECTORS) for each specified frame. tomwalters@0: Compute the pitch-strength of the sector-weights by projecting onto tomwalters@0: the direction in the sector-weights space (given by vector `vec') tomwalters@0: which best explains the variation between weak and strong pitch, tomwalters@0: as exemplified by training data generated from iterated rippled noise. tomwalters@0: tomwalters@0: The sector weights are normalized with respect to angle (pitch) and tomwalters@0: magnitude (loudness), and also by extracting features using the tomwalters@0: method of Fourier descriptors. tomwalters@0: tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: #include tomwalters@0: #include tomwalters@0: #include "options.h" tomwalters@0: #include "units.h" tomwalters@0: #include "strmatch.h" tomwalters@0: tomwalters@0: char applic[] = "Pitch-strength measure from spiral sector-weights contour.\n (Input and output in binary shorts)." ; tomwalters@0: tomwalters@0: static char *helpstr, *debugstr, *fstr, *vstr, *mstr, *shiftstr, *scalestr ; tomwalters@0: tomwalters@0: static Options option[] = { tomwalters@0: { "help" , "off" , &helpstr , "help" , DEBUG }, tomwalters@0: { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, tomwalters@0: { "frames" , "1-max" , &fstr , "select frames inclusively" , VAL }, tomwalters@0: { "nsectors" , "64" , &mstr , "number of sectors" , SVAL }, tomwalters@0: { "vector" , "off" , &vstr , "file for alternative projection vector", SVAL }, tomwalters@0: { "shift" , "212.0" , &shiftstr , "scale shifting by addition" , SVAL }, tomwalters@0: { "scale" , "0.7686" , &scalestr , "scaling by multiplication" , SVAL }, tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: /* projection vector for 64-sector cntour */ tomwalters@0: tomwalters@0: char *defvec[] = { "0.000", "0.150", "-0.260", "-0.190", "-0.252", "-0.372", "-0.121", tomwalters@0: "-0.374", "-0.150", "-0.236", "-0.157", "-0.109", "-0.246", "-0.088", tomwalters@0: "-0.045", "-0.179", "-0.164", "-0.280", "-0.028", "-0.116", "-0.013", tomwalters@0: "-0.065", "-0.252", "-0.005", "-0.216", "-0.086", "0.043", "-0.061", tomwalters@0: "-0.055", "0.084", "-0.045", "-0.203", "211.670" } ; tomwalters@0: tomwalters@0: tomwalters@0: float shift, scale ; tomwalters@0: tomwalters@0: tomwalters@0: main (argc, argv) tomwalters@0: int argc; tomwalters@0: char ** argv; tomwalters@0: { tomwalters@0: FILE *fp, *fp1 ; tomwalters@0: int m, n; /* Number of sectors around spiral. */ tomwalters@0: short *sector; /* Sector-weights contour. */ tomwalters@0: float *vec; tomwalters@0: int i, a, b; tomwalters@0: char *val1, *val2 ; tomwalters@0: tomwalters@0: fp = openopts( option,argc,argv ) ; tomwalters@0: if ( !isoff( helpstr ) ) tomwalters@0: helpopts( helpstr, argv[0], applic, option ) ; tomwalters@0: tomwalters@0: shift = atof( shiftstr ) ; tomwalters@0: scale = atof( scalestr ) ; tomwalters@0: tomwalters@0: m = atoi( mstr ) ; tomwalters@0: n = m>>1 ; tomwalters@0: tomwalters@0: /* parse bounds on number of frames */ tomwalters@0: tomwalters@0: if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) { tomwalters@0: fprintf(stderr,"loudness: bad frame selector [%s]\n", fstr ) ; tomwalters@0: exit( 1 ) ; tomwalters@0: } tomwalters@0: a = atoi( val1 ) ; tomwalters@0: if ( isempty( val2 ) ) b = a ; tomwalters@0: else if ( ismax( val2 ) ) b = 0 ; tomwalters@0: else b = atoi( val2 ) ; tomwalters@0: tomwalters@0: if (b0) fprintf(stderr,"pitch_strength: warning, bad frame specifiers\n"); tomwalters@0: tomwalters@0: if ( ison( debugstr ) ) { tomwalters@0: printf("a=%d b=%d m=%d vector=%s\n", tomwalters@0: a, b, m, vstr ); tomwalters@0: exit(0); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* Allocate space for sector-weights contour and discriminant vector */ tomwalters@0: tomwalters@0: if (( sector = (short *)malloc( m*sizeof(short) )) == NULL) tomwalters@0: fprintf(stderr,"pitch_strength: malloc out of space\n"); tomwalters@0: if (( vec = (float *)malloc( (n+1)*sizeof(float) )) == NULL) tomwalters@0: fprintf(stderr,"pitch_strength: malloc out of space\n"); tomwalters@0: tomwalters@0: tomwalters@0: /* Assign discriminant vector */ tomwalters@0: tomwalters@0: if ( isoff( vstr) ) /* copy internal (default) vector */ tomwalters@0: for (i=0 ; i<=n ; i++) tomwalters@0: vec[i] = atof( defvec[i] ) ; tomwalters@0: else { /* read alternative vector from file */ tomwalters@0: if ((fp1 = fopen( vstr, "r" )) == NULL) { tomwalters@0: fprintf(stderr,"pitch_strength: can't open %s\n", vstr ); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: if ( fread(vec, sizeof(float), n+1, fp1) == NULL ) { tomwalters@0: fprintf(stderr,"pitch_strength: empty discriminant vector\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: fclose(fp1); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /* Seek past a-1 frames, then read the next b-a+1 frames, or all */ tomwalters@0: /* remaining frames if b==0. */ tomwalters@0: tomwalters@0: if (a>0) { tomwalters@0: tomwalters@0: for (i=1 ; i 0) tomwalters@0: for ( ; i<=b && fread(sector,sizeof(short),m,fp) ; i++) tomwalters@0: pitch_strength( sector, m, n, vec ); tomwalters@0: else tomwalters@0: while ( fread(sector,sizeof(short),m,fp) ) tomwalters@0: pitch_strength( sector, m, n, vec ); tomwalters@0: } tomwalters@0: tomwalters@0: fclose(fp); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: pitch_strength( sector, m, n, vec ) tomwalters@0: short *sector; /* Sector-weights contour. */ tomwalters@0: int m, n; /* Number of sectors around spiral. */ tomwalters@0: float *vec; tomwalters@0: { tomwalters@0: float inner_product(); tomwalters@0: short w0; tomwalters@0: tomwalters@0: normalize_scale(sector,m); tomwalters@0: normalize_angle(sector,m); tomwalters@0: Fd(sector,m,n); tomwalters@0: sector[0] = 0; /* normalize for translation */ tomwalters@0: sector[n] = 1; /* Augment each data vector with 1 */ tomwalters@0: w0 = (short)( ( shift - inner_product( vec, sector, n+1 ) ) * scale ) ; tomwalters@0: fwrite (&w0, sizeof(short), 1, stdout); tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /**************************************************************************** tomwalters@0: Inner product (for projection). tomwalters@0: ****************************************************************************/ tomwalters@0: tomwalters@0: float inner_product(W,V,m) tomwalters@0: float *W; tomwalters@0: short *V; tomwalters@0: int m; tomwalters@0: { tomwalters@0: int i; tomwalters@0: float w0=0; tomwalters@0: tomwalters@0: for (i=0 ; i= STDDEV) tomwalters@0: for (i=0 ; i max) { tomwalters@0: max = q; tomwalters@0: phi = k; tomwalters@0: } tomwalters@0: } tomwalters@0: tomwalters@0: /* Sort sector array to rotate contour into normalized orientation */ tomwalters@0: tomwalters@0: if (( tmp = (short *)malloc(m*sizeof(short))) == NULL) tomwalters@0: fprintf(stderr,"pitch_strength: malloc out of space\n"); tomwalters@0: tomwalters@0: for (i=0, k=phi ; kreal ) /* cartesian form */ tomwalters@0: #define Im(C) ( (C)->imag ) tomwalters@0: #define Mod(C) ( (C)->real ) /* polar form */ tomwalters@0: #define Arg(C) ( (C)->imag ) tomwalters@0: #define cscalar_mod(C) ( sqrt(sq(Re(C))+sq(Im(C))) ) tomwalters@0: #define FFT_real(V,n) ( realft((float *)(V)-1, n>>1 ,1) ) tomwalters@0: tomwalters@0: tomwalters@0: Fd(sector,m,n) tomwalters@0: short *sector; tomwalters@0: int m, n; tomwalters@0: { tomwalters@0: static float *V; tomwalters@0: static char first=1; tomwalters@0: int i, j; tomwalters@0: tomwalters@0: if (first) { /* Allocate space first time only */ tomwalters@0: if (( V = (float *) malloc( m*sizeof(float) )) == NULL) { tomwalters@0: fprintf(stderr,"pitch_strength: malloc out of space\n"); tomwalters@0: exit(1); tomwalters@0: } tomwalters@0: first=0; tomwalters@0: } tomwalters@0: tomwalters@0: for (i=0 ; i i) { tomwalters@0: SWAP(data[j],data[i]); tomwalters@0: SWAP(data[j+1],data[i+1]); tomwalters@0: } tomwalters@0: m=n >> 1; tomwalters@0: while (m >= 2 && j > m) { tomwalters@0: j -= m; tomwalters@0: m >>= 1; tomwalters@0: } tomwalters@0: j += m; tomwalters@0: } tomwalters@0: mmax=2; tomwalters@0: while (n > mmax) { tomwalters@0: istep=2*mmax; tomwalters@0: theta=6.28318530717959/(isign*mmax); tomwalters@0: wtemp=sin(0.5*theta); tomwalters@0: wpr = -2.0*wtemp*wtemp; tomwalters@0: wpi=sin(theta); tomwalters@0: wr=1.0; tomwalters@0: wi=0.0; tomwalters@0: for (m=1;m