# HG changeset patch # User mas01mc # Date 1187047516 0 # Node ID 0519fc406b29cd0aa7c16f9597d88fbc885d0ff6 # Parent 0c58842047322a5bde679557995b30479113a650 New major version, mostly tested: both sequence queries (-Q seq --pointnn N and -Q seq --radius R) now work, all reported distances are Euclidean. diff -r 0c5884204732 -r 0519fc406b29 audioDB.cpp --- a/audioDB.cpp Mon Aug 13 20:19:45 2007 +0000 +++ b/audioDB.cpp Mon Aug 13 23:25:16 2007 +0000 @@ -945,9 +945,9 @@ break; case O2_FLAG_SEQUENCE_QUERY: if(radius==0) - trackSequenceQuery(dbName, inFile, adbQueryResult); + trackSequenceQueryNN(dbName, inFile, adbQueryResult); else - trackSequenceQueryEuc(dbName, inFile, adbQueryResult); + trackSequenceQueryRad(dbName, inFile, adbQueryResult); break; case O2_FLAG_TRACK_QUERY: trackPointQuery(dbName, inFile, adbQueryResult); @@ -1140,10 +1140,6 @@ delete dbdurs; } -void audioDB::sequenceQuery(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){ - -} - // trackPointQuery // return the trackNN closest tracks to the query track // uses average of pointNN points per track @@ -1391,15 +1387,13 @@ delete meanDBdur; } - -void audioDB::deleteDB(const char* dbName, const char* inFile){ -} -// NBest matched filter distance between query and target tracks -// efficient implementation -// outputs average of N minimum matched filter distances -void audioDB::trackSequenceQuery(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){ +// k nearest-neighbor (k-NN) search between query and target tracks +// efficient implementation based on matched filter +// assumes normed shingles +// outputs distances of retrieved shingles, max retreived = pointNN shingles per per track +void audioDB::trackSequenceQueryNN(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){ initTables(dbName, inFile); @@ -1425,6 +1419,7 @@ if(verbosity>1) cerr << "performing norms ... "; cerr.flush(); unsigned dbVectors = dbH->length/(sizeof(double)*dbH->dim); + // Make a copy of the query queryCopy = new double[numVectors*dbH->dim]; memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double)); @@ -1434,16 +1429,18 @@ assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&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; for(i=0; inumFiles; i++){ - if(trackTable[i]>sequenceLength){ + if(trackTable[i]>=sequenceLength){ tmp1=*snPtr; j=1; w=sequenceLength-1; @@ -1453,10 +1450,16 @@ w=trackTable[i]-sequenceLength; // +1 - 1 while(w--){ tmp2=*ps; - *ps=*(ps-1)-tmp1+*(ps+sequenceLength); + *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1); tmp1=tmp2; ps++; } + ps = snPtr; + w=trackTable[i]-sequenceLength+1; + while(w--){ + *ps=sqrt(*ps); + ps++; + } } snPtr+=trackTable[i]; } @@ -1469,11 +1472,13 @@ unsigned processedTracks=0; for(i=0; inumFiles; i++){ if(trackTable[i]>sequenceLength-1){ - w = trackTable[i]-sequenceLength+1; + w = trackTable[i]-sequenceLength; pn = sMeanL2+i; + *pn=0; while(w--) - *pn+=*ps++; - *pn/=trackTable[i]-sequenceLength+1; + if(*ps>0) + *pn+=*ps++; + *pn/=trackTable[i]-sequenceLength; SILENCE_THRESH+=*pn; processedTracks++; } @@ -1481,27 +1486,36 @@ } if(verbosity>1) cerr << "processedTracks: " << processedTracks << endl; + + SILENCE_THRESH/=processedTracks; USE_THRESH=1; // Turn thresholding on - DIFF_THRESH=SILENCE_THRESH/2; // 50% of the mean shingle power - SILENCE_THRESH/=10; // 10% of the mean shingle power is SILENCE - + 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=*qNorm; while(w--) *qNorm+=qNorm[i++]; ps = qNorm+1; - qMeanL2 = *qNorm; - w=numVectors-sequenceLength; + w=numVectors-sequenceLength; // +1 -1 while(w--){ tmp2=*ps; - *ps=*(ps-1)-tmp1+*(ps+sequenceLength); + *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1); tmp1=tmp2; - qMeanL2+=*ps; - *ps++; + ps++; + } + ps = qNorm; + qMeanL2 = 0; + w=numVectors-sequenceLength+1; + while(w--){ + *ps=sqrt(*ps); + qMeanL2+=*ps++; } qMeanL2 /= numVectors-sequenceLength+1; + if(verbosity>1) cerr << "done." << endl; @@ -1528,13 +1542,13 @@ double oneOverWL=1.0/wL; for(k=0; knumFiles ; track++, processedTracks++){ // get trackID from file if using a control file @@ -1633,7 +1656,7 @@ if(verbosity>7) cerr << track << "." << trackIndexOffset << "." << trackTable[track] << " | ";cerr.flush(); - // Cross-correlation matrix + // Sum products matrix for(j=0; jdim; @@ -1672,6 +1696,7 @@ *sp+++=*spd++; } } + else{ // HOP_SIZE != 1 for(w=0; w10) + cerr << thisDist << " " << qNorm[j] << " " << sNorm[trackIndexOffset+k] << endl; + // Gather chi^2 statistics + if(thisDistmaxSample) + maxSample=thisDist; + if(thisDist>1e-9){ + sampleCount++; + sampleSum+=thisDist; + logSampleSum+=log(thisDist); + } + + // diffL2 = fabs(qNorm[j] - sNorm[trackIndexOffset+k]); // Power test if(!USE_THRESH || // Threshold on mean L2 of Q and S sequences - (USE_THRESH && qNorm[j]>SILENCE_THRESH && sNorm[k]>SILENCE_THRESH && + (USE_THRESH && qNorm[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH && // Are both query and target windows above mean energy? - (qNorm[j]>qMeanL2 && sNorm[k]>sMeanL2[track] && diffL2 < DIFF_THRESH ))) - thisDist=DD[j][k]*oneOverWL; + (qNorm[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH ))) + thisDist=thisDist; // Computed above else - thisDist=0.0; - - // NBest match algorithm - for(m=0; m=distances[m]){ + thisDist=1000000.0; + + // k-NN match algorithm + m=pointNN; + while(m--){ + if(thisDist<=distances[m]) + if(m==0 || thisDist>=distances[m-1]){ // Shuffle distances up the list for(l=pointNN-1; l>m; l--){ distances[l]=distances[l-1]; @@ -1730,29 +1770,25 @@ qIndexes[m]=j; sIndexes[m]=k; break; - } + } } } // Calculate the mean of the N-Best matches thisDist=0.0; for(m=0; m3) cerr << fileTable+track*O2_FILETABLESIZE << " " << thisDist << endl; + // All the track stuff goes here n=trackNN; while(n--){ - if(thisDist>=trackDistances[n]){ - if((n==0 || thisDist<=trackDistances[n-1])){ + if(thisDist<=trackDistances[n]){ + if((n==0 || thisDist>=trackDistances[n-1])){ // Copy all values above up the queue for( l=trackNN-1 ; l > n ; l--){ trackDistances[l]=trackDistances[l-1]; @@ -1772,14 +1808,7 @@ break; } } // Duration match - - // per-track reset array values - for(unsigned k=0; k1) + if(verbosity>1){ cerr << endl << "processed tracks :" << processedTracks << " matched tracks: " << successfulTracks << " elapsed time:" << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl; - + cerr << "sampleCount: " << sampleCount << " sampleSum: " << sampleSum << " logSampleSum: " << logSampleSum + << " minSample: " << minSample << " maxSample: " << maxSample << endl; + } if(adbQueryResult==0){ if(verbosity>1) cerr<