Mercurial > hg > audiodb
changeset 193:f9d16137e704
Merge powertable branch -r168:227 to trunk.
author | mas01cr |
---|---|
date | Wed, 21 Nov 2007 11:35:44 +0000 |
parents | 10bcea4e5c40 |
children | 0e75deb7d4d1 |
files | audioDB.cpp audioDB.h audioDBws.h gengetopt.in tests/0026/run-test.sh tests/0026/short-description tests/0027/run-test.sh tests/0027/short-description tests/0028/run-test.sh tests/0028/short-description tests/0029/run-test.sh tests/0029/short-description tests/0030/run-test.sh tests/0030/short-description tests/test-utils.sh |
diffstat | 15 files changed, 844 insertions(+), 206 deletions(-) [+] |
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); } -
--- a/audioDB.h Tue Nov 13 17:14:21 2007 +0000 +++ b/audioDB.h Wed Nov 21 11:35:44 2007 +0000 @@ -27,6 +27,7 @@ #define COM_QUERY "--QUERY" #define COM_STATUS "--STATUS" #define COM_L2NORM "--L2NORM" +#define COM_POWER "--POWER" #define COM_DUMP "--DUMP" #define COM_SERVER "--SERVER" @@ -43,10 +44,13 @@ #define COM_QUERYKEY "--key" #define COM_KEYLIST "--keyList" #define COM_TIMES "--times" +#define COM_QUERYPOWER "--power" +#define COM_RELATIVE_THRESH "--relative-threshold" +#define COM_ABSOLUTE_THRESH "--absolute-threshold" #define O2_OLD_MAGIC ('O'|'2'<<8|'D'<<16|'B'<<24) #define O2_MAGIC ('o'|'2'<<8|'d'<<16|'b'<<24) -#define O2_FORMAT_VERSION (0U) +#define O2_FORMAT_VERSION (1U) #define O2_DEFAULT_POINTNN (10U) #define O2_DEFAULT_TRACKNN (10U) @@ -67,6 +71,7 @@ // Flags #define O2_FLAG_L2NORM (0x1U) #define O2_FLAG_MINMAX (0x2U) +#define O2_FLAG_POWER (0x4U) #define O2_FLAG_TIMES (0x20U) // Query types @@ -106,6 +111,7 @@ uint32_t dataOffset; uint32_t l2normTableOffset; uint32_t timesTableOffset; + uint32_t powerTableOffset; uint32_t dbSize; } dbTableHeaderT, *dbTableHeaderPtr; @@ -125,6 +131,9 @@ const char *output; const char *timesFileName; ifstream *timesFile; + const char *powerFileName; + ifstream *powerFile; + int powerfd; int dbfid; int infid; @@ -141,6 +150,7 @@ double* qNorm; double* sNorm; double* timesTable; + double* powerTable; // Flags and parameters unsigned verbosity; // how much do we want to know? @@ -153,11 +163,18 @@ unsigned queryPoint; unsigned usingQueryPoint; unsigned usingTimes; + unsigned usingPower; unsigned isClient; unsigned isServer; unsigned port; double timesTol; double radius; + + bool use_absolute_threshold; + double absolute_threshold; + bool use_relative_threshold; + double relative_threshold; + // Timers struct timeval tv1; @@ -167,6 +184,10 @@ void error(const char* a, const char* b = "", const char *sysFunc = 0); void pointQuery(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse=0); void trackPointQuery(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse=0); + void sequence_sum(double *buffer, int length, int seqlen); + void sequence_sqrt(double *buffer, int length, int seqlen); + void sequence_average(double *buffer, int length, int seqlen); + void trackSequenceQueryNN(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse=0); void trackSequenceQueryRad(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse=0); @@ -176,6 +197,7 @@ void unitNorm(double* X, unsigned d, unsigned n, double* qNorm); void unitNormAndInsertL2(double* X, unsigned dim, unsigned n, unsigned append); void insertTimeStamps(unsigned n, ifstream* timesFile, double* timesdata); + void insertPowerData(unsigned n, int powerfd, double *powerdata); unsigned getKeyPos(char* key); public: @@ -196,6 +218,8 @@ void ws_status(const char*dbName, char* hostport); void ws_query(const char*dbName, const char *trackKey, const char* hostport); void l2norm(const char* dbName); + void power_flag(const char *dbName); + bool powers_acceptable(double p1, double p2); void dump(const char* dbName); // web services @@ -214,6 +238,9 @@ output(0), \ timesFileName(0), \ timesFile(0), \ + powerFileName(0), \ + powerFile(0), \ + powerfd(0), \ dbfid(0), \ infid(0), \ db(0), \ @@ -235,8 +262,13 @@ queryPoint(0), \ usingQueryPoint(0), \ usingTimes(0), \ + usingPower(0), \ isClient(0), \ isServer(0), \ port(0), \ timesTol(0.1), \ - radius(0) + radius(0), \ + use_absolute_threshold(false), \ + absolute_threshold(0.0), \ + use_relative_threshold(false), \ + relative_threshold(0.0)
--- a/audioDBws.h Tue Nov 13 17:14:21 2007 +0000 +++ b/audioDBws.h Wed Nov 21 11:35:44 2007 +0000 @@ -45,3 +45,20 @@ // Query an existing adb database int adb__query(xsd__string dbName, xsd__string qKey, xsd__string keyList, xsd__string timesFileName, xsd__int qType, xsd__int qPos, xsd__int pointNN, xsd__int segNN, xsd__int segLen, struct adb__queryResponse &adbQueryResponse); + +struct adb__sequenceQueryParms { + xsd__string keyList; + xsd__string timesFileName; + xsd__string powerFileName; + xsd__int qPos; + xsd__int pointNN; + xsd__int segNN; + xsd__int segLen; + xsd__double relative_threshold; + xsd__double absolute_threshold; +}; + +// Perform a sequence query +int adb__sequenceQuery(xsd__string dbName, xsd__string qKey, + struct adb__sequenceQueryParms *parms, + struct adb__queryResponse &adbQueryResponse);
--- a/gengetopt.in Tue Nov 13 17:14:21 2007 +0000 +++ b/gengetopt.in Wed Nov 21 11:35:44 2007 +0000 @@ -14,17 +14,20 @@ option "DUMP" D "output all entries: index key size." dependon="database" optional option "output" - "output directory" string dependon="DUMP" default="audioDB.dump" optional option "L2NORM" L "unit norm vectors and norm all future inserts." dependon="database" optional +option "POWER" P "turn on power flag for database." dependon="database" optional section "Database Insertion" sectiondesc="The following commands insert feature files, with optional keys and timestamps.\n" option "INSERT" I "add feature vectors to an existing database." dependon="features" optional option "UPDATE" U "replace inserted vectors associated with key with new input vectors." dependon="features" dependon="key" dependon="database" optional hidden option "features" f "binary series of vectors file {int sz:ieee double[][sz]:eof}." string typestr="filename" dependon="database" optional option "times" t "list of time points (ascii) for feature vectors." string typestr="filename" dependon="features" optional +option "power" w "binary power feature file." string typestr="filename" dependon="database" optional option "key" k "unique identifier associated with features." string typestr="identifier" dependon="features" optional text "" option "BATCHINSERT" B "add feature vectors named in a --featureList file (with optional keys in a --keyList file) to the named database." dependon="featureList" optional option "featureList" F "text file containing list of binary feature vector files to process, one per track" string typestr="filename" dependon="database" optional option "timesList" T "text file containing list of ascii --times for each --features file in --featureList." string typestr="filename" dependon="featureList" optional +option "powerList" W "text file containing list of binary power feature file." string typestr="filename" dependon="database" optional option "keyList" K "text file containing list of unique identifiers associated with --features." string typestr="filename" optional @@ -40,6 +43,8 @@ option "resultlength" r "maximum length of the result list." int typestr="length" default="10" optional option "sequencelength" l "length of sequences for sequence search." int typestr="length" default="16" dependon="QUERY" optional option "sequencehop" h "hop size of sequence window for sequence search." int typestr="hop" default="1" dependon="QUERY" optional +option "absolute-threshold" - "absolute power threshold for consideration of query or target sequence (in Bels)" double dependon="QUERY" optional +option "relative-threshold" - "relative power threshold between query and target sequence (in Bels)" double dependon="QUERY" optional section "Web Services" sectiondesc="These commands enable the database process to establish a connection via the internet and operate as separate client and server processes.\n" option "SERVER" s "run as standalone web service on named port." int typestr="port" default="14475" optional @@ -47,5 +52,3 @@ text "\nCopyright (C) 2007 Michael Casey, Goldsmiths, University of London\n" - -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0026/run-test.sh Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,15 @@ +#! /bin/sh + +. ../test-utils.sh + +if [ -f testdb ]; then rm -f testdb; fi + +${AUDIODB} -N -d testdb + +${AUDIODB} -P -d testdb +${AUDIODB} -d testdb -P + +# should fail (no db given) +expect_clean_error_exit ${AUDIODB} -P + +exit 104
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0026/short-description Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,1 @@ +command-line -P handling \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0027/run-test.sh Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,103 @@ +#! /bin/sh + +. ../test-utils.sh + +if [ -f testdb ]; then rm -f testdb; fi + +${AUDIODB} -d testdb -N + +intstring 2 > testfeature +floatstring 0 1 >> testfeature +floatstring 1 0 >> testfeature + +intstring 1 > testpower +floatstring -0.5 >> testpower +floatstring -1 >> testpower + +expect_clean_error_exit ${AUDIODB} -d testdb -I -f testfeature -w testpower + +${AUDIODB} -d testdb -P + +expect_clean_error_exit ${AUDIODB} -d testdb -I -f testfeature + +${AUDIODB} -d testdb -I -f testfeature -w testpower + +# sequence queries require L2NORM +${AUDIODB} -d testdb -L + +# queries without power files should run as before +echo "query point (0.0,0.5)" +intstring 2 > testquery +floatstring 0 0.5 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -n 1 > testoutput +echo testfeature 0 0 0 > test-expected-output +cmp testoutput test-expected-output + +echo "query point (0.5,0.0)" +intstring 2 > testquery +floatstring 0.5 0 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery > testoutput +echo testfeature 1 0 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -n 1 > testoutput +echo testfeature 0 0 1 > test-expected-output +cmp testoutput test-expected-output + +# queries with power files might do something different +echo "query point (0.0,0.5), p=-0.5" +intstring 2 > testquery +floatstring 0 0.5 >> testquery + +intstring 1 > testquerypower +floatstring -0.5 >> testquerypower + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-1.4 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.6 > testoutput +echo testfeature 0 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.2 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=1 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=0.2 > testoutput +echo testfeature 0 0 0 > test-expected-output +cmp testoutput test-expected-output + +echo "query point (0.5,0.0), p=-0.5" +intstring 2 > testquery +floatstring 0.5 0 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-1.4 > testoutput +echo testfeature 1 0 1 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.6 > testoutput +echo testfeature 2 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.2 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=1 > testoutput +echo testfeature 1 0 1 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=0.2 > testoutput +echo testfeature 2 0 0 > test-expected-output +cmp testoutput test-expected-output + +exit 104
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0027/short-description Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,1 @@ +0006 with power \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0028/run-test.sh Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,106 @@ +#! /bin/sh + +. ../test-utils.sh + +if [ -f testdb ]; then rm -f testdb; fi + +${AUDIODB} -d testdb -N + +intstring 2 > testfeature +floatstring 0 1 >> testfeature +floatstring 1 0 >> testfeature + +intstring 1 > testpower +floatstring -0.5 >> testpower +floatstring -1 >> testpower + +echo testfeature > testFeatureList.txt +echo testpower > testPowerList.txt + +expect_clean_error_exit ${AUDIODB} -d testdb -B -F testFeatureList.txt -W testPowerList.txt + +${AUDIODB} -d testdb -P + +expect_clean_error_exit ${AUDIODB} -d testdb -B -F testFeatureList.txt + +${AUDIODB} -d testdb -B -F testFeatureList.txt -W testPowerList.txt + +# sequence queries require L2NORM +${AUDIODB} -d testdb -L + +# queries without power files should run as before +echo "query point (0.0,0.5)" +intstring 2 > testquery +floatstring 0 0.5 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -n 1 > testoutput +echo testfeature 0 0 0 > test-expected-output +cmp testoutput test-expected-output + +echo "query point (0.5,0.0)" +intstring 2 > testquery +floatstring 0.5 0 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery > testoutput +echo testfeature 1 0 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -n 1 > testoutput +echo testfeature 0 0 1 > test-expected-output +cmp testoutput test-expected-output + +# queries with power files might do something different +echo "query point (0.0,0.5), p=-0.5" +intstring 2 > testquery +floatstring 0 0.5 >> testquery + +intstring 1 > testquerypower +floatstring -0.5 >> testquerypower + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-1.4 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.6 > testoutput +echo testfeature 0 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.2 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=1 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=0.2 > testoutput +echo testfeature 0 0 0 > test-expected-output +cmp testoutput test-expected-output + +echo "query point (0.5,0.0), p=-0.5" +intstring 2 > testquery +floatstring 0.5 0 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-1.4 > testoutput +echo testfeature 1 0 1 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.6 > testoutput +echo testfeature 2 0 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --absolute-threshold=-0.2 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=1 > testoutput +echo testfeature 1 0 1 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -w testquerypower --relative-threshold=0.2 > testoutput +echo testfeature 2 0 0 > test-expected-output +cmp testoutput test-expected-output + +exit 104
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0028/short-description Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,1 @@ +batchinsert version of 0027 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0029/run-test.sh Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,75 @@ +#! /bin/sh + +. ../test-utils.sh + +if [ -f testdb ]; then rm -f testdb; fi + +${AUDIODB} -d testdb -N + +intstring 2 > testfeature +floatstring 0 1 >> testfeature +floatstring 1 0 >> testfeature +floatstring 1 0 >> testfeature +floatstring 0 1 >> testfeature + +intstring 1 > testpower +floatstring -0.5 >> testpower +floatstring -1 >> testpower +floatstring -1 >> testpower +floatstring -0.5 >> testpower + +expect_clean_error_exit ${AUDIODB} -d testdb -I -f testfeature -w testpower +${AUDIODB} -d testdb -P +expect_clean_error_exit ${AUDIODB} -d testdb -I -f testfeature +${AUDIODB} -d testdb -I -f testfeature -w testpower + +# sequence queries require L2NORM +${AUDIODB} -d testdb -L + +echo "query points (0.0,0.5),(0.0,0.5),(0.5,0.0)" +intstring 2 > testquery +floatstring 0 0.5 >> testquery +floatstring 0 0.5 >> testquery +floatstring 0.5 0 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -p 0 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -p 1 > testoutput +echo testfeature 1 1 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -p 0 > testoutput +echo testfeature 1.33333 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -p 1 > testoutput +echo testfeature 1 1 0 > test-expected-output +cmp testoutput test-expected-output + +echo "query points (0.0,0.5)p=-0.5,(0.0,0.5)p=-1,(0.5,0.0)p=-1" + +intstring 1 > testquerypower +floatstring -0.5 -1 -1 >> testquerypower + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-1.4 -p 0 > testoutput +echo testfeature 1.33333 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-1.4 -p 1 > testoutput +echo testfeature 1 1 0 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-0.8 -p 0 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-0.8 -p 1 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --relative-threshold=0.1 -p 0 > testoutput +echo testfeature 1 0 0 > test-expected-output +cmp testoutput test-expected-output + +exit 104
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0029/short-description Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,1 @@ +-l 2 searches with power \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0030/run-test.sh Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,85 @@ +#! /bin/sh + +. ../test-utils.sh + +if [ -f testdb ]; then rm -f testdb; fi + +${AUDIODB} -d testdb -N + +intstring 2 > testfeature +floatstring 0 1 >> testfeature +floatstring 1 0 >> testfeature +floatstring 1 0 >> testfeature +floatstring 0 1 >> testfeature + +intstring 1 > testpower +floatstring -0.5 >> testpower +floatstring -1 >> testpower +floatstring -1 >> testpower +floatstring -0.5 >> testpower + +expect_clean_error_exit ${AUDIODB} -d testdb -I -f testfeature -w testpower +${AUDIODB} -d testdb -P +expect_clean_error_exit ${AUDIODB} -d testdb -I -f testfeature +${AUDIODB} -d testdb -I -f testfeature -w testpower + +# sequence queries require L2NORM +${AUDIODB} -d testdb -L + +echo "query points (0.0,0.5),(0.0,0.5),(0.5,0.0)" +intstring 2 > testquery +floatstring 0 0.5 >> testquery +floatstring 0 0.5 >> testquery +floatstring 0.5 0 >> testquery + +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -R 0.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -p 0 -R 0.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 1 -f testquery -p 1 -R 0.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -p 0 -R 1.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -p 0 -R 0.9 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -p 1 -R 0.9 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output + +echo "query points (0.0,0.5)p=-0.5,(0.0,0.5)p=-1,(0.5,0.0)p=-1" + +intstring 1 > testquerypower +floatstring -0.5 -1 -1 >> testquerypower + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-1.4 -p 0 -R 1.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-0.8 -p 0 -R 1.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-0.7 -p 0 -R 1.1 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-1.4 -p 1 -R 0.9 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --absolute-threshold=-0.9 -p 1 -R 0.9 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --relative-threshold=0.1 -p 0 -R 1.1 > testoutput +echo testfeature 1 > test-expected-output +cmp testoutput test-expected-output + +${AUDIODB} -d testdb -Q sequence -l 2 -f testquery -w testquerypower --relative-threshold=0.1 -p 0 -R 0.9 > testoutput +cat /dev/null > test-expected-output +cmp testoutput test-expected-output + +exit 104
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/0030/short-description Wed Nov 21 11:35:44 2007 +0000 @@ -0,0 +1,1 @@ +single-track sequence radius search with power \ No newline at end of file
--- a/tests/test-utils.sh Tue Nov 13 17:14:21 2007 +0000 +++ b/tests/test-utils.sh Wed Nov 21 11:35:44 2007 +0000 @@ -30,8 +30,12 @@ case ${arg} in 0) printf "\x00\x00\x00\x00\x00\x00\x00\x00";; + -0.5) + printf "\x00\x00\x00\x00\x00\x00\xe0\xbf";; 0.5) printf "\x00\x00\x00\x00\x00\x00\xe0\x3f";; + -1) + printf "\x00\x00\x00\x00\x00\x00\xf0\xbf";; 1) printf "\x00\x00\x00\x00\x00\x00\xf0\x3f";; *)