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