Mercurial > hg > audiodb
diff audioDB.cpp @ 193:f9d16137e704
Merge powertable branch -r168:227 to trunk.
author | mas01cr |
---|---|
date | Wed, 21 Nov 2007 11:35:44 +0000 |
parents | cdd441dcc9a8 |
children | 0e75deb7d4d1 |
line wrap: on
line diff
--- a/audioDB.cpp Tue Nov 13 17:14:21 2007 +0000 +++ b/audioDB.cpp Wed Nov 21 11:35:44 2007 +0000 @@ -72,6 +72,9 @@ else if(O2_ACTION(COM_L2NORM)) l2norm(dbName); + else if(O2_ACTION(COM_POWER)) + power_flag(dbName); + else if(O2_ACTION(COM_DUMP)) dump(dbName); @@ -220,6 +223,12 @@ return 0; } + if(args_info.POWER_given){ + command=COM_POWER; + dbName=args_info.database_arg; + return 0; + } + if(args_info.INSERT_given){ command=COM_INSERT; dbName=args_info.database_arg; @@ -234,6 +243,15 @@ usingTimes=1; } } + if (args_info.power_given) { + powerFileName = args_info.power_arg; + if (strlen(powerFileName) > 0) { + if (!(powerfd = open(powerFileName, O_RDONLY))) { + error("Could not open power file for reading", powerFileName, "open"); + } + usingPower = 1; + } + } return 0; } @@ -261,6 +279,14 @@ usingTimes=1; } } + if(args_info.powerList_given){ + powerFileName=args_info.powerList_arg; + if(strlen(powerFileName)>0){ + if(!(powerFile = new ifstream(powerFileName,ios::in))) + error("Could not open powerList file for reading", powerFileName); + usingPower=1; + } + } return 0; } @@ -284,6 +310,16 @@ usingTimes=1; } } + + if(args_info.power_given){ + powerFileName=args_info.power_arg; + if(strlen(powerFileName)>0){ + if (!(powerfd = open(powerFileName, O_RDONLY))) { + error("Could not open power file for reading", powerFileName, "open"); + } + usingPower = 1; + } + } // query type if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0) @@ -318,6 +354,18 @@ if(sequenceHop < 1 || sequenceHop > 1000) { error("seqhop out of range: 1 <= seqhop <= 1000"); } + + if (args_info.absolute_threshold_given) { + if (args_info.absolute_threshold_arg >= 0) { + error("absolute threshold out of range: should be negative"); + } + use_absolute_threshold = true; + absolute_threshold = args_info.absolute_threshold_arg; + } + if (args_info.relative_threshold_given) { + use_relative_threshold = true; + relative_threshold = args_info.relative_threshold_arg; + } return 0; } return -1; // no command found @@ -412,6 +460,7 @@ dbH->dataOffset = ALIGN_UP(dbH->trackTableOffset + O2_TRACKTABLESIZE*maxfiles, 8); dbH->l2normTableOffset = ALIGN_DOWN(size - maxfiles*O2_MEANNUMVECTORS*sizeof(double), 8); dbH->timesTableOffset = ALIGN_DOWN(dbH->l2normTableOffset - maxfiles*O2_MEANNUMVECTORS*sizeof(double), 8); + dbH->powerTableOffset = ALIGN_DOWN(dbH->timesTableOffset - maxfiles*O2_MEANNUMVECTORS*sizeof(double), 8); dbH->dbSize = size; memcpy (db, dbH, O2_HEADERSIZE); @@ -470,6 +519,7 @@ dataBuf = (double *) (db + dbH->dataOffset); l2normTable = (double *) (db + dbH->l2normTableOffset); timesTable = (double *) (db + dbH->timesTableOffset); + powerTable = (double *) (db + dbH->powerTableOffset); } void audioDB::initInputFile (const char *inFile) { @@ -523,6 +573,9 @@ if(!usingTimes && (dbH->flags & O2_FLAG_TIMES)) error("Must use timestamps with timestamped database","use --times"); + if(!usingPower && (dbH->flags & O2_FLAG_POWER)) + error("Must use power with power-enabled database", dbName); + // Check that there is room for at least 1 more file if((char*)timesTable<((char*)dataBuf+dbH->length+statbuf.st_size-sizeof(int))) error("Insert failed: no more room in database", inFile); @@ -567,6 +620,9 @@ assert(timesdata+numVectors<l2normTable); insertTimeStamps(numVectors, timesFile, timesdata); + double *powerdata = powerTable + timesoffset; + insertPowerData(numVectors, powerfd, powerdata); + // Increment file count dbH->numFiles++; @@ -652,6 +708,32 @@ } } +void audioDB::insertPowerData(unsigned numVectors, int powerfd, double *powerdata) { + if (usingPower) { + if (!(dbH->flags & O2_FLAG_POWER)) { + error("Cannot insert power data on non-power DB", dbName); + } + + int one; + unsigned int count; + + count = read(powerfd, &one, sizeof(unsigned int)); + if (count != sizeof(unsigned int)) { + error("powerfd read failed", "int", "read"); + } + if (one != 1) { + error("dimensionality of power file not 1", powerFileName); + } + + // FIXME: should check that the powerfile is the right size for + // this. -- CSR, 2007-10-30 + count = read(powerfd, powerdata, numVectors * sizeof(double)); + if (count != numVectors * sizeof(double)) { + error("powerfd read failed", "double", "read"); + } + } +} + void audioDB::batchinsert(const char* dbName, const char* inFile) { initDBHeader(dbName, true); @@ -661,6 +743,7 @@ ifstream *filesIn = 0; ifstream *keysIn = 0; ifstream* thisTimesFile = 0; + int thispowerfd = 0; if(!(filesIn = new ifstream(inFile))) error("Could not open batch in file", inFile); @@ -671,10 +754,14 @@ if(!usingTimes && (dbH->flags & O2_FLAG_TIMES)) error("Must use timestamps with timestamped database","use --times"); + if(!usingPower && (dbH->flags & O2_FLAG_POWER)) + error("Must use power with power-enabled database", dbName); + unsigned totalVectors=0; char *thisKey = new char[MAXSTR]; char *thisFile = new char[MAXSTR]; char *thisTimesFileName = new char[MAXSTR]; + char *thisPowerFileName = new char[MAXSTR]; do{ filesIn->getline(thisFile,MAXSTR); @@ -684,6 +771,8 @@ thisKey = thisFile; if(usingTimes) timesFile->getline(thisTimesFileName,MAXSTR); + if(usingPower) + powerFile->getline(thisPowerFileName, MAXSTR); if(filesIn->eof()) break; @@ -717,7 +806,7 @@ cerr << "Warning: ignoring zero-length feature vector file:" << thisKey << endl; } } - else{ + else{ if(usingTimes){ if(timesFile->eof()) error("not enough timestamp files in timesList"); @@ -732,7 +821,23 @@ if(thisTimesFile) delete thisTimesFile; } - + + if (usingPower) { + if(powerFile->eof()) { + error("not enough power files in powerList", powerFileName); + } + thispowerfd = open(thisPowerFileName, O_RDONLY); + if (thispowerfd < 0) { + error("failed to open power file", thisPowerFileName); + } + unsigned insertoffset = dbH->length; + unsigned poweroffset = insertoffset / (dbH->dim * sizeof(double)); + double *powerdata = powerTable + poweroffset; + insertPowerData(numVectors, thispowerfd, powerdata); + if (0 < thispowerfd) { + close(thispowerfd); + } + } strncpy(fileTable + dbH->numFiles*O2_FILETABLESIZE, thisKey, strlen(thisKey)); unsigned insertoffset = dbH->length;// Store current state @@ -879,18 +984,27 @@ error("error changing working directory", output, "chdir"); } - int fLfd, tLfd = 0, kLfd; - FILE *fLFile, *tLFile = 0, *kLFile; + int fLfd, tLfd = 0, pLfd = 0, kLfd; + FILE *fLFile, *tLFile = 0, *pLFile = 0, *kLFile; if ((fLfd = open("featureList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { error("error creating featureList file", "featureList.txt", "open"); } + int times = dbH->flags & O2_FLAG_TIMES; if (times) { if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { error("error creating timesList file", "timesList.txt", "open"); } } + + int power = dbH->flags & O2_FLAG_POWER; + if (power) { + if ((pLfd = open("powerList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { + error("error creating powerList file", "powerList.txt", "open"); + } + } + if ((kLfd = open("keyList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { error("error creating keyList file", "keyList.txt", "open"); } @@ -900,10 +1014,13 @@ if (times) { tLFile = fdopen(tLfd, "w"); } + if (power) { + pLFile = fdopen(pLfd, "w"); + } kLFile = fdopen(kLfd, "w"); char *fName = new char[256]; - int ffd; + int ffd, pfd; FILE *tFile; unsigned pos = 0; for(unsigned k = 0; k < dbH->numFiles; k++) { @@ -937,6 +1054,22 @@ fprintf(tLFile, "%s\n", fName); } + if (power) { + uint32_t one = 1; + snprintf(fName, 256, "%05d.power", k); + if ((pfd = open(fName, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { + error("error creating power file", fName, "open"); + } + if ((write(pfd, &one, sizeof(uint32_t))) < 0) { + error("error writing one", fName, "write"); + } + if ((write(pfd, powerTable + pos, trackTable[k] * sizeof(double))) < 0) { + error("error writing data", fName, "write"); + } + fprintf(pLFile, "%s\n", fName); + close(pfd); + } + pos += trackTable[k]; cout << fileTable+k*O2_FILETABLESIZE << " " << trackTable[k] << endl; } @@ -954,10 +1087,16 @@ if(dbH->flags & O2_FLAG_L2NORM) { fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n"); } + if(power) { + fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -P\n"); + } fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -B -F featureList.txt -K keyList.txt"); if(times) { fprintf(scriptFile, " -T timesList.txt"); } + if(power) { + fprintf(scriptFile, " -W powerList.txt"); + } fprintf(scriptFile, "\n"); fclose(scriptFile); @@ -969,6 +1108,9 @@ if(times) { fclose(tLFile); } + if(power) { + fclose(pLFile); + } fclose(kLFile); delete[] fName; @@ -985,7 +1127,29 @@ dbH->flags = dbH->flags|O2_FLAG_L2NORM; memcpy (db, dbH, O2_HEADERSIZE); } - + +void audioDB::power_flag(const char *dbName) { + initTables(dbName, true, 0); + if (dbH->length > 0) { + error("cannot turn on power storage for non-empty database", dbName); + } + dbH->flags |= O2_FLAG_POWER; + memcpy(db, dbH, O2_HEADERSIZE); +} + +bool audioDB::powers_acceptable(double p1, double p2) { + if (use_absolute_threshold) { + if ((p1 < absolute_threshold) || (p2 < absolute_threshold)) { + return false; + } + } + if (use_relative_threshold) { + if (fabs(p1-p2) > fabs(relative_threshold)) { + return false; + } + } + return true; +} void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse){ @@ -1450,6 +1614,46 @@ } +// This is a common pattern in sequence queries: what we are doing is +// taking a window of length seqlen over a buffer of length length, +// and placing the sum of the elements in that window in the first +// element of the window: thus replacing all but the last seqlen +// elements in the buffer the corresponding windowed sum. +void audioDB::sequence_sum(double *buffer, int length, int seqlen) { + double tmp1, tmp2, *ps; + int j, w; + + tmp1 = *buffer; + j = 1; + w = seqlen - 1; + while(w--) { + *buffer += buffer[j++]; + } + ps = buffer + 1; + w = length - seqlen; // +1 - 1 + while(w--) { + tmp2 = *ps; + *ps = *(ps - 1) - tmp1 + *(ps + seqlen - 1); + tmp1 = tmp2; + ps++; + } +} + +void audioDB::sequence_sqrt(double *buffer, int length, int seqlen) { + int w = length - seqlen + 1; + while(w--) { + *buffer = sqrt(*buffer); + buffer++; + } +} + +void audioDB::sequence_average(double *buffer, int length, int seqlen) { + int w = length - seqlen + 1; + while(w--) { + *buffer /= seqlen; + buffer++; + } +} // k nearest-neighbor (k-NN) search between query and target tracks // efficient implementation based on matched filter @@ -1465,13 +1669,6 @@ double* query = (double*)(indata+sizeof(int)); double* queryCopy = 0; - double qMeanL2; - double* sMeanL2; - - unsigned USE_THRESH=0; - double SILENCE_THRESH=0; - double DIFF_THRESH=0; - if(!(dbH->flags & O2_FLAG_L2NORM) ) error("Database must be L2 normed for sequence query","use -L2NORM"); @@ -1488,98 +1685,67 @@ memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double)); qNorm = new double[numVectors]; sNorm = new double[dbVectors]; - sMeanL2=new double[dbH->numFiles]; - assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&sequenceLength); + assert(qNorm&&sNorm&&queryCopy&&sequenceLength); unitNorm(queryCopy, dbH->dim, numVectors, qNorm); query = queryCopy; // Make norm measurements relative to sequenceLength unsigned w = sequenceLength-1; unsigned i,j; - double* ps; - double tmp1,tmp2; // Copy the L2 norm values to core to avoid disk random access later on memcpy(sNorm, l2normTable, dbVectors*sizeof(double)); double* qnPtr = qNorm; double* snPtr = sNorm; + + double *sPower = 0, *qPower = 0; + double *spPtr = 0, *qpPtr = 0; + + if (usingPower) { + if (!(dbH->flags & O2_FLAG_POWER)) { + error("database not power-enabled", dbName); + } + sPower = new double[dbVectors]; + spPtr = sPower; + memcpy(sPower, powerTable, dbVectors * sizeof(double)); + } + for(i=0; i<dbH->numFiles; i++){ - if(trackTable[i]>=sequenceLength){ - tmp1=*snPtr; - j=1; - w=sequenceLength-1; - while(w--) - *snPtr+=snPtr[j++]; - ps = snPtr+1; - w=trackTable[i]-sequenceLength; // +1 - 1 - while(w--){ - tmp2=*ps; - *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1); - tmp1=tmp2; - ps++; - } - ps = snPtr; - w=trackTable[i]-sequenceLength+1; - while(w--){ - *ps=sqrt(*ps); - ps++; + if(trackTable[i]>=sequenceLength) { + sequence_sum(snPtr, trackTable[i], sequenceLength); + sequence_sqrt(snPtr, trackTable[i], sequenceLength); + + if (usingPower) { + sequence_sum(spPtr, trackTable[i], sequenceLength); + sequence_average(spPtr, trackTable[i], sequenceLength); } } - snPtr+=trackTable[i]; + snPtr += trackTable[i]; + if (usingPower) { + spPtr += trackTable[i]; + } } - double* pn = sMeanL2; - w=dbH->numFiles; - while(w--) - *pn++=0.0; - ps=sNorm; - unsigned processedTracks=0; - for(i=0; i<dbH->numFiles; i++){ - if(trackTable[i]>sequenceLength-1){ - w = trackTable[i]-sequenceLength+1; - pn = sMeanL2+i; - *pn=0; - while(w--) - if(*ps>0) - *pn+=*ps++; - *pn/=trackTable[i]-sequenceLength+1; - SILENCE_THRESH+=*pn; - processedTracks++; + sequence_sum(qnPtr, numVectors, sequenceLength); + sequence_sqrt(qnPtr, numVectors, sequenceLength); + + if (usingPower) { + qPower = new double[numVectors]; + qpPtr = qPower; + if (lseek(powerfd, sizeof(int), SEEK_SET) == (off_t) -1) { + error("error seeking to data", powerFileName, "lseek"); } - ps = sNorm + trackTable[i]; + int count = read(powerfd, qPower, numVectors * sizeof(double)); + if (count == -1) { + error("error reading data", powerFileName, "read"); + } + if ((unsigned) count != numVectors * sizeof(double)) { + error("short read", powerFileName); + } + + sequence_sum(qpPtr, numVectors, sequenceLength); + sequence_average(qpPtr, numVectors, sequenceLength); } - if(verbosity>1) { - cerr << "processedTracks: " << processedTracks << endl; - } - - SILENCE_THRESH/=processedTracks; - USE_THRESH=1; // Turn thresholding on - DIFF_THRESH=SILENCE_THRESH; // mean shingle power - SILENCE_THRESH/=5; // 20% of the mean shingle power is SILENCE - if(verbosity>4) { - cerr << "silence thresh: " << SILENCE_THRESH; - } - w=sequenceLength-1; - i=1; - tmp1=*qnPtr; - while(w--) - *qnPtr+=qnPtr[i++]; - ps = qnPtr+1; - w=numVectors-sequenceLength; // +1 -1 - while(w--){ - tmp2=*ps; - *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1); - tmp1=tmp2; - ps++; - } - ps = qnPtr; - qMeanL2 = 0; - w=numVectors-sequenceLength+1; - while(w--){ - *ps=sqrt(*ps); - qMeanL2+=*ps++; - } - qMeanL2 /= numVectors-sequenceLength+1; if(verbosity>1) { cerr << "done." << endl; @@ -1662,8 +1828,11 @@ if(verbosity>1) { cerr << "query point: " << queryPoint << endl; cerr.flush(); } - query=query+queryPoint*dbH->dim; - qnPtr=qnPtr+queryPoint; + query = query + queryPoint * dbH->dim; + qnPtr = qnPtr + queryPoint; + if (usingPower) { + qpPtr = qpPtr + queryPoint; + } numVectors=wL; } @@ -1676,7 +1845,7 @@ assert(DD); gettimeofday(&tv1, NULL); - processedTracks=0; + unsigned processedTracks = 0; unsigned successfulTracks=0; double* qp; @@ -1794,7 +1963,7 @@ for(j=0;j<=numVectors-wL;j+=HOP_SIZE) for(k=0;k<=trackTable[track]-wL;k+=HOP_SIZE){ thisDist=2-(2/(qnPtr[j]*sNorm[trackIndexOffset+k]))*DD[j][k]; - if(verbosity>10) { + if(verbosity>9) { cerr << thisDist << " " << qnPtr[j] << " " << sNorm[trackIndexOffset+k] << endl; } // Gather chi^2 statistics @@ -1810,14 +1979,11 @@ // diffL2 = fabs(qnPtr[j] - sNorm[trackIndexOffset+k]); // Power test - if(!USE_THRESH || - // Threshold on mean L2 of Q and S sequences - (USE_THRESH && qnPtr[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH && - // Are both query and target windows above mean energy? - (qnPtr[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH ))) - thisDist=thisDist; // Computed above - else - thisDist=1000000.0; + if (usingPower) { + if (!(powers_acceptable(qpPtr[j], sPower[trackIndexOffset + k]))) { + thisDist = 1000000.0; + } + } // k-NN match algorithm m=pointNN; @@ -1934,7 +2100,6 @@ } } - // Clean up if(trackOffsetTable) delete[] trackOffsetTable; @@ -1944,8 +2109,10 @@ delete[] qNorm; if(sNorm) delete[] sNorm; - if(sMeanL2) - delete[] sMeanL2; + if(qPower) + delete[] qPower; + if(sPower) + delete[] sPower; if(D) delete[] D; if(DD) @@ -1954,8 +2121,6 @@ delete[] timesdata; if(meanDBdur) delete[] meanDBdur; - - } // Radius search between query and target tracks @@ -1972,13 +2137,6 @@ double* query = (double*)(indata+sizeof(int)); double* queryCopy = 0; - double qMeanL2; - double* sMeanL2; - - unsigned USE_THRESH=0; - double SILENCE_THRESH=0; - double DIFF_THRESH=0; - if(!(dbH->flags & O2_FLAG_L2NORM) ) error("Database must be L2 normed for sequence query","use -l2norm"); @@ -1992,98 +2150,66 @@ memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double)); qNorm = new double[numVectors]; sNorm = new double[dbVectors]; - sMeanL2=new double[dbH->numFiles]; - assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&sequenceLength); + assert(qNorm&&sNorm&&queryCopy&&sequenceLength); unitNorm(queryCopy, dbH->dim, numVectors, qNorm); query = queryCopy; // Make norm measurements relative to sequenceLength unsigned w = sequenceLength-1; unsigned i,j; - double* ps; - double tmp1,tmp2; // Copy the L2 norm values to core to avoid disk random access later on memcpy(sNorm, l2normTable, dbVectors*sizeof(double)); double* snPtr = sNorm; double* qnPtr = qNorm; + + double *sPower = 0, *qPower = 0; + double *spPtr = 0, *qpPtr = 0; + + if (usingPower) { + if(!(dbH->flags & O2_FLAG_POWER)) { + error("database not power-enabled", dbName); + } + sPower = new double[dbVectors]; + spPtr = sPower; + memcpy(sPower, powerTable, dbVectors * sizeof(double)); + } + for(i=0; i<dbH->numFiles; i++){ - if(trackTable[i]>=sequenceLength){ - tmp1=*snPtr; - j=1; - w=sequenceLength-1; - while(w--) - *snPtr+=snPtr[j++]; - ps = snPtr+1; - w=trackTable[i]-sequenceLength; // +1 - 1 - while(w--){ - tmp2=*ps; - *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1); - tmp1=tmp2; - ps++; - } - ps = snPtr; - w=trackTable[i]-sequenceLength+1; - while(w--){ - *ps=sqrt(*ps); - ps++; + if(trackTable[i]>=sequenceLength) { + sequence_sum(snPtr, trackTable[i], sequenceLength); + sequence_sqrt(snPtr, trackTable[i], sequenceLength); + if (usingPower) { + sequence_sum(spPtr, trackTable[i], sequenceLength); + sequence_average(spPtr, trackTable[i], sequenceLength); } } - snPtr+=trackTable[i]; + snPtr += trackTable[i]; + if (usingPower) { + spPtr += trackTable[i]; + } } - double* pn = sMeanL2; - w=dbH->numFiles; - while(w--) - *pn++=0.0; - ps=sNorm; - unsigned processedTracks=0; - for(i=0; i<dbH->numFiles; i++){ - if(trackTable[i]>sequenceLength-1){ - w = trackTable[i]-sequenceLength+1; - pn = sMeanL2+i; - *pn=0; - while(w--) - if(*ps>0) - *pn+=*ps++; - *pn/=trackTable[i]-sequenceLength+1; - SILENCE_THRESH+=*pn; - processedTracks++; + sequence_sum(qnPtr, numVectors, sequenceLength); + sequence_sqrt(qnPtr, numVectors, sequenceLength); + + if (usingPower) { + qPower = new double[numVectors]; + qpPtr = qPower; + if (lseek(powerfd, sizeof(int), SEEK_SET) == (off_t) -1) { + error("error seeking to data", powerFileName, "lseek"); } - ps = sNorm + trackTable[i]; + int count = read(powerfd, qPower, numVectors * sizeof(double)); + if (count == -1) { + error("error reading data", powerFileName, "read"); + } + if ((unsigned) count != numVectors * sizeof(double)) { + error("short read", powerFileName); + } + + sequence_sum(qpPtr, numVectors, sequenceLength); + sequence_average(qpPtr, numVectors, sequenceLength); } - if(verbosity>1) { - cerr << "processedTracks: " << processedTracks << endl; - } - - SILENCE_THRESH/=processedTracks; - USE_THRESH=1; // Turn thresholding on - DIFF_THRESH=SILENCE_THRESH; // mean shingle power - SILENCE_THRESH/=5; // 20% of the mean shingle power is SILENCE - if(verbosity>4) { - cerr << "silence thresh: " << SILENCE_THRESH; - } - w=sequenceLength-1; - i=1; - tmp1=*qnPtr; - while(w--) - *qnPtr+=qnPtr[i++]; - ps = qnPtr+1; - w=numVectors-sequenceLength; // +1 -1 - while(w--){ - tmp2=*ps; - *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1); - tmp1=tmp2; - ps++; - } - ps = qnPtr; - qMeanL2 = 0; - w=numVectors-sequenceLength+1; - while(w--){ - *ps=sqrt(*ps); - qMeanL2+=*ps++; - } - qMeanL2 /= numVectors-sequenceLength+1; if(verbosity>1) { cerr << "done." << endl; @@ -2166,8 +2292,11 @@ if(verbosity>1) { cerr << "query point: " << queryPoint << endl; cerr.flush(); } - query=query+queryPoint*dbH->dim; - qnPtr=qnPtr+queryPoint; + query = query + queryPoint*dbH->dim; + qnPtr = qnPtr + queryPoint; + if (usingPower) { + qpPtr = qpPtr + queryPoint; + } numVectors=wL; } @@ -2180,7 +2309,7 @@ assert(DD); gettimeofday(&tv1, NULL); - processedTracks=0; + unsigned processedTracks = 0; unsigned successfulTracks=0; double* qp; @@ -2298,7 +2427,7 @@ for(j=0;j<=numVectors-wL;j+=HOP_SIZE) for(k=0;k<=trackTable[track]-wL;k+=HOP_SIZE){ thisDist=2-(2/(qnPtr[j]*sNorm[trackIndexOffset+k]))*DD[j][k]; - if(verbosity>10) { + if(verbosity>9) { cerr << thisDist << " " << qnPtr[j] << " " << sNorm[trackIndexOffset+k] << endl; } // Gather chi^2 statistics @@ -2314,14 +2443,12 @@ // diffL2 = fabs(qnPtr[j] - sNorm[trackIndexOffset+k]); // Power test - if(!USE_THRESH || - // Threshold on mean L2 of Q and S sequences - (USE_THRESH && qnPtr[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH && - // Are both query and target windows above mean energy? - (qnPtr[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH ))) - thisDist=thisDist; // Computed above - else - thisDist=1000000.0; + if (usingPower) { + if (!(powers_acceptable(qpPtr[j], sPower[trackIndexOffset + k]))) { + thisDist = 1000000.0; + } + } + if(thisDist>=0 && thisDist<=radius){ distances[0]++; // increment count break; // only need one track point per query point @@ -2424,8 +2551,10 @@ delete[] qNorm; if(sNorm) delete[] sNorm; - if(sMeanL2) - delete[] sMeanL2; + if(qPower) + delete[] qPower; + if(sPower) + delete[] sPower; if(D) delete[] D; if(DD) @@ -2434,8 +2563,6 @@ delete[] timesdata; if(meanDBdur) delete[] meanDBdur; - - } // Unit norm block of features @@ -2645,7 +2772,73 @@ } } +int adb__sequenceQuery(struct soap* soap, xsd__string dbName, xsd__string qKey, + adb__sequenceQueryParms *parms, + adb__queryResponse &adbQueryResponse) { + + char qPosStr[256]; + char pointNNStr[256]; + char trackNNStr[256]; + char seqLenStr[256]; + char relative_thresholdStr[256]; + char absolute_thresholdStr[256]; + + /* When the branch is merged, move this to a header and use it + elsewhere */ +#define INTSTRINGIFY(val, str) \ + snprintf(str, 256, "%d", val); +#define DOUBLESTRINGIFY(val, str) \ + snprintf(str, 256, "%f", val); + + INTSTRINGIFY(parms->qPos, qPosStr); + INTSTRINGIFY(parms->pointNN, pointNNStr); + INTSTRINGIFY(parms->segNN, trackNNStr); + /* FIXME: decide which of segLen and seqLen should live */ + INTSTRINGIFY(parms->segLen, seqLenStr); + + DOUBLESTRINGIFY(parms->relative_threshold, relative_thresholdStr); + DOUBLESTRINGIFY(parms->absolute_threshold, absolute_thresholdStr); + + const char *argv[] = { + "./audioDB", + COM_QUERY, + "sequence", + COM_DATABASE, + dbName, + COM_FEATURES, + qKey, + COM_KEYLIST, + /* FIXME: when this branch is merged, use ENSURE_STRING */ + parms->keyList==0?"":parms->keyList, + COM_TIMES, + parms->timesFileName==0?"":parms->timesFileName, + COM_QUERYPOWER, + parms->powerFileName==0?"":parms->powerFileName, + COM_QPOINT, + qPosStr, + COM_POINTNN, + pointNNStr, + COM_TRACKNN, + trackNNStr, + COM_SEQLEN, + seqLenStr, + COM_RELATIVE_THRESH, + relative_thresholdStr, + COM_ABSOLUTE_THRESH, + absolute_thresholdStr + }; + + const unsigned argc = 25; + + try { + audioDB(argc, (char* const*)argv, &adbQueryResponse); + return SOAP_OK; + } catch (char *err) { + soap_receiver_fault(soap, err, ""); + return SOAP_FAULT; + } +} + int main(const unsigned argc, char* const argv[]){ audioDB(argc, argv); } -