comparison PyPluginObject.cpp @ 35:24eedd23a812

Fix outputs, add getRemainingFeatures
author Chris Cannam
date Wed, 26 Nov 2014 13:45:25 +0000
parents f0195e45351b
children 20a9fcbc2f5f
comparison
equal deleted inserted replaced
34:f0195e45351b 35:24eedd23a812
113 (infodict, "copyright", pystr(plugin->getCopyright())); 113 (infodict, "copyright", pystr(plugin->getCopyright()));
114 pd->info = infodict; 114 pd->info = infodict;
115 115
116 pd->inputDomain = plugin->getInputDomain(); 116 pd->inputDomain = plugin->getInputDomain();
117 117
118 VectorConversion conv;
119
118 Plugin::ParameterList pl = plugin->getParameterDescriptors(); 120 Plugin::ParameterList pl = plugin->getParameterDescriptors();
119
120 PyObject *params = PyList_New(pl.size()); 121 PyObject *params = PyList_New(pl.size());
121
122 VectorConversion conv;
123 122
124 for (int i = 0; i < (int)pl.size(); ++i) { 123 for (int i = 0; i < (int)pl.size(); ++i) {
125 PyObject *paramdict = PyDict_New(); 124 PyObject *paramdict = PyDict_New();
126 PyDict_SetItemString 125 PyDict_SetItemString
127 (paramdict, "identifier", pystr(pl[i].identifier)); 126 (paramdict, "identifier", pystr(pl[i].identifier));
153 152
154 PyList_SET_ITEM(params, i, paramdict); 153 PyList_SET_ITEM(params, i, paramdict);
155 } 154 }
156 155
157 pd->parameters = params; 156 pd->parameters = params;
157
158 Plugin::OutputList ol = plugin->getOutputDescriptors();
159 PyObject *outputs = PyList_New(ol.size());
160
161 for (int i = 0; i < (int)ol.size(); ++i) {
162 PyObject *outdict = PyDict_New();
163 PyDict_SetItemString
164 (outdict, "identifier", pystr(ol[i].identifier));
165 PyDict_SetItemString
166 (outdict, "name", pystr(ol[i].name));
167 PyDict_SetItemString
168 (outdict, "description", pystr(ol[i].description));
169 PyDict_SetItemString
170 (outdict, "binCount", PyInt_FromLong(ol[i].binCount));
171 if (ol[i].binCount > 0) {
172 if (ol[i].hasKnownExtents) {
173 PyDict_SetItemString
174 (outdict, "hasKnownExtents", Py_True);
175 PyDict_SetItemString
176 (outdict, "minValue", PyFloat_FromDouble(ol[i].minValue));
177 PyDict_SetItemString
178 (outdict, "maxValue", PyFloat_FromDouble(ol[i].maxValue));
179 } else {
180 PyDict_SetItemString
181 (outdict, "hasKnownExtents", Py_False);
182 }
183 if (ol[i].isQuantized) {
184 PyDict_SetItemString
185 (outdict, "isQuantized", Py_True);
186 PyDict_SetItemString
187 (outdict, "quantizeStep", PyFloat_FromDouble(ol[i].quantizeStep));
188 } else {
189 PyDict_SetItemString
190 (outdict, "isQuantized", Py_False);
191 }
192 }
193 PyDict_SetItemString
194 (outdict, "sampleType", PyInt_FromLong((int)ol[i].sampleType));
195 PyDict_SetItemString
196 (outdict, "sampleRate", PyFloat_FromDouble(ol[i].sampleRate));
197 PyDict_SetItemString
198 (outdict, "hasDuration", ol[i].hasDuration ? Py_True : Py_False);
199
200 PyList_SET_ITEM(outputs, i, outdict);
201 }
202
203 pd->outputs = outputs;
158 204
159 return (PyObject *)pd; 205 return (PyObject *)pd;
160 } 206 }
161 207
162 static void 208 static void
257 303
258 pd->plugin->setParameter(PyString_AS_STRING(pyParam), value); 304 pd->plugin->setParameter(PyString_AS_STRING(pyParam), value);
259 return Py_True; 305 return Py_True;
260 } 306 }
261 307
262 static PyObject * 308 static
263 vampyhost_process(PyObject *self, PyObject *args) 309 PyObject *
264 { 310 convertFeatureSet(const Plugin::FeatureSet &fs)
265 cerr << "vampyhost_process" << endl; 311 {
266
267 PyObject *pyBuffer;
268 PyObject *pyRealTime;
269
270 if (!PyArg_ParseTuple(args, "OO",
271 &pyBuffer, // Audio data
272 &pyRealTime)) { // TimeStamp
273 PyErr_SetString(PyExc_TypeError,
274 "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments");
275 return 0; }
276
277 if (!PyRealTime_Check(pyRealTime)) {
278 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
279 return 0; }
280
281 if (!PyList_Check(pyBuffer)) {
282 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
283 return 0;
284 }
285
286 PyPluginObject *pd = getPluginObject(self);
287 if (!pd) return 0;
288
289 if (!pd->isInitialised) {
290 PyErr_SetString(PyExc_StandardError,
291 "Plugin has not been initialised.");
292 return 0;
293 }
294
295 int channels = pd->channels;
296
297 if (PyList_GET_SIZE(pyBuffer) != channels) {
298 cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
299 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
300 return 0;
301 }
302
303 float **inbuf = new float *[channels];
304
305 VectorConversion typeConv;
306
307 vector<vector<float> > data;
308 for (int c = 0; c < channels; ++c) {
309 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
310 data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
311 }
312
313 for (int c = 0; c < channels; ++c) {
314 if (data[c].size() != pd->blockSize) {
315 cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
316 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
317 return 0;
318 }
319 inbuf[c] = &data[c][0];
320 }
321
322 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
323
324 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
325
326 delete[] inbuf;
327
328 VectorConversion conv; 312 VectorConversion conv;
329 313
330 PyObject *pyFs = PyDict_New(); 314 PyObject *pyFs = PyDict_New();
331 315
332 for (Plugin::FeatureSet::const_iterator fsi = fs.begin(); 316 for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
371 355
372 return pyFs; 356 return pyFs;
373 } 357 }
374 358
375 static PyObject * 359 static PyObject *
360 vampyhost_process(PyObject *self, PyObject *args)
361 {
362 cerr << "vampyhost_process" << endl;
363
364 PyObject *pyBuffer;
365 PyObject *pyRealTime;
366
367 if (!PyArg_ParseTuple(args, "OO",
368 &pyBuffer, // Audio data
369 &pyRealTime)) { // TimeStamp
370 PyErr_SetString(PyExc_TypeError,
371 "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments");
372 return 0; }
373
374 if (!PyRealTime_Check(pyRealTime)) {
375 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
376 return 0; }
377
378 if (!PyList_Check(pyBuffer)) {
379 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
380 return 0;
381 }
382
383 PyPluginObject *pd = getPluginObject(self);
384 if (!pd) return 0;
385
386 if (!pd->isInitialised) {
387 PyErr_SetString(PyExc_StandardError,
388 "Plugin has not been initialised.");
389 return 0;
390 }
391
392 int channels = pd->channels;
393
394 if (PyList_GET_SIZE(pyBuffer) != channels) {
395 cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
396 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
397 return 0;
398 }
399
400 float **inbuf = new float *[channels];
401
402 VectorConversion typeConv;
403
404 vector<vector<float> > data;
405 for (int c = 0; c < channels; ++c) {
406 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
407 data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
408 }
409
410 for (int c = 0; c < channels; ++c) {
411 if (data[c].size() != pd->blockSize) {
412 cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
413 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
414 return 0;
415 }
416 inbuf[c] = &data[c][0];
417 }
418
419 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
420
421 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
422
423 delete[] inbuf;
424
425 return convertFeatureSet(fs);
426 }
427
428 static PyObject *
429 vampyhost_getRemainingFeatures(PyObject *self, PyObject *)
430 {
431 cerr << "vampyhost_getRemainingFeatures" << endl;
432
433 PyPluginObject *pd = getPluginObject(self);
434 if (!pd) return 0;
435
436 if (!pd->isInitialised) {
437 PyErr_SetString(PyExc_StandardError,
438 "Plugin has not been initialised.");
439 return 0;
440 }
441
442 Plugin::FeatureSet fs = pd->plugin->getRemainingFeatures();
443
444 return convertFeatureSet(fs);
445 }
446
447 static PyObject *
376 vampyhost_unload(PyObject *self, PyObject *) 448 vampyhost_unload(PyObject *self, PyObject *)
377 { 449 {
378 cerr << "vampyhost_unloadPlugin" << endl; 450 cerr << "vampyhost_unloadPlugin" << endl;
379 451
380 PyPluginObject *pd = getPluginObject(self); 452 PyPluginObject *pd = getPluginObject(self);
395 {(char *)"inputDomain", T_INT, offsetof(PyPluginObject, inputDomain), READONLY, 467 {(char *)"inputDomain", T_INT, offsetof(PyPluginObject, inputDomain), READONLY,
396 xx_foo_doc}, 468 xx_foo_doc},
397 469
398 {(char *)"parameters", T_OBJECT, offsetof(PyPluginObject, parameters), READONLY, 470 {(char *)"parameters", T_OBJECT, offsetof(PyPluginObject, parameters), READONLY,
399 xx_foo_doc}, 471 xx_foo_doc},
472
473 {(char *)"outputs", T_OBJECT, offsetof(PyPluginObject, outputs), READONLY,
474 xx_foo_doc},
400 475
401 {0, 0} 476 {0, 0}
402 }; 477 };
403 478
404 static PyMethodDef PyPluginObject_methods[] = 479 static PyMethodDef PyPluginObject_methods[] =
414 489
415 {"reset", vampyhost_reset, METH_NOARGS, 490 {"reset", vampyhost_reset, METH_NOARGS,
416 xx_foo_doc}, 491 xx_foo_doc},
417 492
418 {"process", vampyhost_process, METH_VARARGS, 493 {"process", vampyhost_process, METH_VARARGS,
494 xx_foo_doc},
495
496 {"getRemainingFeatures", vampyhost_getRemainingFeatures, METH_NOARGS,
419 xx_foo_doc}, 497 xx_foo_doc},
420 498
421 {"unload", vampyhost_unload, METH_NOARGS, 499 {"unload", vampyhost_unload, METH_NOARGS,
422 xx_foo_doc}, 500 xx_foo_doc},
423 501