/**
class which encapsulates most of CIPIC data structure
for HRIR
@author Reynald Hoskinson (reynald@cs.ubc.ca)
*/
package jass.generators;
public class CIPIC_HRTF {
final boolean DEBUG = true;
int elmax = 50;
int [] elindices;
double [] elevations;
double [] azimuths;
double [] azimuths_err;
double elerr;
double azerr;
int [] returnValue;
public CIPIC_HRTF() {
elindices = new int[elmax];
elevations = new double[elmax];
azimuths = new double[25];
azimuths_err = new double[25];
returnValue = new int[2];
int i;
for (i = 0; i < elmax; i++) {
elindices[i] = i;
elevations[i] = -45 + 5.625*(elindices[i]-1);
}
azimuths[0] = -80.0;
azimuths[1] = -65.0;
azimuths[2] = -55.0;
i = 3;
for (int j = -45; j < 50; j+=5) {
azimuths[i++] = j;
}
azimuths[i++] = 55;
azimuths[i++] = 65;
azimuths[i] = 80;
}
// gets a coordinate in th HRTF for specific azimuth, elevation
// need to interpolate
// from CIPIC
// errors are recorded, and can be looked at later.
/* returns coordinates of azimuth, elevation
closest to those given as inputs
*/
public int[] getNearest(double azimuth, double elevation) {
// System.out.println("getnearest: az: " + azimuth + " elev " + elevation);
if ((azimuth < -90.0) || (azimuth > 90.0)) {
System.out.println("error: invalid azimuth");
}
double el = Math.round((elevation+45.0)/5.625);
el = Math.max(el, 1.0);
elerr = elevation - elevations[(int)el];
double min = 180f;
int min_index = 0;
for (int i = 0; i < azimuths.length; i++) {
azimuths_err[i] = Math.abs(Math.abs(azimuths[i] - azimuth));
if (azimuths_err[i] < min ) {
min = azimuths_err[i];
min_index = i;
}
}
azerr = min;
returnValue[0] = min_index; // azimuth
returnValue[1] = (int)el -1;
// System.out.println("return : " + returnValue[0] + " " + returnValue[1]);
return returnValue;
}
public int[] getNearestPVALDEG(double azimuth, double elevation) {
// System.out.println("getnearest: az: " + azimuth + " elev " + elevation);
double az = pvaldeg(azimuth);
if ((az < -90.0) || (az > 90.0)) {
System.out.println("error: invalid azimuth");
}
double elev = pvaldeg(elevation);
double el = Math.round((elev+45.0)/5.625);
el = Math.max(el, 1.0);
// el = Math.min(el, elmax);
// is this really true? aren't I pdvadeg'ing elev twice?
if (DEBUG) {
if (el > 50.0) {
System.out.println("el: " + el);
}
elerr = pvaldeg(elev - elevations[(int)el]);
}
double min = 180f;
int min_index = 0;
for (int i = 0; i < azimuths.length; i++) {
azimuths_err[i] = Math.abs(pvaldeg(Math.abs(azimuths[i] - az)));
if (azimuths_err[i] < min ) {
min = azimuths_err[i];
min_index = i;
}
}
az = min_index;
azerr = min;
returnValue[0] = min_index;
returnValue[1] = (int)el -1;
// System.out.println("return : " + returnValue[0] + " " + returnValue[1]);
return returnValue;
}
// returns azimuth error for last pulse caclulated
public double getAzimuthError() {
return azerr;
}
// returns elevation error for last pulse caclulated
public double getElevationError() {
return elerr;
}
/*
finds a principal value of an angle, converting it to the range
[-90, 270]
*/
public double pvaldeg(double angle) {
double dtr = Math.PI/180.0;
/*
atan2 returns the theta component of the point (r, theta)
in polar coordinates that corresponds to the point (x, y)
in Cartesian coordinates.
*/
double angl = Math.atan2(Math.sin(angle*dtr), Math.cos(angle*dtr))/dtr;
if (angl < -90.0) {
angl = angle + 360.0;
}
return angl;
}
}