annotate bindings/python/pyadbmodule.c @ 679:047415d1805e

Make the python bindings compile again using the new hopsize stuff It's not an ideal fix; it ties together the query and instance hops. Nevertheless, building is better than not building.
author mas01cr
date Fri, 05 Mar 2010 16:01:22 +0000
parents e1f7cab30701
children 26a19beb7e3d
rev   line source
map01bf@620 1 // pyadbmodule.c
map01bf@620 2 //
map01bf@620 3 // the internal portion of the wrapper for audio
map01bf@620 4 // see pyadb.py for the public classes
map01bf@620 5 //
map01bf@620 6 // Created by Benjamin Fields on 2009-09-04.
map01bf@621 7 // Copyright (c) 2009 Goldsmith University of London.
map01bf@621 8 // Distributed and licensed under GPL2. See ../../license.txt for details.
map01bf@620 9 //
map01bf@620 10 #include <fcntl.h>
map01bf@621 11 #include <string.h>
map01bf@620 12 #include "Python.h"
map01bf@622 13 #include "structmember.h"
map01bf@620 14 #include "audioDB_API.h"
map01bf@620 15 #include "numpy/arrayobject.h"
map01bf@620 16
map01bf@620 17 static void _pyadb_close(void *ptr);
map01bf@620 18
map01bf@620 19
map01bf@620 20 /* create a new database */
map01bf@620 21 /* returns a struct or NULL on failure */
map01bf@620 22 /* api call: */
mas01cr@671 23 /* adb_t *audiodb_create(const char *path, unsigned datasize, unsigned ntracks, unsigned datadim);*/
map01bf@620 24 PyObject * _pyadb_create(PyObject *self, PyObject *args)
map01bf@620 25 {
map01bf@620 26 unsigned datasize, ntracks, datadim;
map01bf@620 27 const char *path;
map01bf@620 28 int ok;
mas01cr@671 29 adb_t *new_database;
map01bf@620 30 ok = PyArg_ParseTuple(args, "sIII", &path, &datasize, &ntracks, &datadim);
map01bf@620 31 if (!ok) return 0;
map01bf@620 32 new_database = audiodb_create(path, datasize, ntracks, datadim);
map01bf@620 33 if (!new_database) return 0;
map01bf@620 34
map01bf@620 35 return PyCObject_FromVoidPtr( new_database, _pyadb_close);
map01bf@620 36 }
map01bf@620 37
map01bf@620 38 /* open an existing database */
map01bf@620 39 /* returns a struct or NULL on failure */
map01bf@620 40 /* flags expects fcntl flags concerning the opening mode */
map01bf@620 41 /* api call: */
mas01cr@671 42 // adb_t *audiodb_open(const char *path, int flags);
map01bf@620 43 PyObject * _pyadb_open(PyObject *self, PyObject *args)
map01bf@620 44 {
map01bf@620 45 const char *path;
map01bf@620 46 char mode;
map01bf@620 47 int ok;//in python layer need to translate boolean flags to byte mask
mas01cr@671 48 adb_t *fresh_database;
map01bf@620 49 ok = PyArg_ParseTuple(args, "sc", &path, &mode);
map01bf@620 50 if (!ok) return 0;
map01bf@620 51 if (mode == 'r'){
map01bf@620 52 fresh_database = audiodb_open(path, O_RDONLY);
map01bf@620 53 }else if (mode == 'w'){
map01bf@620 54 fresh_database = audiodb_open(path, O_RDWR);
map01bf@620 55 }else{
map01bf@620 56 PyErr_SetString(PyExc_ValueError,
map01bf@620 57 "mode must be either \'r\' or \'w\'. It appears to be something else.");
map01bf@620 58 return 0;
map01bf@620 59 }
map01bf@620 60 if (!fresh_database) return 0;
map01bf@620 61
map01bf@620 62 return PyCObject_FromVoidPtr( fresh_database, _pyadb_close);
map01bf@620 63 }
map01bf@620 64
map01bf@620 65 /* database status */
map01bf@620 66 /* api call: */
mas01cr@671 67 // int audiodb_status(adb_t *mydb, adb_status_ptr status);
map01bf@620 68 PyObject * _pyadb_status(PyObject *self, PyObject *args)
map01bf@620 69 {
mas01cr@671 70 adb_t *check_db;
mas01cr@671 71 adb_status_t *status;
map01bf@620 72 int flags, ok;
map01bf@620 73 PyObject * incoming = 0;
mas01cr@671 74 status = (adb_status_t *)malloc(sizeof(adb_status_t));
map01bf@620 75
map01bf@620 76 ok = PyArg_ParseTuple(args, "O", &incoming);
map01bf@620 77 if (!ok) return 0;
mas01cr@671 78 check_db = (adb_t *)PyCObject_AsVoidPtr(incoming);
map01bf@620 79
map01bf@620 80
map01bf@620 81 flags = audiodb_status(check_db, status);
map01bf@620 82 return Py_BuildValue("IIIIILL", status->numFiles,
map01bf@620 83 status->dim,
map01bf@620 84 status->dudCount,
map01bf@620 85 status->nullCount,
map01bf@620 86 status->flags,
map01bf@620 87 status->length,
map01bf@620 88 status->data_region_size);
map01bf@620 89
map01bf@620 90 }
map01bf@620 91
map01bf@620 92 /*engage l2norm in the referenced db*/
map01bf@620 93 /*api call:*/
mas01cr@671 94 //int audiodb_l2norm(adb_t *mydb);
map01bf@620 95 PyObject * _pyadb_l2norm(PyObject *self, PyObject *args)
map01bf@620 96 {
mas01cr@671 97 adb_t *current_db;
map01bf@620 98 int ok;
map01bf@620 99 PyObject * incoming = 0;
map01bf@620 100
map01bf@620 101 ok = PyArg_ParseTuple(args, "O", &incoming);
map01bf@620 102 if (!ok) return 0;
mas01cr@671 103 current_db = (adb_t *)PyCObject_AsVoidPtr(incoming);
map01bf@620 104
map01bf@620 105 ok = audiodb_l2norm(current_db);
map01bf@622 106 return PyBool_FromLong(ok-1);
map01bf@620 107
map01bf@620 108 }
map01bf@620 109
map01bf@620 110 /*engage power thresholding in the referenced db*/
map01bf@620 111 /*api call:*/
mas01cr@671 112 // int audiodb_power(adb_t *mydb);
map01bf@620 113 PyObject * _pyadb_power(PyObject *self, PyObject *args)
map01bf@620 114 {
mas01cr@671 115 adb_t *current_db;
map01bf@620 116 int ok;
map01bf@620 117 PyObject * incoming = 0;
map01bf@620 118
map01bf@620 119 ok = PyArg_ParseTuple(args, "O", &incoming);
map01bf@620 120 if (!ok) return 0;
mas01cr@671 121 current_db = (adb_t *)PyCObject_AsVoidPtr(incoming);
map01bf@620 122
map01bf@620 123 ok = audiodb_power(current_db);
map01bf@622 124 return PyBool_FromLong(ok-1);
map01bf@620 125
map01bf@620 126 }
map01bf@621 127 /* insert feature data stored in a file */
map01bf@621 128 /* this is a bit gross, */
map01bf@621 129 /* should be replaced eventually by a numpy based feature.*/
map01bf@621 130 /* api call: */
mas01cr@673 131 // struct adb_insert {
map01bf@621 132 // const char *features;
map01bf@621 133 // const char *power;
map01bf@621 134 // const char *key;
map01bf@621 135 // const char *times;
map01bf@621 136 // };
mas01cr@671 137 // int audiodb_insert(adb_t *mydb, adb_insert_t *ins);
map01bf@621 138 PyObject * _pyadb_insertFromFile(PyObject *self, PyObject *args, PyObject *keywds)
map01bf@621 139 {
mas01cr@671 140 adb_t *current_db;
mas01cr@671 141 adb_insert_t *ins;
map01bf@621 142 int ok;
map01bf@621 143 const char *features;
map01bf@621 144 const char *power = NULL;
map01bf@621 145 const char *key = NULL;
map01bf@621 146 const char *times = NULL;
map01bf@621 147 PyObject * incoming = 0;
map01bf@621 148 static char *kwlist[] = { "db", "features", "power", "key", "times" , NULL};
map01bf@621 149
map01bf@621 150 ok = PyArg_ParseTupleAndKeywords(args, keywds, "Os|sss", kwlist, &incoming, &features, &power, &key, &times);
map01bf@621 151 if (!ok){return NULL;}
map01bf@621 152
mas01cr@671 153 current_db = (adb_t *)PyCObject_AsVoidPtr(incoming);
mas01cr@671 154 ins = (adb_insert_t *)malloc(sizeof(adb_insert_t));
map01bf@621 155 ins->features = features;
map01bf@621 156 ins->power = power;
map01bf@621 157 ins->key = key;
map01bf@621 158 ins->times = times;
map01bf@622 159 //printf("features::%s\npower::%s\nkey::%s\ntimes::%s\n", ins->features, ins->power, ins->key, ins->times);
map01bf@621 160 ok = audiodb_insert(current_db, ins);
map01bf@622 161 return PyBool_FromLong(ok-1);
map01bf@621 162
map01bf@621 163 }
map01bf@621 164
map01bf@622 165 /* base query. The nomenclature here is about a far away as pythonic as is possible.
map01bf@622 166 * This should be taken care of via the higher level python structure
map01bf@622 167 * returns a dict that should be result ordered and key = result key
map01bf@622 168 * and value is a list of tuples one per result associated with that key, of the form:
map01bf@622 169 * (dist, qpos, ipos)
map01bf@622 170 * Note as well that this is by no means the most efficient way to cast from C, simply the most direct
map01bf@622 171 * and what it lacks in effeciency it gains in python side access. It remains to be seen if this is
map01bf@622 172 * a sensible trade.
map01bf@622 173 * api call:
map01bf@622 174 * adb_query_results_t *audiodb_query_spec(adb_t *, const adb_query_spec_t *);
map01bf@622 175 ***/
map01bf@622 176 PyObject * _pyadb_queryFromKey(PyObject *self, PyObject *args, PyObject *keywds)
map01bf@622 177 {
mas01cr@671 178 adb_t *current_db;
map01bf@622 179 adb_query_spec_t *spec;
map01bf@622 180 adb_query_results_t *result;
map01bf@622 181 int ok, exhaustive, falsePositives;
map01bf@622 182 uint32_t i;
map01bf@622 183 const char *key;
map01bf@622 184 const char *accuMode = "db";
map01bf@622 185 const char *distMode = "dot";
map01bf@624 186 const char *resFmt = "dict";
map01bf@622 187 uint32_t hop = 0;
map01bf@622 188 double radius = 0;
map01bf@622 189 double absThres = 0;
map01bf@622 190 double relThres = 0;
map01bf@622 191 double durRatio = 0;
map01bf@622 192 PyObject *includeKeys = NULL;
map01bf@622 193 PyObject *excludeKeys = NULL;
map01bf@622 194 PyObject *incoming = 0;
map01bf@622 195 PyObject *outgoing = NULL;
map01bf@622 196 PyObject *thisKey = NULL;
map01bf@622 197 PyObject *currentValue = 0;
map01bf@622 198 PyObject *newBits = 0;
map01bf@622 199 static char *kwlist[] = { "db", "key",
map01bf@622 200 "seqLength",
map01bf@622 201 "seqStart",
map01bf@622 202 "exhaustive",
map01bf@622 203 "falsePositives",
map01bf@622 204 "accumulation",
map01bf@622 205 "distance",
map01bf@622 206 "npoints",//nearest neighbor points per track
map01bf@624 207 "ntracks",
map01bf@622 208 "includeKeys",
map01bf@622 209 "excludeKeys",
map01bf@622 210 "radius",
map01bf@622 211 "absThres",
map01bf@622 212 "relThres",
map01bf@622 213 "durRatio",
map01bf@624 214 "hopSize",
mas01cr@665 215 "resFmt",
mas01cr@665 216 NULL
map01bf@622 217 };
map01bf@622 218 spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t));
map01bf@622 219 spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t));
map01bf@622 220 result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t));
map01bf@622 221
map01bf@622 222 spec->qid.sequence_length = 16;
map01bf@622 223 spec->qid.sequence_start = 0;
map01bf@622 224 spec->qid.flags = 0;
map01bf@622 225 spec->params.npoints = 1;
map01bf@622 226 spec->params.ntracks = 100;//number of results returned in db mode
map01bf@622 227 spec->refine.flags = 0;
map01bf@622 228
map01bf@624 229 ok = PyArg_ParseTupleAndKeywords(args, keywds, "Os|iiiissIIOOddddIs", kwlist,
map01bf@622 230 &incoming, &key,
map01bf@622 231 &spec->qid.sequence_length,
map01bf@622 232 &spec->qid.sequence_start,
map01bf@622 233 &exhaustive, &falsePositives,
map01bf@622 234 &accuMode,&distMode,
map01bf@622 235 &spec->params.npoints,
map01bf@622 236 &spec->params.ntracks,
map01bf@622 237 &includeKeys, &excludeKeys,
map01bf@624 238 &radius, &absThres, &relThres, &durRatio, &hop,
map01bf@624 239 &resFmt
map01bf@622 240 );
map01bf@622 241
map01bf@622 242 if (!ok) {return NULL;}
mas01cr@671 243 current_db = (adb_t *)PyCObject_AsVoidPtr(incoming);
map01bf@622 244
map01bf@622 245 if (exhaustive){
map01bf@622 246 spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE;
map01bf@622 247 }
map01bf@622 248 if (falsePositives){
map01bf@622 249 spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_ALLOW_FALSE_POSITIVES;
map01bf@622 250 }
map01bf@622 251
map01bf@622 252 //set up spec->params
map01bf@622 253 if (strcmp(accuMode,"db")){
map01bf@622 254 spec->params.accumulation = ADB_ACCUMULATION_DB;
map01bf@622 255 } else if (strcmp(accuMode,"track")){
map01bf@622 256 spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK;
map01bf@622 257 } else if (strcmp(accuMode,"one2one")){
map01bf@622 258 spec->params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
map01bf@622 259 } else{
map01bf@624 260 PyErr_SetString(PyExc_ValueError,
map01bf@624 261 "Poorly specified distance mode. distance must either be \'db\', \'track\' or \'one2one\'.\n");
map01bf@622 262 return NULL;
map01bf@622 263 }
map01bf@622 264 if (strcmp(distMode, "dot")){
map01bf@622 265 spec->params.distance = ADB_DISTANCE_DOT_PRODUCT;
map01bf@622 266 }else if (strcmp(distMode, "eucNorm")){
map01bf@622 267 spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
map01bf@622 268 }else if (strcmp(distMode, "euclidean")){
map01bf@622 269 spec->params.distance = ADB_DISTANCE_EUCLIDEAN;
map01bf@622 270 }else{
map01bf@624 271 PyErr_SetString(PyExc_ValueError,
map01bf@624 272 "Poorly specified distance mode. distance must either be \'dot\', \'eucNorm\' or \'euclidean\'.\n");
map01bf@622 273 return NULL;
map01bf@622 274 }
map01bf@622 275
map01bf@622 276 //set up spec->refine
map01bf@622 277 //include/exclude keys
map01bf@622 278 if (includeKeys){
map01bf@622 279 if (!PyList_Check(includeKeys)){
map01bf@624 280 PyErr_SetString(PyExc_TypeError, "Include keys must be specified as a list of strings.\n");
map01bf@622 281 return NULL;
map01bf@622 282 }
map01bf@622 283 spec->refine.flags = spec->refine.flags | ADB_REFINE_INCLUDE_KEYLIST;
map01bf@622 284 spec->refine.include.nkeys = (uint32_t)PyList_Size(includeKeys);
map01bf@622 285 spec->refine.include.keys = (const char **)calloc(sizeof(const char *), spec->refine.include.nkeys);
map01bf@622 286 for (i=0;i<spec->refine.include.nkeys;i++){
map01bf@622 287 if (PyString_Check(PyList_GetItem(includeKeys, (Py_ssize_t)i))){
map01bf@622 288 spec->refine.include.keys[i] = PyString_AsString(PyList_GetItem(includeKeys, (Py_ssize_t)i));
map01bf@622 289 }else{
map01bf@624 290 PyErr_SetString(PyExc_TypeError, "Include keys must each be specified as a string.\nFound one that was not.\n");
map01bf@622 291 return NULL;
map01bf@622 292 }
map01bf@622 293 }
map01bf@622 294 }
map01bf@622 295 if (excludeKeys){
map01bf@622 296 if (!PyList_Check(excludeKeys)){
map01bf@624 297 PyErr_SetString(PyExc_TypeError, "Exclude keys must be specified as a list of strings.\n");
map01bf@622 298 return NULL;
map01bf@622 299 }
map01bf@622 300 spec->refine.flags = spec->refine.flags | ADB_REFINE_EXCLUDE_KEYLIST;
map01bf@622 301 spec->refine.exclude.nkeys = (uint32_t)PyList_Size(excludeKeys);
map01bf@622 302 spec->refine.exclude.keys = (const char **)calloc(sizeof(const char *), spec->refine.exclude.nkeys);
map01bf@622 303 for (i=0;i<spec->refine.exclude.nkeys;i++){
map01bf@622 304 if (PyString_Check(PyList_GetItem(excludeKeys, (Py_ssize_t)i))){
map01bf@622 305 spec->refine.exclude.keys[i] = PyString_AsString(PyList_GetItem(excludeKeys, (Py_ssize_t)i));
map01bf@622 306 }else{
map01bf@624 307 PyErr_SetString(PyExc_TypeError, "Exclude keys must each be specified as a string.\nFound one that was not.\n");
map01bf@622 308 return NULL;
map01bf@622 309 }
map01bf@622 310 }
map01bf@622 311 }
map01bf@622 312 //the rest of spec->refine
map01bf@622 313 if (radius){
map01bf@622 314 spec->refine.flags = spec->refine.flags | ADB_REFINE_RADIUS;
map01bf@622 315 spec->refine.radius = radius;
map01bf@622 316 }
map01bf@622 317 if (absThres){
map01bf@622 318 spec->refine.flags = spec->refine.flags | ADB_REFINE_ABSOLUTE_THRESHOLD;
map01bf@622 319 spec->refine.absolute_threshold = absThres;
map01bf@622 320 }
map01bf@622 321 if (relThres){
map01bf@622 322 spec->refine.flags = spec->refine.flags | ADB_REFINE_RELATIVE_THRESHOLD;
map01bf@622 323 spec->refine.relative_threshold = relThres;
map01bf@622 324 }
map01bf@622 325 if (durRatio){
map01bf@622 326 spec->refine.flags = spec->refine.flags | ADB_REFINE_DURATION_RATIO;
map01bf@622 327 spec->refine.duration_ratio = durRatio;
map01bf@622 328 }
map01bf@622 329 if (hop){
map01bf@622 330 spec->refine.flags = spec->refine.flags | ADB_REFINE_HOP_SIZE;
mas01cr@679 331 /* not ideal but a temporary bandage fix */
mas01cr@679 332 spec->refine.qhopsize = hop;
mas01cr@679 333 spec->refine.ihopsize = hop;
map01bf@622 334 }
map01bf@622 335 //setup the datum
map01bf@622 336 spec->qid.datum->data = NULL;
map01bf@622 337 spec->qid.datum->power = NULL;
map01bf@622 338 spec->qid.datum->times = NULL;
map01bf@622 339 //grab the datum from the key
map01bf@622 340 ok = audiodb_retrieve_datum(current_db, key, spec->qid.datum);
map01bf@622 341 if (ok != 0){
map01bf@622 342 PyErr_SetString(PyExc_RuntimeError, "Encountered an error while trying to retrieve the data associated with the passed key.\n");
map01bf@622 343 return NULL;
map01bf@622 344 }
map01bf@622 345 result = audiodb_query_spec(current_db, spec);
map01bf@622 346 if (result == NULL){
map01bf@622 347 PyErr_SetString(PyExc_RuntimeError, "Encountered an error while running the actual query.\n");
map01bf@622 348 return NULL;
map01bf@622 349 }
map01bf@624 350 if(strcmp(resFmt, "dict")==0){
map01bf@624 351 outgoing = PyDict_New();
map01bf@624 352 for (i=0;i<result->nresults;i++){
mas01cr@672 353 thisKey = PyString_FromString(result->results[i].ikey);
map01bf@624 354 if (!PyDict_Contains(outgoing, thisKey)){
map01bf@624 355 newBits = Py_BuildValue("[(dII)]",
map01bf@624 356 result->results[i].dist,
map01bf@624 357 result->results[i].qpos,
map01bf@624 358 result->results[i].ipos);
map01bf@624 359 if (PyDict_SetItem(outgoing, thisKey,newBits)){
mas01cr@672 360 printf("key : %s\ndist : %f\nqpos : %i\nipos : %i\n", result->results[i].ikey, result->results[i].dist, result->results[i].qpos, result->results[i].ipos);
map01bf@624 361 PyErr_SetString(PyExc_AttributeError, "Error adding a tuple to the result dict\n");
map01bf@624 362 Py_XDECREF(newBits);
map01bf@624 363 return NULL;
map01bf@624 364 }
map01bf@624 365 Py_DECREF(newBits);
map01bf@624 366 }else {
map01bf@624 367 //the key already has a value, so we need to fetch the value, confirm it's a list and append another tuple to it.
map01bf@624 368 currentValue = PyDict_GetItem(outgoing, thisKey);
map01bf@624 369 if (!PyList_Check(currentValue)){
map01bf@624 370 PyErr_SetString(PyExc_TypeError, "The result dictionary appears to be malformed.\n");
map01bf@624 371 return NULL;
map01bf@624 372 }
map01bf@624 373 newBits = Py_BuildValue("dII",result->results[i].dist,
map01bf@624 374 result->results[i].qpos,
map01bf@624 375 result->results[i].ipos);
map01bf@624 376 if (PyList_Append(currentValue, newBits)){
map01bf@624 377 //error msg here
map01bf@624 378 Py_XDECREF(newBits);
map01bf@624 379 return NULL;
map01bf@624 380 }
map01bf@624 381 if (PyDict_SetItem(outgoing, thisKey, newBits)){
map01bf@624 382 PyErr_SetString(PyExc_AttributeError, "Error adding a tuple to the result dict\n");
map01bf@624 383 Py_XDECREF(newBits);
map01bf@624 384 return NULL;
map01bf@624 385 }
map01bf@624 386 Py_DECREF(newBits);
map01bf@624 387
map01bf@624 388 }
map01bf@624 389 }
map01bf@624 390 }else if(strcmp(resFmt, "list")==0){
map01bf@624 391 outgoing = PyList_New((Py_ssize_t)0);
map01bf@624 392 for (i=0;i<result->nresults;i++){
mas01cr@672 393 newBits = Py_BuildValue("sdII",result->results[i].ikey,
map01bf@622 394 result->results[i].dist,
map01bf@622 395 result->results[i].qpos,
map01bf@622 396 result->results[i].ipos);
map01bf@624 397 if (PyList_Append(outgoing, newBits)){
map01bf@624 398 //error msg here
map01bf@622 399 Py_XDECREF(newBits);
map01bf@622 400 return NULL;
map01bf@622 401 }
map01bf@622 402 Py_DECREF(newBits);
map01bf@624 403 }
map01bf@624 404 if(PyList_Reverse(outgoing)){//need to do this as things come off the accumulator backward.
map01bf@624 405 printf("the reverse failed, hopefully a sensable error will follow.\nIf not, fix it.\n");
map01bf@624 406 return NULL;
map01bf@622 407 }
map01bf@624 408 }else{
map01bf@624 409 PyErr_SetString(PyExc_ValueError,
map01bf@624 410 "Poorly specified result mode. Result must be either \'dist\' or \'list\'.\n");
map01bf@624 411 return NULL;
map01bf@622 412 }
map01bf@628 413 if (audiodb_query_free_results(current_db, spec, result)){
map01bf@622 414 printf("bit of trouble freeing the result and spec...\ncheck for leaks.");
map01bf@622 415 }
map01bf@622 416
map01bf@622 417 return outgoing;
map01bf@622 418
map01bf@622 419
map01bf@622 420
map01bf@622 421 }
map01bf@622 422
map01bf@622 423
map01bf@622 424
map01bf@622 425
map01bf@620 426 /* close a database */
map01bf@620 427 /* api call: */
mas01cr@671 428 // void audiodb_close(adb_t *db);
map01bf@620 429 static void _pyadb_close(void *ptr)
map01bf@620 430 {
mas01cr@671 431 adb_t *stale_database;
mas01cr@671 432 stale_database = (adb_t *)ptr;
map01bf@620 433
map01bf@620 434 audiodb_close(stale_database);
map01bf@620 435 }
map01bf@620 436
map01bf@620 437 static PyMethodDef _pyadbMethods[] =
map01bf@620 438 {
map01bf@620 439 { "_pyadb_create", _pyadb_create, METH_VARARGS,
map01bf@620 440 "_pyadb_create(string path, unsigned datasize, unsigned ntracks, unsigned datadim)->adb object"},
map01bf@620 441 { "_pyadb_open", _pyadb_open, METH_VARARGS,
map01bf@620 442 "_pyadb_open(string path, [\'r\'|\'w\'])->adb object\nNote that specifing \'w\' opens the file in read and write mode. \
map01bf@620 443 There is currently no way to open in write only."},
map01bf@620 444 { "_pyadb_status", _pyadb_status, METH_VARARGS,
mas01cr@671 445 "_status(adb_t *)->(numFiles, dims, dudCount, nullCount, flags, length, data_region_size)"},
map01bf@620 446 { "_pyadb_l2norm", _pyadb_l2norm, METH_VARARGS,
mas01cr@671 447 "_pyadb_l2norm(adb_t *)->int return code (0 for sucess)"},
map01bf@620 448 { "_pyadb_power", _pyadb_power, METH_VARARGS,
mas01cr@671 449 "_pyadb_power(adb_t *)->int return code (0 for sucess)"},
map01bf@622 450 { "_pyadb_insertFromFile", (PyCFunction)_pyadb_insertFromFile, METH_VARARGS | METH_KEYWORDS,
mas01cr@671 451 "_pyadb_insertFromFile(adb_t *, features=featureFile, [power=powerfile | key=keystring | times=timingFile])->\
map01bf@621 452 int return code (0 for sucess)"},
map01bf@622 453 { "_pyadb_queryFromKey", (PyCFunction)_pyadb_queryFromKey, METH_VARARGS | METH_KEYWORDS,
map01bf@622 454 "base query. The nomenclature here is about a far away as pythonic as is possible.\n\
map01bf@622 455 This should be taken care of via the higher level python structure\n\
map01bf@622 456 returns a dict that should be result ordered and key = result key\n\
map01bf@622 457 and value is a list of tuples one per result associated with that key, of the form:\n\
map01bf@622 458 \t(dist, qpos, ipos)\n\
map01bf@622 459 Note as well that this is by no means the most efficient way to cast from C, simply the most direct\n\
map01bf@622 460 and what it lacks in effeciency it gains in python side access. It remains to be seen if this is\n\
map01bf@622 461 a sensible trade.\n\
mas01cr@671 462 _pyadb_queryFromKey(adb_t *, query key,\n\
map01bf@622 463 [seqLength = Int Sequence Length, \n\
map01bf@622 464 seqStart = Int offset from start for key, \n\
map01bf@622 465 exhaustive = boolean - True for exhaustive (false by default),\n\
map01bf@622 466 falsePositives= boolean - True to keep fps (false by defaults),\n\
map01bf@622 467 accumulation = [\"db\"|\"track\"|\"one2one\"] (\"db\" by default),\n\
map01bf@622 468 distance = [\"dot\"|\"eucNorm\"|\"euclidean\"] (\"dot\" by default),\n\
map01bf@622 469 npoints = int number of points per track,\n\
map01bf@622 470 ntracks = max number of results returned in db accu mode,\n\
map01bf@622 471 includeKeys = list of strings to include (use all by default),\n\
map01bf@622 472 excludeKeys = list of strings to exclude (none by default),\n\
map01bf@622 473 radius = double of nnRadius (1.0 default, overrides npoints if specified),\n\
map01bf@622 474 absThres = double absolute power threshold (db must have power),\n\
map01bf@622 475 relThres = double relative power threshold (db must have power),\n\
map01bf@622 476 durRatio = double time expansion/compresion ratio,\n\
map01bf@628 477 hopSize = int hopsize (1 by default)])->resultDict\n\
map01bf@628 478 resFmt = [\"list\"|\"dict\"](\"dict\" by default)"},
map01bf@620 479 {NULL,NULL, 0, NULL}
map01bf@620 480 };
map01bf@620 481
map01bf@620 482 void init_pyadb()
map01bf@620 483 {
map01bf@620 484 Py_InitModule3("_pyadb", _pyadbMethods, "internal c bindings for audioDB. Use pyadb for pythonic access to adb (when it exists).");
map01bf@620 485 // import_array();
map01bf@620 486 return;
map01bf@620 487 }
map01bf@620 488
map01bf@620 489