annotate query.cpp @ 462:f689510baaf4 api-inversion

Simplify audioDB::query_loop_points. Using the new functions audiodb_track_id_datum() and audiodb_datum_qpointers(), much of the body of the method disappears. Of course, we've probably introduced some inefficiencies and extra memory copies, but I'm fairly sure that this method is going to be dominated by disk i/o time anyway, so it doesn't matter.
author mas01cr
date Tue, 30 Dec 2008 15:38:55 +0000
parents 2b8cfec91ed7
children 35bb388d0eac
rev   line source
mas01cr@239 1 #include "audioDB.h"
mas01cr@239 2 #include "reporter.h"
mas01cr@239 3
mas01cr@422 4 #include "audioDB-internals.h"
mas01cr@422 5 #include "accumulators.h"
mas01cr@422 6
mas01cr@444 7 bool audiodb_powers_acceptable(adb_query_refine_t *r, double p1, double p2) {
mas01cr@425 8 if (r->flags & ADB_REFINE_ABSOLUTE_THRESHOLD) {
mas01cr@425 9 if ((p1 < r->absolute_threshold) || (p2 < r->absolute_threshold)) {
mas01cr@239 10 return false;
mas01cr@239 11 }
mas01cr@239 12 }
mas01cr@425 13 if (r->flags & ADB_REFINE_RELATIVE_THRESHOLD) {
mas01cr@425 14 if (fabs(p1-p2) > fabs(r->relative_threshold)) {
mas01cr@239 15 return false;
mas01cr@239 16 }
mas01cr@239 17 }
mas01cr@239 18 return true;
mas01cr@239 19 }
mas01cr@239 20
mas01cr@239 21 void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse) {
mas01cr@425 22
mas01cr@431 23 // init database tables and dbH first
mas01cr@431 24 if(query_from_key)
mas01cr@431 25 initTables(dbName);
mas01cr@431 26 else
mas01cr@431 27 initTables(dbName, inFile);
mas01cr@431 28
mas01cr@435 29 adb_query_spec_t qspec;
mas01cr@444 30 adb_datum_t datum = {0};
mas01cr@435 31
mas01cr@435 32 qspec.refine.flags = 0;
mas01cr@453 33 if(trackFile) {
mas01cr@453 34 qspec.refine.flags |= ADB_REFINE_INCLUDE_KEYLIST;
mas01cr@453 35 std::vector<const char *> v;
mas01cr@453 36 char *k = new char[MAXSTR];
mas01cr@453 37 trackFile->getline(k, MAXSTR);
mas01cr@453 38 while(!trackFile->eof()) {
mas01cr@453 39 v.push_back(k);
mas01cr@453 40 k = new char[MAXSTR];
mas01cr@453 41 trackFile->getline(k, MAXSTR);
mas01cr@453 42 }
mas01cr@453 43 delete [] k;
mas01cr@453 44 qspec.refine.include.nkeys = v.size();
mas01cr@453 45 qspec.refine.include.keys = new const char *[qspec.refine.include.nkeys];
mas01cr@453 46 for(unsigned int k = 0; k < qspec.refine.include.nkeys; k++) {
mas01cr@453 47 qspec.refine.include.keys[k] = v[k];
mas01cr@453 48 }
mas01cr@453 49 }
mas01cr@453 50 if(query_from_key) {
mas01cr@453 51 qspec.refine.flags |= ADB_REFINE_EXCLUDE_KEYLIST;
mas01cr@453 52 qspec.refine.exclude.nkeys = 1;
mas01cr@453 53 qspec.refine.exclude.keys = &key;
mas01cr@453 54 }
mas01cr@425 55 if(radius) {
mas01cr@435 56 qspec.refine.flags |= ADB_REFINE_RADIUS;
mas01cr@435 57 qspec.refine.radius = radius;
mas01cr@425 58 }
mas01cr@425 59 if(use_absolute_threshold) {
mas01cr@435 60 qspec.refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD;
mas01cr@435 61 qspec.refine.absolute_threshold = absolute_threshold;
mas01cr@425 62 }
mas01cr@425 63 if(use_relative_threshold) {
mas01cr@435 64 qspec.refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD;
mas01cr@435 65 qspec.refine.relative_threshold = relative_threshold;
mas01cr@425 66 }
mas01cr@425 67 if(usingTimes) {
mas01cr@435 68 qspec.refine.flags |= ADB_REFINE_DURATION_RATIO;
mas01cr@435 69 qspec.refine.duration_ratio = timesTol;
mas01cr@425 70 }
mas01cr@439 71 /* FIXME: not sure about this any more; maybe it belongs in
mas01cr@439 72 query_id? Or maybe we just don't need a flag for it? */
mas01cr@439 73 qspec.refine.hopsize = sequenceHop;
mas01cr@425 74 if(sequenceHop != 1) {
mas01cr@435 75 qspec.refine.flags |= ADB_REFINE_HOP_SIZE;
mas01cr@425 76 }
mas01cr@425 77
mas01cr@444 78 if(query_from_key) {
mas01cr@444 79 datum.key = key;
mas01cr@444 80 } else {
mas01cr@444 81 int fd;
mas01cr@444 82 struct stat st;
mas01cr@444 83
mas01cr@444 84 /* FIXME: around here there are all sorts of hideous leaks. */
mas01cr@444 85 fd = open(inFile, O_RDONLY);
mas01cr@444 86 if(fd < 0) {
mas01cr@444 87 error("failed to open feature file", inFile);
mas01cr@444 88 }
mas01cr@444 89 fstat(fd, &st);
mas01cr@444 90 read(fd, &datum.dim, sizeof(uint32_t));
mas01cr@444 91 datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double));
mas01cr@444 92 datum.data = (double *) malloc(st.st_size - sizeof(uint32_t));
mas01cr@444 93 read(fd, datum.data, st.st_size - sizeof(uint32_t));
mas01cr@444 94 close(fd);
mas01cr@444 95 if(usingPower) {
mas01cr@444 96 uint32_t one;
mas01cr@444 97 fd = open(powerFileName, O_RDONLY);
mas01cr@444 98 if(fd < 0) {
mas01cr@444 99 error("failed to open power file", powerFileName);
mas01cr@444 100 }
mas01cr@444 101 read(fd, &one, sizeof(uint32_t));
mas01cr@444 102 if(one != 1) {
mas01cr@444 103 error("malformed power file dimensionality", powerFileName);
mas01cr@444 104 }
mas01cr@444 105 datum.power = (double *) malloc(datum.nvectors * sizeof(double));
mas01cr@444 106 if(read(fd, datum.power, datum.nvectors * sizeof(double)) != (ssize_t) (datum.nvectors * sizeof(double))) {
mas01cr@444 107 error("malformed power file", powerFileName);
mas01cr@444 108 }
mas01cr@444 109 close(fd);
mas01cr@444 110 }
mas01cr@444 111 if(usingTimes) {
mas01cr@444 112 datum.times = (double *) malloc(2 * datum.nvectors * sizeof(double));
mas01cr@444 113 insertTimeStamps(datum.nvectors, timesFile, datum.times);
mas01cr@444 114 }
mas01cr@444 115 }
mas01cr@444 116
mas01cr@444 117 qspec.qid.datum = &datum;
mas01cr@435 118 qspec.qid.sequence_length = sequenceLength;
mas01cr@435 119 qspec.qid.flags = usingQueryPoint ? 0 : ADB_QUERY_ID_FLAG_EXHAUSTIVE;
mas01cr@435 120 qspec.qid.sequence_start = queryPoint;
mas01cr@435 121
mas01cr@431 122 switch(queryType) {
mas01cr@431 123 case O2_POINT_QUERY:
mas01cr@435 124 qspec.qid.sequence_length = 1;
mas01cr@435 125 qspec.params.accumulation = ADB_ACCUMULATION_DB;
mas01cr@435 126 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
mas01cr@435 127 qspec.params.npoints = pointNN;
mas01cr@435 128 qspec.params.ntracks = 0;
mas01cr@431 129 reporter = new pointQueryReporter< std::greater < NNresult > >(pointNN);
mas01cr@431 130 break;
mas01cr@431 131 case O2_TRACK_QUERY:
mas01cr@435 132 qspec.qid.sequence_length = 1;
mas01cr@435 133 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01cr@435 134 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
mas01cr@435 135 qspec.params.npoints = pointNN;
mas01cr@435 136 qspec.params.ntracks = trackNN;
mas01cr@431 137 reporter = new trackAveragingReporter< std::greater< NNresult > >(pointNN, trackNN, dbH->numFiles);
mas01cr@431 138 break;
mas01cr@431 139 case O2_SEQUENCE_QUERY:
mas01cr@431 140 case O2_N_SEQUENCE_QUERY:
mas01cr@435 141 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01cr@435 142 qspec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01cr@435 143 qspec.params.npoints = pointNN;
mas01cr@435 144 qspec.params.ntracks = trackNN;
mas01cr@431 145 switch(queryType) {
mas01cr@431 146 case O2_SEQUENCE_QUERY:
mas01cr@435 147 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@431 148 reporter = new trackAveragingReporter< std::less< NNresult > >(pointNN, trackNN, dbH->numFiles);
mas01cr@460 149 } else if (audiodb_index_exists(adb->path, qspec.refine.radius, qspec.qid.sequence_length)) {
mas01cr@460 150 char *indexName = audiodb_index_get_name(adb->path, qspec.refine.radius, qspec.qid.sequence_length);
mas01cr@431 151 lsh = index_allocate(indexName, false);
mas01cr@458 152 reporter = new trackSequenceQueryRadReporter(trackNN, audiodb_index_to_track_id(lsh->get_maxp(), audiodb_lsh_n_point_bits(adb))+1);
mas01cr@431 153 delete[] indexName;
mas01cr@431 154 } else {
mas01cr@431 155 reporter = new trackSequenceQueryRadReporter(trackNN, dbH->numFiles);
mas01cr@431 156 }
mas01cr@431 157 break;
mas01cr@431 158 case O2_N_SEQUENCE_QUERY:
mas01cr@435 159 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@431 160 reporter = new trackSequenceQueryNNReporter< std::less < NNresult > >(pointNN, trackNN, dbH->numFiles);
mas01cr@460 161 } else if (audiodb_index_exists(adb->path, qspec.refine.radius, qspec.qid.sequence_length)){
mas01cr@460 162 char *indexName = audiodb_index_get_name(adb->path, qspec.refine.radius, qspec.qid.sequence_length);
mas01cr@431 163 lsh = index_allocate(indexName, false);
mas01cr@460 164 reporter = new trackSequenceQueryRadNNReporter(pointNN, trackNN, audiodb_index_to_track_id(lsh->get_maxp(), audiodb_lsh_n_point_bits(adb))+1);
mas01cr@431 165 delete[] indexName;
mas01cr@431 166 } else {
mas01cr@460 167 reporter = new trackSequenceQueryRadNNReporter(pointNN, trackNN, dbH->numFiles);
mas01cr@431 168 }
mas01cr@431 169 break;
mas01cr@431 170 }
mas01cr@431 171 break;
mas01cr@431 172 case O2_ONE_TO_ONE_N_SEQUENCE_QUERY:
mas01cr@435 173 qspec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
mas01cr@435 174 qspec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01cr@435 175 qspec.params.npoints = 0;
mas01cr@435 176 qspec.params.ntracks = 0;
mas01cr@431 177 break;
mas01cr@431 178 default:
mas01cr@431 179 error("unrecognized queryType");
mas01cr@431 180 }
mas01mc@292 181
mas01cr@458 182 /* Somewhere around here is where the implementation of
mas01cr@458 183 * audiodb_query_spec() starts. */
mas01cr@458 184
mas01cr@458 185 adb_qstate_internal_t qstate;
mas01cr@458 186 qstate.allowed_keys = new std::set<std::string>;
mas01cr@458 187 if(qspec.refine.flags & ADB_REFINE_INCLUDE_KEYLIST) {
mas01cr@458 188 for(unsigned int k = 0; k < qspec.refine.include.nkeys; k++) {
mas01cr@458 189 qstate.allowed_keys->insert(qspec.refine.include.keys[k]);
mas01cr@458 190 }
mas01cr@458 191 } else {
mas01cr@458 192 for(unsigned int k = 0; k < adb->header->numFiles; k++) {
mas01cr@458 193 qstate.allowed_keys->insert((*adb->keys)[k]);
mas01cr@458 194 }
mas01cr@458 195 }
mas01cr@458 196 if(qspec.refine.flags & ADB_REFINE_EXCLUDE_KEYLIST) {
mas01cr@458 197 for(unsigned int k = 0; k < qspec.refine.exclude.nkeys; k++) {
mas01cr@458 198 qstate.allowed_keys->erase(qspec.refine.exclude.keys[k]);
mas01cr@458 199 }
mas01cr@458 200 }
mas01cr@431 201
mas01cr@435 202 switch(qspec.params.distance) {
mas01cr@431 203 case ADB_DISTANCE_DOT_PRODUCT:
mas01cr@435 204 switch(qspec.params.accumulation) {
mas01cr@431 205 case ADB_ACCUMULATION_DB:
mas01cr@458 206 qstate.accumulator = new DBAccumulator<adb_result_dist_gt>(qspec.params.npoints);
mas01cr@431 207 break;
mas01cr@431 208 case ADB_ACCUMULATION_PER_TRACK:
mas01cr@458 209 qstate.accumulator = new PerTrackAccumulator<adb_result_dist_gt>(qspec.params.npoints, qspec.params.ntracks);
mas01cr@431 210 break;
mas01cr@431 211 case ADB_ACCUMULATION_ONE_TO_ONE:
mas01cr@458 212 qstate.accumulator = new NearestAccumulator<adb_result_dist_gt>();
mas01cr@431 213 break;
mas01cr@431 214 default:
mas01cr@431 215 error("unknown accumulation");
mas01cr@239 216 }
mas01cr@239 217 break;
mas01cr@431 218 case ADB_DISTANCE_EUCLIDEAN_NORMED:
mas01cr@431 219 case ADB_DISTANCE_EUCLIDEAN:
mas01cr@435 220 switch(qspec.params.accumulation) {
mas01cr@431 221 case ADB_ACCUMULATION_DB:
mas01cr@458 222 qstate.accumulator = new DBAccumulator<adb_result_dist_lt>(qspec.params.npoints);
mas01cr@431 223 break;
mas01cr@431 224 case ADB_ACCUMULATION_PER_TRACK:
mas01cr@458 225 qstate.accumulator = new PerTrackAccumulator<adb_result_dist_lt>(qspec.params.npoints, qspec.params.ntracks);
mas01cr@431 226 break;
mas01cr@431 227 case ADB_ACCUMULATION_ONE_TO_ONE:
mas01cr@458 228 qstate.accumulator = new NearestAccumulator<adb_result_dist_lt>();
mas01cr@431 229 break;
mas01cr@431 230 default:
mas01cr@431 231 error("unknown accumulation");
mas01mc@263 232 }
mas01mc@263 233 break;
mas01cr@239 234 default:
mas01cr@431 235 error("unknown distance function");
mas01cr@431 236 }
mas01cr@431 237
mas01mc@292 238 // Test for index (again) here
mas01cr@460 239 if((qspec.refine.flags & ADB_REFINE_RADIUS) && audiodb_index_exists(adb->path, qspec.refine.radius, qspec.qid.sequence_length)){
mas01cr@436 240 VERB_LOG(1, "Calling indexed query on database %s, radius=%f, sequence_length=%d\n", adb->path, qspec.refine.radius, qspec.qid.sequence_length);
mas01cr@458 241 index_query_loop(adb, &qspec, &qstate);
mas01mc@329 242 }
mas01mc@329 243 else{
mas01mc@329 244 VERB_LOG(1, "Calling brute-force query on database %s\n", dbName);
mas01cr@458 245 if(query_loop(adb, &qspec, &qstate)) {
mas01cr@452 246 error("query_loop failed");
mas01cr@452 247 }
mas01mc@329 248 }
mas01mc@292 249
mas01cr@458 250 adb_query_results_t *rs = qstate.accumulator->get_points();
mas01cr@458 251
mas01cr@458 252 delete qstate.accumulator;
mas01cr@458 253 delete qstate.allowed_keys;
mas01cr@458 254
mas01cr@458 255 /* End of audiodb_query_spec() function */
mas01cr@458 256
mas01cr@423 257 for(unsigned int k = 0; k < rs->nresults; k++) {
mas01cr@423 258 adb_result_t r = rs->results[k];
mas01cr@430 259 reporter->add_point(audiodb_key_index(adb, r.key), r.qpos, r.ipos, r.dist);
mas01cr@423 260 }
mas01cr@459 261 audiodb_query_free_results(adb, &qspec, rs);
mas01cr@423 262
mas01mc@292 263 reporter->report(fileTable, adbQueryResponse);
mas01cr@239 264 }
mas01cr@239 265
mas01cr@459 266 int audiodb_query_free_results(adb_t *adb, adb_query_spec_t *spec, adb_query_results_t *rs) {
mas01cr@459 267 free(rs->results);
mas01cr@459 268 free(rs);
mas01cr@459 269 return 0;
mas01cr@459 270 }
mas01cr@459 271
mas01cr@439 272 static void audiodb_initialize_arrays(adb_t *adb, adb_query_spec_t *spec, int track, unsigned int numVectors, double *query, double *data_buffer, double **D, double **DD) {
mas01cr@239 273 unsigned int j, k, l, w;
mas01cr@239 274 double *dp, *qp, *sp;
mas01cr@239 275
mas01cr@439 276 const unsigned HOP_SIZE = spec->refine.hopsize;
mas01cr@435 277 const unsigned wL = spec->qid.sequence_length;
mas01cr@239 278
mas01cr@239 279 for(j = 0; j < numVectors; j++) {
mas01cr@239 280 // Sum products matrix
mas01cr@433 281 D[j] = new double[(*adb->track_lengths)[track]];
mas01cr@239 282 assert(D[j]);
mas01cr@239 283 // Matched filter matrix
mas01cr@433 284 DD[j]=new double[(*adb->track_lengths)[track]];
mas01cr@239 285 assert(DD[j]);
mas01cr@239 286 }
mas01cr@239 287
mas01cr@239 288 // Dot product
mas01cr@239 289 for(j = 0; j < numVectors; j++)
mas01cr@433 290 for(k = 0; k < (*adb->track_lengths)[track]; k++){
mas01cr@439 291 qp = query + j * adb->header->dim;
mas01cr@439 292 sp = data_buffer + k * adb->header->dim;
mas01cr@239 293 DD[j][k] = 0.0; // Initialize matched filter array
mas01cr@239 294 dp = &D[j][k]; // point to correlation cell j,k
mas01cr@239 295 *dp = 0.0; // initialize correlation cell
mas01cr@439 296 l = adb->header->dim; // size of vectors
mas01cr@239 297 while(l--)
mas01cr@239 298 *dp += *qp++ * *sp++;
mas01cr@239 299 }
mas01cr@239 300
mas01cr@239 301 // Matched Filter
mas01cr@239 302 // HOP SIZE == 1
mas01cr@239 303 double* spd;
mas01cr@239 304 if(HOP_SIZE == 1) { // HOP_SIZE = shingleHop
mas01cr@239 305 for(w = 0; w < wL; w++) {
mas01cr@239 306 for(j = 0; j < numVectors - w; j++) {
mas01cr@239 307 sp = DD[j];
mas01cr@239 308 spd = D[j+w] + w;
mas01cr@433 309 k = (*adb->track_lengths)[track] - w;
mas01mc@292 310 while(k--)
mas01mc@292 311 *sp++ += *spd++;
mas01cr@239 312 }
mas01cr@239 313 }
mas01cr@239 314 } else { // HOP_SIZE != 1
mas01cr@239 315 for(w = 0; w < wL; w++) {
mas01cr@239 316 for(j = 0; j < numVectors - w; j += HOP_SIZE) {
mas01cr@239 317 sp = DD[j];
mas01cr@239 318 spd = D[j+w]+w;
mas01cr@433 319 for(k = 0; k < (*adb->track_lengths)[track] - w; k += HOP_SIZE) {
mas01cr@239 320 *sp += *spd;
mas01cr@239 321 sp += HOP_SIZE;
mas01cr@239 322 spd += HOP_SIZE;
mas01cr@239 323 }
mas01cr@239 324 }
mas01cr@239 325 }
mas01cr@239 326 }
mas01cr@239 327 }
mas01cr@239 328
mas01cr@433 329 static void audiodb_delete_arrays(int track, unsigned int numVectors, double **D, double **DD) {
mas01cr@239 330 if(D != NULL) {
mas01cr@239 331 for(unsigned int j = 0; j < numVectors; j++) {
mas01cr@239 332 delete[] D[j];
mas01cr@239 333 }
mas01cr@239 334 }
mas01cr@239 335 if(DD != NULL) {
mas01cr@239 336 for(unsigned int j = 0; j < numVectors; j++) {
mas01cr@239 337 delete[] DD[j];
mas01cr@239 338 }
mas01cr@239 339 }
mas01cr@239 340 }
mas01cr@239 341
mas01cr@433 342 int audiodb_read_data(adb_t *adb, int trkfid, int track, double **data_buffer_p, size_t *data_buffer_size_p) {
mas01cr@433 343 uint32_t track_length = (*adb->track_lengths)[track];
mas01cr@433 344 size_t track_size = track_length * sizeof(double) * adb->header->dim;
mas01cr@433 345 if (track_size > *data_buffer_size_p) {
mas01cr@239 346 if(*data_buffer_p) {
mas01cr@239 347 free(*data_buffer_p);
mas01cr@239 348 }
mas01cr@239 349 {
mas01cr@433 350 *data_buffer_size_p = track_size;
mas01cr@433 351 void *tmp = malloc(track_size);
mas01cr@239 352 if (tmp == NULL) {
mas01cr@433 353 goto error;
mas01cr@239 354 }
mas01cr@239 355 *data_buffer_p = (double *) tmp;
mas01cr@239 356 }
mas01cr@239 357 }
mas01cr@239 358
mas01cr@433 359 read_or_goto_error(trkfid, *data_buffer_p, track_size);
mas01cr@433 360 return 0;
mas01cr@433 361
mas01cr@433 362 error:
mas01cr@433 363 return 1;
mas01cr@239 364 }
mas01cr@239 365
mas01cr@405 366 void audioDB::insertTimeStamps(unsigned numVectors, std::ifstream *timesFile, double *timesdata) {
mas01cr@405 367 assert(usingTimes);
mas01cr@405 368
mas01cr@405 369 unsigned numtimes = 0;
mas01cr@405 370
mas01cr@405 371 if(!timesFile->is_open()) {
mas01cr@405 372 error("problem opening times file on timestamped database", timesFileName);
mas01cr@405 373 }
mas01cr@405 374
mas01cr@405 375 double timepoint, next;
mas01cr@405 376 *timesFile >> timepoint;
mas01cr@405 377 if (timesFile->eof()) {
mas01cr@405 378 error("no entries in times file", timesFileName);
mas01cr@405 379 }
mas01cr@405 380 numtimes++;
mas01cr@405 381 do {
mas01cr@405 382 *timesFile >> next;
mas01cr@405 383 if (timesFile->eof()) {
mas01cr@405 384 break;
mas01cr@405 385 }
mas01cr@405 386 numtimes++;
mas01cr@405 387 timesdata[0] = timepoint;
mas01cr@405 388 timepoint = (timesdata[1] = next);
mas01cr@405 389 timesdata += 2;
mas01cr@405 390 } while (numtimes < numVectors + 1);
mas01cr@405 391
mas01cr@405 392 if (numtimes < numVectors + 1) {
mas01cr@405 393 error("too few timepoints in times file", timesFileName);
mas01cr@405 394 }
mas01cr@405 395
mas01cr@405 396 *timesFile >> next;
mas01cr@405 397 if (!timesFile->eof()) {
mas01cr@405 398 error("too many timepoints in times file", timesFileName);
mas01cr@405 399 }
mas01cr@405 400 }
mas01cr@405 401
mas01cr@461 402 int audiodb_track_id_datum(adb_t *adb, uint32_t track_id, adb_datum_t *d) {
mas01cr@461 403 off_t track_offset = (*adb->track_offsets)[track_id];
mas01cr@461 404 if(adb->header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@461 405 /* create a reference/insert, then use adb_insert_create_datum() */
mas01cr@461 406 adb_reference_t reference = {0};
mas01cr@461 407 char features[MAXSTR], power[MAXSTR], times[MAXSTR];
mas01cr@461 408 lseek(adb->fd, adb->header->dataOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@461 409 /* FIXME: learn not to worry and love the bomb^Wbuffer overflow */
mas01cr@461 410 read(adb->fd, features, MAXSTR);
mas01cr@461 411 reference.features = features;
mas01cr@461 412 if(adb->header->flags & O2_FLAG_POWER) {
mas01cr@461 413 lseek(adb->fd, adb->header->powerTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@461 414 read(adb->fd, power, MAXSTR);
mas01cr@461 415 reference.power = power;
mas01cr@461 416 }
mas01cr@461 417 if(adb->header->flags & O2_FLAG_TIMES) {
mas01cr@461 418 lseek(adb->fd, adb->header->timesTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
mas01cr@461 419 read(adb->fd, times, MAXSTR);
mas01cr@461 420 reference.times = times;
mas01cr@461 421 }
mas01cr@461 422 audiodb_insert_create_datum(&reference, d);
mas01cr@461 423 } else {
mas01cr@461 424 /* initialize from sources of data that we already have */
mas01cr@461 425 d->nvectors = (*adb->track_lengths)[track_id];
mas01cr@461 426 d->dim = adb->header->dim;
mas01cr@461 427 d->key = (*adb->keys)[track_id].c_str();
mas01cr@461 428 /* read out stuff from the database tables */
mas01cr@461 429 d->data = (double *) malloc(d->nvectors * d->dim * sizeof(double));
mas01cr@461 430 lseek(adb->fd, adb->header->dataOffset + track_offset, SEEK_SET);
mas01cr@461 431 read(adb->fd, d->data, d->nvectors * d->dim * sizeof(double));
mas01cr@461 432 if(adb->header->flags & O2_FLAG_POWER) {
mas01cr@461 433 d->power = (double *) malloc(d->nvectors * sizeof(double));
mas01cr@461 434 lseek(adb->fd, adb->header->powerTableOffset + track_offset / d->dim, SEEK_SET);
mas01cr@461 435 read(adb->fd, d->power, d->nvectors * sizeof(double));
mas01cr@461 436 }
mas01cr@461 437 if(adb->header->flags & O2_FLAG_TIMES) {
mas01cr@461 438 d->times = (double *) malloc(2 * d->nvectors * sizeof(double));
mas01cr@461 439 lseek(adb->fd, adb->header->timesTableOffset + track_offset / d->dim, SEEK_SET);
mas01cr@461 440 read(adb->fd, d->times, 2 * d->nvectors * sizeof(double));
mas01cr@461 441 }
mas01cr@461 442 }
mas01cr@461 443 return 0;
mas01cr@461 444 }
mas01cr@461 445
mas01cr@461 446 int audiodb_datum_qpointers(adb_datum_t *d, uint32_t sequence_length, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) {
mas01cr@461 447 uint32_t nvectors = d->nvectors;
mas01cr@461 448
mas01cr@461 449 qpointers->nvectors = nvectors;
mas01cr@461 450
mas01cr@461 451 size_t vector_size = nvectors * sizeof(double) * d->dim;
mas01cr@461 452 *vector_data = new double[vector_size];
mas01cr@461 453 memcpy(*vector_data, d->data, vector_size);
mas01cr@461 454
mas01cr@461 455 qpointers->l2norm_data = new double[vector_size / d->dim];
mas01cr@461 456 audiodb_l2norm_buffer(*vector_data, d->dim, nvectors, qpointers->l2norm_data);
mas01cr@461 457 audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length);
mas01cr@461 458 audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length);
mas01cr@461 459
mas01cr@461 460 if(d->power) {
mas01cr@461 461 qpointers->power_data = new double[vector_size / d->dim];
mas01cr@461 462 memcpy(qpointers->power_data, d->power, vector_size / d->dim);
mas01cr@461 463 audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length);
mas01cr@461 464 audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length);
mas01cr@461 465 }
mas01cr@461 466
mas01cr@461 467 if(d->times) {
mas01cr@461 468 qpointers->mean_duration = new double[1];
mas01cr@461 469 *qpointers->mean_duration = 0;
mas01cr@461 470 for(unsigned int k = 0; k < nvectors; k++) {
mas01cr@461 471 *qpointers->mean_duration += d->times[2*k+1] - d->times[2*k];
mas01cr@461 472 }
mas01cr@461 473 *qpointers->mean_duration /= nvectors;
mas01cr@461 474 }
mas01cr@461 475
mas01cr@461 476 *vector = *vector_data;
mas01cr@461 477 qpointers->l2norm = qpointers->l2norm_data;
mas01cr@461 478 qpointers->power = qpointers->power_data;
mas01cr@461 479 return 0;
mas01cr@461 480 }
mas01cr@461 481
mas01cr@444 482 int audiodb_query_spec_qpointers(adb_t *adb, adb_query_spec_t *spec, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) {
mas01cr@443 483 adb_datum_t *datum;
mas01cr@443 484 adb_datum_t d = {0};
mas01cr@443 485 uint32_t sequence_length;
mas01cr@443 486 uint32_t sequence_start;
mas01cr@443 487
mas01cr@443 488 datum = spec->qid.datum;
mas01cr@443 489 sequence_length = spec->qid.sequence_length;
mas01cr@443 490 sequence_start = spec->qid.sequence_start;
mas01cr@443 491
mas01cr@443 492 if(datum->data) {
mas01cr@443 493 if(datum->dim != adb->header->dim) {
mas01cr@443 494 return 1;
mas01cr@443 495 }
mas01cr@443 496 /* initialize d, and mark that nothing needs freeing later. */
mas01cr@443 497 d = *datum;
mas01cr@443 498 datum = &d;
mas01cr@443 499 } else if (datum->key) {
mas01cr@449 500 uint32_t track_id;
mas01cr@449 501 if((track_id = audiodb_key_index(adb, datum->key)) == (uint32_t) -1) {
mas01cr@443 502 return 1;
mas01cr@443 503 }
mas01cr@461 504 audiodb_track_id_datum(adb, track_id, &d);
mas01cr@443 505 } else {
mas01cr@443 506 return 1;
mas01cr@443 507 }
mas01cr@443 508
mas01cr@444 509 /* FIXME: check the overflow logic here */
mas01cr@461 510 if(sequence_start + sequence_length > d.nvectors) {
mas01cr@461 511 if(datum != &d) {
mas01cr@461 512 audiodb_free_datum(&d);
mas01cr@461 513 }
mas01cr@443 514 return 1;
mas01cr@443 515 }
mas01cr@443 516
mas01cr@461 517 audiodb_datum_qpointers(&d, sequence_length, vector_data, vector, qpointers);
mas01cr@443 518
mas01cr@461 519 /* Finally, if applicable, set up the moving qpointers. */
mas01cr@443 520 if(spec->qid.flags & ADB_QUERY_ID_FLAG_EXHAUSTIVE) {
mas01cr@461 521 /* the qpointers are already at the start, and so correct. */
mas01cr@443 522 } else {
mas01cr@461 523 /* adjust the qpointers to point to the correct place in the sequence */
mas01cr@443 524 *vector = *vector_data + spec->qid.sequence_start * d.dim;
mas01cr@443 525 qpointers->l2norm = qpointers->l2norm_data + spec->qid.sequence_start;
mas01cr@444 526 if(d.power) {
mas01cr@444 527 qpointers->power = qpointers->power_data + spec->qid.sequence_start;
mas01cr@444 528 }
mas01cr@444 529 qpointers->nvectors = sequence_length;
mas01cr@443 530 }
mas01cr@443 531
mas01cr@443 532 /* Clean up: free any bits of datum that we have ourselves
mas01cr@443 533 * allocated. */
mas01cr@443 534 if(datum != &d) {
mas01cr@443 535 audiodb_free_datum(&d);
mas01cr@443 536 }
mas01cr@444 537
mas01cr@444 538 return 0;
mas01cr@443 539 }
mas01cr@443 540
mas01cr@448 541 static int audiodb_set_up_dbpointers(adb_t *adb, adb_query_spec_t *spec, adb_qpointers_internal_t *dbpointers) {
mas01cr@438 542 uint32_t nvectors = adb->header->length / (adb->header->dim * sizeof(double));
mas01cr@435 543 uint32_t sequence_length = spec->qid.sequence_length;
mas01cr@438 544
mas01cr@437 545 bool using_power = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD);
mas01cr@437 546 bool using_times = spec->refine.flags & ADB_REFINE_DURATION_RATIO;
mas01cr@437 547 double *times_table = NULL;
mas01cr@435 548
mas01cr@239 549
mas01cr@438 550 dbpointers->nvectors = nvectors;
mas01cr@438 551 dbpointers->l2norm_data = new double[nvectors];
mas01cr@438 552
mas01cr@438 553 double *snpp = dbpointers->l2norm_data, *sppp = 0;
mas01cr@434 554 lseek(adb->fd, adb->header->l2normTableOffset, SEEK_SET);
mas01cr@438 555 read_or_goto_error(adb->fd, dbpointers->l2norm_data, nvectors * sizeof(double));
mas01cr@239 556
mas01cr@437 557 if (using_power) {
mas01cr@434 558 if (!(adb->header->flags & O2_FLAG_POWER)) {
mas01cr@434 559 goto error;
mas01cr@239 560 }
mas01cr@438 561 dbpointers->power_data = new double[nvectors];
mas01cr@438 562 sppp = dbpointers->power_data;
mas01cr@434 563 lseek(adb->fd, adb->header->powerTableOffset, SEEK_SET);
mas01cr@438 564 read_or_goto_error(adb->fd, dbpointers->power_data, nvectors * sizeof(double));
mas01cr@239 565 }
mas01cr@239 566
mas01cr@434 567 for(unsigned int i = 0; i < adb->header->numFiles; i++){
mas01cr@434 568 size_t track_length = (*adb->track_lengths)[i];
mas01cr@435 569 if(track_length >= sequence_length) {
mas01cr@435 570 audiodb_sequence_sum(snpp, track_length, sequence_length);
mas01cr@435 571 audiodb_sequence_sqrt(snpp, track_length, sequence_length);
mas01cr@437 572 if (using_power) {
mas01cr@435 573 audiodb_sequence_sum(sppp, track_length, sequence_length);
mas01cr@435 574 audiodb_sequence_average(sppp, track_length, sequence_length);
mas01cr@239 575 }
mas01cr@239 576 }
mas01cr@434 577 snpp += track_length;
mas01cr@437 578 if (using_power) {
mas01cr@434 579 sppp += track_length;
mas01cr@239 580 }
mas01cr@239 581 }
mas01cr@239 582
mas01cr@437 583 if (using_times) {
mas01cr@434 584 if(!(adb->header->flags & O2_FLAG_TIMES)) {
mas01cr@437 585 goto error;
mas01cr@239 586 }
mas01cr@239 587
mas01cr@438 588 dbpointers->mean_duration = new double[adb->header->numFiles];
mas01cr@239 589
mas01cr@438 590 times_table = (double *) malloc(2 * nvectors * sizeof(double));
mas01cr@437 591 if(!times_table) {
mas01cr@437 592 goto error;
mas01cr@437 593 }
mas01cr@437 594 lseek(adb->fd, adb->header->timesTableOffset, SEEK_SET);
mas01cr@438 595 read_or_goto_error(adb->fd, times_table, 2 * nvectors * sizeof(double));
mas01cr@434 596 for(unsigned int k = 0; k < adb->header->numFiles; k++) {
mas01cr@434 597 size_t track_length = (*adb->track_lengths)[k];
mas01cr@239 598 unsigned int j;
mas01cr@438 599 dbpointers->mean_duration[k] = 0.0;
mas01cr@434 600 for(j = 0; j < track_length; j++) {
mas01cr@438 601 dbpointers->mean_duration[k] += times_table[2*j+1] - times_table[2*j];
mas01cr@239 602 }
mas01cr@438 603 dbpointers->mean_duration[k] /= j;
mas01cr@239 604 }
mas01cr@437 605
mas01cr@437 606 free(times_table);
mas01cr@437 607 times_table = NULL;
mas01cr@239 608 }
mas01cr@239 609
mas01cr@438 610 dbpointers->l2norm = dbpointers->l2norm_data;
mas01cr@438 611 dbpointers->power = dbpointers->power_data;
mas01cr@434 612 return 0;
mas01cr@434 613
mas01cr@434 614 error:
mas01cr@438 615 if(dbpointers->l2norm_data) {
mas01cr@438 616 delete [] dbpointers->l2norm_data;
mas01cr@434 617 }
mas01cr@438 618 if(dbpointers->power_data) {
mas01cr@438 619 delete [] dbpointers->power_data;
mas01cr@434 620 }
mas01cr@438 621 if(dbpointers->mean_duration) {
mas01cr@438 622 delete [] dbpointers->mean_duration;
mas01cr@434 623 }
mas01cr@437 624 if(times_table) {
mas01cr@437 625 free(times_table);
mas01cr@437 626 }
mas01cr@434 627 return 1;
mas01cr@434 628
mas01cr@239 629 }
mas01cr@239 630
mas01mc@292 631 // query_points()
mas01mc@292 632 //
mas01mc@292 633 // using PointPairs held in the exact_evaluation_queue compute squared distance for each PointPair
mas01mc@292 634 // and insert result into the current reporter.
mas01mc@292 635 //
mas01mc@292 636 // Preconditions:
mas01mc@292 637 // A query inFile has been opened with setup_query(...) and query pointers initialized
mas01mc@292 638 // The database contains some points
mas01mc@292 639 // An exact_evaluation_queue has been allocated and populated
mas01mc@292 640 // A reporter has been allocated
mas01mc@292 641 //
mas01mc@292 642 // Postconditions:
mas01mc@292 643 // reporter contains the points and distances that meet the reporter constraints
mas01mc@292 644
mas01cr@458 645 void audioDB::query_loop_points(adb_t *adb, adb_query_spec_t *spec, adb_qstate_internal_t *qstate, double *query, adb_qpointers_internal_t *qpointers) {
mas01cr@438 646 adb_qpointers_internal_t dbpointers = {0};
mas01mc@292 647
mas01cr@436 648 uint32_t sequence_length = spec->qid.sequence_length;
mas01cr@437 649 bool power_refine = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD);
mas01cr@436 650
mas01cr@458 651 if(qstate->exact_evaluation_queue->size() == 0) {
mas01mc@292 652 return;
mas01cr@455 653 }
mas01mc@292 654
mas01cr@462 655 /* We are guaranteed that the order of points is sorted by:
mas01cr@462 656 * {trackID, spos, qpos} so we can be relatively efficient in
mas01cr@462 657 * initialization of track data. We assume that points usually
mas01cr@462 658 * don't overlap, so we will use exhaustive dot product evaluation
mas01cr@462 659 * (instead of memoization of partial sums, as in query_loop()). */
mas01cr@462 660 double dist;
mas01cr@462 661 double *dbdata = 0, *dbdata_pointer;
mas01cr@462 662 Uns32T currentTrack = 0x80000000; // KLUDGE: Initialize with a value outside of track index range
mas01cr@462 663 Uns32T npairs = qstate->exact_evaluation_queue->size();
mas01cr@462 664 while(npairs--) {
mas01cr@462 665 PointPair pp = qstate->exact_evaluation_queue->top();
mas01cr@462 666 if(currentTrack != pp.trackID) {
mas01cr@462 667 SAFE_DELETE_ARRAY(dbdata);
mas01cr@462 668 SAFE_DELETE_ARRAY(dbpointers.l2norm_data);
mas01cr@462 669 SAFE_DELETE_ARRAY(dbpointers.power_data);
mas01cr@462 670 SAFE_DELETE_ARRAY(dbpointers.mean_duration);
mas01cr@462 671 currentTrack = pp.trackID;
mas01cr@462 672 adb_datum_t d = {0};
mas01cr@462 673 if(audiodb_track_id_datum(adb, pp.trackID, &d)) {
mas01cr@462 674 error("failed to get datum");
mas01cr@462 675 }
mas01cr@462 676 if(audiodb_datum_qpointers(&d, sequence_length, &dbdata, &dbdata_pointer, &dbpointers)) {
mas01cr@462 677 audiodb_free_datum(&d);
mas01cr@462 678 error("failed to get dbpointers");
mas01cr@462 679 }
mas01cr@462 680 audiodb_free_datum(&d);
mas01cr@434 681 }
mas01mc@324 682 Uns32T qPos = usingQueryPoint?0:pp.qpos;// index for query point
mas01cr@462 683 Uns32T sPos = pp.spos; // index into l2norm table
mas01mc@324 684 // Test power thresholds before computing distance
mas01cr@438 685 if( ( (!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers->power[qPos], dbpointers.power[sPos])) &&
mas01cr@462 686 ( qPos<qpointers->nvectors-sequence_length+1 && sPos<(*adb->track_lengths)[pp.trackID]-sequence_length+1 ) ){
mas01mc@324 687 // Compute distance
mas01cr@462 688 dist = audiodb_dot_product(query + qPos*adb->header->dim, dbdata + sPos*adb->header->dim, adb->header->dim*sequence_length);
mas01cr@437 689 double qn = qpointers->l2norm[qPos];
mas01cr@438 690 double sn = dbpointers.l2norm[sPos];
mas01cr@435 691 switch(spec->params.distance) {
mas01cr@431 692 case ADB_DISTANCE_EUCLIDEAN_NORMED:
mas01mc@324 693 dist = 2 - (2/(qn*sn))*dist;
mas01cr@431 694 break;
mas01cr@431 695 case ADB_DISTANCE_EUCLIDEAN:
mas01cr@431 696 dist = qn*qn + sn*sn - 2*dist;
mas01cr@431 697 break;
mas01cr@431 698 }
mas01cr@424 699 if((!radius) || dist <= (O2_LSH_EXACT_MULT*radius+O2_DISTANCE_TOLERANCE)) {
mas01cr@424 700 adb_result_t r;
mas01cr@453 701 r.key = (*adb->keys)[pp.trackID].c_str();
mas01cr@424 702 r.dist = dist;
mas01cr@424 703 r.qpos = pp.qpos;
mas01cr@424 704 r.ipos = pp.spos;
mas01cr@458 705 qstate->accumulator->add_point(&r);
mas01cr@424 706 }
mas01mc@292 707 }
mas01cr@458 708 qstate->exact_evaluation_queue->pop();
mas01mc@292 709 }
mas01mc@315 710 // Cleanup
mas01cr@462 711 SAFE_DELETE_ARRAY(dbdata);
mas01cr@438 712 SAFE_DELETE_ARRAY(dbpointers.l2norm_data);
mas01cr@438 713 SAFE_DELETE_ARRAY(dbpointers.power_data);
mas01cr@438 714 SAFE_DELETE_ARRAY(dbpointers.mean_duration);
mas01cr@458 715 delete qstate->exact_evaluation_queue;
mas01mc@292 716 }
mas01mc@292 717
mas01cr@458 718 int audioDB::query_loop(adb_t *adb, adb_query_spec_t *spec, adb_qstate_internal_t *qstate) {
mas01cr@239 719
mas01cr@239 720 double *query, *query_data;
mas01cr@438 721 adb_qpointers_internal_t qpointers = {0}, dbpointers = {0};
mas01cr@437 722
mas01cr@437 723 bool power_refine = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD);
mas01cr@239 724
mas01cr@452 725 if(adb->header->flags & O2_FLAG_LARGE_ADB) {
mas01cr@452 726 /* FIXME: actually it would be nice to support this mode of
mas01cr@452 727 * operation, but for now... */
mas01cr@452 728 return 1;
mas01cr@452 729 }
mas01mc@324 730
mas01cr@444 731 if(audiodb_query_spec_qpointers(adb, spec, &query_data, &query, &qpointers)) {
mas01cr@452 732 return 1;
mas01cr@444 733 }
mas01cr@239 734
mas01cr@448 735 if(audiodb_set_up_dbpointers(adb, spec, &dbpointers)) {
mas01cr@452 736 return 1;
mas01cr@434 737 }
mas01cr@239 738
mas01cr@451 739 unsigned j,k,track,trackOffset=0, HOP_SIZE = spec->refine.hopsize;
mas01cr@435 740 unsigned wL = spec->qid.sequence_length;
mas01cr@239 741 double **D = 0; // Differences query and target
mas01cr@239 742 double **DD = 0; // Matched filter distance
mas01cr@239 743
mas01cr@437 744 D = new double*[qpointers.nvectors]; // pre-allocate
mas01cr@437 745 DD = new double*[qpointers.nvectors];
mas01cr@239 746
mas01cr@239 747 off_t trackIndexOffset;
mas01cr@239 748
mas01cr@239 749 // Track loop
mas01cr@239 750 size_t data_buffer_size = 0;
mas01cr@239 751 double *data_buffer = 0;
mas01cr@451 752 lseek(adb->fd, adb->header->dataOffset, SEEK_SET);
mas01cr@239 753
mas01cr@458 754 std::set<std::string>::iterator keys_end = qstate->allowed_keys->end();
mas01cr@453 755 for(track = 0; track < adb->header->numFiles; track++) {
mas01cr@453 756 unsigned t = track;
mas01cr@458 757
mas01cr@458 758 while (qstate->allowed_keys->find((*adb->keys)[track]) == keys_end) {
mas01cr@453 759 track++;
mas01cr@453 760 if(track == adb->header->numFiles) {
mas01cr@453 761 goto loop_finish;
mas01cr@239 762 }
mas01cr@239 763 }
mas01cr@453 764 trackOffset = (*adb->track_offsets)[track];
mas01cr@453 765 if(track != t) {
mas01cr@453 766 lseek(adb->fd, adb->header->dataOffset + trackOffset, SEEK_SET);
mas01mc@292 767 }
mas01cr@451 768 trackIndexOffset = trackOffset / (adb->header->dim * sizeof(double)); // dbpointers.nvectors offset
mas01cr@239 769
mas01cr@452 770 if(audiodb_read_data(adb, adb->fd, track, &data_buffer, &data_buffer_size)) {
mas01cr@452 771 return 1;
mas01cr@452 772 }
mas01cr@451 773 if(wL <= (*adb->track_lengths)[track]) { // test for short sequences
mas01cr@239 774
mas01cr@439 775 audiodb_initialize_arrays(adb, spec, track, qpointers.nvectors, query, data_buffer, D, DD);
mas01cr@239 776
mas01cr@437 777 if((!(spec->refine.flags & ADB_REFINE_DURATION_RATIO)) ||
mas01cr@438 778 fabs(dbpointers.mean_duration[track]-qpointers.mean_duration[0]) < qpointers.mean_duration[0]*spec->refine.duration_ratio) {
mas01cr@239 779
mas01cr@239 780 // Search for minimum distance by shingles (concatenated vectors)
mas01cr@437 781 for(j = 0; j <= qpointers.nvectors - wL; j += HOP_SIZE) {
mas01cr@451 782 for(k = 0; k <= (*adb->track_lengths)[track] - wL; k += HOP_SIZE) {
mas01cr@431 783 double thisDist = 0;
mas01cr@438 784 double qn = qpointers.l2norm[j];
mas01cr@438 785 double sn = dbpointers.l2norm[trackIndexOffset + k];
mas01cr@435 786 switch(spec->params.distance) {
mas01cr@431 787 case ADB_DISTANCE_EUCLIDEAN_NORMED:
mas01cr@438 788 thisDist = 2-(2/(qn*sn))*DD[j][k];
mas01cr@431 789 break;
mas01cr@431 790 case ADB_DISTANCE_EUCLIDEAN:
mas01cr@438 791 thisDist = qn*qn + sn*sn - 2*DD[j][k];
mas01cr@431 792 break;
mas01cr@431 793 case ADB_DISTANCE_DOT_PRODUCT:
mas01cr@431 794 thisDist = DD[j][k];
mas01cr@431 795 break;
mas01cr@431 796 }
mas01cr@239 797 // Power test
mas01cr@438 798 if ((!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers.power[j], dbpointers.power[trackIndexOffset + k])) {
mas01cr@239 799 // radius test
mas01cr@435 800 if((!(spec->refine.flags & ADB_REFINE_RADIUS)) ||
mas01cr@435 801 thisDist <= (spec->refine.radius+O2_DISTANCE_TOLERANCE)) {
mas01cr@423 802 adb_result_t r;
mas01cr@453 803 r.key = (*adb->keys)[track].c_str();
mas01cr@423 804 r.dist = thisDist;
mas01cr@451 805 if(spec->qid.flags & ADB_QUERY_ID_FLAG_EXHAUSTIVE) {
mas01cr@451 806 r.qpos = j;
mas01cr@451 807 } else {
mas01cr@451 808 r.qpos = spec->qid.sequence_start;
mas01cr@451 809 }
mas01cr@423 810 r.ipos = k;
mas01cr@458 811 qstate->accumulator->add_point(&r);
mas01cr@239 812 }
mas01cr@239 813 }
mas01cr@239 814 }
mas01cr@239 815 }
mas01cr@239 816 } // Duration match
mas01cr@437 817 audiodb_delete_arrays(track, qpointers.nvectors, D, DD);
mas01cr@239 818 }
mas01cr@239 819 }
mas01cr@239 820
mas01cr@453 821 loop_finish:
mas01cr@453 822
mas01cr@239 823 free(data_buffer);
mas01cr@239 824
mas01cr@239 825 // Clean up
mas01cr@239 826 if(query_data)
mas01cr@239 827 delete[] query_data;
mas01cr@437 828 if(qpointers.l2norm_data)
mas01cr@437 829 delete[] qpointers.l2norm_data;
mas01cr@437 830 if(qpointers.power_data)
mas01cr@437 831 delete[] qpointers.power_data;
mas01cr@437 832 if(qpointers.mean_duration)
mas01cr@437 833 delete[] qpointers.mean_duration;
mas01cr@438 834 if(dbpointers.power_data)
mas01cr@438 835 delete[] dbpointers.power_data;
mas01cr@438 836 if(dbpointers.l2norm_data)
mas01cr@438 837 delete[] dbpointers.l2norm_data;
mas01cr@239 838 if(D)
mas01cr@239 839 delete[] D;
mas01cr@239 840 if(DD)
mas01cr@239 841 delete[] DD;
mas01cr@438 842 if(dbpointers.mean_duration)
mas01cr@438 843 delete[] dbpointers.mean_duration;
mas01cr@452 844
mas01cr@452 845 return 0;
mas01cr@239 846 }