mas01mj@725: #include mas01mj@722: #include "org_omras2_AudioDB.h" mas01mj@722: #include "org_omras2_AudioDB_Mode.h" mas01mj@722: #include mas01mj@722: #include "audioDB_API.h" mas01mj@724: #include mas01mj@725: #include mas01mj@726: #include mas01mj@725: mas01mj@725: // Following Ben's lead here! mas01mj@725: #define ADB_HEADER_FLAG_L2NORM 0x1 mas01mj@725: #define ADB_HEADER_FLAG_POWER 0x4 mas01mj@725: #define ADB_HEADER_FLAG_TIMES 0x20 mas01mj@725: #define ADB_HEADER_FLAG_REFERENCES 0x40 mas01mj@725: mas01mj@729: jdoubleArray get_double_array(JNIEnv *env, jclass classValue, jobject objectValue, char* field) mas01mj@729: { mas01mj@729: jfieldID fid = (*env)->GetFieldID(env, classValue, field, "[D"); mas01mj@729: if(fid == NULL) return NULL; mas01mj@729: jdoubleArray arr = (*env)->GetObjectField(env, objectValue, fid); mas01mj@729: return arr; mas01mj@729: } mas01mj@729: mas01mj@729: int get_int_val(JNIEnv *env, jclass classValue, jobject objectValue, char* field, int defaultValue) mas01mj@726: { mas01mj@726: jfieldID fid = (*env)->GetFieldID(env, classValue, field, "I"); mas01mj@726: if(fid == NULL) return defaultValue; mas01mj@726: int val = (*env)->GetIntField(env, objectValue, fid); mas01mj@726: return (val ? val : defaultValue); mas01mj@726: } mas01mj@726: mas01mj@726: double get_double_val(JNIEnv *env, jclass classValue, jobject objectValue, char* field, double defaultValue) mas01mj@726: { mas01mj@726: jfieldID fid = (*env)->GetFieldID(env, classValue, field, "D"); mas01mj@726: if(fid == NULL) return defaultValue; mas01mj@726: double val = (*env)->GetDoubleField(env, objectValue, fid); mas01mj@726: return (val ? val : defaultValue); mas01mj@726: } mas01mj@726: mas01mj@726: const char* get_enum_val(JNIEnv *env, jclass queryClass, jobject queryObject, char* fieldName, char* enumClassName) mas01mj@726: { mas01mj@726: char signature[strlen(enumClassName)+2]; mas01mj@726: sprintf(signature, "L%s;", enumClassName); mas01mj@726: mas01mj@726: // Get the value of the enum field mas01mj@726: jfieldID fid = (*env)->GetFieldID(env, queryClass, fieldName, signature); mas01mj@726: if(fid == NULL) return; mas01mj@726: mas01mj@726: jobject field = (*env)->GetObjectField(env, queryObject, fid); mas01mj@726: if(field == NULL) return; mas01mj@726: mas01mj@726: // Retrieve the string value via name() mas01mj@726: jclass enumClass = (*env)->FindClass(env, enumClassName); mas01mj@726: if(enumClass == NULL) return; mas01mj@726: mas01mj@726: jmethodID getNameMethod = (*env)->GetMethodID(env, enumClass, "name", "()Ljava/lang/String;"); mas01mj@726: if(getNameMethod == NULL) return; mas01mj@726: mas01mj@726: jstring value = (jstring)((*env)->CallObjectMethod(env, field, getNameMethod)); mas01mj@726: if(value == NULL) return; mas01mj@726: mas01mj@726: return (*env)->GetStringUTFChars(env, value, 0); mas01mj@726: } mas01mj@725: mas01mj@725: adb_t* get_handle(JNIEnv *env, jobject obj) mas01mj@725: { mas01mj@725: // Fetch the adb pointer mas01mj@725: mas01mj@725: adb_t *handle; mas01mj@725: mas01mj@725: jclass adbClass = (*env)->GetObjectClass(env, obj); mas01mj@725: jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J"); mas01mj@725: if(fid == NULL) { mas01mj@725: return; mas01mj@725: } mas01mj@725: mas01mj@725: handle = (adb_t*)((*env)->GetLongField(env, obj, fid)); mas01mj@725: (*env)->DeleteLocalRef(env, adbClass); mas01mj@725: return handle; mas01mj@725: } mas01mj@722: mas01mj@722: JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1create (JNIEnv *env, jobject obj, jstring path, jint datasize, jint ntracks, jint datadim) mas01mj@722: { mas01mj@722: char buf[256]; mas01mj@722: const char *str; mas01mj@722: str = (*env)->GetStringUTFChars(env, path, NULL); mas01mj@722: if (str == NULL) mas01mj@722: return; mas01mj@722: mas01mj@722: adb_t *handle; mas01mj@722: handle = audiodb_create(str, datasize, ntracks, datadim); mas01mj@722: if(!handle) mas01mj@722: return JNI_FALSE; mas01mj@724: mas01mj@725: (*env)->ReleaseStringUTFChars(env, path, str); mas01mj@725: return JNI_TRUE; mas01mj@725: } mas01mj@725: mas01mj@725: JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1open (JNIEnv *env, jobject obj, jstring path, jobject mode) mas01mj@725: { mas01mj@725: // TODO: If we have a handle, close the old one. mas01mj@725: if(get_handle(env, obj)) mas01mj@725: return; mas01mj@725: mas01mj@725: jclass modeClass = (*env)->FindClass(env, "org/omras2/AudioDB$Mode"); mas01mj@725: jmethodID getNameMethod = (*env)->GetMethodID(env, modeClass, "name", "()Ljava/lang/String;"); mas01mj@725: jstring value = (jstring)(*env)->CallObjectMethod(env, mode, getNameMethod); mas01mj@725: const char* openMode = (*env)->GetStringUTFChars(env, value, 0); mas01mj@725: const char* pathVal = (*env)->GetStringUTFChars(env, path, 0); mas01mj@725: int modeVal = 0; mas01mj@725: if(strcmp(openMode, "O_RDWR") == 0) mas01mj@725: { mas01mj@725: modeVal = O_RDWR; mas01mj@725: } mas01mj@725: else if(strcmp(openMode, "O_RDONLY") == 0) mas01mj@725: { mas01mj@725: modeVal = O_RDONLY; mas01mj@725: } mas01mj@725: else mas01mj@725: return; mas01mj@725: mas01mj@725: adb_t *handle; mas01mj@725: handle = audiodb_open(pathVal, modeVal); mas01mj@724: jclass adbClass = (*env)->GetObjectClass(env, obj); mas01mj@724: jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J"); mas01mj@724: if(fid == NULL) { mas01mj@724: return; mas01mj@724: } mas01mj@724: (*env)->SetLongField(env, obj, fid, (long)handle); mas01mj@724: (*env)->DeleteLocalRef(env, adbClass); mas01mj@722: mas01mj@722: return JNI_TRUE; mas01mj@722: } mas01mj@722: mas01mj@725: JNIEXPORT void JNICALL Java_org_omras2_AudioDB_audiodb_1close (JNIEnv *env, jobject obj) mas01mj@722: { mas01mj@725: adb_t *handle = get_handle(env, obj); mas01mj@725: if(!handle) mas01mj@725: return; mas01mj@725: mas01mj@725: audiodb_close(handle); mas01mj@725: mas01mj@725: jclass adbClass = (*env)->GetObjectClass(env, obj); mas01mj@725: jfieldID fid = (*env)->GetFieldID(env, adbClass, "adbHandle", "J"); mas01mj@725: mas01mj@725: if(fid == NULL) { mas01mj@725: return; mas01mj@725: } mas01mj@725: mas01mj@725: (*env)->SetLongField(env, obj, fid, 0); mas01mj@725: (*env)->DeleteLocalRef(env, adbClass); mas01mj@725: } mas01mj@725: mas01mj@728: JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1insert_1data(JNIEnv *env, jobject obj, jstring key, int nvectors, int dim, jdoubleArray features, jdoubleArray power, jdoubleArray times) mas01mj@728: { mas01mj@728: adb_t *handle = get_handle(env, obj); mas01mj@728: if(!handle) mas01mj@728: return JNI_FALSE; mas01mj@728: mas01mj@728: adb_datum_t* ins = (adb_datum_t *)malloc(sizeof(adb_datum_t)); mas01mj@728: if(!features || !key) mas01mj@728: return JNI_FALSE; mas01mj@728: mas01mj@728: ins->data = (*env)->GetDoubleArrayElements(env, features, NULL); mas01mj@728: ins->power = NULL; mas01mj@728: ins->times = NULL; mas01mj@728: mas01mj@728: if(power) mas01mj@728: ins->power = (*env)->GetDoubleArrayElements(env, power, NULL); mas01mj@728: if(times) mas01mj@728: ins->times = (*env)->GetDoubleArrayElements(env, times, NULL); mas01mj@728: mas01mj@728: ins->key = (*env)->GetStringUTFChars(env, key, 0); mas01mj@728: ins->nvectors = nvectors; mas01mj@728: ins->dim = dim; mas01mj@728: mas01mj@728: int result = audiodb_insert_datum(handle, ins); mas01mj@728: if(result) mas01mj@728: return JNI_FALSE; mas01mj@728: mas01mj@728: return JNI_TRUE; mas01mj@728: } mas01mj@728: mas01mj@725: JNIEXPORT jboolean JNICALL Java_org_omras2_AudioDB_audiodb_1insert_1path(JNIEnv *env, jobject obj, jstring key, jstring features, jstring power, jstring times) mas01mj@725: { mas01mj@725: adb_t *handle = get_handle(env, obj); mas01mj@725: if(!handle) mas01mj@725: return JNI_FALSE; mas01mj@725: mas01mj@725: adb_insert_t* ins = (adb_insert_t *)malloc(sizeof(adb_insert_t)); mas01mj@725: ins->key = NULL; mas01mj@725: ins->features = NULL; mas01mj@725: ins->power = NULL; mas01mj@725: ins->times = NULL; mas01mj@725: mas01mj@725: if(key) mas01mj@725: ins->key = (*env)->GetStringUTFChars(env, key, 0); mas01mj@725: if(features) mas01mj@725: ins->features = (*env)->GetStringUTFChars(env, features, 0); mas01mj@725: if(power) mas01mj@725: ins->power = (*env)->GetStringUTFChars(env, power, 0); mas01mj@725: if(times) mas01mj@725: ins->times = (*env)->GetStringUTFChars(env, times, 0); mas01mj@725: mas01mj@725: int result = audiodb_insert(handle, ins); mas01mj@725: mas01mj@725: if(result) mas01mj@725: return JNI_FALSE; mas01mj@725: mas01mj@725: return JNI_TRUE; mas01mj@722: } mas01mj@722: mas01mj@722: JNIEXPORT void JNICALL Java_org_omras2_AudioDB_query(JNIEnv *env, jobject obj) mas01mj@722: { mas01mj@722: } mas01mj@722: mas01mj@724: JNIEXPORT jobject JNICALL Java_org_omras2_AudioDB_audiodb_1status(JNIEnv *env, jobject obj) mas01mj@722: { mas01mj@725: adb_t *handle = get_handle(env, obj); mas01mj@725: if(!handle) mas01mj@725: return NULL; mas01mj@724: adb_status_t *status; mas01mj@724: status = (adb_status_t *)malloc(sizeof(adb_status_t)); mas01mj@724: int flags = audiodb_status(handle, status); mas01mj@724: mas01mj@724: jclass statusClass = (*env)->FindClass(env, "org/omras2/Status"); mas01mj@724: if(statusClass == NULL) { mas01mj@724: return NULL; mas01mj@724: } mas01mj@724: jmethodID cid = (*env)->GetMethodID(env, statusClass, "", "()V"); mas01mj@724: if(cid == NULL) { mas01mj@724: return NULL; mas01mj@724: } mas01mj@724: mas01mj@724: jobject result = (*env)->NewObject(env, statusClass, cid); mas01mj@724: mas01mj@725: // This needs a macro! mas01mj@725: jfieldID fid = (*env)->GetFieldID(env, statusClass, "numFiles", "I"); mas01mj@725: if(fid == NULL) return; mas01mj@724: (*env)->SetIntField(env, result, fid, status->numFiles); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "dim", "I"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetIntField(env, result, fid, status->dim); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "dudCount", "I"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetIntField(env, result, fid, status->dudCount); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "nullCount", "I"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetIntField(env, result, fid, status->nullCount); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "length", "I"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetIntField(env, result, fid, status->length); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "dataRegionSize", "I"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetIntField(env, result, fid, status->data_region_size); mas01mj@725: mas01mj@725: // Flags mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "isL2Normed", "Z"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_L2NORM)); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "hasPower", "Z"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_POWER)); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "hasTimes", "Z"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_TIMES)); mas01mj@725: mas01mj@725: fid = (*env)->GetFieldID(env, statusClass, "hasReferences", "Z"); mas01mj@725: if(fid == NULL) return; mas01mj@725: (*env)->SetBooleanField(env, result, fid, (status->flags & ADB_HEADER_FLAG_REFERENCES)); mas01mj@724: mas01mj@724: (*env)->DeleteLocalRef(env, statusClass); mas01mj@724: mas01mj@724: return result; mas01mj@722: } mas01mj@722: mas01mj@727: jobject build_results(JNIEnv *env, adb_query_results_t *result) mas01mj@727: { mas01mj@727: int i; mas01mj@727: // Create a vector mas01mj@727: jclass vectorClass = (*env)->FindClass(env, "java/util/Vector"); mas01mj@727: if(vectorClass == NULL) return; mas01mj@727: jmethodID vectorCtor = (*env)->GetMethodID(env, vectorClass, "", "()V"); mas01mj@727: if(vectorCtor == NULL) return; mas01mj@727: jobject vector = (*env)->NewObject(env, vectorClass, vectorCtor); mas01mj@727: mas01mj@727: jmethodID addElementMethod = (*env)->GetMethodID(env, vectorClass, "addElement", "(Ljava/lang/Object;)V"); mas01mj@727: if(addElementMethod == NULL) return; mas01mj@727: mas01mj@727: jclass resultClass = (*env)->FindClass(env, "org/omras2/Result"); mas01mj@727: if(resultClass == NULL) return; mas01mj@727: jmethodID resultCtor = (*env)->GetMethodID(env, resultClass, "", "(Ljava/lang/String;DII)V"); mas01mj@727: if(resultCtor == NULL) return; mas01mj@727: mas01mj@727: for(i=0; inresults; i++) mas01mj@727: { mas01mj@727: jstring keyStr = (*env)->NewStringUTF(env, result->results[i].ikey); mas01mj@727: jobject resultObj = (*env)->NewObject(env, resultClass, resultCtor, mas01mj@727: keyStr, mas01mj@727: (double)(result->results[i].dist), mas01mj@727: (int)(result->results[i].qpos), mas01mj@727: (int)(result->results[i].ipos)); mas01mj@727: mas01mj@727: (*env)->CallObjectMethod(env, vector, addElementMethod, resultObj); mas01mj@727: mas01mj@727: } mas01mj@727: (*env)->DeleteLocalRef(env, resultClass); mas01mj@727: (*env)->DeleteLocalRef(env, vectorClass); mas01mj@727: return vector; mas01mj@727: } mas01mj@727: mas01mj@729: JNIEXPORT jobject JNICALL Java_org_omras2_AudioDB_audiodb_1query(JNIEnv *env, jobject adbobj, jstring key, jobject queryObject) mas01mj@726: { mas01mj@726: adb_t* handle = get_handle(env, adbobj); mas01mj@726: mas01mj@726: if(!handle) mas01mj@726: return; mas01mj@726: mas01mj@729: jclass queryClass = (*env)->GetObjectClass(env, queryObject); mas01mj@726: mas01mj@729: jclass datumClass = (*env)->FindClass(env, "org/omras2/Datum"); mas01mj@729: jfieldID datumFid = (*env)->GetFieldID(env, queryClass, "datum", "Lorg/omras2/Datum;"); mas01mj@729: if(datumFid == NULL) return; mas01mj@729: mas01mj@729: jobject datumObject = (*env)->GetObjectField(env, queryObject, datumFid); mas01mj@729: if(datumObject == NULL) return; mas01mj@729: mas01mj@726: adb_query_spec_t* spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t)); mas01mj@726: spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t)); mas01mj@726: adb_query_results_t* result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t)); mas01mj@726: mas01mj@726: // As in python bindings mas01mj@726: spec->refine.flags = 0; mas01mj@726: mas01mj@726: spec->qid.sequence_length = get_int_val(env, queryClass, queryObject, "seqLength", 16); mas01mj@726: spec->qid.sequence_start = get_int_val(env, queryClass, queryObject, "seqStart", 0); mas01mj@726: spec->params.npoints = get_int_val(env, queryClass, queryObject, "npoints", 1); mas01mj@726: spec->params.ntracks = get_int_val(env, queryClass, queryObject, "ntracks", 100); mas01mj@726: mas01mj@726: jfieldID fid = (*env)->GetFieldID(env, queryClass, "exhaustive", "Z"); mas01mj@726: if(fid == NULL) return; mas01mj@726: if((*env)->GetBooleanField(env, queryObject, fid)) { mas01mj@726: spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE; mas01mj@726: } mas01mj@726: mas01mj@726: fid = (*env)->GetFieldID(env, queryClass, "hasFalsePositives", "Z"); mas01mj@726: if(fid == NULL) return; mas01mj@726: if((*env)->GetBooleanField(env, queryObject, fid)) { mas01mj@726: spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_ALLOW_FALSE_POSITIVES; mas01mj@726: } mas01mj@726: mas01mj@726: const char* accType = get_enum_val(env, queryClass, queryObject, "accumulation", "org/omras2/Query$Accumulation"); mas01mj@726: const char* distType = get_enum_val(env, queryClass, queryObject, "distance", "org/omras2/Query$Distance"); mas01mj@726: mas01mj@726: if(strcmp(accType, "DB") == 0) mas01mj@726: spec->params.accumulation = ADB_ACCUMULATION_DB; mas01mj@726: else if(strcmp(accType, "PER_TRACK") == 0) mas01mj@726: spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK; mas01mj@726: else if(strcmp(accType, "ONE_TO_ONE") == 0) mas01mj@726: spec->params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE; mas01mj@726: else { mas01mj@726: return; mas01mj@726: } mas01mj@726: mas01mj@726: if(strcmp(distType, "DOT_PRODUCT") == 0) mas01mj@726: spec->params.distance = ADB_DISTANCE_DOT_PRODUCT; mas01mj@726: else if(strcmp(distType, "EUCLIDEAN_NORMED") == 0) mas01mj@726: spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; mas01mj@726: else if(strcmp(distType, "EUCLIDEAN") == 0) mas01mj@726: spec->params.distance = ADB_DISTANCE_EUCLIDEAN; mas01mj@726: else { mas01mj@726: return; mas01mj@726: } mas01mj@726: mas01mj@727: int i; mas01mj@727: mas01mj@727: fid = (*env)->GetFieldID(env, queryClass, "includeKeys", "[Ljava/lang/String;"); mas01mj@727: if(fid == NULL) return; mas01mj@727: jobjectArray includeObj = (jobjectArray)((*env)->GetObjectField(env, queryObject, fid)); mas01mj@727: jsize len = (*env)->GetArrayLength(env, includeObj); mas01mj@727: mas01mj@727: if(len > 0) mas01mj@727: { mas01mj@727: spec->refine.flags |= ADB_REFINE_INCLUDE_KEYLIST; mas01mj@727: spec->refine.include.nkeys = len; mas01mj@727: spec->refine.include.keys = (const char **)calloc(sizeof(const char *), spec->refine.include.nkeys); mas01mj@727: for(i=0; irefine.include.nkeys; i++) { mas01mj@727: jstring key = (*env)->GetObjectArrayElement(env, includeObj, i); mas01mj@727: spec->refine.include.keys[i] = (*env)->GetStringUTFChars(env, key, NULL); mas01mj@727: } mas01mj@727: } mas01mj@727: mas01mj@727: fid = (*env)->GetFieldID(env, queryClass, "excludeKeys", "[Ljava/lang/String;"); mas01mj@727: if(fid == NULL) return; mas01mj@727: jobjectArray excludeObj = (jobjectArray)((*env)->GetObjectField(env, queryObject, fid)); mas01mj@727: len = (*env)->GetArrayLength(env, excludeObj); mas01mj@727: mas01mj@727: if(len > 0) mas01mj@727: { mas01mj@727: spec->refine.flags |= ADB_REFINE_EXCLUDE_KEYLIST; mas01mj@727: spec->refine.exclude.nkeys = len; mas01mj@727: spec->refine.exclude.keys = (const char **)calloc(sizeof(const char *), spec->refine.exclude.nkeys); mas01mj@727: for(i=0; irefine.exclude.nkeys; i++) { mas01mj@727: jstring key = (*env)->GetObjectArrayElement(env, excludeObj, i); mas01mj@727: spec->refine.exclude.keys[i] = (*env)->GetStringUTFChars(env, key, NULL); mas01mj@727: } mas01mj@727: } mas01mj@727: mas01mj@726: // Rest of refine mas01mj@726: mas01mj@726: double radius = get_double_val(env, queryClass, queryObject, "radius", 0); mas01mj@726: double absThres = get_double_val(env, queryClass, queryObject, "absThres", 0); mas01mj@726: double relThres = get_double_val(env, queryClass, queryObject, "relThres", 0); mas01mj@726: double durRatio = get_double_val(env, queryClass, queryObject, "durRatio", 0); mas01mj@726: int hopSize = get_int_val(env, queryClass, queryObject, "hopSize", 0); mas01mj@726: mas01mj@726: if(radius) { mas01mj@726: spec->refine.flags |= ADB_REFINE_RADIUS; mas01mj@726: spec->refine.radius = radius; mas01mj@726: } mas01mj@726: mas01mj@726: if(absThres) { mas01mj@726: spec->refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD; mas01mj@726: spec->refine.absolute_threshold = absThres; mas01mj@726: } mas01mj@726: mas01mj@726: if(relThres) { mas01mj@726: spec->refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD; mas01mj@726: spec->refine.relative_threshold = relThres; mas01mj@726: } mas01mj@726: mas01mj@726: if(durRatio) { mas01mj@726: spec->refine.flags |= ADB_REFINE_DURATION_RATIO; mas01mj@726: spec->refine.duration_ratio = durRatio; mas01mj@726: } mas01mj@726: mas01mj@726: if(hopSize) { mas01mj@726: spec->refine.flags |= ADB_REFINE_HOP_SIZE; mas01mj@726: spec->refine.qhopsize = hopSize; mas01mj@726: spec->refine.ihopsize = hopSize; mas01mj@726: } mas01mj@726: mas01mj@726: spec->qid.datum->data = NULL; mas01mj@726: spec->qid.datum->power = NULL; mas01mj@726: spec->qid.datum->times = NULL; mas01mj@726: mas01mj@729: if (key != NULL) mas01mj@729: { mas01mj@729: const char* keyStr = (*env)->GetStringUTFChars(env, key, NULL); mas01mj@729: if(keyStr != NULL) mas01mj@729: { mas01mj@729: int ok = audiodb_retrieve_datum(handle, keyStr, spec->qid.datum); mas01mj@729: if(ok != 0) mas01mj@729: return; mas01mj@729: } mas01mj@726: } mas01mj@729: else mas01mj@729: { mas01mj@729: jdoubleArray data = get_double_array(env, datumClass, datumObject, "data"); mas01mj@729: jdouble *dataBody = (*env)->GetDoubleArrayElements(env, data, 0); mas01mj@729: spec->qid.datum->data = dataBody; mas01mj@729: mas01mj@729: jdoubleArray power = get_double_array(env, datumClass, datumObject, "power"); mas01mj@729: jdouble *powerBody = (*env)->GetDoubleArrayElements(env, power, 0); mas01mj@729: spec->qid.datum->power = powerBody; mas01mj@729: mas01mj@729: jdoubleArray times = get_double_array(env, datumClass, datumObject, "times"); mas01mj@729: jdouble *timesBody = (*env)->GetDoubleArrayElements(env, times, 0); mas01mj@729: spec->qid.datum->times = timesBody; mas01mj@729: mas01mj@729: spec->qid.datum->nvectors = get_int_val(env, datumClass, datumObject, "nvectors", 0); mas01mj@729: spec->qid.datum->dim = get_int_val(env, datumClass, datumObject, "dim", 0); mas01mj@729: mas01mj@729: (*env)->ReleaseDoubleArrayElements(env, data, dataBody, 0); mas01mj@729: (*env)->ReleaseDoubleArrayElements(env, power, powerBody, 0); mas01mj@729: (*env)->ReleaseDoubleArrayElements(env, times, timesBody, 0); mas01mj@729: } mas01mj@729: mas01mj@726: result = audiodb_query_spec(handle, spec); mas01mj@726: mas01mj@726: if(result == NULL) { mas01mj@726: return; mas01mj@726: } mas01mj@726: (*env)->DeleteLocalRef(env, queryClass); mas01mj@729: (*env)->DeleteLocalRef(env, datumClass); mas01mj@729: mas01mj@727: mas01mj@727: return build_results(env, result); mas01mj@726: } mas01mj@726: