[py] digital_filter.set_* raise ValueError (see #gh-241)
[aubio.git] / python / ext / py-filter.c
index ad508be..19dcc60 100644 (file)
@@ -5,9 +5,63 @@ typedef struct
   PyObject_HEAD
   aubio_filter_t * o;
   uint_t order;
+  fvec_t vec;
+  PyObject *out;
+  fvec_t c_out;
 } Py_filter;
 
-static char Py_filter_doc[] = "filter object";
+static char Py_filter_doc[] = ""
+"digital_filter(order=7)\n"
+"\n"
+"Create a digital filter.\n"
+"";
+
+static char Py_filter_set_c_weighting_doc[] = ""
+"set_c_weighting(samplerate)\n"
+"\n"
+"Set filter coefficients to C-weighting.\n"
+"\n"
+"`samplerate` should be one of 8000, 11025, 16000, 22050, 24000, 32000,\n"
+"44100, 48000, 88200, 96000, or 192000. `order` of the filter should be 5.\n"
+"\n"
+"Parameters\n"
+"----------\n"
+"samplerate : int\n"
+"    Sampling-rate of the input signal, in Hz.\n"
+"";
+
+static char Py_filter_set_a_weighting_doc[] = ""
+"set_a_weighting(samplerate)\n"
+"\n"
+"Set filter coefficients to A-weighting.\n"
+"\n"
+"`samplerate` should be one of 8000, 11025, 16000, 22050, 24000, 32000,\n"
+"44100, 48000, 88200, 96000, or 192000. `order` of the filter should be 7.\n"
+"\n"
+"Parameters\n"
+"----------\n"
+"samplerate : int\n"
+"    Sampling-rate of the input signal.\n"
+"";
+
+static char Py_filter_set_biquad_doc[] = ""
+"set_biquad(b0, b1, b2, a1, a2)\n"
+"\n"
+"Set biquad coefficients. `order` of the filter should be 3.\n"
+"\n"
+"Parameters\n"
+"----------\n"
+"b0 : float\n"
+"    Forward filter coefficient.\n"
+"b1 : float\n"
+"    Forward filter coefficient.\n"
+"b2 : float\n"
+"    Forward filter coefficient.\n"
+"a1 : float\n"
+"    Feedback filter coefficient.\n"
+"a2 : float\n"
+"    Feedback filter coefficient.\n"
+"";
 
 static PyObject *
 Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
@@ -47,22 +101,23 @@ Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds)
   if (self->o == NULL) {
     return -1;
   }
-
+  self->out = NULL;
   return 0;
 }
 
 static void
 Py_filter_del (Py_filter * self)
 {
-  del_aubio_filter (self->o);
+  Py_XDECREF(self->out);
+  if (self->o)
+    del_aubio_filter (self->o);
   Py_TYPE(self)->tp_free ((PyObject *) self);
 }
 
-static PyObject * 
+static PyObject *
 Py_filter_do(Py_filter * self, PyObject * args)
 {
   PyObject *input;
-  fvec_t *vec;
 
   if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) {
     return NULL;
@@ -72,19 +127,25 @@ Py_filter_do(Py_filter * self, PyObject * args)
     return NULL;
   }
 
-  vec = PyAubio_ArrayToCFvec (input);
-
-  if (vec == NULL) {
+  if (!PyAubio_ArrayToCFvec(input, &(self->vec))) {
     return NULL;
   }
 
+  // initialize output now
+  if (self->out == NULL) {
+    self->out = new_py_fvec(self->vec.length);
+  }
+
+  Py_INCREF(self->out);
+  if (!PyAubio_ArrayToCFvec(self->out, &(self->c_out)) ) {
+    return NULL;
+  }
   // compute the function
-  fvec_t * out = new_fvec(vec->length);
-  aubio_filter_do_outplace (self->o, vec, out);
-  return PyAubio_CFvecToArray(out);
+  aubio_filter_do_outplace (self->o, &(self->vec), &(self->c_out));
+  return self->out;
 }
 
-static PyObject * 
+static PyObject *
 Py_filter_set_c_weighting (Py_filter * self, PyObject *args)
 {
   uint_t err = 0;
@@ -95,14 +156,21 @@ Py_filter_set_c_weighting (Py_filter * self, PyObject *args)
 
   err = aubio_filter_set_c_weighting (self->o, samplerate);
   if (err > 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "error when setting filter to C-weighting");
+    if (PyErr_Occurred() == NULL) {
+      PyErr_SetString (PyExc_ValueError,
+          "error when setting filter to C-weighting");
+    } else {
+      // change the RuntimeError into ValueError
+      PyObject *type, *value, *traceback;
+      PyErr_Fetch(&type, &value, &traceback);
+      PyErr_Restore(PyExc_ValueError, value, traceback);
+    }
     return NULL;
   }
   Py_RETURN_NONE;
 }
 
-static PyObject * 
+static PyObject *
 Py_filter_set_a_weighting (Py_filter * self, PyObject *args)
 {
   uint_t err = 0;
@@ -113,8 +181,15 @@ Py_filter_set_a_weighting (Py_filter * self, PyObject *args)
 
   err = aubio_filter_set_a_weighting (self->o, samplerate);
   if (err > 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "error when setting filter to A-weighting");
+    if (PyErr_Occurred() == NULL) {
+      PyErr_SetString (PyExc_ValueError,
+          "error when setting filter to A-weighting");
+    } else {
+      // change the RuntimeError into ValueError
+      PyObject *type, *value, *traceback;
+      PyErr_Fetch(&type, &value, &traceback);
+      PyErr_Restore(PyExc_ValueError, value, traceback);
+    }
     return NULL;
   }
   Py_RETURN_NONE;
@@ -131,8 +206,15 @@ Py_filter_set_biquad(Py_filter * self, PyObject *args)
 
   err = aubio_filter_set_biquad (self->o, b0, b1, b2, a1, a2);
   if (err > 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "error when setting filter with biquad coefficients");
+    if (PyErr_Occurred() == NULL) {
+      PyErr_SetString (PyExc_ValueError,
+          "error when setting filter with biquad coefficients");
+    } else {
+      // change the RuntimeError into ValueError
+      PyObject *type, *value, *traceback;
+      PyErr_Fetch(&type, &value, &traceback);
+      PyErr_Restore(PyExc_ValueError, value, traceback);
+    }
     return NULL;
   }
   Py_RETURN_NONE;
@@ -147,17 +229,16 @@ static PyMemberDef Py_filter_members[] = {
 
 static PyMethodDef Py_filter_methods[] = {
   {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_VARARGS,
-      "set filter coefficients to C-weighting"},
+      Py_filter_set_c_weighting_doc},
   {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_VARARGS,
-      "set filter coefficients to A-weighting"},
+      Py_filter_set_a_weighting_doc},
   {"set_biquad", (PyCFunction) Py_filter_set_biquad, METH_VARARGS,
-      "set b0, b1, b2, a1, a2 biquad coefficients"},
+      Py_filter_set_biquad_doc},
   {NULL}
 };
 
 PyTypeObject Py_filterType = {
-  PyObject_HEAD_INIT (NULL)
-  0,                            /* ob_size           */
+  PyVarObject_HEAD_INIT(NULL, 0)
   "aubio.digital_filter",       /* tp_name           */
   sizeof (Py_filter),           /* tp_basicsize      */
   0,                            /* tp_itemsize       */
@@ -195,4 +276,13 @@ PyTypeObject Py_filterType = {
   (initproc) Py_filter_init,    /* tp_init           */
   0,                            /* tp_alloc          */
   Py_filter_new,                /* tp_new            */
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
 };