comparison query.cpp @ 443:cb44e57a96fa api-inversion

New (internal) function audiodb_query_spec_qpointers() Intended to replace audioDB::set_up_query and audioDB::set_up_query_from_key; it isn't yet called, but I want to save my work now before messing with stuff, because the function itself is long and complicated: it handles three separate ways of getting data together (datum provided, key provided + LARGE_ADB, key provided + !LARGE_ADB). There is insufficient error checking as yet, but hey.
author mas01cr
date Wed, 24 Dec 2008 10:56:33 +0000
parents 5294ea1b1bf2
children 4fe90fd568fc
comparison
equal deleted inserted replaced
442:16c5c51a4c32 443:cb44e57a96fa
302 } 302 }
303 303
304 *timesFile >> next; 304 *timesFile >> next;
305 if (!timesFile->eof()) { 305 if (!timesFile->eof()) {
306 error("too many timepoints in times file", timesFileName); 306 error("too many timepoints in times file", timesFileName);
307 }
308 }
309
310 static int audiodb_query_spec_qpointers(adb_t *adb, adb_query_spec_t *spec, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) {
311 adb_datum_t *datum;
312 adb_datum_t d = {0};
313 uint32_t nvectors;
314 uint32_t sequence_length;
315 uint32_t sequence_start;
316
317 datum = spec->qid.datum;
318 sequence_length = spec->qid.sequence_length;
319 sequence_start = spec->qid.sequence_start;
320
321 if(datum->data) {
322 if(datum->dim != adb->header->dim) {
323 return 1;
324 }
325 /* initialize d, and mark that nothing needs freeing later. */
326 d = *datum;
327 datum = &d;
328 } else if (datum->key) {
329 std::map<std::string,uint32_t>::iterator it;
330 it = adb->keys->find(datum->key);
331 if(it == adb->keys->end()) {
332 return 1;
333 }
334 uint32_t track_id = (*it).second;
335 off_t track_offset = (*adb->track_offsets)[track_id];
336
337 if(adb->header->flags & O2_FLAG_LARGE_ADB) {
338 /* create a reference/insert, then use adb_insert_create_datum() */
339 adb_reference_t reference = {0};
340 char features[MAXSTR], power[MAXSTR], times[MAXSTR];
341 lseek(adb->fd, adb->header->dataOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
342 /* FIXME: learn not to worry and love the bomb^Wbuffer overflow */
343 read(adb->fd, features, MAXSTR);
344 reference.features = features;
345 if(adb->header->flags & O2_FLAG_POWER) {
346 lseek(adb->fd, adb->header->powerTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
347 read(adb->fd, power, MAXSTR);
348 reference.power = power;
349 }
350 if(adb->header->flags & O2_FLAG_TIMES) {
351 lseek(adb->fd, adb->header->timesTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET);
352 read(adb->fd, times, MAXSTR);
353 reference.times = times;
354 }
355 audiodb_insert_create_datum(&reference, &d);
356 } else {
357 /* initialize from sources of data that we already have */
358 d.nvectors = (*adb->track_lengths)[track_id];
359 d.dim = adb->header->dim;
360 d.key = datum->key;
361 /* read out stuff from the database tables */
362 d.data = (double *) malloc(d.nvectors * d.dim * sizeof(double));
363 lseek(adb->fd, adb->header->dataOffset + track_offset, SEEK_SET);
364 read(adb->fd, d.data, d.nvectors * d.dim * sizeof(double));
365 if(adb->header->flags & O2_FLAG_POWER) {
366 d.power = (double *) malloc(d.nvectors * sizeof(double));
367 lseek(adb->fd, adb->header->powerTableOffset + track_offset / d.dim, SEEK_SET);
368 read(adb->fd, d.power, d.nvectors * sizeof(double));
369 }
370 if(adb->header->flags & O2_FLAG_TIMES) {
371 d.times = (double *) malloc(2 * d.nvectors * sizeof(double));
372 lseek(adb->fd, adb->header->timesTableOffset + track_offset / d.dim, SEEK_SET);
373 read(adb->fd, d.times, 2 * d.nvectors * sizeof(double));
374 }
375 }
376 } else {
377 return 1;
378 }
379
380 /* Now we have a full(ish) datum, compute all the qpointery stuff
381 that we care about (l2norm/power/mean duration). (This bit could
382 conceivably become a new function) */
383 nvectors = d.nvectors;
384 if(sequence_start > nvectors - sequence_length) {
385 /* is there something to free? goto error */
386 return 1;
387 }
388
389 qpointers->nvectors = nvectors;
390
391 size_t vector_size = nvectors * sizeof(double) * d.dim;
392 *vector_data = (double *) malloc(vector_size);
393 memcpy(*vector_data, d.data, vector_size);
394
395 qpointers->l2norm_data = (double *) malloc(vector_size / d.dim);
396 audiodb_l2norm_buffer(*vector_data, d.dim, nvectors, qpointers->l2norm_data);
397 audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length);
398 audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length);
399
400 if(d.power) {
401 qpointers->power_data = (double *) malloc(vector_size / d.dim);
402 memcpy(qpointers->power_data, d.power, vector_size / d.dim);
403 audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length);
404 audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length);
405 }
406
407 if(d.times) {
408 qpointers->mean_duration = (double *) calloc(1, sizeof(double));
409 for(unsigned int k = 0; k < nvectors; k++) {
410 *qpointers->mean_duration += d.times[2*k+1] - d.times[2*k];
411 }
412 *qpointers->mean_duration /= nvectors;
413 }
414
415
416 /* Finally, set up the moving qpointers. */
417 if(spec->qid.flags & ADB_QUERY_ID_FLAG_EXHAUSTIVE) {
418 *vector = *vector_data;
419 qpointers->l2norm = qpointers->l2norm_data;
420 qpointers->power = qpointers->power_data;
421 } else {
422 *vector = *vector_data + spec->qid.sequence_start * d.dim;
423 qpointers->l2norm = qpointers->l2norm_data + spec->qid.sequence_start;
424 qpointers->power = qpointers->power_data + spec->qid.sequence_start;
425 }
426
427
428 /* Clean up: free any bits of datum that we have ourselves
429 * allocated. */
430 if(datum != &d) {
431 audiodb_free_datum(&d);
307 } 432 }
308 } 433 }
309 434
310 // These names deserve some unpicking. The names starting with a "q" 435 // These names deserve some unpicking. The names starting with a "q"
311 // are pointers to the query, norm and power vectors; the names 436 // are pointers to the query, norm and power vectors; the names