Mercurial > hg > audiodb
changeset 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 | 16c5c51a4c32 |
children | 4fe90fd568fc |
files | audioDB-internals.h insert.cpp query.cpp |
diffstat | 3 files changed, 129 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/audioDB-internals.h Wed Dec 24 10:56:29 2008 +0000 +++ b/audioDB-internals.h Wed Dec 24 10:56:33 2008 +0000 @@ -183,3 +183,5 @@ } int audiodb_read_data(adb_t *, int, int, double **, size_t *); +int audiodb_insert_create_datum(adb_insert_t *, adb_datum_t *); +int audiodb_free_datum(adb_datum_t *);
--- a/insert.cpp Wed Dec 24 10:56:29 2008 +0000 +++ b/insert.cpp Wed Dec 24 10:56:33 2008 +0000 @@ -274,7 +274,7 @@ } } -static int audiodb_free_datum(adb_datum_t *datum) { +int audiodb_free_datum(adb_datum_t *datum) { if(datum->data) { free(datum->data); } @@ -287,7 +287,7 @@ return 0; } -static int audiodb_insert_create_datum(adb_insert_t *insert, adb_datum_t *datum) { +int audiodb_insert_create_datum(adb_insert_t *insert, adb_datum_t *datum) { int fd = 0; FILE *file = NULL; struct stat st;
--- a/query.cpp Wed Dec 24 10:56:29 2008 +0000 +++ b/query.cpp Wed Dec 24 10:56:33 2008 +0000 @@ -307,6 +307,131 @@ } } +static int audiodb_query_spec_qpointers(adb_t *adb, adb_query_spec_t *spec, double **vector_data, double **vector, adb_qpointers_internal_t *qpointers) { + adb_datum_t *datum; + adb_datum_t d = {0}; + uint32_t nvectors; + uint32_t sequence_length; + uint32_t sequence_start; + + datum = spec->qid.datum; + sequence_length = spec->qid.sequence_length; + sequence_start = spec->qid.sequence_start; + + if(datum->data) { + if(datum->dim != adb->header->dim) { + return 1; + } + /* initialize d, and mark that nothing needs freeing later. */ + d = *datum; + datum = &d; + } else if (datum->key) { + std::map<std::string,uint32_t>::iterator it; + it = adb->keys->find(datum->key); + if(it == adb->keys->end()) { + return 1; + } + uint32_t track_id = (*it).second; + off_t track_offset = (*adb->track_offsets)[track_id]; + + if(adb->header->flags & O2_FLAG_LARGE_ADB) { + /* create a reference/insert, then use adb_insert_create_datum() */ + adb_reference_t reference = {0}; + char features[MAXSTR], power[MAXSTR], times[MAXSTR]; + lseek(adb->fd, adb->header->dataOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + /* FIXME: learn not to worry and love the bomb^Wbuffer overflow */ + read(adb->fd, features, MAXSTR); + reference.features = features; + if(adb->header->flags & O2_FLAG_POWER) { + lseek(adb->fd, adb->header->powerTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + read(adb->fd, power, MAXSTR); + reference.power = power; + } + if(adb->header->flags & O2_FLAG_TIMES) { + lseek(adb->fd, adb->header->timesTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + read(adb->fd, times, MAXSTR); + reference.times = times; + } + audiodb_insert_create_datum(&reference, &d); + } else { + /* initialize from sources of data that we already have */ + d.nvectors = (*adb->track_lengths)[track_id]; + d.dim = adb->header->dim; + d.key = datum->key; + /* read out stuff from the database tables */ + d.data = (double *) malloc(d.nvectors * d.dim * sizeof(double)); + lseek(adb->fd, adb->header->dataOffset + track_offset, SEEK_SET); + read(adb->fd, d.data, d.nvectors * d.dim * sizeof(double)); + if(adb->header->flags & O2_FLAG_POWER) { + d.power = (double *) malloc(d.nvectors * sizeof(double)); + lseek(adb->fd, adb->header->powerTableOffset + track_offset / d.dim, SEEK_SET); + read(adb->fd, d.power, d.nvectors * sizeof(double)); + } + if(adb->header->flags & O2_FLAG_TIMES) { + d.times = (double *) malloc(2 * d.nvectors * sizeof(double)); + lseek(adb->fd, adb->header->timesTableOffset + track_offset / d.dim, SEEK_SET); + read(adb->fd, d.times, 2 * d.nvectors * sizeof(double)); + } + } + } else { + return 1; + } + + /* Now we have a full(ish) datum, compute all the qpointery stuff + that we care about (l2norm/power/mean duration). (This bit could + conceivably become a new function) */ + nvectors = d.nvectors; + if(sequence_start > nvectors - sequence_length) { + /* is there something to free? goto error */ + return 1; + } + + qpointers->nvectors = nvectors; + + size_t vector_size = nvectors * sizeof(double) * d.dim; + *vector_data = (double *) malloc(vector_size); + memcpy(*vector_data, d.data, vector_size); + + qpointers->l2norm_data = (double *) malloc(vector_size / d.dim); + audiodb_l2norm_buffer(*vector_data, d.dim, nvectors, qpointers->l2norm_data); + audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length); + audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length); + + if(d.power) { + qpointers->power_data = (double *) malloc(vector_size / d.dim); + memcpy(qpointers->power_data, d.power, vector_size / d.dim); + audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length); + audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length); + } + + if(d.times) { + qpointers->mean_duration = (double *) calloc(1, sizeof(double)); + for(unsigned int k = 0; k < nvectors; k++) { + *qpointers->mean_duration += d.times[2*k+1] - d.times[2*k]; + } + *qpointers->mean_duration /= nvectors; + } + + + /* Finally, set up the moving qpointers. */ + if(spec->qid.flags & ADB_QUERY_ID_FLAG_EXHAUSTIVE) { + *vector = *vector_data; + qpointers->l2norm = qpointers->l2norm_data; + qpointers->power = qpointers->power_data; + } else { + *vector = *vector_data + spec->qid.sequence_start * d.dim; + qpointers->l2norm = qpointers->l2norm_data + spec->qid.sequence_start; + qpointers->power = qpointers->power_data + spec->qid.sequence_start; + } + + + /* Clean up: free any bits of datum that we have ourselves + * allocated. */ + if(datum != &d) { + audiodb_free_datum(&d); + } +} + // These names deserve some unpicking. The names starting with a "q" // are pointers to the query, norm and power vectors; the names // starting with "v" are things that will end up pointing to the