diff 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
line wrap: on
line diff
--- a/PyPluginObject.cpp	Wed Nov 26 15:23:56 2014 +0000
+++ b/PyPluginObject.cpp	Wed Nov 26 15:58:46 2014 +0000
@@ -376,6 +376,52 @@
     return pyFs;
 }
 
+static vector<vector<float> >
+convertPluginInput(PyObject *pyBuffer, int channels, int blockSize)
+{
+    vector<vector<float> > data;
+
+    VectorConversion conv;
+
+    if (PyArray_CheckExact(pyBuffer)) {
+
+        data = conv.Py2DArray_To_FloatVector(pyBuffer);
+
+        if (conv.error) {
+            PyErr_SetString(PyExc_TypeError, conv.getError().str().c_str());
+            return data;
+        }
+
+    } else {
+        
+        if (!PyList_Check(pyBuffer)) {
+            PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
+            return data;
+        }
+
+        if (PyList_GET_SIZE(pyBuffer) != channels) {
+            cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
+            PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
+            return data;
+        }
+
+        for (int c = 0; c < channels; ++c) {
+            PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
+            data.push_back(conv.PyValue_To_FloatVector(cbuf));
+        }
+    
+        for (int c = 0; c < channels; ++c) {
+            if ((int)data[c].size() != blockSize) {
+                cerr << "Wrong number of samples on channel " << c << ": expected " << blockSize << " (plugin's block size), got " << data[c].size() << endl;
+                PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
+                return vector<vector<float> >();
+            }
+        }
+    }
+    
+    return data;
+}
+
 static PyObject *
 process(PyObject *self, PyObject *args)
 {
@@ -386,18 +432,13 @@
                           &pyBuffer,                    // Audio data
                           &pyRealTime)) {               // TimeStamp
         PyErr_SetString(PyExc_TypeError,
-                        "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments");
+                        "process() takes plugin handle (object), buffer (list of arrays of floats, one array per channel) and timestamp (RealTime) arguments");
         return 0; }
 
     if (!PyRealTime_Check(pyRealTime)) {
-        PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
+        PyErr_SetString(PyExc_TypeError, "Valid timestamp required.");
         return 0; }
 
-    if (!PyList_Check(pyBuffer)) {
-        PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
-        return 0;
-    }
-
     PyPluginObject *pd = getPluginObject(self);
     if (!pd) return 0;
 
@@ -407,37 +448,17 @@
         return 0;
     }
 
-    int channels =  pd->channels;
-
-    if (PyList_GET_SIZE(pyBuffer) != channels) {
-        cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
-        PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
-        return 0;
-    }
+    int channels = pd->channels;
+    vector<vector<float> > data =
+        convertPluginInput(pyBuffer, channels, pd->blockSize);
+    if (data.empty()) return 0;
 
     float **inbuf = new float *[channels];
-
-    VectorConversion typeConv;
-
-    vector<vector<float> > data;
     for (int c = 0; c < channels; ++c) {
-        PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
-        data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
-    }
-    
-    for (int c = 0; c < channels; ++c) {
-        if (data[c].size() != pd->blockSize) {
-            cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
-            PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
-            return 0;
-        }
         inbuf[c] = &data[c][0];
     }
-
     RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
-
     Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
-
     delete[] inbuf;
 
     return convertFeatureSet(fs);
@@ -590,7 +611,7 @@
     PyObject_GenericSetAttr,            /*tp_setattro*/
     0,                                  /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT,                 /*tp_flags*/
-    "Vamp plugin object.",                    /*tp_doc*/
+    "Plugin object, providing a low-level API for running a Vamp plugin.", /*tp_doc*/
     0,                                  /*tp_traverse*/
     0,                                  /*tp_clear*/
     0,                                  /*tp_richcompare*/