annotate query.cpp @ 263:210b2f661b88

Added new query type "onetoonensequence" for matching each query sequence to the single closest match in the database. Most useful if query is not also in the database.
author mas01mc
date Mon, 09 Jun 2008 19:20:39 +0000
parents 4dcb09f5fe85
children d9a88cfd4ab6
rev   line source
mas01cr@239 1 #include "audioDB.h"
mas01cr@239 2
mas01cr@239 3 #include "reporter.h"
mas01cr@239 4
mas01cr@239 5 bool audioDB::powers_acceptable(double p1, double p2) {
mas01cr@239 6 if (use_absolute_threshold) {
mas01cr@239 7 if ((p1 < absolute_threshold) || (p2 < absolute_threshold)) {
mas01cr@239 8 return false;
mas01cr@239 9 }
mas01cr@239 10 }
mas01cr@239 11 if (use_relative_threshold) {
mas01cr@239 12 if (fabs(p1-p2) > fabs(relative_threshold)) {
mas01cr@239 13 return false;
mas01cr@239 14 }
mas01cr@239 15 }
mas01cr@239 16 return true;
mas01cr@239 17 }
mas01cr@239 18
mas01cr@239 19 void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse) {
mas01cr@239 20 initTables(dbName, inFile);
mas01cr@239 21 Reporter *r = 0;
mas01cr@239 22 switch (queryType) {
mas01cr@239 23 case O2_POINT_QUERY:
mas01cr@239 24 sequenceLength = 1;
mas01cr@239 25 normalizedDistance = false;
mas01cr@239 26 r = new pointQueryReporter<std::greater < NNresult > >(pointNN);
mas01cr@239 27 break;
mas01cr@239 28 case O2_TRACK_QUERY:
mas01cr@239 29 sequenceLength = 1;
mas01cr@239 30 normalizedDistance = false;
mas01cr@239 31 r = new trackAveragingReporter<std::greater < NNresult > >(pointNN, trackNN, dbH->numFiles);
mas01cr@239 32 break;
mas01cr@239 33 case O2_SEQUENCE_QUERY:
mas01cr@239 34 if(radius == 0) {
mas01cr@239 35 r = new trackAveragingReporter<std::less < NNresult > >(pointNN, trackNN, dbH->numFiles);
mas01cr@239 36 } else {
mas01cr@239 37 r = new trackSequenceQueryRadReporter(trackNN, dbH->numFiles);
mas01cr@239 38 }
mas01cr@239 39 break;
mas01mc@248 40 case O2_N_SEQUENCE_QUERY :
mas01mc@248 41 if(radius == 0) {
mas01mc@248 42 r = new trackSequenceQueryNNReporter<std::less < NNresult > >(pointNN, trackNN, dbH->numFiles);
mas01mc@248 43 } else {
mas01mc@250 44 r = new trackSequenceQueryRadNNReporter(pointNN,trackNN, dbH->numFiles);
mas01mc@248 45 }
mas01mc@248 46 break;
mas01mc@263 47 case O2_ONE_TO_ONE_N_SEQUENCE_QUERY :
mas01mc@263 48 if(radius == 0) {
mas01mc@263 49 error("query-type not yet supported");
mas01mc@263 50 } else {
mas01mc@263 51 r = new trackSequenceQueryRadNNReporterOneToOne(pointNN,trackNN, dbH->numFiles);
mas01mc@263 52 }
mas01mc@263 53 break;
mas01cr@239 54 default:
mas01cr@239 55 error("unrecognized queryType in query()");
mas01cr@239 56 }
mas01cr@240 57 query_loop(dbName, inFile, r);
mas01cr@239 58 r->report(fileTable, adbQueryResponse);
mas01cr@239 59 delete r;
mas01cr@239 60 }
mas01cr@239 61
mas01cr@239 62 // return ordinal position of key in keyTable
mas01cr@239 63 unsigned audioDB::getKeyPos(char* key){
mas01cr@239 64 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@256 65 if(strncmp(fileTable + k*O2_FILETABLE_ENTRY_SIZE, key, strlen(key))==0)
mas01cr@239 66 return k;
mas01cr@239 67 error("Key not found",key);
mas01cr@239 68 return O2_ERR_KEYNOTFOUND;
mas01cr@239 69 }
mas01cr@239 70
mas01cr@239 71 // This is a common pattern in sequence queries: what we are doing is
mas01cr@239 72 // taking a window of length seqlen over a buffer of length length,
mas01cr@239 73 // and placing the sum of the elements in that window in the first
mas01cr@239 74 // element of the window: thus replacing all but the last seqlen
mas01cr@239 75 // elements in the buffer with the corresponding windowed sum.
mas01cr@239 76 void audioDB::sequence_sum(double *buffer, int length, int seqlen) {
mas01cr@239 77 double tmp1, tmp2, *ps;
mas01cr@239 78 int j, w;
mas01cr@239 79
mas01cr@239 80 tmp1 = *buffer;
mas01cr@239 81 j = 1;
mas01cr@239 82 w = seqlen - 1;
mas01cr@239 83 while(w--) {
mas01cr@239 84 *buffer += buffer[j++];
mas01cr@239 85 }
mas01cr@239 86 ps = buffer + 1;
mas01cr@239 87 w = length - seqlen; // +1 - 1
mas01cr@239 88 while(w--) {
mas01cr@239 89 tmp2 = *ps;
mas01cr@239 90 if(isfinite(tmp1)) {
mas01cr@239 91 *ps = *(ps - 1) - tmp1 + *(ps + seqlen - 1);
mas01cr@239 92 } else {
mas01cr@239 93 for(int i = 1; i < seqlen; i++) {
mas01cr@239 94 *ps += *(ps + i);
mas01cr@239 95 }
mas01cr@239 96 }
mas01cr@239 97 tmp1 = tmp2;
mas01cr@239 98 ps++;
mas01cr@239 99 }
mas01cr@239 100 }
mas01cr@239 101
mas01cr@239 102 // In contrast to sequence_sum() above, sequence_sqrt() and
mas01cr@239 103 // sequence_average() below are simple mappers across the sequence.
mas01cr@239 104 void audioDB::sequence_sqrt(double *buffer, int length, int seqlen) {
mas01cr@239 105 int w = length - seqlen + 1;
mas01cr@239 106 while(w--) {
mas01cr@239 107 *buffer = sqrt(*buffer);
mas01cr@239 108 buffer++;
mas01cr@239 109 }
mas01cr@239 110 }
mas01cr@239 111
mas01cr@239 112 void audioDB::sequence_average(double *buffer, int length, int seqlen) {
mas01cr@239 113 int w = length - seqlen + 1;
mas01cr@239 114 while(w--) {
mas01cr@239 115 *buffer /= seqlen;
mas01cr@239 116 buffer++;
mas01cr@239 117 }
mas01cr@239 118 }
mas01cr@239 119
mas01cr@239 120 void audioDB::initialize_arrays(int track, unsigned int numVectors, double *query, double *data_buffer, double **D, double **DD) {
mas01cr@239 121 unsigned int j, k, l, w;
mas01cr@239 122 double *dp, *qp, *sp;
mas01cr@239 123
mas01cr@239 124 const unsigned HOP_SIZE = sequenceHop;
mas01cr@239 125 const unsigned wL = sequenceLength;
mas01cr@239 126
mas01cr@239 127 for(j = 0; j < numVectors; j++) {
mas01cr@239 128 // Sum products matrix
mas01cr@239 129 D[j] = new double[trackTable[track]];
mas01cr@239 130 assert(D[j]);
mas01cr@239 131 // Matched filter matrix
mas01cr@239 132 DD[j]=new double[trackTable[track]];
mas01cr@239 133 assert(DD[j]);
mas01cr@239 134 }
mas01cr@239 135
mas01cr@239 136 // Dot product
mas01cr@239 137 for(j = 0; j < numVectors; j++)
mas01cr@239 138 for(k = 0; k < trackTable[track]; k++){
mas01cr@239 139 qp = query + j * dbH->dim;
mas01cr@239 140 sp = data_buffer + k * dbH->dim;
mas01cr@239 141 DD[j][k] = 0.0; // Initialize matched filter array
mas01cr@239 142 dp = &D[j][k]; // point to correlation cell j,k
mas01cr@239 143 *dp = 0.0; // initialize correlation cell
mas01cr@239 144 l = dbH->dim; // size of vectors
mas01cr@239 145 while(l--)
mas01cr@239 146 *dp += *qp++ * *sp++;
mas01cr@239 147 }
mas01cr@239 148
mas01cr@239 149 // Matched Filter
mas01cr@239 150 // HOP SIZE == 1
mas01cr@239 151 double* spd;
mas01cr@239 152 if(HOP_SIZE == 1) { // HOP_SIZE = shingleHop
mas01cr@239 153 for(w = 0; w < wL; w++) {
mas01cr@239 154 for(j = 0; j < numVectors - w; j++) {
mas01cr@239 155 sp = DD[j];
mas01cr@239 156 spd = D[j+w] + w;
mas01cr@239 157 k = trackTable[track] - w;
mas01cr@239 158 while(k--)
mas01cr@239 159 *sp++ += *spd++;
mas01cr@239 160 }
mas01cr@239 161 }
mas01cr@239 162 } else { // HOP_SIZE != 1
mas01cr@239 163 for(w = 0; w < wL; w++) {
mas01cr@239 164 for(j = 0; j < numVectors - w; j += HOP_SIZE) {
mas01cr@239 165 sp = DD[j];
mas01cr@239 166 spd = D[j+w]+w;
mas01cr@239 167 for(k = 0; k < trackTable[track] - w; k += HOP_SIZE) {
mas01cr@239 168 *sp += *spd;
mas01cr@239 169 sp += HOP_SIZE;
mas01cr@239 170 spd += HOP_SIZE;
mas01cr@239 171 }
mas01cr@239 172 }
mas01cr@239 173 }
mas01cr@239 174 }
mas01cr@239 175 }
mas01cr@239 176
mas01cr@239 177 void audioDB::delete_arrays(int track, unsigned int numVectors, double **D, double **DD) {
mas01cr@239 178 if(D != NULL) {
mas01cr@239 179 for(unsigned int j = 0; j < numVectors; j++) {
mas01cr@239 180 delete[] D[j];
mas01cr@239 181 }
mas01cr@239 182 }
mas01cr@239 183 if(DD != NULL) {
mas01cr@239 184 for(unsigned int j = 0; j < numVectors; j++) {
mas01cr@239 185 delete[] DD[j];
mas01cr@239 186 }
mas01cr@239 187 }
mas01cr@239 188 }
mas01cr@239 189
mas01cr@239 190 void audioDB::read_data(int track, double **data_buffer_p, size_t *data_buffer_size_p) {
mas01cr@239 191 if (trackTable[track] * sizeof(double) * dbH->dim > *data_buffer_size_p) {
mas01cr@239 192 if(*data_buffer_p) {
mas01cr@239 193 free(*data_buffer_p);
mas01cr@239 194 }
mas01cr@239 195 {
mas01cr@239 196 *data_buffer_size_p = trackTable[track] * sizeof(double) * dbH->dim;
mas01cr@239 197 void *tmp = malloc(*data_buffer_size_p);
mas01cr@239 198 if (tmp == NULL) {
mas01cr@239 199 error("error allocating data buffer");
mas01cr@239 200 }
mas01cr@239 201 *data_buffer_p = (double *) tmp;
mas01cr@239 202 }
mas01cr@239 203 }
mas01cr@239 204
mas01cr@239 205 read(dbfid, *data_buffer_p, trackTable[track] * sizeof(double) * dbH->dim);
mas01cr@239 206 }
mas01cr@239 207
mas01cr@239 208 // These names deserve some unpicking. The names starting with a "q"
mas01cr@239 209 // are pointers to the query, norm and power vectors; the names
mas01cr@239 210 // starting with "v" are things that will end up pointing to the
mas01cr@239 211 // actual query point's information. -- CSR, 2007-12-05
mas01cr@239 212 void audioDB::set_up_query(double **qp, double **vqp, double **qnp, double **vqnp, double **qpp, double **vqpp, double *mqdp, unsigned *nvp) {
mas01cr@239 213 *nvp = (statbuf.st_size - sizeof(int)) / (dbH->dim * sizeof(double));
mas01cr@239 214
mas01cr@239 215 if(!(dbH->flags & O2_FLAG_L2NORM)) {
mas01cr@239 216 error("Database must be L2 normed for sequence query","use -L2NORM");
mas01cr@239 217 }
mas01cr@239 218
mas01cr@239 219 if(*nvp < sequenceLength) {
mas01cr@239 220 error("Query shorter than requested sequence length", "maybe use -l");
mas01cr@239 221 }
mas01cr@239 222
mas01cr@239 223 VERB_LOG(1, "performing norms... ");
mas01cr@239 224
mas01cr@239 225 *qp = new double[*nvp * dbH->dim];
mas01cr@239 226 memcpy(*qp, indata+sizeof(int), *nvp * dbH->dim * sizeof(double));
mas01cr@239 227 *qnp = new double[*nvp];
mas01cr@239 228 unitNorm(*qp, dbH->dim, *nvp, *qnp);
mas01cr@239 229
mas01cr@239 230 sequence_sum(*qnp, *nvp, sequenceLength);
mas01cr@239 231 sequence_sqrt(*qnp, *nvp, sequenceLength);
mas01cr@239 232
mas01cr@239 233 if (usingPower) {
mas01cr@239 234 *qpp = new double[*nvp];
mas01cr@239 235 if (lseek(powerfd, sizeof(int), SEEK_SET) == (off_t) -1) {
mas01cr@239 236 error("error seeking to data", powerFileName, "lseek");
mas01cr@239 237 }
mas01cr@239 238 int count = read(powerfd, *qpp, *nvp * sizeof(double));
mas01cr@239 239 if (count == -1) {
mas01cr@239 240 error("error reading data", powerFileName, "read");
mas01cr@239 241 }
mas01cr@239 242 if ((unsigned) count != *nvp * sizeof(double)) {
mas01cr@239 243 error("short read", powerFileName);
mas01cr@239 244 }
mas01cr@239 245
mas01cr@239 246 sequence_sum(*qpp, *nvp, sequenceLength);
mas01cr@239 247 sequence_average(*qpp, *nvp, sequenceLength);
mas01cr@239 248 }
mas01cr@239 249
mas01cr@239 250 if (usingTimes) {
mas01cr@239 251 unsigned int k;
mas01cr@239 252 *mqdp = 0.0;
mas01cr@239 253 double *querydurs = new double[*nvp];
mas01cr@239 254 double *timesdata = new double[*nvp*2];
mas01cr@239 255 insertTimeStamps(*nvp, timesFile, timesdata);
mas01cr@239 256 for(k = 0; k < *nvp; k++) {
mas01cr@239 257 querydurs[k] = timesdata[2*k+1] - timesdata[2*k];
mas01cr@239 258 *mqdp += querydurs[k];
mas01cr@239 259 }
mas01cr@239 260 *mqdp /= k;
mas01cr@239 261
mas01cr@239 262 VERB_LOG(1, "mean query file duration: %f\n", *mqdp);
mas01cr@239 263
mas01cr@239 264 delete [] querydurs;
mas01cr@239 265 delete [] timesdata;
mas01cr@239 266 }
mas01cr@239 267
mas01cr@239 268 // Defaults, for exhaustive search (!usingQueryPoint)
mas01cr@239 269 *vqp = *qp;
mas01cr@239 270 *vqnp = *qnp;
mas01cr@239 271 *vqpp = *qpp;
mas01cr@239 272
mas01cr@239 273 if(usingQueryPoint) {
mas01cr@239 274 if(queryPoint > *nvp || queryPoint > *nvp - sequenceLength + 1) {
mas01cr@239 275 error("queryPoint > numVectors-wL+1 in query");
mas01cr@239 276 } else {
mas01cr@239 277 VERB_LOG(1, "query point: %u\n", queryPoint);
mas01cr@239 278 *vqp = *qp + queryPoint * dbH->dim;
mas01cr@239 279 *vqnp = *qnp + queryPoint;
mas01cr@239 280 if (usingPower) {
mas01cr@239 281 *vqpp = *qpp + queryPoint;
mas01cr@239 282 }
mas01cr@239 283 *nvp = sequenceLength;
mas01cr@239 284 }
mas01cr@239 285 }
mas01cr@239 286 }
mas01cr@239 287
mas01cr@239 288 // FIXME: this is not the right name; we're not actually setting up
mas01cr@239 289 // the database, but copying various bits of it out of mmap()ed tables
mas01cr@239 290 // in order to reduce seeks.
mas01cr@239 291 void audioDB::set_up_db(double **snp, double **vsnp, double **spp, double **vspp, double **mddp, unsigned int *dvp) {
mas01cr@239 292 *dvp = dbH->length / (dbH->dim * sizeof(double));
mas01cr@239 293 *snp = new double[*dvp];
mas01cr@239 294
mas01cr@239 295 double *snpp = *snp, *sppp = 0;
mas01cr@239 296 memcpy(*snp, l2normTable, *dvp * sizeof(double));
mas01cr@239 297
mas01cr@239 298 if (usingPower) {
mas01cr@239 299 if (!(dbH->flags & O2_FLAG_POWER)) {
mas01cr@239 300 error("database not power-enabled", dbName);
mas01cr@239 301 }
mas01cr@239 302 *spp = new double[*dvp];
mas01cr@239 303 sppp = *spp;
mas01cr@239 304 memcpy(*spp, powerTable, *dvp * sizeof(double));
mas01cr@239 305 }
mas01cr@239 306
mas01cr@239 307 for(unsigned int i = 0; i < dbH->numFiles; i++){
mas01cr@239 308 if(trackTable[i] >= sequenceLength) {
mas01cr@239 309 sequence_sum(snpp, trackTable[i], sequenceLength);
mas01cr@239 310 sequence_sqrt(snpp, trackTable[i], sequenceLength);
mas01cr@239 311
mas01cr@239 312 if (usingPower) {
mas01cr@239 313 sequence_sum(sppp, trackTable[i], sequenceLength);
mas01cr@239 314 sequence_average(sppp, trackTable[i], sequenceLength);
mas01cr@239 315 }
mas01cr@239 316 }
mas01cr@239 317 snpp += trackTable[i];
mas01cr@239 318 if (usingPower) {
mas01cr@239 319 sppp += trackTable[i];
mas01cr@239 320 }
mas01cr@239 321 }
mas01cr@239 322
mas01cr@239 323 if (usingTimes) {
mas01cr@239 324 if(!(dbH->flags & O2_FLAG_TIMES)) {
mas01cr@239 325 error("query timestamps provided for non-timed database", dbName);
mas01cr@239 326 }
mas01cr@239 327
mas01cr@239 328 *mddp = new double[dbH->numFiles];
mas01cr@239 329
mas01cr@239 330 for(unsigned int k = 0; k < dbH->numFiles; k++) {
mas01cr@239 331 unsigned int j;
mas01cr@239 332 (*mddp)[k] = 0.0;
mas01cr@239 333 for(j = 0; j < trackTable[k]; j++) {
mas01cr@239 334 (*mddp)[k] += timesTable[2*j+1] - timesTable[2*j];
mas01cr@239 335 }
mas01cr@239 336 (*mddp)[k] /= j;
mas01cr@239 337 }
mas01cr@239 338 }
mas01cr@239 339
mas01cr@239 340 *vsnp = *snp;
mas01cr@239 341 *vspp = *spp;
mas01cr@239 342 }
mas01cr@239 343
mas01cr@240 344 void audioDB::query_loop(const char* dbName, const char* inFile, Reporter *reporter) {
mas01cr@239 345
mas01cr@239 346 unsigned int numVectors;
mas01cr@239 347 double *query, *query_data;
mas01cr@239 348 double *qNorm, *qnPtr, *qPower = 0, *qpPtr = 0;
mas01cr@239 349 double meanQdur;
mas01cr@239 350
mas01cr@239 351 set_up_query(&query_data, &query, &qNorm, &qnPtr, &qPower, &qpPtr, &meanQdur, &numVectors);
mas01cr@239 352
mas01cr@239 353 unsigned int dbVectors;
mas01cr@239 354 double *sNorm, *snPtr, *sPower = 0, *spPtr = 0;
mas01cr@239 355 double *meanDBdur = 0;
mas01cr@239 356
mas01cr@239 357 set_up_db(&sNorm, &snPtr, &sPower, &spPtr, &meanDBdur, &dbVectors);
mas01cr@239 358
mas01cr@239 359 VERB_LOG(1, "matching tracks...");
mas01cr@239 360
mas01cr@239 361 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01cr@239 362 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01cr@239 363
mas01cr@239 364 unsigned j,k,track,trackOffset=0, HOP_SIZE=sequenceHop, wL=sequenceLength;
mas01cr@239 365 double **D = 0; // Differences query and target
mas01cr@239 366 double **DD = 0; // Matched filter distance
mas01cr@239 367
mas01cr@239 368 D = new double*[numVectors];
mas01cr@239 369 DD = new double*[numVectors];
mas01cr@239 370
mas01cr@239 371 gettimeofday(&tv1, NULL);
mas01cr@239 372 unsigned processedTracks = 0;
mas01cr@239 373
mas01cr@239 374 // build track offset table
mas01cr@239 375 off_t *trackOffsetTable = new off_t[dbH->numFiles];
mas01cr@239 376 unsigned cumTrack=0;
mas01cr@239 377 off_t trackIndexOffset;
mas01cr@239 378 for(k = 0; k < dbH->numFiles; k++){
mas01cr@239 379 trackOffsetTable[k] = cumTrack;
mas01cr@239 380 cumTrack += trackTable[k] * dbH->dim;
mas01cr@239 381 }
mas01cr@239 382
mas01cr@239 383 char nextKey[MAXSTR];
mas01cr@239 384
mas01cr@239 385 // Track loop
mas01cr@239 386 size_t data_buffer_size = 0;
mas01cr@239 387 double *data_buffer = 0;
mas01cr@239 388 lseek(dbfid, dbH->dataOffset, SEEK_SET);
mas01cr@239 389
mas01cr@239 390 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++) {
mas01cr@239 391
mas01cr@239 392 trackOffset = trackOffsetTable[track]; // numDoubles offset
mas01cr@239 393
mas01cr@239 394 // get trackID from file if using a control file
mas01cr@239 395 if(trackFile) {
mas01cr@239 396 trackFile->getline(nextKey,MAXSTR);
mas01cr@239 397 if(!trackFile->eof()) {
mas01cr@239 398 track = getKeyPos(nextKey);
mas01cr@239 399 trackOffset = trackOffsetTable[track];
mas01cr@239 400 lseek(dbfid, dbH->dataOffset + trackOffset * sizeof(double), SEEK_SET);
mas01cr@239 401 } else {
mas01cr@239 402 break;
mas01cr@239 403 }
mas01cr@239 404 }
mas01cr@239 405
mas01cr@239 406 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01cr@239 407
mas01cr@239 408 read_data(track, &data_buffer, &data_buffer_size);
mas01cr@239 409 if(sequenceLength <= trackTable[track]) { // test for short sequences
mas01cr@239 410
mas01cr@239 411 VERB_LOG(7,"%u.%jd.%u | ", track, (intmax_t) trackIndexOffset, trackTable[track]);
mas01cr@239 412
mas01cr@239 413 initialize_arrays(track, numVectors, query, data_buffer, D, DD);
mas01cr@239 414
mas01cr@239 415 if(usingTimes) {
mas01cr@239 416 VERB_LOG(3,"meanQdur=%f meanDBdur=%f\n", meanQdur, meanDBdur[track]);
mas01cr@239 417 }
mas01cr@239 418
mas01cr@239 419 if((!usingTimes) || fabs(meanDBdur[track]-meanQdur) < meanQdur*timesTol) {
mas01cr@239 420 if(usingTimes) {
mas01cr@239 421 VERB_LOG(3,"within duration tolerance.\n");
mas01cr@239 422 }
mas01cr@239 423
mas01cr@239 424 // Search for minimum distance by shingles (concatenated vectors)
mas01cr@239 425 for(j = 0; j <= numVectors - wL; j += HOP_SIZE) {
mas01cr@239 426 for(k = 0; k <= trackTable[track] - wL; k += HOP_SIZE) {
mas01cr@239 427 double thisDist;
mas01cr@239 428 if(normalizedDistance) {
mas01cr@239 429 thisDist = 2-(2/(qnPtr[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
mas01cr@239 430 } else {
mas01cr@239 431 thisDist = DD[j][k];
mas01cr@239 432 }
mas01cr@239 433 // Power test
mas01cr@239 434 if ((!usingPower) || powers_acceptable(qpPtr[j], sPower[trackIndexOffset + k])) {
mas01cr@239 435 // radius test
mas01cr@239 436 if((!radius) || thisDist < radius) {
mas01cr@239 437 reporter->add_point(track, usingQueryPoint ? queryPoint : j, k, thisDist);
mas01cr@239 438 }
mas01cr@239 439 }
mas01cr@239 440 }
mas01cr@239 441 }
mas01cr@239 442 } // Duration match
mas01cr@239 443 delete_arrays(track, numVectors, D, DD);
mas01cr@239 444 }
mas01cr@239 445 }
mas01cr@239 446
mas01cr@239 447 free(data_buffer);
mas01cr@239 448
mas01cr@239 449 gettimeofday(&tv2,NULL);
mas01cr@239 450 VERB_LOG(1,"elapsed time: %ld msec\n",
mas01cr@239 451 (tv2.tv_sec*1000 + tv2.tv_usec/1000) -
mas01cr@239 452 (tv1.tv_sec*1000 + tv1.tv_usec/1000))
mas01cr@239 453
mas01cr@239 454 // Clean up
mas01cr@239 455 if(trackOffsetTable)
mas01cr@239 456 delete[] trackOffsetTable;
mas01cr@239 457 if(query_data)
mas01cr@239 458 delete[] query_data;
mas01cr@239 459 if(qNorm)
mas01cr@239 460 delete[] qNorm;
mas01cr@239 461 if(sNorm)
mas01cr@239 462 delete[] sNorm;
mas01cr@239 463 if(qPower)
mas01cr@239 464 delete[] qPower;
mas01cr@239 465 if(sPower)
mas01cr@239 466 delete[] sPower;
mas01cr@239 467 if(D)
mas01cr@239 468 delete[] D;
mas01cr@239 469 if(DD)
mas01cr@239 470 delete[] DD;
mas01cr@239 471 if(meanDBdur)
mas01cr@239 472 delete[] meanDBdur;
mas01cr@239 473 }
mas01cr@239 474
mas01cr@239 475 // Unit norm block of features
mas01cr@239 476 void audioDB::unitNorm(double* X, unsigned dim, unsigned n, double* qNorm){
mas01cr@239 477 unsigned d;
mas01cr@239 478 double L2, *p;
mas01cr@239 479
mas01cr@239 480 VERB_LOG(2, "norming %u vectors...", n);
mas01cr@239 481 while(n--) {
mas01cr@239 482 p = X;
mas01cr@239 483 L2 = 0.0;
mas01cr@239 484 d = dim;
mas01cr@239 485 while(d--) {
mas01cr@239 486 L2 += *p * *p;
mas01cr@239 487 p++;
mas01cr@239 488 }
mas01cr@239 489 if(qNorm) {
mas01cr@239 490 *qNorm++=L2;
mas01cr@239 491 }
mas01cr@239 492 X += dim;
mas01cr@239 493 }
mas01cr@239 494 VERB_LOG(2, "done.\n");
mas01cr@239 495 }