/* Main calibration and execution program for MyHRTF. See accompanied README file for instructions and syntax. Class structure taken from testMyJCRev by John Chowning Rego Sen, 220C Project, Spring Quarter 2003-2004 */ #include "WvIn.h" // STK-4 sound input support #include "WvOut.h" // STK-4 sound output support #include "Stk.h" // for dealing with global sampling rate #include "FDNJot4LP.h" #include "MyHRTF.h" #include "RtWvOut.h" #include // for fabs() #include // for atof(() #include #include #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)<(b))?(b):(a)) int play(char *hfile, int nargc, char *nargv[], int playback); int main(int argc, char *argv[]) { int ROUNDS = 6; int j; int z; char c[32]; char * hfile; char holder[32]; //char proceed[32]; char **dargv = (char**)malloc(70*sizeof(char)); //WvIn * inFile; //cin.unsetf(ios::skipws); for (j=0;j<7;j++) dargv[j] = (char*)malloc(10*sizeof(char)); strncpy(dargv[1],"t1.wav",10); strncpy(dargv[2],"temp.wav",10); strncpy(dargv[3],"0.5",10); int dummy=0; int calib = 1; if (argv[6] == NULL) { cout << endl << "REGO'S HRTF CALIBRATION SYSTEM" << endl; cout << "Please enter your user name: "; cin >> holder; int L = strcspn (holder," "); hfile = (char*) malloc(L+5); strcpy(hfile,strtok(holder," ")); strcat(hfile,".hrtf"); FILE * rx; FILE * tmp; rx=fopen(hfile,"w"); tmp=fopen("temp.hrtf","w"); int i; MY_FLOAT r[6]; MY_FLOAT cleftA[6] = {0,1,5,5,5,5}; MY_FLOAT cleftB[6] = {0,2,4,7,11,13}; MY_FLOAT cleftD[6] = {0,1,0.5,0.5,0.5,0.5}; MY_FLOAT crightA[6] = {0,1,5,5,5,5}; MY_FLOAT crightB[6] = {0,2,4,7,11,13}; MY_FLOAT crightD[6] = {0,1,0.5,0.5,0.5,0.5}; MY_FLOAT cleftPinnaP[6] = {0,0.5,-1,0.5,-0.25,0.25}; MY_FLOAT crightPinnaP[6] = {0,0.5,-1,0.5,-0.25,0.25}; MY_FLOAT headR=0.07; MY_FLOAT aleftD[6] = {0,0.75,0.25,0.25,0.25,0.25}; MY_FLOAT arightD[6] = {0,0.75,0.25,0.25,0.25,0.25}; MY_FLOAT aheadR=0.08; fprintf(rx,"%lf\n",headR); fprintf(tmp,"%lf\n",aheadR); for (i=0;i<6;i++) { fprintf(rx,"%lf\n",cleftA[i]); fprintf(rx,"%lf\n",cleftB[i]); fprintf(rx,"%lf\n",cleftD[i]); fprintf(rx,"%lf\n",crightA[i]); fprintf(rx,"%lf\n",crightB[i]); fprintf(rx,"%lf\n",crightD[i]); fprintf(rx,"%lf\n",cleftPinnaP[i]); fprintf(rx,"%lf\n",crightPinnaP[i]); fprintf(tmp,"%lf\n",cleftA[i]); fprintf(tmp,"%lf\n",cleftB[i]); fprintf(tmp,"%lf\n",aleftD[i]); fprintf(tmp,"%lf\n",crightA[i]); fprintf(tmp,"%lf\n",crightB[i]); fprintf(tmp,"%lf\n",arightD[i]); fprintf(tmp,"%lf\n",cleftPinnaP[i]); fprintf(tmp,"%lf\n",crightPinnaP[i]); } fclose(rx); fclose(tmp); cout << endl; cout << "Welcome to my HRTF calibration system. You will undergo" << endl; cout << "six rounds of impulse comparisons to test your front/back" << endl; cout << "spatialization, and then four more for above/below." << endl << endl;; cout << "You will now hear two impulses of noise *behind* you." << endl; cout << "You will be prompted before hearing each impulse." << endl; cout << "You will then be asked which one sounds more spatially accurate." << endl; strncpy(dargv[4],"-20",10); strncpy(dargv[5],"-180",10); calib=1; do { cout << endl << "ROUND " << calib << " OF " << ROUNDS; cout << endl << "Press RETURN to hear the first sample:"; do { z=cin.get(); } while( z == ' ' ); do { z=cin.get(); } while( z == ' ' ); //cin >> proceed; cout << "Playing first sample..." << endl; strncpy(dargv[1],"t2.wav",10); dummy = play(hfile, 7, dargv, 1); cout << endl << "Press RETURN to hear the second sample:"; //cin >> proceed; do { z=cin.get(); } while( z == ' ' ); cout << "Playing second sample..." << endl; strncpy(dargv[1],"t1.wav",10); dummy = play("temp.hrtf", 7, dargv, 1); cout << endl << "Which sounded more *behind* you? Enter one of the following:" << endl; cout << " '1' for the first sample" << endl; cout << " '2' for the second sample" << endl; cout << " '0' if you can't tell any difference" << endl; cout << " 'r' to play the samples again" << endl; cin >> c; if ((strncmp (c,"1",1) == 0) || (strncmp (c,"0",1) == 0)){ calib++; if (strncmp (c,"1",1) == 0) cout << "You have selected the first sample." << endl; for (j=1;j<6;j++) { r[j]=0.9*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); aleftD[j]= cleftD[j]+r[j]*(calib!=4); arightD[j]=crightD[j]+r[j]*(calib!=4); } r[0]=.05*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); aheadR=headR+r[0]*(calib==4); } else if (strncmp (c,"2",1) == 0) { calib++; cout << "You have selected the second sample." << endl; for (j=1;j<6;j++) { r[j]=0.9*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); cleftD[j]= aleftD[j]+r[j]*(calib!=4); crightD[j]=arightD[j]+r[j]*(calib!=4); } r[0]=.05*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); headR=aheadR+r[0]*(calib==4); } rx=fopen(hfile,"w"); tmp=fopen("temp.hrtf","w"); fprintf(rx,"%lf\n",headR); fprintf(tmp,"%lf\n",aheadR); for (i=0;i<6;i++) { fprintf(rx,"%lf\n",cleftA[i]); fprintf(rx,"%lf\n",cleftB[i]); fprintf(rx,"%lf\n",cleftD[i]); fprintf(rx,"%lf\n",crightA[i]); fprintf(rx,"%lf\n",crightB[i]); fprintf(rx,"%lf\n",crightD[i]); fprintf(rx,"%lf\n",cleftPinnaP[i]); fprintf(rx,"%lf\n",crightPinnaP[i]); fprintf(tmp,"%lf\n",cleftA[i]); fprintf(tmp,"%lf\n",cleftB[i]); fprintf(tmp,"%lf\n",aleftD[i]); fprintf(tmp,"%lf\n",crightA[i]); fprintf(tmp,"%lf\n",crightB[i]); fprintf(tmp,"%lf\n",arightD[i]); fprintf(tmp,"%lf\n",cleftPinnaP[i]); fprintf(tmp,"%lf\n",crightPinnaP[i]); } fclose(rx); fclose(tmp); //calib++; if (calib>ROUNDS) { calib = 0; } } while (calib>0); cout << endl << "----------------------------------------------------" << endl; cout << endl << "You will now hear two impulses of noise *above* you." << endl; cout << "You will be prompted before hearing each impulse." << endl; cout << "You will then be asked which one sounds more spatially accurate." << endl; strncpy(dargv[4],"-20",10); strncpy(dargv[5],"80",10); calib=1; do { cout << endl << "ROUND " << calib << " OF " << ROUNDS; cout << endl << "Press RETURN to hear the first sample:"; //cin >> proceed; do { z=cin.get(); } while( z == ' ' ); do { z=cin.get(); } while( z == ' ' ); cout << "Playing first sample..." << endl; strncpy(dargv[1],"t2.wav",10); dummy = play(hfile, 7, dargv, 1); cout << endl << "Press RETURN to hear the second sample:"; //cin >> proceed; do { z=cin.get(); } while( z == ' ' ); cout << "Playing second sample..." << endl; strncpy(dargv[1],"t1.wav",10); dummy = play("temp.hrtf", 7, dargv, 1); cout << endl << "Which sounded more *above* you? Enter one of the following:" << endl; cout << " '1' for the first sample" << endl; cout << " '2' for the second sample" << endl; cout << " '0' if you can't tell any difference" << endl; cout << " 'r' to play the samples again" << endl; cin >> c; if ((strncmp (c,"1",1) == 0) || (strncmp (c,"0",1) == 0)){ calib++; if (strncmp (c,"1",1) == 0) cout << "You have selected the first sample." << endl; for (j=1;j<6;j++) { r[j]=0.9*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); aleftD[j]= cleftD[j]+r[j]*(calib!=4); arightD[j]=crightD[j]+r[j]*(calib!=4); } r[0]=.05*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); aheadR=headR+r[0]*(calib==4); } else if (strncmp (c,"2",1) == 0) { cout << "You have selected the second sample." << endl; calib++; for (j=1;j<6;j++) { r[j]=0.9*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); cleftD[j]= aleftD[j]+r[j]*(calib!=4); crightD[j]=arightD[j]+r[j]*(calib!=4); } r[0]=.05*(.5-((MY_FLOAT)rand()/(MY_FLOAT)RAND_MAX)/sqrt(calib)); headR=aheadR+r[0]*(calib==4); } rx=fopen(hfile,"w"); tmp=fopen("temp.hrtf","w"); fprintf(rx,"%lf\n",headR); fprintf(tmp,"%lf\n",aheadR); for (i=0;i<6;i++) { fprintf(rx,"%lf\n",cleftA[i]); fprintf(rx,"%lf\n",cleftB[i]); fprintf(rx,"%lf\n",cleftD[i]); fprintf(rx,"%lf\n",crightA[i]); fprintf(rx,"%lf\n",crightB[i]); fprintf(rx,"%lf\n",crightD[i]); fprintf(rx,"%lf\n",cleftPinnaP[i]); fprintf(rx,"%lf\n",crightPinnaP[i]); fprintf(tmp,"%lf\n",cleftA[i]); fprintf(tmp,"%lf\n",cleftB[i]); fprintf(tmp,"%lf\n",aleftD[i]); fprintf(tmp,"%lf\n",crightA[i]); fprintf(tmp,"%lf\n",crightB[i]); fprintf(tmp,"%lf\n",arightD[i]); fprintf(tmp,"%lf\n",cleftPinnaP[i]); fprintf(tmp,"%lf\n",crightPinnaP[i]); } fclose(rx); fclose(tmp); if (calib>ROUNDS) { calib = 0; } } while (calib>0); if (strncmp (c,"1",1) == 0) { for (j=1;j<6;j++) { cleftD[j]= aleftD[j]; crightD[j]=arightD[j]; } headR=aheadR; } else { for (j=1;j<6;j++) { aleftD[j]= cleftD[j]; arightD[j]=crightD[j]; } aheadR=headR; } rewind(rx); rewind(tmp); fprintf(rx,"%lf\n",headR); fprintf(tmp,"%lf\n",aheadR); for (i=0;i<6;i++) { fprintf(rx,"%lf\n",cleftA[i]); fprintf(rx,"%lf\n",cleftB[i]); fprintf(rx,"%lf\n",cleftD[i]); fprintf(rx,"%lf\n",crightA[i]); fprintf(rx,"%lf\n",crightB[i]); fprintf(rx,"%lf\n",crightD[i]); fprintf(rx,"%lf\n",cleftPinnaP[i]); fprintf(rx,"%lf\n",crightPinnaP[i]); fprintf(tmp,"%lf\n",cleftA[i]); fprintf(tmp,"%lf\n",cleftB[i]); fprintf(tmp,"%lf\n",aleftD[i]); fprintf(tmp,"%lf\n",crightA[i]); fprintf(tmp,"%lf\n",crightB[i]); fprintf(tmp,"%lf\n",arightD[i]); fprintf(tmp,"%lf\n",cleftPinnaP[i]); fprintf(tmp,"%lf\n",crightPinnaP[i]); } fclose(rx); fclose(tmp); //inFile->closeFile(); cout << endl << "CALIBRATION COMPLETE!" << endl; cout << "Your spatial profile has been saved as " << hfile << endl; } else { hfile = (char*) malloc(strlen(argv[6])); hfile = argv[6]; dummy = play(hfile, argc, argv, 0); } dummy = dummy + 1; } int play(char *hfile, int nargc, char *nargv[], int playback) { //cout << "argc= " << argc << endl; RtWvOut * rt = new RtWvOut(2); MY_FLOAT thetaDeg = 70; MY_FLOAT phiDeg = -20; char * filename; long M[4] = {113,331,1051,4791}; // delay line lengths in samples MY_FLOAT gCoeff = 1.0; // gain coefficient for the A feedback matrix MY_FLOAT t60_DC = 2.0; // reverberation time at DC MY_FLOAT t60_pi = 1.0; // reverberation time at half the sampling rate char *outputName; // output soundfile name MY_FLOAT computeSeconds = 2; // seconds to compute if (nargc<2) { printf("You must give at minimum an argument for the soundfile input\n"); } if (nargc>2) { outputName = nargv[2]; } else { outputName = nargv[0]; // default: take the name of this .cpp file } if (nargc>5) { computeSeconds = atof(nargv[3]); thetaDeg = atof(nargv[4]); phiDeg = atof(nargv[5]); filename = hfile; } //cout << "AZIMUTH = " << thetaDeg << " degrees" << endl; //cout << "ELEVATION = " << phiDeg << " degrees" << endl; WvIn input_temp(nargv[1]); // reads input MY_FLOAT fs = input_temp.getFileRate(); // sampling rate of input soundfile Stk::setSampleRate(fs); // set sampling rate to that of input WvIn input(nargv[1]); // rereads input at new sampling rate WvOut output(outputName,2); // creates audio file output //MY_FLOAT maxValue = 0.0; //MY_FLOAT maxRev = 0.0; long double nSamps = (long double) (fs*computeSeconds); MY_FLOAT forOutputL; // output buffer MY_FLOAT forOutputR; // create a MyHRTF module MyHRTF *simpleHRTF; MyHRTF *revHRTF; MyHRTF *floorHRTF; Delay *floorDelay; MY_FLOAT phiFloor = -45.0; if ((phiDeg>90) || (phiDeg<-90)) phiFloor = -135.0; int floor = (int)fs/1000; simpleHRTF = new MyHRTF(thetaDeg,phiDeg,filename); revHRTF = new MyHRTF(thetaDeg,phiDeg,filename); floorHRTF = new MyHRTF(thetaDeg,phiFloor,filename); floorDelay = new Delay(floor,floor); MY_FLOAT inputSamp, outputSamp[2], hrtfOut[2], filtResultL, filtResultR, echoOut[2], echoL, echoR; // REVERB STUFF MY_FLOAT revOutputL; // output buffer MY_FLOAT revOutputR; FDNJot4LP *FDN4LP = new FDNJot4LP(t60_DC,t60_pi,gCoeff,M); MY_FLOAT revIn, revOut[2]; //MY_FLOAT absRevOut, absFiltResult MY_FLOAT gainRev = 0.001; for (long double i=0;itick(inputSamp, hrtfOut); floorHRTF->tick(floorDelay->tick(inputSamp),echoOut); filtResultL = simpleHRTF->lastOutLeft(); // left channel reverb samples filtResultR = simpleHRTF->lastOutRight(); echoL = floorHRTF->lastOutLeft(); echoR = floorHRTF->lastOutRight(); forOutputL = filtResultL+0.3*echoL; forOutputR = filtResultR+0.3*echoR; //absFiltResult = max(fabs(filtResultL+0.3*echoL),fabs(filtResultR+0.3*echoR)); //absFiltResult = fabs(filtResultL-filtResultR); //if (absFiltResult > maxValue) maxValue = absFiltResult; revIn = FDN4LP->tick(inputSamp); revHRTF->tick(revIn, revOut); //absRevOut = max(fabs(revOut[0]),fabs(revOut[1])); revOutputL = revOut[0]; // save FDN output samples revOutputR = revOut[1]; // save FDN output samples //if (absRevOut > maxRev) maxRev = absRevOut; //} //for (long double i=0;itickFrame(outputSamp); output.tickFrame(outputSamp); // output samples to a soundfile } delete rt; input.closeFile(); output.closeFile(); input_temp.closeFile(); delete simpleHRTF; delete revHRTF; delete floorHRTF; delete floorDelay; delete FDN4LP; return 0; }