annotate query.cpp @ 256:4dcb09f5fe85

Commit patch deprecating the --size argument, replacing it with --ntracks, --datadims and --datasize. These names are not ideal, but will serve for now.
author mas01cr
date Wed, 16 Apr 2008 09:59:43 +0000
parents a6ee49f10296
children 210b2f661b88
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@256 58 if(strncmp(fileTable + k*O2_FILETABLE_ENTRY_SIZE, 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 }