changeset 437:9a065b8db769 api-inversion

Hey, who let audioDB::set_up_query into the room? audioDB::set_up_query and audioDB::set_up_db both do all sorts of horrible pointer manipulation. Define a structure to contain all the pointers, rather than having the hideous argument lists full of double **, and use it in audioDB::set_up_query and audioDB::set_up_query_from_key. (Those two functions are desperately close to becoming one function, incidentally, or possibly even no functions given the existence of adb_datum_t...)
author mas01cr
date Wed, 24 Dec 2008 10:56:07 +0000
parents e43f8a7aca93
children 8c1d8a40db91
files audioDB.h index.cpp query.cpp
diffstat 3 files changed, 141 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/audioDB.h	Wed Dec 24 10:56:01 2008 +0000
+++ b/audioDB.h	Wed Dec 24 10:56:07 2008 +0000
@@ -32,6 +32,16 @@
 #include "soapH.h"
 #include "cmdline.h"
 
+// should be in -internals.h
+typedef struct adb_qpointers_internal {
+  uint32_t nvectors;
+  double *l2norm_data;
+  double *l2norm;
+  double *power_data;
+  double *power;
+  double *mean_duration;
+} adb_qpointers_internal_t;
+
 #define MAXSTR 512
 
 // Databse PRIMARY commands
@@ -321,11 +331,10 @@
 
   void initialize_arrays(adb_t *adb, adb_query_spec_t *spec, int track, unsigned int numVectors, double *query, double *data_buffer, double **D, double **DD);
   void insertTimeStamps(unsigned n, std::ifstream* timesFile, double* timesdata);
-  void set_up_query(adb_query_spec_t *spec, double **qp, double **vqp, double **qnp, double **vqnp, double **qpp, double **vqpp, double *mqdp, unsigned int *nvp);
-  void set_up_query_from_key(adb_query_spec_t *spec, double **qp, double **vqp, double **qnp, double **vqnp, double **qpp, double **vqpp, double *mqdp, unsigned *nvp, Uns32T queryIndex);
-  int set_up_db(adb_t *adb, adb_query_spec_t *spec, double **snp, double **vsnp, double **spp, double **vspp, double **mddp, unsigned int *dvp);
+  void set_up_query(adb_query_spec_t *spec, double **qp, double **vqp, adb_qpointers_internal_t *qpointers);
+  void set_up_query_from_key(adb_query_spec_t *spec, double **qp, double **vqp, adb_qpointers_internal_t *qpointers, Uns32T queryIndex);
   void query_loop(adb_query_spec_t *spec, Uns32T queryIndex);
-  void query_loop_points(adb_query_spec_t *spec, double* query, double* qnPtr, double* qpPtr, double meanQdur, Uns32T numVectors);
+  void query_loop_points(adb_query_spec_t *spec, double* query, adb_qpointers_internal_t *qpointers);
   void initRNG();
   void initDBHeader(const char *dbName);
   void initInputFile(const char *inFile, bool loadData = true);
--- a/index.cpp	Wed Dec 24 10:56:01 2008 +0000
+++ b/index.cpp	Wed Dec 24 10:56:07 2008 +0000
@@ -578,10 +578,9 @@
 // return nqv: if index exists
 int audioDB::index_query_loop(adb_query_spec_t *spec, const char* dbName, Uns32T queryIndex) {
   
-  unsigned int numVectors = 0;
   double *query = 0, *query_data = 0;
-  double *qNorm = 0, *qnPtr = 0, *qPower = 0, *qpPtr = 0;
-  double meanQdur = 0;
+  adb_qpointers_internal_t qpointers = {0};
+
   void (*add_point_func)(void*,Uns32T,Uns32T,float);
 
   sequenceLength = spec->qid.sequence_length;
@@ -601,15 +600,15 @@
   char* database = index_get_name(dbName, radius, sequenceLength);
 
   if(query_from_key)
-    set_up_query_from_key(spec, &query_data, &query, &qNorm, &qnPtr, &qPower, &qpPtr, &meanQdur, &numVectors, queryIndex);
+    set_up_query_from_key(spec, &query_data, &query, &qpointers, queryIndex);
   else
-    set_up_query(spec, &query_data, &query, &qNorm, &qnPtr, &qPower, &qpPtr, &meanQdur, &numVectors); // get query vectors
+    set_up_query(spec, &query_data, &query, &qpointers);
 
   VERB_LOG(1, "retrieving tracks...");
   
   gettimeofday(&tv1, NULL);   
   // query vector index
-  Uns32T Nq = (numVectors>O2_MAXTRACKLEN?O2_MAXTRACKLEN:numVectors) - sequenceLength + 1;
+  Uns32T Nq = (qpointers.nvectors>O2_MAXTRACKLEN?O2_MAXTRACKLEN:qpointers.nvectors) - sequenceLength + 1;
   vv = index_initialize_shingles(Nq); // allocate memory to copy query vectors to shingles
   VERB_LOG(1, "Nq=%d", Nq);
   // Construct shingles from query features  
@@ -617,12 +616,12 @@
     index_make_shingle(vv, pointID, query, dbH->dim, sequenceLength);
   
   // Normalize query vectors
-  Uns32T numVecsAboveThreshold = index_norm_shingles( vv, qnPtr, qpPtr );
+  Uns32T numVecsAboveThreshold = index_norm_shingles( vv, qpointers.l2norm, qpointers.power );
   VERB_LOG(1, "Nq'=%d\n", numVecsAboveThreshold);
 
   // Nq contains number of inspected points in query file, 
   // numVecsAboveThreshold is number of points with power >= absolute_threshold
-  double* qpp = qpPtr; // Keep original qpPtr for possible exact evaluation
+  double* qpp = qpointers.power; // Keep original qpPtr for possible exact evaluation
   if(usingQueryPoint && numVecsAboveThreshold){
     if((lsh->get_lshHeader()->flags&O2_SERIAL_FILEFORMAT2) || lsh_in_core)
       lsh->retrieve_point((*vv)[0], queryPoint, add_point_func, (void*)this);
@@ -641,7 +640,7 @@
 
   if(lsh_exact)
     // Perform exact distance computation on point pairs in exact_evaluation_queue
-    query_loop_points(spec, query, qnPtr, qpPtr, meanQdur, numVectors); 
+    query_loop_points(spec, query, &qpointers);
   
   gettimeofday(&tv2,NULL);
   VERB_LOG(1,"elapsed time: %ld msec\n",
@@ -654,10 +653,12 @@
  // Clean up
   if(query_data)
     delete[] query_data;
-  if(qNorm)
-    delete[] qNorm;
-  if(qPower)
-    delete[] qPower;
+  if(qpointers.l2norm_data)
+    delete[] qpointers.l2norm_data;
+  if(qpointers.power_data)
+    delete[] qpointers.power_data;
+  if(qpointers.mean_duration)
+    delete[] qpointers.mean_duration;
   if(database)
     delete[] database;
 
--- a/query.cpp	Wed Dec 24 10:56:01 2008 +0000
+++ b/query.cpp	Wed Dec 24 10:56:07 2008 +0000
@@ -310,58 +310,60 @@
 // are pointers to the query, norm and power vectors; the names
 // starting with "v" are things that will end up pointing to the
 // actual query point's information.  -- CSR, 2007-12-05
-void audioDB::set_up_query(adb_query_spec_t *spec, double **qp, double **vqp, double **qnp, double **vqnp, double **qpp, double **vqpp, double *mqdp, unsigned *nvp) {
-  *nvp = (statbuf.st_size - sizeof(int)) / (dbH->dim * sizeof(double));
+void audioDB::set_up_query(adb_query_spec_t *spec, double **qp, double **vqp, adb_qpointers_internal_t *qpointers) {
+  uint32_t nvectors = (statbuf.st_size - sizeof(int)) / (dbH->dim * sizeof(double));
+  qpointers->nvectors = nvectors;
 
   uint32_t sequence_length = spec->qid.sequence_length;
   if(!(dbH->flags & O2_FLAG_L2NORM)) {
     error("Database must be L2 normed for sequence query","use -L2NORM");
   }
 
-  if(*nvp < sequence_length) {
+  if(nvectors < sequence_length) {
     error("Query shorter than requested sequence length", "maybe use -l");
   }
   
   VERB_LOG(1, "performing norms... ");
 
-  *qp = new double[*nvp * dbH->dim];
-  memcpy(*qp, indata+sizeof(int), *nvp * dbH->dim * sizeof(double));
-  *qnp = new double[*nvp];
-  audiodb_l2norm_buffer(*qp, dbH->dim, *nvp, *qnp);
+  *qp = new double[nvectors * dbH->dim];
+  memcpy(*qp, indata+sizeof(int), nvectors * dbH->dim * sizeof(double));
+  qpointers->l2norm_data = new double[nvectors];
+  audiodb_l2norm_buffer(*qp, dbH->dim, nvectors, qpointers->l2norm_data);
 
-  audiodb_sequence_sum(*qnp, *nvp, sequence_length);
-  audiodb_sequence_sqrt(*qnp, *nvp, sequence_length);
+  audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length);
+  audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length);
 
   if (usingPower) {
-    *qpp = new double[*nvp];
+    qpointers->power_data = new double[nvectors];
     if (lseek(powerfd, sizeof(int), SEEK_SET) == (off_t) -1) {
       error("error seeking to data", powerFileName, "lseek");
     }
-    int count = read(powerfd, *qpp, *nvp * sizeof(double));
+    int count = read(powerfd, qpointers->power_data, nvectors * sizeof(double));
     if (count == -1) {
       error("error reading data", powerFileName, "read");
     }
-    if ((unsigned) count != *nvp * sizeof(double)) {
+    if ((unsigned) count != nvectors * sizeof(double)) {
       error("short read", powerFileName);
     }
 
-    audiodb_sequence_sum(*qpp, *nvp, sequence_length);
-    audiodb_sequence_average(*qpp, *nvp, sequence_length);
+    audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length);
+    audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length);
   }
 
   if (usingTimes) {
     unsigned int k;
-    *mqdp = 0.0;
-    double *querydurs = new double[*nvp];
-    double *timesdata = new double[*nvp*2];
-    insertTimeStamps(*nvp, timesFile, timesdata);
-    for(k = 0; k < *nvp; k++) {
+    qpointers->mean_duration = new double[1];
+    *qpointers->mean_duration = 0.0;
+    double *querydurs = new double[nvectors];
+    double *timesdata = new double[2*nvectors];
+    insertTimeStamps(nvectors, timesFile, timesdata);
+    for(k = 0; k < nvectors; k++) {
       querydurs[k] = timesdata[2*k+1] - timesdata[2*k];
-      *mqdp += querydurs[k];
+      *qpointers->mean_duration += querydurs[k];
     }
-    *mqdp /= k;
+    *qpointers->mean_duration /= k;
 
-    VERB_LOG(1, "mean query file duration: %f\n", *mqdp);
+    VERB_LOG(1, "mean query file duration: %f\n", *qpointers->mean_duration);
 
     delete [] querydurs;
     delete [] timesdata;
@@ -369,27 +371,27 @@
 
   // Defaults, for exhaustive search (!usingQueryPoint)
   *vqp = *qp;
-  *vqnp = *qnp;
-  *vqpp = *qpp;
+  qpointers->l2norm = qpointers->l2norm_data;
+  qpointers->power = qpointers->power_data;
 
   if(usingQueryPoint) {
-    if( !(queryPoint < *nvp && queryPoint < *nvp - sequence_length + 1) ) {
-      error("queryPoint >= numVectors-sequence_length+1 in query");
+    if( !(queryPoint < nvectors && queryPoint < nvectors - sequence_length + 1) ) {
+      error("queryPoint >= nvectors-sequence_length+1 in query");
     } else {
       VERB_LOG(1, "query point: %u\n", queryPoint);
       *vqp = *qp + queryPoint * dbH->dim;
-      *vqnp = *qnp + queryPoint;
+      qpointers->l2norm = qpointers->l2norm_data + queryPoint;
       if (usingPower) {
-        *vqpp = *qpp + queryPoint;
+        qpointers->power = qpointers->power_data + queryPoint;
       }
-      *nvp = sequence_length;
+      qpointers->nvectors = sequence_length;
     }
   }
 }
 
 // Does the same as set_up_query(...) but from database features instead of from a file
 // Constructs the same outputs as set_up_query
-void audioDB::set_up_query_from_key(adb_query_spec_t *spec, double **qp, double **vqp, double **qnp, double **vqnp, double **qpp, double **vqpp, double *mqdp, unsigned *nvp, Uns32T queryIndex) {
+void audioDB::set_up_query_from_key(adb_query_spec_t *spec, double **qp, double **vqp, adb_qpointers_internal_t *qpointers, Uns32T queryIndex) {
   uint32_t sequence_length = spec->qid.sequence_length;
   if(!trackTable)
     error("trackTable not initialized","set_up_query_from_key");
@@ -404,8 +406,9 @@
   if(dbH->flags & O2_FLAG_TIMES)
     usingTimes = true;
 
-  *nvp = trackTable[queryIndex];  
-  if(*nvp < sequence_length) {
+  uint32_t nvectors = trackTable[queryIndex];
+  qpointers->nvectors = nvectors;
+  if(nvectors < sequence_length) {
     error("Query shorter than requested sequence length", "maybe use -l");
   }
   
@@ -426,10 +429,10 @@
     if(audiodb_read_data(adb, infid, queryIndex, qp, &allocatedSize))
       error("failed to read data"); // over-writes qp and allocatedSize
     // Consistency check on allocated memory and query feature size
-    if(*nvp*sizeof(double)*dbH->dim != allocatedSize)
+    if(nvectors*sizeof(double)*dbH->dim != allocatedSize)
       error("Query memory allocation failed consitency check","set_up_query_from_key");
     // Allocated and calculate auxillary sequences: l2norm and power
-    init_track_aux_data(queryIndex, *qp, qnp, vqnp, qpp, vqpp);
+    init_track_aux_data(queryIndex, *qp, &qpointers->l2norm_data, &qpointers->l2norm, &qpointers->power_data, &qpointers->power);
   }
   else{ // Load from self-contained ADB database
     // Read query feature vectors from database
@@ -439,38 +442,39 @@
     if(audiodb_read_data(adb, dbfid, queryIndex, qp, &allocatedSize))
       error("failed to read data");
     // Consistency check on allocated memory and query feature size
-    if(*nvp*sizeof(double)*dbH->dim != allocatedSize)
+    if(nvectors*sizeof(double)*dbH->dim != allocatedSize)
       error("Query memory allocation failed consitency check","set_up_query_from_key");
     
     Uns32T trackIndexOffset = trackOffsetTable[queryIndex]/dbH->dim; // Convert num data elements to num vectors
     // Copy L2 norm partial-sum coefficients
-    assert(*qnp = new double[*nvp]);
-    memcpy(*qnp, l2normTable+trackIndexOffset, *nvp*sizeof(double));
-    audiodb_sequence_sum(*qnp, *nvp, sequence_length);
-    audiodb_sequence_sqrt(*qnp, *nvp, sequence_length);
+    assert(qpointers->l2norm_data = new double[nvectors]);
+    memcpy(qpointers->l2norm_data, l2normTable+trackIndexOffset, nvectors*sizeof(double));
+    audiodb_sequence_sum(qpointers->l2norm_data, nvectors, sequence_length);
+    audiodb_sequence_sqrt(qpointers->l2norm_data, nvectors, sequence_length);
     
     if( usingPower ){
       // Copy Power partial-sum coefficients
-      assert(*qpp = new double[*nvp]);
-      memcpy(*qpp, powerTable+trackIndexOffset, *nvp*sizeof(double));
-      audiodb_sequence_sum(*qpp, *nvp, sequence_length);
-      audiodb_sequence_average(*qpp, *nvp, sequence_length);
+      assert(qpointers->power_data = new double[nvectors]);
+      memcpy(qpointers->power_data, powerTable+trackIndexOffset, nvectors*sizeof(double));
+      audiodb_sequence_sum(qpointers->power_data, nvectors, sequence_length);
+      audiodb_sequence_average(qpointers->power_data, nvectors, sequence_length);
     }
     
     if (usingTimes) {
       unsigned int k;
-      *mqdp = 0.0;
-      double *querydurs = new double[*nvp];
-      double *timesdata = new double[*nvp*2];
+      qpointers->mean_duration = new double[1];
+      *qpointers->mean_duration = 0.0;
+      double *querydurs = new double[nvectors];
+      double *timesdata = new double[nvectors*2];
       assert(querydurs && timesdata);
-      memcpy(timesdata, timesTable+trackIndexOffset, *nvp*sizeof(double));    
-      for(k = 0; k < *nvp; k++) {
+      memcpy(timesdata, timesTable+trackIndexOffset, nvectors*sizeof(double));    
+      for(k = 0; k < nvectors; k++) {
 	querydurs[k] = timesdata[2*k+1] - timesdata[2*k];
-	*mqdp += querydurs[k];
+	*qpointers->mean_duration += querydurs[k];
       }
-      *mqdp /= k;
+      *qpointers->mean_duration /= k;
       
-      VERB_LOG(1, "mean query file duration: %f\n", *mqdp);
+      VERB_LOG(1, "mean query file duration: %f\n", *qpointers->mean_duration);
       
       delete [] querydurs;
       delete [] timesdata;
@@ -479,20 +483,20 @@
 
   // Defaults, for exhaustive search (!usingQueryPoint)
   *vqp = *qp;
-  *vqnp = *qnp;
-  *vqpp = *qpp;
+  qpointers->l2norm = qpointers->l2norm_data;
+  qpointers->power = qpointers->power_data;
 
   if(usingQueryPoint) {
-    if( !(queryPoint < *nvp && queryPoint < *nvp - sequence_length + 1) ) {
-      error("queryPoint >= numVectors-sequence_length+1 in query");
+    if( !(queryPoint < nvectors && queryPoint < nvectors - sequence_length + 1) ) {
+      error("queryPoint >= nvectors-sequence_length+1 in query");
     } else {
       VERB_LOG(1, "query point: %u\n", queryPoint);
       *vqp = *qp + queryPoint * dbH->dim;
-      *vqnp = *qnp + queryPoint;
+      qpointers->l2norm = qpointers->l2norm_data + queryPoint;
       if (usingPower) {
-        *vqpp = *qpp + queryPoint;
+        qpointers->power = qpointers->power_data + queryPoint;
       }
-      *nvp = sequence_length;
+      qpointers->nvectors = sequence_length;
     }
   }
 }
@@ -501,8 +505,11 @@
 // FIXME: this is not the right name; we're not actually setting up
 // the database, but copying various bits of it out of mmap()ed tables
 // in order to reduce seeks.
-int audioDB::set_up_db(adb_t *adb, adb_query_spec_t *spec, double **snp, double **vsnp, double **spp, double **vspp, double **mddp, unsigned int *dvp) {
+static int audiodb_set_up_db(adb_t *adb, adb_query_spec_t *spec, double **snp, double **vsnp, double **spp, double **vspp, double **mddp, unsigned int *dvp) {
   uint32_t sequence_length = spec->qid.sequence_length;
+  bool using_power = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD);
+  bool using_times = spec->refine.flags & ADB_REFINE_DURATION_RATIO;
+  double *times_table = NULL;
 
   *dvp = adb->header->length / (adb->header->dim * sizeof(double));
   *snp = new double[*dvp];
@@ -511,7 +518,7 @@
   lseek(adb->fd, adb->header->l2normTableOffset, SEEK_SET);
   read_or_goto_error(adb->fd, *snp, *dvp * sizeof(double));
 
-  if (usingPower) {
+  if (using_power) {
     if (!(adb->header->flags & O2_FLAG_POWER)) {
       goto error;
     }
@@ -526,33 +533,42 @@
     if(track_length >= sequence_length) {
       audiodb_sequence_sum(snpp, track_length, sequence_length);
       audiodb_sequence_sqrt(snpp, track_length, sequence_length);
-      if (usingPower) {
+      if (using_power) {
 	audiodb_sequence_sum(sppp, track_length, sequence_length);
         audiodb_sequence_average(sppp, track_length, sequence_length);
       }
     }
     snpp += track_length;
-    if (usingPower) {
+    if (using_power) {
       sppp += track_length;
     }
   }
 
-  if (usingTimes) {
+  if (using_times) {
     if(!(adb->header->flags & O2_FLAG_TIMES)) {
-      error("query timestamps provided for non-timed database", dbName);
+      goto error;
     }
 
     *mddp = new double[adb->header->numFiles];
 
+    times_table = (double *) malloc(2 * *dvp * sizeof(double));
+    if(!times_table) {
+      goto error;
+    }
+    lseek(adb->fd, adb->header->timesTableOffset, SEEK_SET);
+    read_or_goto_error(adb->fd, times_table, 2 * *dvp * sizeof(double));
     for(unsigned int k = 0; k < adb->header->numFiles; k++) {
       size_t track_length = (*adb->track_lengths)[k];
       unsigned int j;
       (*mddp)[k] = 0.0;
       for(j = 0; j < track_length; j++) {
-	(*mddp)[k] += timesTable[2*j+1] - timesTable[2*j];
+	(*mddp)[k] += times_table[2*j+1] - times_table[2*j];
       }
       (*mddp)[k] /= j;
     }
+
+    free(times_table);
+    times_table = NULL;
   }
 
   *vsnp = *snp;
@@ -569,6 +585,9 @@
   if(*mddp) {
     delete [] *mddp;
   }
+  if(times_table) {
+    free(times_table);
+  }
   return 1;
   
 }
@@ -587,12 +606,13 @@
 // Postconditions:
 // reporter contains the points and distances that meet the reporter constraints 
 
-void audioDB::query_loop_points(adb_query_spec_t *spec, double* query, double* qnPtr, double* qpPtr, double meanQdur, Uns32T numVectors){ 
+void audioDB::query_loop_points(adb_query_spec_t *spec, double* query, adb_qpointers_internal_t *qpointers) {
   unsigned int dbVectors;
   double *sNorm = 0, *snPtr, *sPower = 0, *spPtr = 0;
   double *meanDBdur = 0;
 
   uint32_t sequence_length = spec->qid.sequence_length;
+  bool power_refine = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD);
 
   // check pre-conditions
   assert(exact_evaluation_queue&&reporter);
@@ -603,7 +623,7 @@
   // FIXME: we more than likely don't need very much of the database
   // so make a new method to build these values per-track or, even better, per-point
   if( !( dbH->flags & O2_FLAG_LARGE_ADB) )
-    if(set_up_db(adb, spec, &sNorm, &snPtr, &sPower, &spPtr, &meanDBdur, &dbVectors)) {
+    if(audiodb_set_up_db(adb, spec, &sNorm, &snPtr, &sPower, &spPtr, &meanDBdur, &dbVectors)) {
       error("failed to set up db");
     }
 
@@ -658,8 +678,8 @@
     Uns32T qPos = usingQueryPoint?0:pp.qpos;// index for query point
     Uns32T sPos = trackIndexOffset+pp.spos; // index into l2norm table
     // Test power thresholds before computing distance
-    if( ( !usingPower || audiodb_powers_acceptable(&spec->refine, qpPtr[qPos], sPower[sPos])) &&
-	( qPos<numVectors-sequence_length+1 && pp.spos<trackTable[pp.trackID]-sequence_length+1 ) ){
+    if( ( (!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers->power[qPos], sPower[sPos])) &&
+	( qPos<qpointers->nvectors-sequence_length+1 && pp.spos<trackTable[pp.trackID]-sequence_length+1 ) ){
       // Non-large ADB track data is loaded inside power test for efficiency
       if( !(dbH->flags & O2_FLAG_LARGE_ADB) && (currentTrack!=pp.trackID) ){
 	// On currentTrack change, allocate and load track data
@@ -670,7 +690,7 @@
       }
       // Compute distance
       dist = audiodb_dot_product(query+qPos*dbH->dim, data_buffer+pp.spos*dbH->dim, dbH->dim*sequence_length);
-      double qn = qnPtr[qPos];
+      double qn = qpointers->l2norm[qPos];
       double sn = sNorm[sPos];
       switch(spec->params.distance) {
       case ADB_DISTANCE_EUCLIDEAN_NORMED:
@@ -699,24 +719,24 @@
 
 void audioDB::query_loop(adb_query_spec_t *spec, Uns32T queryIndex) {
   
-  unsigned int numVectors;
   double *query, *query_data;
-  double *qNorm, *qnPtr, *qPower = 0, *qpPtr = 0;
-  double meanQdur;
+  adb_qpointers_internal_t qpointers = {0};
+
+  bool power_refine = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD);
 
   if( dbH->flags & O2_FLAG_LARGE_ADB )
     error("error: LARGE_ADB requires indexed query");
 
   if(query_from_key)
-    set_up_query_from_key(spec, &query_data, &query, &qNorm, &qnPtr, &qPower, &qpPtr, &meanQdur, &numVectors, queryIndex);
+    set_up_query_from_key(spec, &query_data, &query, &qpointers, queryIndex);
   else
-    set_up_query(spec, &query_data, &query, &qNorm, &qnPtr, &qPower, &qpPtr, &meanQdur, &numVectors);
+    set_up_query(spec, &query_data, &query, &qpointers);
 
   unsigned int dbVectors;
   double *sNorm, *snPtr, *sPower = 0, *spPtr = 0;
   double *meanDBdur = 0;
 
-  if(set_up_db(adb, spec, &sNorm, &snPtr, &sPower, &spPtr, &meanDBdur, &dbVectors)) {
+  if(audiodb_set_up_db(adb, spec, &sNorm, &snPtr, &sPower, &spPtr, &meanDBdur, &dbVectors)) {
     error("failed to set up db");
   }
 
@@ -727,8 +747,8 @@
   double **D = 0;    // Differences query and target 
   double **DD = 0;   // Matched filter distance
 
-  D = new double*[numVectors]; // pre-allocate 
-  DD = new double*[numVectors];
+  D = new double*[qpointers.nvectors]; // pre-allocate 
+  DD = new double*[qpointers.nvectors];
 
   gettimeofday(&tv1, NULL); 
   unsigned processedTracks = 0;
@@ -771,7 +791,7 @@
       }
     }
 
-    trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
+    trackIndexOffset=trackOffset/dbH->dim; // qpointers.nvectors offset
 
     if(audiodb_read_data(adb, dbfid, track, &data_buffer, &data_buffer_size))
       error("failed to read data");
@@ -779,34 +799,35 @@
       
       VERB_LOG(7,"%u.%jd.%u | ", track, (intmax_t) trackIndexOffset, trackTable[track]);
       
-      initialize_arrays(adb, spec, track, numVectors, query, data_buffer, D, DD);
+      initialize_arrays(adb, spec, track, qpointers.nvectors, query, data_buffer, D, DD);
 
       if(spec->refine.flags & ADB_REFINE_DURATION_RATIO) {
-        VERB_LOG(3,"meanQdur=%f meanDBdur=%f\n", meanQdur, meanDBdur[track]);
+        VERB_LOG(3,"meanQdur=%f meanDBdur=%f\n", qpointers.mean_duration[0], meanDBdur[track]);
       }
 
-      if((!(spec->refine.flags & ADB_REFINE_DURATION_RATIO)) || fabs(meanDBdur[track]-meanQdur) < meanQdur*spec->refine.duration_ratio) {
+      if((!(spec->refine.flags & ADB_REFINE_DURATION_RATIO)) || 
+         fabs(meanDBdur[track]-qpointers.mean_duration[0]) < qpointers.mean_duration[0]*spec->refine.duration_ratio) {
         if(spec->refine.flags & ADB_REFINE_DURATION_RATIO) {
           VERB_LOG(3,"within duration tolerance.\n");
         }
 
 	// Search for minimum distance by shingles (concatenated vectors)
-	for(j = 0; j <= numVectors - wL; j += HOP_SIZE) {
+	for(j = 0; j <= qpointers.nvectors - wL; j += HOP_SIZE) {
 	  for(k = 0; k <= trackTable[track] - wL; k += HOP_SIZE) {
             double thisDist = 0;
             switch(spec->params.distance) {
             case ADB_DISTANCE_EUCLIDEAN_NORMED:
-              thisDist = 2-(2/(qnPtr[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
+              thisDist = 2-(2/(qpointers.l2norm[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
               break;
             case ADB_DISTANCE_EUCLIDEAN:
-              thisDist = qnPtr[j]*qnPtr[j]+sNorm[trackIndexOffset+k]*sNorm[trackIndexOffset+k] - 2*DD[j][k];
+              thisDist = qpointers.l2norm[j]*qpointers.l2norm[j]+sNorm[trackIndexOffset+k]*sNorm[trackIndexOffset+k] - 2*DD[j][k];
               break;
             case ADB_DISTANCE_DOT_PRODUCT:
               thisDist = DD[j][k];
               break;
             }
 	    // Power test
-	    if ((!usingPower) || audiodb_powers_acceptable(&spec->refine, qpPtr[j], sPower[trackIndexOffset + k])) {
+	    if ((!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers.power[j], sPower[trackIndexOffset + k])) {
               // radius test
               if((!(spec->refine.flags & ADB_REFINE_RADIUS)) || 
                  thisDist <= (spec->refine.radius+O2_DISTANCE_TOLERANCE)) {
@@ -821,7 +842,7 @@
           }
         }
       } // Duration match            
-      audiodb_delete_arrays(track, numVectors, D, DD);
+      audiodb_delete_arrays(track, qpointers.nvectors, D, DD);
     }
   }
 
@@ -835,12 +856,14 @@
   // Clean up
   if(query_data)
     delete[] query_data;
-  if(qNorm)
-    delete[] qNorm;
+  if(qpointers.l2norm_data)
+    delete[] qpointers.l2norm_data;
+  if(qpointers.power_data)
+    delete[] qpointers.power_data;
+  if(qpointers.mean_duration)
+    delete[] qpointers.mean_duration;
   if(sNorm)
     delete[] sNorm;
-  if(qPower)
-    delete[] qPower;
   if(sPower)
     delete[] sPower;
   if(D)