comparison PyPluginObject.cpp @ 40:fa3f80d4e340

2D array conversion (incorrect, crashing)
author Chris Cannam
date Wed, 26 Nov 2014 15:58:46 +0000
parents 13dcfe8c7ed7
children 55fcd0e3e513
comparison
equal deleted inserted replaced
39:13dcfe8c7ed7 40:fa3f80d4e340
374 } 374 }
375 375
376 return pyFs; 376 return pyFs;
377 } 377 }
378 378
379 static vector<vector<float> >
380 convertPluginInput(PyObject *pyBuffer, int channels, int blockSize)
381 {
382 vector<vector<float> > data;
383
384 VectorConversion conv;
385
386 if (PyArray_CheckExact(pyBuffer)) {
387
388 data = conv.Py2DArray_To_FloatVector(pyBuffer);
389
390 if (conv.error) {
391 PyErr_SetString(PyExc_TypeError, conv.getError().str().c_str());
392 return data;
393 }
394
395 } else {
396
397 if (!PyList_Check(pyBuffer)) {
398 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
399 return data;
400 }
401
402 if (PyList_GET_SIZE(pyBuffer) != channels) {
403 cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
404 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
405 return data;
406 }
407
408 for (int c = 0; c < channels; ++c) {
409 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
410 data.push_back(conv.PyValue_To_FloatVector(cbuf));
411 }
412
413 for (int c = 0; c < channels; ++c) {
414 if ((int)data[c].size() != blockSize) {
415 cerr << "Wrong number of samples on channel " << c << ": expected " << blockSize << " (plugin's block size), got " << data[c].size() << endl;
416 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
417 return vector<vector<float> >();
418 }
419 }
420 }
421
422 return data;
423 }
424
379 static PyObject * 425 static PyObject *
380 process(PyObject *self, PyObject *args) 426 process(PyObject *self, PyObject *args)
381 { 427 {
382 PyObject *pyBuffer; 428 PyObject *pyBuffer;
383 PyObject *pyRealTime; 429 PyObject *pyRealTime;
384 430
385 if (!PyArg_ParseTuple(args, "OO", 431 if (!PyArg_ParseTuple(args, "OO",
386 &pyBuffer, // Audio data 432 &pyBuffer, // Audio data
387 &pyRealTime)) { // TimeStamp 433 &pyRealTime)) { // TimeStamp
388 PyErr_SetString(PyExc_TypeError, 434 PyErr_SetString(PyExc_TypeError,
389 "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments"); 435 "process() takes plugin handle (object), buffer (list of arrays of floats, one array per channel) and timestamp (RealTime) arguments");
390 return 0; } 436 return 0; }
391 437
392 if (!PyRealTime_Check(pyRealTime)) { 438 if (!PyRealTime_Check(pyRealTime)) {
393 PyErr_SetString(PyExc_TypeError,"Valid timestamp required."); 439 PyErr_SetString(PyExc_TypeError, "Valid timestamp required.");
394 return 0; } 440 return 0; }
395
396 if (!PyList_Check(pyBuffer)) {
397 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
398 return 0;
399 }
400 441
401 PyPluginObject *pd = getPluginObject(self); 442 PyPluginObject *pd = getPluginObject(self);
402 if (!pd) return 0; 443 if (!pd) return 0;
403 444
404 if (!pd->isInitialised) { 445 if (!pd->isInitialised) {
405 PyErr_SetString(PyExc_StandardError, 446 PyErr_SetString(PyExc_StandardError,
406 "Plugin has not been initialised."); 447 "Plugin has not been initialised.");
407 return 0; 448 return 0;
408 } 449 }
409 450
410 int channels = pd->channels; 451 int channels = pd->channels;
411 452 vector<vector<float> > data =
412 if (PyList_GET_SIZE(pyBuffer) != channels) { 453 convertPluginInput(pyBuffer, channels, pd->blockSize);
413 cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl; 454 if (data.empty()) return 0;
414 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
415 return 0;
416 }
417 455
418 float **inbuf = new float *[channels]; 456 float **inbuf = new float *[channels];
419
420 VectorConversion typeConv;
421
422 vector<vector<float> > data;
423 for (int c = 0; c < channels; ++c) { 457 for (int c = 0; c < channels; ++c) {
424 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
425 data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
426 }
427
428 for (int c = 0; c < channels; ++c) {
429 if (data[c].size() != pd->blockSize) {
430 cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
431 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
432 return 0;
433 }
434 inbuf[c] = &data[c][0]; 458 inbuf[c] = &data[c][0];
435 } 459 }
436
437 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime); 460 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
438
439 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp); 461 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
440
441 delete[] inbuf; 462 delete[] inbuf;
442 463
443 return convertFeatureSet(fs); 464 return convertFeatureSet(fs);
444 } 465 }
445 466
588 0, /*tp_str*/ 609 0, /*tp_str*/
589 PyObject_GenericGetAttr, /*tp_getattro*/ 610 PyObject_GenericGetAttr, /*tp_getattro*/
590 PyObject_GenericSetAttr, /*tp_setattro*/ 611 PyObject_GenericSetAttr, /*tp_setattro*/
591 0, /*tp_as_buffer*/ 612 0, /*tp_as_buffer*/
592 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 613 Py_TPFLAGS_DEFAULT, /*tp_flags*/
593 "Vamp plugin object.", /*tp_doc*/ 614 "Plugin object, providing a low-level API for running a Vamp plugin.", /*tp_doc*/
594 0, /*tp_traverse*/ 615 0, /*tp_traverse*/
595 0, /*tp_clear*/ 616 0, /*tp_clear*/
596 0, /*tp_richcompare*/ 617 0, /*tp_richcompare*/
597 0, /*tp_weaklistoffset*/ 618 0, /*tp_weaklistoffset*/
598 0, /*tp_iter*/ 619 0, /*tp_iter*/