annotate query.cpp @ 250:a6ee49f10296

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