Mercurial > hg > audiodb
changeset 726:fe2282b9bfb0
Initial querying: doesn't return results yet, but handles almost all params.
author | mas01mj |
---|---|
date | Mon, 26 Jul 2010 13:19:09 +0000 |
parents | 7e1fa27b67ee |
children | 4d9e4ff0a9cd |
files | bindings/java/ext/libAudioDB_JNI.c bindings/java/src/org/omras2/AudioDB.java bindings/java/src/org/omras2/Query.java bindings/java/test/TestQuery.java |
diffstat | 4 files changed, 210 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/bindings/java/ext/libAudioDB_JNI.c Wed Jul 21 14:27:07 2010 +0000 +++ b/bindings/java/ext/libAudioDB_JNI.c Mon Jul 26 13:19:09 2010 +0000 @@ -5,6 +5,7 @@ #include "audioDB_API.h" #include <stdlib.h> #include <fcntl.h> +#include <string.h> // Following Ben's lead here! #define ADB_HEADER_FLAG_L2NORM 0x1 @@ -12,6 +13,46 @@ #define ADB_HEADER_FLAG_TIMES 0x20 #define ADB_HEADER_FLAG_REFERENCES 0x40 +double get_int_val(JNIEnv *env, jclass classValue, jobject objectValue, char* field, int defaultValue) +{ + jfieldID fid = (*env)->GetFieldID(env, classValue, field, "I"); + if(fid == NULL) return defaultValue; + int val = (*env)->GetIntField(env, objectValue, fid); + return (val ? val : defaultValue); +} + +double get_double_val(JNIEnv *env, jclass classValue, jobject objectValue, char* field, double defaultValue) +{ + jfieldID fid = (*env)->GetFieldID(env, classValue, field, "D"); + if(fid == NULL) return defaultValue; + double val = (*env)->GetDoubleField(env, objectValue, fid); + return (val ? val : defaultValue); +} + +const char* get_enum_val(JNIEnv *env, jclass queryClass, jobject queryObject, char* fieldName, char* enumClassName) +{ + char signature[strlen(enumClassName)+2]; + sprintf(signature, "L%s;", enumClassName); + + // Get the value of the enum field + jfieldID fid = (*env)->GetFieldID(env, queryClass, fieldName, signature); + if(fid == NULL) return; + + jobject field = (*env)->GetObjectField(env, queryObject, fid); + if(field == NULL) return; + + // Retrieve the string value via name() + jclass enumClass = (*env)->FindClass(env, enumClassName); + if(enumClass == NULL) return; + + jmethodID getNameMethod = (*env)->GetMethodID(env, enumClass, "name", "()Ljava/lang/String;"); + if(getNameMethod == NULL) return; + + jstring value = (jstring)((*env)->CallObjectMethod(env, field, getNameMethod)); + if(value == NULL) return; + + return (*env)->GetStringUTFChars(env, value, 0); +} adb_t* get_handle(JNIEnv *env, jobject obj) { @@ -51,9 +92,7 @@ { // TODO: If we have a handle, close the old one. if(get_handle(env, obj)) - { return; - } jclass modeClass = (*env)->FindClass(env, "org/omras2/AudioDB$Mode"); jmethodID getNameMethod = (*env)->GetMethodID(env, modeClass, "name", "()Ljava/lang/String;"); @@ -205,3 +244,126 @@ return result; } +JNIEXPORT void JNICALL Java_org_omras2_AudioDB_audiodb_1query_1by_1key(JNIEnv *env, jobject adbobj, jstring key, jobject queryObject) +{ + adb_t* handle = get_handle(env, adbobj); + + if(!handle) + return; + + const char* keyStr = (*env)->GetStringUTFChars(env, key, NULL); + if (keyStr == NULL) + return; + + adb_query_spec_t* spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t)); + spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t)); + adb_query_results_t* result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t)); + + // As in python bindings + spec->refine.flags = 0; + + jclass queryClass = (*env)->GetObjectClass(env, queryObject); + + spec->qid.sequence_length = get_int_val(env, queryClass, queryObject, "seqLength", 16); + spec->qid.sequence_start = get_int_val(env, queryClass, queryObject, "seqStart", 0); + spec->params.npoints = get_int_val(env, queryClass, queryObject, "npoints", 1); + spec->params.ntracks = get_int_val(env, queryClass, queryObject, "ntracks", 100); + + jfieldID fid = (*env)->GetFieldID(env, queryClass, "exhaustive", "Z"); + if(fid == NULL) return; + if((*env)->GetBooleanField(env, queryObject, fid)) { + spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE; + } + + fid = (*env)->GetFieldID(env, queryClass, "hasFalsePositives", "Z"); + if(fid == NULL) return; + if((*env)->GetBooleanField(env, queryObject, fid)) { + spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_ALLOW_FALSE_POSITIVES; + } + + const char* accType = get_enum_val(env, queryClass, queryObject, "accumulation", "org/omras2/Query$Accumulation"); + const char* distType = get_enum_val(env, queryClass, queryObject, "distance", "org/omras2/Query$Distance"); + + if(strcmp(accType, "DB") == 0) + spec->params.accumulation = ADB_ACCUMULATION_DB; + else if(strcmp(accType, "PER_TRACK") == 0) + spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK; + else if(strcmp(accType, "ONE_TO_ONE") == 0) + spec->params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE; + else { + printf("Invalid acc\n"); + return; + } + + if(strcmp(distType, "DOT_PRODUCT") == 0) + spec->params.distance = ADB_DISTANCE_DOT_PRODUCT; + else if(strcmp(distType, "EUCLIDEAN_NORMED") == 0) + spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; + else if(strcmp(distType, "EUCLIDEAN") == 0) + spec->params.distance = ADB_DISTANCE_EUCLIDEAN; + else { + printf("Invalid dist\n"); + return; + } + + // Rest of refine + + double radius = get_double_val(env, queryClass, queryObject, "radius", 0); + double absThres = get_double_val(env, queryClass, queryObject, "absThres", 0); + double relThres = get_double_val(env, queryClass, queryObject, "relThres", 0); + double durRatio = get_double_val(env, queryClass, queryObject, "durRatio", 0); + int hopSize = get_int_val(env, queryClass, queryObject, "hopSize", 0); + + if(radius) { + spec->refine.flags |= ADB_REFINE_RADIUS; + spec->refine.radius = radius; + } + + if(absThres) { + spec->refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD; + spec->refine.absolute_threshold = absThres; + } + + if(relThres) { + spec->refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD; + spec->refine.relative_threshold = relThres; + } + + if(durRatio) { + spec->refine.flags |= ADB_REFINE_DURATION_RATIO; + spec->refine.duration_ratio = durRatio; + } + + if(hopSize) { + spec->refine.flags |= ADB_REFINE_HOP_SIZE; + spec->refine.qhopsize = hopSize; + spec->refine.ihopsize = hopSize; + } + + spec->qid.datum->data = NULL; + spec->qid.datum->power = NULL; + spec->qid.datum->times = NULL; + + printf("seq length: %d seq start: %d points: %d tracks: %d\n", + spec->qid.sequence_length, + spec->qid.sequence_start, + spec->params.npoints, + spec->params.ntracks); + printf("Radius: %f Abs: %f Rel: %f Dur: %f Hop: %d\n", radius, absThres, relThres, durRatio, hopSize); + printf("Key: %s Acc: %s Dist: %s\n", keyStr, accType, distType); + + int ok = audiodb_retrieve_datum(handle, keyStr, spec->qid.datum); + if(ok != 0) { + printf("No datum\n"); + return; + } + result = audiodb_query_spec(handle, spec); + + if(result == NULL) { + printf("No result\n"); + return; + } + printf("OK: %d\n", ok); + (*env)->DeleteLocalRef(env, queryClass); +} +
--- a/bindings/java/src/org/omras2/AudioDB.java Wed Jul 21 14:27:07 2010 +0000 +++ b/bindings/java/src/org/omras2/AudioDB.java Mon Jul 26 13:19:09 2010 +0000 @@ -9,7 +9,7 @@ public native void audiodb_close(); public native Status audiodb_status(); public native boolean audiodb_insert_path(String key, String features, String power, String times); -// public native void query(); + public native void audiodb_query_by_key(String key, Query config); public enum Mode { O_RDONLY, O_RDWR } @@ -41,7 +41,6 @@ return audiodb_insert_path(key, features.getPath(), (power == null ? null : power.getPath()), (times == null ? null : times.getPath())); } - public boolean create(int datasize, int ntracks, int datadim) { return audiodb_create(path.toString(), datasize, ntracks, datadim); @@ -52,6 +51,11 @@ return audiodb_open(path.toString(), mode); } + public void query(String key, Query config) + { + audiodb_query_by_key(key, config); + } + public Status getStatus() { return audiodb_status();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bindings/java/src/org/omras2/Query.java Mon Jul 26 13:19:09 2010 +0000 @@ -0,0 +1,35 @@ +package org.omras2; +import lombok.Getter; +import lombok.Setter; + +public class Query +{ + public enum Accumulation { DB, PER_TRACK, ONE_TO_ONE }; + public enum Distance { DOT, EUCLIDEAN_NORMED, EUCLIDEAN }; + + @Getter @Setter private int seqLength; + @Getter @Setter private int seqStart; + @Getter @Setter private int npoints; + @Getter @Setter private int ntracks; + @Getter @Setter private int hopSize; + + @Getter @Setter private boolean exhaustive; + @Getter @Setter private boolean hasFalsePositives; + @Getter @Setter private Accumulation accumulation; + @Getter @Setter private Distance distance; + + @Getter @Setter private String[] includeKeys = {}; + @Getter @Setter private String[] excludeKeys = {}; + + @Getter @Setter private double radius; + @Getter @Setter private double absThres; + @Getter @Setter private double relThres; + @Getter @Setter private double durRatio; + + public Query() + { + accumulation = Accumulation.PER_TRACK; + distance = Distance.EUCLIDEAN_NORMED; + } + +}
--- a/bindings/java/test/TestQuery.java Wed Jul 21 14:27:07 2010 +0000 +++ b/bindings/java/test/TestQuery.java Mon Jul 26 13:19:09 2010 +0000 @@ -27,6 +27,11 @@ testDB.open(AudioDB.Mode.O_RDONLY); Status status = testDB.getStatus(); assertEquals("Two features", 2, status.getNumFiles()); + + Query query = new Query(); + query.setSeqLength(1); + query.setSeqStart(0); + testDB.query("feat1", query); } }