Mercurial > hg > audiodb
comparison query.cpp @ 461:2b8cfec91ed7 api-inversion
Factor out some bits of audiodb_query_spec_qpointers()
New functions audiodb_track_id_datum() and audiodb_datum_qpointers()
will be useful in places where audioDB::init_track_aux_data is currently
being called. We should be able to simplify audioDB::query_loop_points
quite a lot this way...
author | mas01cr |
---|---|
date | Tue, 30 Dec 2008 15:38:50 +0000 |
parents | 17003dff8127 |
children | f689510baaf4 |
comparison
equal
deleted
inserted
replaced
460:17003dff8127 | 461:2b8cfec91ed7 |
---|---|
397 if (!timesFile->eof()) { | 397 if (!timesFile->eof()) { |
398 error("too many timepoints in times file", timesFileName); | 398 error("too many timepoints in times file", timesFileName); |
399 } | 399 } |
400 } | 400 } |
401 | 401 |
402 int audiodb_track_id_datum(adb_t *adb, uint32_t track_id, adb_datum_t *d) { | |
403 off_t track_offset = (*adb->track_offsets)[track_id]; | |
404 if(adb->header->flags & O2_FLAG_LARGE_ADB) { | |
405 /* create a reference/insert, then use adb_insert_create_datum() */ | |
406 adb_reference_t reference = {0}; | |
407 char features[MAXSTR], power[MAXSTR], times[MAXSTR]; | |
408 lseek(adb->fd, adb->header->dataOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); | |
409 /* FIXME: learn not to worry and love the bomb^Wbuffer overflow */ | |
410 read(adb->fd, features, MAXSTR); | |
411 reference.features = features; | |
412 if(adb->header->flags & O2_FLAG_POWER) { | |
413 lseek(adb->fd, adb->header->powerTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); | |
414 read(adb->fd, power, MAXSTR); | |
415 reference.power = power; | |
416 } | |
417 if(adb->header->flags & O2_FLAG_TIMES) { | |
418 lseek(adb->fd, adb->header->timesTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); | |
419 read(adb->fd, times, MAXSTR); | |
420 reference.times = times; | |
421 } | |
422 audiodb_insert_create_datum(&reference, d); | |
423 } else { | |
424 /* initialize from sources of data that we already have */ | |
425 d->nvectors = (*adb->track_lengths)[track_id]; | |
426 d->dim = adb->header->dim; | |
427 d->key = (*adb->keys)[track_id].c_str(); | |
428 /* read out stuff from the database tables */ | |
429 d->data = (double *) malloc(d->nvectors * d->dim * sizeof(double)); | |
430 lseek(adb->fd, adb->header->dataOffset + track_offset, SEEK_SET); | |
431 read(adb->fd, d->data, d->nvectors * d->dim * sizeof(double)); | |
432 if(adb->header->flags & O2_FLAG_POWER) { | |
433 d->power = (double *) malloc(d->nvectors * sizeof(double)); | |
434 lseek(adb->fd, adb->header->powerTableOffset + track_offset / d->dim, SEEK_SET); | |
435 read(adb->fd, d->power, d->nvectors * sizeof(double)); | |
436 } | |
437 if(adb->header->flags & O2_FLAG_TIMES) { | |
438 d->times = (double *) malloc(2 * d->nvectors * sizeof(double)); | |
439 lseek(adb->fd, adb->header->timesTableOffset + track_offset / d->dim, SEEK_SET); | |
440 read(adb->fd, d->times, 2 * d->nvectors * sizeof(double)); | |
441 } | |
442 } | |
443 return 0; | |
444 } | |
445 | |
446 int audiodb_datum_qpointers(adb_datum_t *d, uint32_t sequence_length, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) { | |
447 uint32_t nvectors = d->nvectors; | |
448 | |
449 qpointers->nvectors = nvectors; | |
450 | |
451 size_t vector_size = nvectors * sizeof(double) * d->dim; | |
452 *vector_data = new double[vector_size]; | |
453 memcpy(*vector_data, d->data, vector_size); | |
454 | |
455 qpointers->l2norm_data = new double[vector_size / d->dim]; | |
456 audiodb_l2norm_buffer(*vector_data, d->dim, nvectors, qpointers->l2norm_data); | |
457 audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length); | |
458 audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length); | |
459 | |
460 if(d->power) { | |
461 qpointers->power_data = new double[vector_size / d->dim]; | |
462 memcpy(qpointers->power_data, d->power, vector_size / d->dim); | |
463 audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length); | |
464 audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length); | |
465 } | |
466 | |
467 if(d->times) { | |
468 qpointers->mean_duration = new double[1]; | |
469 *qpointers->mean_duration = 0; | |
470 for(unsigned int k = 0; k < nvectors; k++) { | |
471 *qpointers->mean_duration += d->times[2*k+1] - d->times[2*k]; | |
472 } | |
473 *qpointers->mean_duration /= nvectors; | |
474 } | |
475 | |
476 *vector = *vector_data; | |
477 qpointers->l2norm = qpointers->l2norm_data; | |
478 qpointers->power = qpointers->power_data; | |
479 return 0; | |
480 } | |
481 | |
402 int audiodb_query_spec_qpointers(adb_t *adb, adb_query_spec_t *spec, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) { | 482 int audiodb_query_spec_qpointers(adb_t *adb, adb_query_spec_t *spec, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) { |
403 adb_datum_t *datum; | 483 adb_datum_t *datum; |
404 adb_datum_t d = {0}; | 484 adb_datum_t d = {0}; |
405 uint32_t nvectors; | |
406 uint32_t sequence_length; | 485 uint32_t sequence_length; |
407 uint32_t sequence_start; | 486 uint32_t sequence_start; |
408 | 487 |
409 datum = spec->qid.datum; | 488 datum = spec->qid.datum; |
410 sequence_length = spec->qid.sequence_length; | 489 sequence_length = spec->qid.sequence_length; |
420 } else if (datum->key) { | 499 } else if (datum->key) { |
421 uint32_t track_id; | 500 uint32_t track_id; |
422 if((track_id = audiodb_key_index(adb, datum->key)) == (uint32_t) -1) { | 501 if((track_id = audiodb_key_index(adb, datum->key)) == (uint32_t) -1) { |
423 return 1; | 502 return 1; |
424 } | 503 } |
425 off_t track_offset = (*adb->track_offsets)[track_id]; | 504 audiodb_track_id_datum(adb, track_id, &d); |
426 | |
427 if(adb->header->flags & O2_FLAG_LARGE_ADB) { | |
428 /* create a reference/insert, then use adb_insert_create_datum() */ | |
429 adb_reference_t reference = {0}; | |
430 char features[MAXSTR], power[MAXSTR], times[MAXSTR]; | |
431 lseek(adb->fd, adb->header->dataOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); | |
432 /* FIXME: learn not to worry and love the bomb^Wbuffer overflow */ | |
433 read(adb->fd, features, MAXSTR); | |
434 reference.features = features; | |
435 if(adb->header->flags & O2_FLAG_POWER) { | |
436 lseek(adb->fd, adb->header->powerTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); | |
437 read(adb->fd, power, MAXSTR); | |
438 reference.power = power; | |
439 } | |
440 if(adb->header->flags & O2_FLAG_TIMES) { | |
441 lseek(adb->fd, adb->header->timesTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); | |
442 read(adb->fd, times, MAXSTR); | |
443 reference.times = times; | |
444 } | |
445 audiodb_insert_create_datum(&reference, &d); | |
446 } else { | |
447 /* initialize from sources of data that we already have */ | |
448 d.nvectors = (*adb->track_lengths)[track_id]; | |
449 d.dim = adb->header->dim; | |
450 d.key = datum->key; | |
451 /* read out stuff from the database tables */ | |
452 d.data = (double *) malloc(d.nvectors * d.dim * sizeof(double)); | |
453 lseek(adb->fd, adb->header->dataOffset + track_offset, SEEK_SET); | |
454 read(adb->fd, d.data, d.nvectors * d.dim * sizeof(double)); | |
455 if(adb->header->flags & O2_FLAG_POWER) { | |
456 d.power = (double *) malloc(d.nvectors * sizeof(double)); | |
457 lseek(adb->fd, adb->header->powerTableOffset + track_offset / d.dim, SEEK_SET); | |
458 read(adb->fd, d.power, d.nvectors * sizeof(double)); | |
459 } | |
460 if(adb->header->flags & O2_FLAG_TIMES) { | |
461 d.times = (double *) malloc(2 * d.nvectors * sizeof(double)); | |
462 lseek(adb->fd, adb->header->timesTableOffset + track_offset / d.dim, SEEK_SET); | |
463 read(adb->fd, d.times, 2 * d.nvectors * sizeof(double)); | |
464 } | |
465 } | |
466 } else { | 505 } else { |
467 return 1; | 506 return 1; |
468 } | 507 } |
469 | 508 |
470 /* Now we have a full(ish) datum, compute all the qpointery stuff | |
471 that we care about (l2norm/power/mean duration). (This bit could | |
472 conceivably become a new function) */ | |
473 nvectors = d.nvectors; | |
474 /* FIXME: check the overflow logic here */ | 509 /* FIXME: check the overflow logic here */ |
475 if(sequence_start + sequence_length > nvectors) { | 510 if(sequence_start + sequence_length > d.nvectors) { |
476 /* is there something to free? goto error */ | 511 if(datum != &d) { |
512 audiodb_free_datum(&d); | |
513 } | |
477 return 1; | 514 return 1; |
478 } | 515 } |
479 | 516 |
480 qpointers->nvectors = nvectors; | 517 audiodb_datum_qpointers(&d, sequence_length, vector_data, vector, qpointers); |
481 | 518 |
482 size_t vector_size = nvectors * sizeof(double) * d.dim; | 519 /* Finally, if applicable, set up the moving qpointers. */ |
483 *vector_data = new double[vector_size]; | |
484 memcpy(*vector_data, d.data, vector_size); | |
485 | |
486 qpointers->l2norm_data = new double[vector_size / d.dim]; | |
487 audiodb_l2norm_buffer(*vector_data, d.dim, nvectors, qpointers->l2norm_data); | |
488 audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length); | |
489 audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length); | |
490 | |
491 if(d.power) { | |
492 qpointers->power_data = new double[vector_size / d.dim]; | |
493 memcpy(qpointers->power_data, d.power, vector_size / d.dim); | |
494 audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length); | |
495 audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length); | |
496 } | |
497 | |
498 if(d.times) { | |
499 qpointers->mean_duration = new double[1]; | |
500 *qpointers->mean_duration = 0; | |
501 for(unsigned int k = 0; k < nvectors; k++) { | |
502 *qpointers->mean_duration += d.times[2*k+1] - d.times[2*k]; | |
503 } | |
504 *qpointers->mean_duration /= nvectors; | |
505 } | |
506 | |
507 | |
508 /* Finally, set up the moving qpointers. */ | |
509 if(spec->qid.flags & ADB_QUERY_ID_FLAG_EXHAUSTIVE) { | 520 if(spec->qid.flags & ADB_QUERY_ID_FLAG_EXHAUSTIVE) { |
510 *vector = *vector_data; | 521 /* the qpointers are already at the start, and so correct. */ |
511 qpointers->l2norm = qpointers->l2norm_data; | |
512 qpointers->power = qpointers->power_data; | |
513 } else { | 522 } else { |
523 /* adjust the qpointers to point to the correct place in the sequence */ | |
514 *vector = *vector_data + spec->qid.sequence_start * d.dim; | 524 *vector = *vector_data + spec->qid.sequence_start * d.dim; |
515 qpointers->l2norm = qpointers->l2norm_data + spec->qid.sequence_start; | 525 qpointers->l2norm = qpointers->l2norm_data + spec->qid.sequence_start; |
516 if(d.power) { | 526 if(d.power) { |
517 qpointers->power = qpointers->power_data + spec->qid.sequence_start; | 527 qpointers->power = qpointers->power_data + spec->qid.sequence_start; |
518 } | 528 } |
519 /* FIXME: this is a little bit ugly. No, a lot ugly. But at the | |
520 * moment this is how query_loop() knows when to stop, so for | |
521 * now... */ | |
522 qpointers->nvectors = sequence_length; | 529 qpointers->nvectors = sequence_length; |
523 } | 530 } |
524 | 531 |
525 /* Clean up: free any bits of datum that we have ourselves | 532 /* Clean up: free any bits of datum that we have ourselves |
526 * allocated. */ | 533 * allocated. */ |