annotate query.cpp @ 277:abfb26e08d9c audiodb-debian

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