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: */
|
map01bf@620
|
23 /* adb_ptr 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;
|
map01bf@620
|
29 adb_ptr 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: */
|
map01bf@620
|
42 // adb_ptr 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
|
map01bf@620
|
48 adb_ptr 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: */
|
map01bf@620
|
67 // int audiodb_status(adb_ptr mydb, adb_status_ptr status);
|
map01bf@620
|
68 PyObject * _pyadb_status(PyObject *self, PyObject *args)
|
map01bf@620
|
69 {
|
map01bf@620
|
70 adb_ptr check_db;
|
map01bf@620
|
71 adb_status_ptr status;
|
map01bf@620
|
72 int flags, ok;
|
map01bf@620
|
73 PyObject * incoming = 0;
|
map01bf@620
|
74 status = (adb_status_ptr)malloc(sizeof(struct adbstatus));
|
map01bf@620
|
75
|
map01bf@620
|
76 ok = PyArg_ParseTuple(args, "O", &incoming);
|
map01bf@620
|
77 if (!ok) return 0;
|
map01bf@620
|
78 check_db = (adb_ptr)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:*/
|
map01bf@620
|
94 //int audiodb_l2norm(adb_ptr mydb);
|
map01bf@620
|
95 PyObject * _pyadb_l2norm(PyObject *self, PyObject *args)
|
map01bf@620
|
96 {
|
map01bf@620
|
97 adb_ptr 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;
|
map01bf@620
|
103 current_db = (adb_ptr)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:*/
|
map01bf@620
|
112 // int audiodb_power(adb_ptr mydb);
|
map01bf@620
|
113 PyObject * _pyadb_power(PyObject *self, PyObject *args)
|
map01bf@620
|
114 {
|
map01bf@620
|
115 adb_ptr 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;
|
map01bf@620
|
121 current_db = (adb_ptr)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: */
|
map01bf@621
|
131 // struct adbinsert {
|
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 // };
|
map01bf@621
|
137 // int audiodb_insert(adb_ptr mydb, adb_insert_ptr ins);
|
map01bf@621
|
138 PyObject * _pyadb_insertFromFile(PyObject *self, PyObject *args, PyObject *keywds)
|
map01bf@621
|
139 {
|
map01bf@621
|
140 adb_ptr current_db;
|
map01bf@621
|
141 adb_insert_ptr 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, ×);
|
map01bf@621
|
151 if (!ok){return NULL;}
|
map01bf@621
|
152
|
map01bf@621
|
153 current_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
|
map01bf@621
|
154 ins = (adb_insert_ptr)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@621
|
165
|
map01bf@622
|
166 /* base query. The nomenclature here is about a far away as pythonic as is possible.
|
map01bf@622
|
167 * This should be taken care of via the higher level python structure
|
map01bf@622
|
168 * returns a dict that should be result ordered and key = result key
|
map01bf@622
|
169 * and value is a list of tuples one per result associated with that key, of the form:
|
map01bf@622
|
170 * (dist, qpos, ipos)
|
map01bf@622
|
171 * Note as well that this is by no means the most efficient way to cast from C, simply the most direct
|
map01bf@622
|
172 * and what it lacks in effeciency it gains in python side access. It remains to be seen if this is
|
map01bf@622
|
173 * a sensible trade.
|
map01bf@622
|
174 * api call:
|
map01bf@622
|
175 * adb_query_results_t *audiodb_query_spec(adb_t *, const adb_query_spec_t *);
|
map01bf@622
|
176 ***/
|
map01bf@622
|
177 PyObject * _pyadb_queryFromKey(PyObject *self, PyObject *args, PyObject *keywds)
|
map01bf@622
|
178 {
|
map01bf@622
|
179 adb_ptr current_db;
|
map01bf@622
|
180 adb_query_spec_t *spec;
|
map01bf@622
|
181 adb_query_results_t *result;
|
map01bf@622
|
182 int ok, exhaustive, falsePositives;
|
map01bf@622
|
183 uint32_t i;
|
map01bf@622
|
184 const char *key;
|
map01bf@622
|
185 const char *accuMode = "db";
|
map01bf@622
|
186 const char *distMode = "dot";
|
map01bf@622
|
187 const char *errMsg = NULL;
|
map01bf@622
|
188 uint32_t hop = 0;
|
map01bf@622
|
189 double radius = 0;
|
map01bf@622
|
190 double absThres = 0;
|
map01bf@622
|
191 double relThres = 0;
|
map01bf@622
|
192 double durRatio = 0;
|
map01bf@622
|
193 PyObject *includeKeys = NULL;
|
map01bf@622
|
194 PyObject *excludeKeys = NULL;
|
map01bf@622
|
195 PyObject *incoming = 0;
|
map01bf@622
|
196 PyObject *outgoing = NULL;
|
map01bf@622
|
197 PyObject *thisKey = NULL;
|
map01bf@622
|
198 PyObject *currentValue = 0;
|
map01bf@622
|
199 PyObject *newBits = 0;
|
map01bf@622
|
200 static char *kwlist[] = { "db", "key",
|
map01bf@622
|
201 "seqLength",
|
map01bf@622
|
202 "seqStart",
|
map01bf@622
|
203 "exhaustive",
|
map01bf@622
|
204 "falsePositives",
|
map01bf@622
|
205 "accumulation",
|
map01bf@622
|
206 "distance",
|
map01bf@622
|
207 "npoints",//nearest neighbor points per track
|
map01bf@622
|
208 "ntracks",//I don't know what this one is... Maybe number of results...
|
map01bf@622
|
209 "includeKeys",
|
map01bf@622
|
210 "excludeKeys",
|
map01bf@622
|
211 "radius",
|
map01bf@622
|
212 "absThres",
|
map01bf@622
|
213 "relThres",
|
map01bf@622
|
214 "durRatio",
|
map01bf@622
|
215 "hopSize"
|
map01bf@622
|
216 };
|
map01bf@622
|
217 spec = (adb_query_spec_t *)malloc(sizeof(adb_query_spec_t));
|
map01bf@622
|
218 spec->qid.datum = (adb_datum_t *)malloc(sizeof(adb_datum_t));
|
map01bf@622
|
219 result = (adb_query_results_t *)malloc(sizeof(adb_query_results_t));
|
map01bf@622
|
220
|
map01bf@622
|
221 spec->qid.sequence_length = 16;
|
map01bf@622
|
222 spec->qid.sequence_start = 0;
|
map01bf@622
|
223 spec->qid.flags = 0;
|
map01bf@622
|
224 spec->params.npoints = 1;
|
map01bf@622
|
225 spec->params.ntracks = 100;//number of results returned in db mode
|
map01bf@622
|
226 spec->refine.flags = 0;
|
map01bf@622
|
227
|
map01bf@622
|
228 ok = PyArg_ParseTupleAndKeywords(args, keywds, "Os|iiiissIIOOddddI", kwlist,
|
map01bf@622
|
229 &incoming, &key,
|
map01bf@622
|
230 &spec->qid.sequence_length,
|
map01bf@622
|
231 &spec->qid.sequence_start,
|
map01bf@622
|
232 &exhaustive, &falsePositives,
|
map01bf@622
|
233 &accuMode,&distMode,
|
map01bf@622
|
234 &spec->params.npoints,
|
map01bf@622
|
235 &spec->params.ntracks,
|
map01bf@622
|
236 &includeKeys, &excludeKeys,
|
map01bf@622
|
237 &radius, &absThres, &relThres, &durRatio, &hop
|
map01bf@622
|
238 );
|
map01bf@622
|
239
|
map01bf@622
|
240 if (!ok) {return NULL;}
|
map01bf@622
|
241 current_db = (adb_ptr)PyCObject_AsVoidPtr(incoming);
|
map01bf@622
|
242
|
map01bf@622
|
243 if (exhaustive){
|
map01bf@622
|
244 spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_EXHAUSTIVE;
|
map01bf@622
|
245 }
|
map01bf@622
|
246 if (falsePositives){
|
map01bf@622
|
247 spec->qid.flags = spec->qid.flags | ADB_QID_FLAG_ALLOW_FALSE_POSITIVES;
|
map01bf@622
|
248 }
|
map01bf@622
|
249
|
map01bf@622
|
250 //set up spec->params
|
map01bf@622
|
251 if (strcmp(accuMode,"db")){
|
map01bf@622
|
252 spec->params.accumulation = ADB_ACCUMULATION_DB;
|
map01bf@622
|
253 } else if (strcmp(accuMode,"track")){
|
map01bf@622
|
254 spec->params.accumulation = ADB_ACCUMULATION_PER_TRACK;
|
map01bf@622
|
255 } else if (strcmp(accuMode,"one2one")){
|
map01bf@622
|
256 spec->params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
|
map01bf@622
|
257 } else{
|
map01bf@622
|
258 //error dump
|
map01bf@622
|
259 return NULL;
|
map01bf@622
|
260 }
|
map01bf@622
|
261 if (strcmp(distMode, "dot")){
|
map01bf@622
|
262 spec->params.distance = ADB_DISTANCE_DOT_PRODUCT;
|
map01bf@622
|
263 }else if (strcmp(distMode, "eucNorm")){
|
map01bf@622
|
264 spec->params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
|
map01bf@622
|
265 }else if (strcmp(distMode, "euclidean")){
|
map01bf@622
|
266 spec->params.distance = ADB_DISTANCE_EUCLIDEAN;
|
map01bf@622
|
267 }else{
|
map01bf@622
|
268 //error dump
|
map01bf@622
|
269 return NULL;
|
map01bf@622
|
270 }
|
map01bf@622
|
271
|
map01bf@622
|
272 //set up spec->refine
|
map01bf@622
|
273 //include/exclude keys
|
map01bf@622
|
274 if (includeKeys){
|
map01bf@622
|
275 if (!PyList_Check(includeKeys)){
|
map01bf@622
|
276 //error!
|
map01bf@622
|
277 return NULL;
|
map01bf@622
|
278 }
|
map01bf@622
|
279 spec->refine.flags = spec->refine.flags | ADB_REFINE_INCLUDE_KEYLIST;
|
map01bf@622
|
280 spec->refine.include.nkeys = (uint32_t)PyList_Size(includeKeys);
|
map01bf@622
|
281 spec->refine.include.keys = (const char **)calloc(sizeof(const char *), spec->refine.include.nkeys);
|
map01bf@622
|
282 for (i=0;i<spec->refine.include.nkeys;i++){
|
map01bf@622
|
283 if (PyString_Check(PyList_GetItem(includeKeys, (Py_ssize_t)i))){
|
map01bf@622
|
284 spec->refine.include.keys[i] = PyString_AsString(PyList_GetItem(includeKeys, (Py_ssize_t)i));
|
map01bf@622
|
285 }else{
|
map01bf@622
|
286 //bad string no cookie!
|
map01bf@622
|
287 return NULL;
|
map01bf@622
|
288 }
|
map01bf@622
|
289 }
|
map01bf@622
|
290 }
|
map01bf@622
|
291 if (excludeKeys){
|
map01bf@622
|
292 if (!PyList_Check(excludeKeys)){
|
map01bf@622
|
293 //error!
|
map01bf@622
|
294 return NULL;
|
map01bf@622
|
295 }
|
map01bf@622
|
296 spec->refine.flags = spec->refine.flags | ADB_REFINE_EXCLUDE_KEYLIST;
|
map01bf@622
|
297 spec->refine.exclude.nkeys = (uint32_t)PyList_Size(excludeKeys);
|
map01bf@622
|
298 spec->refine.exclude.keys = (const char **)calloc(sizeof(const char *), spec->refine.exclude.nkeys);
|
map01bf@622
|
299 for (i=0;i<spec->refine.exclude.nkeys;i++){
|
map01bf@622
|
300 if (PyString_Check(PyList_GetItem(excludeKeys, (Py_ssize_t)i))){
|
map01bf@622
|
301 spec->refine.exclude.keys[i] = PyString_AsString(PyList_GetItem(excludeKeys, (Py_ssize_t)i));
|
map01bf@622
|
302 }else{
|
map01bf@622
|
303 //bad string no cookie!
|
map01bf@622
|
304 return NULL;
|
map01bf@622
|
305 }
|
map01bf@622
|
306 }
|
map01bf@622
|
307 }
|
map01bf@622
|
308 //the rest of spec->refine
|
map01bf@622
|
309 if (radius){
|
map01bf@622
|
310 spec->refine.flags = spec->refine.flags | ADB_REFINE_RADIUS;
|
map01bf@622
|
311 spec->refine.radius = radius;
|
map01bf@622
|
312 }
|
map01bf@622
|
313 if (absThres){
|
map01bf@622
|
314 spec->refine.flags = spec->refine.flags | ADB_REFINE_ABSOLUTE_THRESHOLD;
|
map01bf@622
|
315 spec->refine.absolute_threshold = absThres;
|
map01bf@622
|
316 }
|
map01bf@622
|
317 if (relThres){
|
map01bf@622
|
318 spec->refine.flags = spec->refine.flags | ADB_REFINE_RELATIVE_THRESHOLD;
|
map01bf@622
|
319 spec->refine.relative_threshold = relThres;
|
map01bf@622
|
320 }
|
map01bf@622
|
321 if (durRatio){
|
map01bf@622
|
322 spec->refine.flags = spec->refine.flags | ADB_REFINE_DURATION_RATIO;
|
map01bf@622
|
323 spec->refine.duration_ratio = durRatio;
|
map01bf@622
|
324 }
|
map01bf@622
|
325 if (hop){
|
map01bf@622
|
326 spec->refine.flags = spec->refine.flags | ADB_REFINE_HOP_SIZE;
|
map01bf@622
|
327 spec->refine.hopsize = hop;
|
map01bf@622
|
328 }
|
map01bf@622
|
329 //setup the datum
|
map01bf@622
|
330 spec->qid.datum->data = NULL;
|
map01bf@622
|
331 spec->qid.datum->power = NULL;
|
map01bf@622
|
332 spec->qid.datum->times = NULL;
|
map01bf@622
|
333 //grab the datum from the key
|
map01bf@622
|
334 ok = audiodb_retrieve_datum(current_db, key, spec->qid.datum);
|
map01bf@622
|
335 if (ok != 0){
|
map01bf@622
|
336 PyErr_SetString(PyExc_RuntimeError, "Encountered an error while trying to retrieve the data associated with the passed key.\n");
|
map01bf@622
|
337 return NULL;
|
map01bf@622
|
338 }
|
map01bf@622
|
339 result = audiodb_query_spec(current_db, spec);
|
map01bf@622
|
340 if (result == NULL){
|
map01bf@622
|
341 PyErr_SetString(PyExc_RuntimeError, "Encountered an error while running the actual query.\n");
|
map01bf@622
|
342 return NULL;
|
map01bf@622
|
343 }
|
map01bf@622
|
344 outgoing = PyDict_New();
|
map01bf@622
|
345 for (i=0;i<result->nresults;i++){
|
map01bf@622
|
346 thisKey = PyString_FromString(result->results[i].key);
|
map01bf@622
|
347 if (!PyDict_Contains(outgoing, thisKey)){
|
map01bf@622
|
348 newBits = Py_BuildValue("[(dII)]",
|
map01bf@622
|
349 result->results[i].dist,
|
map01bf@622
|
350 result->results[i].qpos,
|
map01bf@622
|
351 result->results[i].ipos);
|
map01bf@622
|
352 if (PyDict_SetItem(outgoing, thisKey,newBits)){
|
map01bf@622
|
353 printf("key : %s\ndist : %f\nqpos : %i\nipos : %i\n", result->results[i].key, result->results[i].dist, result->results[i].qpos, result->results[i].ipos);
|
map01bf@622
|
354 PyErr_SetString(PyExc_AttributeError, "Error adding a tuple to the result dict\n");
|
map01bf@622
|
355 // PyObject_Print(newBits, STDOUT, Py_PRINT_RAW);
|
map01bf@622
|
356 Py_XDECREF(newBits);
|
map01bf@622
|
357 return NULL;
|
map01bf@622
|
358 }
|
map01bf@622
|
359 Py_DECREF(newBits);
|
map01bf@622
|
360 }else {
|
map01bf@622
|
361 //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@622
|
362 currentValue = PyDict_GetItem(outgoing, thisKey);
|
map01bf@622
|
363 if (!PyList_Check(currentValue)){
|
map01bf@622
|
364 //add some error msg...
|
map01bf@622
|
365 return NULL;
|
map01bf@622
|
366 }
|
map01bf@622
|
367 newBits = Py_BuildValue("dII",result->results[i].dist,
|
map01bf@622
|
368 result->results[i].qpos,
|
map01bf@622
|
369 result->results[i].ipos);
|
map01bf@622
|
370 if (PyList_Append(currentValue, newBits)){
|
map01bf@622
|
371 //error msg here
|
map01bf@622
|
372 Py_XDECREF(newBits);
|
map01bf@622
|
373 return NULL;
|
map01bf@622
|
374 }
|
map01bf@622
|
375 if (PyDict_SetItem(outgoing, thisKey, newBits)){
|
map01bf@622
|
376 PyErr_SetString(PyExc_AttributeError, "Error adding a tuple to the result dict\n");
|
map01bf@622
|
377 // PyObject_Print(newBits, STDOUT, Py_PRINT_RAW);
|
map01bf@622
|
378 Py_XDECREF(newBits);
|
map01bf@622
|
379 return NULL;
|
map01bf@622
|
380 }
|
map01bf@622
|
381 Py_DECREF(newBits);
|
map01bf@622
|
382
|
map01bf@622
|
383 }
|
map01bf@622
|
384 }
|
map01bf@622
|
385 if (!audiodb_query_free_results(current_db, spec, result)){
|
map01bf@622
|
386 printf("bit of trouble freeing the result and spec...\ncheck for leaks.");
|
map01bf@622
|
387 }
|
map01bf@622
|
388
|
map01bf@622
|
389 return outgoing;
|
map01bf@622
|
390
|
map01bf@622
|
391
|
map01bf@622
|
392
|
map01bf@622
|
393 }
|
map01bf@622
|
394
|
map01bf@622
|
395
|
map01bf@622
|
396
|
map01bf@622
|
397
|
map01bf@622
|
398
|
map01bf@622
|
399
|
map01bf@622
|
400
|
map01bf@621
|
401
|
map01bf@620
|
402
|
map01bf@620
|
403 /* close a database */
|
map01bf@620
|
404 /* api call: */
|
map01bf@620
|
405 // void audiodb_close(adb_ptr db);
|
map01bf@620
|
406 static void _pyadb_close(void *ptr)
|
map01bf@620
|
407 {
|
map01bf@620
|
408 adb_ptr stale_database;
|
map01bf@620
|
409 stale_database = (adb_ptr)ptr;
|
map01bf@620
|
410
|
map01bf@620
|
411 audiodb_close(stale_database);
|
map01bf@620
|
412 }
|
map01bf@620
|
413
|
map01bf@620
|
414 static PyMethodDef _pyadbMethods[] =
|
map01bf@620
|
415 {
|
map01bf@620
|
416 { "_pyadb_create", _pyadb_create, METH_VARARGS,
|
map01bf@620
|
417 "_pyadb_create(string path, unsigned datasize, unsigned ntracks, unsigned datadim)->adb object"},
|
map01bf@620
|
418 { "_pyadb_open", _pyadb_open, METH_VARARGS,
|
map01bf@620
|
419 "_pyadb_open(string path, [\'r\'|\'w\'])->adb object\nNote that specifing \'w\' opens the file in read and write mode. \
|
map01bf@620
|
420 There is currently no way to open in write only."},
|
map01bf@620
|
421 { "_pyadb_status", _pyadb_status, METH_VARARGS,
|
map01bf@620
|
422 "_status(adb_ptr)->(numFiles, dims, dudCount, nullCount, flags, length, data_region_size)"},
|
map01bf@620
|
423 { "_pyadb_l2norm", _pyadb_l2norm, METH_VARARGS,
|
map01bf@620
|
424 "_pyadb_l2norm(adb_ptr)->int return code (0 for sucess)"},
|
map01bf@620
|
425 { "_pyadb_power", _pyadb_power, METH_VARARGS,
|
map01bf@620
|
426 "_pyadb_power(adb_ptr)->int return code (0 for sucess)"},
|
map01bf@622
|
427 { "_pyadb_insertFromFile", (PyCFunction)_pyadb_insertFromFile, METH_VARARGS | METH_KEYWORDS,
|
map01bf@621
|
428 "_pyadb_insertFromFile(adb_ptr, features=featureFile, [power=powerfile | key=keystring | times=timingFile])->\
|
map01bf@621
|
429 int return code (0 for sucess)"},
|
map01bf@622
|
430 { "_pyadb_queryFromKey", (PyCFunction)_pyadb_queryFromKey, METH_VARARGS | METH_KEYWORDS,
|
map01bf@622
|
431 "base query. The nomenclature here is about a far away as pythonic as is possible.\n\
|
map01bf@622
|
432 This should be taken care of via the higher level python structure\n\
|
map01bf@622
|
433 returns a dict that should be result ordered and key = result key\n\
|
map01bf@622
|
434 and value is a list of tuples one per result associated with that key, of the form:\n\
|
map01bf@622
|
435 \t(dist, qpos, ipos)\n\
|
map01bf@622
|
436 Note as well that this is by no means the most efficient way to cast from C, simply the most direct\n\
|
map01bf@622
|
437 and what it lacks in effeciency it gains in python side access. It remains to be seen if this is\n\
|
map01bf@622
|
438 a sensible trade.\n\
|
map01bf@622
|
439 _pyadb_queryFromKey(adb_ptr, query key,\n\
|
map01bf@622
|
440 [seqLength = Int Sequence Length, \n\
|
map01bf@622
|
441 seqStart = Int offset from start for key, \n\
|
map01bf@622
|
442 exhaustive = boolean - True for exhaustive (false by default),\n\
|
map01bf@622
|
443 falsePositives= boolean - True to keep fps (false by defaults),\n\
|
map01bf@622
|
444 accumulation = [\"db\"|\"track\"|\"one2one\"] (\"db\" by default),\n\
|
map01bf@622
|
445 distance = [\"dot\"|\"eucNorm\"|\"euclidean\"] (\"dot\" by default),\n\
|
map01bf@622
|
446 npoints = int number of points per track,\n\
|
map01bf@622
|
447 ntracks = max number of results returned in db accu mode,\n\
|
map01bf@622
|
448 includeKeys = list of strings to include (use all by default),\n\
|
map01bf@622
|
449 excludeKeys = list of strings to exclude (none by default),\n\
|
map01bf@622
|
450 radius = double of nnRadius (1.0 default, overrides npoints if specified),\n\
|
map01bf@622
|
451 absThres = double absolute power threshold (db must have power),\n\
|
map01bf@622
|
452 relThres = double relative power threshold (db must have power),\n\
|
map01bf@622
|
453 durRatio = double time expansion/compresion ratio,\n\
|
map01bf@622
|
454 hopSize = int hopsize (1 by default)])->resultDict\n"},
|
map01bf@620
|
455 {NULL,NULL, 0, NULL}
|
map01bf@620
|
456 };
|
map01bf@620
|
457
|
map01bf@620
|
458 void init_pyadb()
|
map01bf@620
|
459 {
|
map01bf@620
|
460 Py_InitModule3("_pyadb", _pyadbMethods, "internal c bindings for audioDB. Use pyadb for pythonic access to adb (when it exists).");
|
map01bf@620
|
461 // import_array();
|
map01bf@620
|
462 return;
|
map01bf@620
|
463 }
|
map01bf@620
|
464
|
map01bf@620
|
465
|