ref: f826349105769d84a141f6883102dc7f6b7e2d1b
parent: 9b23eb311431d5862a5920b69082cca1a93bcb8e
author: Paul Brossier <piem@piem.org>
date: Mon Oct 5 22:50:49 EDT 2009
interfaces/python: add cvec and filter types
--- /dev/null
+++ b/interfaces/python/py-cvec.c
@@ -1,0 +1,331 @@
+#include "aubio-types.h"
+
+/* cvec type definition
+
+class cvec():
+ def __init__(self, length = 1024, channels = 1):
+ self.length = length
+ self.channels = channels
+ self.norm = array(length, channels)
+ self.phas = array(length, channels)
+
+*/
+
+typedef struct
+{
+ PyObject_HEAD
+ cvec_t * o;
+ uint_t length;
+ uint_t channels;
+} Py_cvec;
+
+static char Py_cvec_doc[] = "cvec object";
+
+static PyObject *
+Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
+{
+ int length= 0, channels = 0;
+ Py_cvec *self;
+ static char *kwlist[] = { "length", "channels", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
+ &length, &channels)) {
+ return NULL;
+ }
+
+
+ self = (Py_cvec *) type->tp_alloc (type, 0);
+
+ self->length = Py_default_vector_length;
+ self->channels = Py_default_vector_channels;
+
+ if (self == NULL) {
+ return NULL;
+ }
+
+ if (length > 0) {
+ self->length = length;
+ } else if (length < 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "can not use negative number of elements");
+ return NULL;
+ }
+
+ if (channels > 0) {
+ self->channels = channels;
+ } else if (channels < 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "can not use negative number of channels");
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
+{
+ self->o = new_cvec (self->length, self->channels);
+ if (self->o == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+Py_cvec_del (Py_cvec * self)
+{
+ del_cvec (self->o);
+ self->ob_type->tp_free ((PyObject *) self);
+}
+
+static PyObject *
+Py_cvec_repr (Py_cvec * self, PyObject * unused)
+{
+ PyObject *format = NULL;
+ PyObject *args = NULL;
+ PyObject *result = NULL;
+
+ format = PyString_FromString ("aubio cvec of %d elements with %d channels");
+ if (format == NULL) {
+ goto fail;
+ }
+
+ args = Py_BuildValue ("II", self->length, self->channels);
+ if (args == NULL) {
+ goto fail;
+ }
+ cvec_print ( self->o );
+
+ result = PyString_Format (format, args);
+
+fail:
+ Py_XDECREF (format);
+ Py_XDECREF (args);
+
+ return result;
+}
+
+Py_cvec *
+PyAubio_ArrayToCvec (PyObject *input) {
+ PyObject *array;
+ Py_cvec *vec;
+ uint_t i;
+ // parsing input object into a Py_cvec
+ if (PyObject_TypeCheck (input, &Py_cvecType)) {
+ // input is an cvec, nothing else to do
+ vec = (Py_cvec *) input;
+ } else if (PyArray_Check(input)) {
+
+ // we got an array, convert it to an cvec
+ if (PyArray_NDIM (input) == 0) {
+ PyErr_SetString (PyExc_ValueError, "input array is a scalar");
+ goto fail;
+ } else if (PyArray_NDIM (input) > 2) {
+ PyErr_SetString (PyExc_ValueError,
+ "input array has more than two dimensions");
+ goto fail;
+ }
+
+ if (!PyArray_ISFLOAT (input)) {
+ PyErr_SetString (PyExc_ValueError, "input array should be float");
+ goto fail;
+#if AUBIO_DO_CASTING
+ } else if (PyArray_TYPE (input) != AUBIO_FLOAT) {
+ // input data type is not float32, casting
+ array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_FLOAT);
+ if (array == NULL) {
+ PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT");
+ goto fail;
+ }
+#else
+ } else if (PyArray_TYPE (input) != AUBIO_FLOAT) {
+ PyErr_SetString (PyExc_ValueError, "input array should be float32");
+ goto fail;
+#endif
+ } else {
+ // input data type is float32, nothing else to do
+ array = input;
+ }
+
+ // create a new cvec object
+ vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
+ if (PyArray_NDIM (array) == 1) {
+ vec->channels = 1;
+ vec->length = PyArray_SIZE (array);
+ } else {
+ vec->channels = PyArray_DIM (array, 0);
+ vec->length = PyArray_DIM (array, 1);
+ }
+
+ // no need to really allocate cvec, just its struct member
+ // vec->o = new_cvec (vec->length, vec->channels);
+ vec->o = (cvec_t *)malloc(sizeof(cvec_t));
+ vec->o->length = vec->length; vec->o->channels = vec->channels;
+ vec->o->norm = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
+ vec->o->phas = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
+ // hat data[i] point to array line
+ for (i = 0; i < vec->channels; i++) {
+ vec->o->norm[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
+ }
+
+ } else {
+ PyErr_SetString (PyExc_ValueError, "can only accept array or cvec as input");
+ return NULL;
+ }
+
+ return vec;
+
+fail:
+ return NULL;
+}
+
+PyObject *
+PyAubio_CvecToArray (Py_cvec * self)
+{
+ PyObject *array = NULL;
+ if (self->channels == 1) {
+ npy_intp dims[] = { self->length, 1 };
+ array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[0]);
+ } else {
+ uint_t i;
+ npy_intp dims[] = { self->length, 1 };
+ PyObject *concat = PyList_New (0), *tmp = NULL;
+ for (i = 0; i < self->channels; i++) {
+ tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[i]);
+ PyList_Append (concat, tmp);
+ Py_DECREF (tmp);
+ }
+ array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
+ Py_DECREF (concat);
+ }
+ return array;
+}
+
+static Py_ssize_t
+Py_cvec_getchannels (Py_cvec * self)
+{
+ return self->channels;
+}
+
+static PyObject *
+Py_cvec_getitem (Py_cvec * self, Py_ssize_t index)
+{
+ PyObject *array;
+
+ if (index < 0 || index >= self->channels) {
+ PyErr_SetString (PyExc_IndexError, "no such channel");
+ return NULL;
+ }
+
+ npy_intp dims[] = { self->length, 1 };
+ array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[index]);
+ return array;
+}
+
+static int
+Py_cvec_setitem (Py_cvec * self, Py_ssize_t index, PyObject * o)
+{
+ PyObject *array;
+
+ if (index < 0 || index >= self->channels) {
+ PyErr_SetString (PyExc_IndexError, "no such channel");
+ return -1;
+ }
+
+ array = PyArray_FROM_OT (o, NPY_FLOAT);
+ if (array == NULL) {
+ PyErr_SetString (PyExc_ValueError, "should be an array of float");
+ goto fail;
+ }
+
+ if (PyArray_NDIM (array) != 1) {
+ PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
+ goto fail;
+ }
+
+ if (PyArray_SIZE (array) != self->length) {
+ PyErr_SetString (PyExc_ValueError,
+ "should be an array of same length as target cvec");
+ goto fail;
+ }
+
+ self->o->norm[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+static PyMemberDef Py_cvec_members[] = {
+ // TODO remove READONLY flag and define getter/setter
+ {"length", T_INT, offsetof (Py_cvec, length), READONLY,
+ "length attribute"},
+ {"channels", T_INT, offsetof (Py_cvec, channels), READONLY,
+ "channels attribute"},
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef Py_cvec_methods[] = {
+ {"__array__", (PyCFunction) PyAubio_FvecToArray, METH_NOARGS,
+ "Returns the first channel as a numpy array."},
+ {NULL}
+};
+
+static PySequenceMethods Py_cvec_tp_as_sequence = {
+ (lenfunc) Py_cvec_getchannels, /* sq_length */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ (ssizeargfunc) Py_cvec_getitem, /* sq_item */
+ 0, /* sq_slice */
+ (ssizeobjargproc) Py_cvec_setitem, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ 0, /* sq_contains */
+ 0, /* sq_inplace_concat */
+ 0, /* sq_inplace_repeat */
+};
+
+
+PyTypeObject Py_cvecType = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /* ob_size */
+ "aubio.cvec", /* tp_name */
+ sizeof (Py_cvec), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) Py_cvec_del, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc) Py_cvec_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ &Py_cvec_tp_as_sequence, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_cvec_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Py_cvec_methods, /* tp_methods */
+ Py_cvec_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) Py_cvec_init, /* tp_init */
+ 0, /* tp_alloc */
+ Py_cvec_new, /* tp_new */
+};
--- /dev/null
+++ b/interfaces/python/py-filter.c
@@ -1,0 +1,199 @@
+#include "aubio-types.h"
+
+typedef struct
+{
+ PyObject_HEAD
+ aubio_filter_t * o;
+ uint_t samplerate;
+ uint_t order;
+ uint_t channels;
+} Py_filter;
+
+static char Py_filter_doc[] = "filter object";
+
+static PyObject *
+Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
+{
+ int samplerate= 0, order= 0, channels = 0;
+ Py_filter *self;
+ static char *kwlist[] = { "samplerate", "order", "channels", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwds, "|III", kwlist,
+ &samplerate, &order, &channels)) {
+ return NULL;
+ }
+
+ self = (Py_filter *) type->tp_alloc (type, 0);
+
+ self->samplerate = Py_aubio_default_samplerate;
+ self->order = 7;
+ self->channels = Py_default_vector_channels;
+
+ if (self == NULL) {
+ return NULL;
+ }
+
+ if (samplerate > 0) {
+ self->samplerate = samplerate;
+ } else if (samplerate < 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "can not use negative samplerate");
+ return NULL;
+ }
+
+ if (order > 0) {
+ self->order = order;
+ } else if (order < 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "can not use negative order");
+ return NULL;
+ }
+
+ if (channels > 0) {
+ self->channels = channels;
+ } else if (channels < 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "can not use negative number of channels");
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds)
+{
+ self->o = new_aubio_filter (self->samplerate, self->order, self->channels);
+ if (self->o == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+Py_filter_del (Py_filter * self)
+{
+ del_aubio_filter (self->o);
+ self->ob_type->tp_free ((PyObject *) self);
+}
+
+static PyObject *
+Py_filter_do(PyObject * self, PyObject * args)
+{
+ PyObject *input;
+ Py_fvec *vec;
+
+ if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) {
+ return NULL;
+ }
+
+ if (input == NULL) {
+ return NULL;
+ }
+
+ vec = PyAubio_ArrayToFvec (input);
+
+ if (vec == NULL) {
+ return NULL;
+ }
+
+ // compute the function
+#if 1
+ aubio_filter_do (((Py_filter *)self)->o, vec->o);
+ Py_INCREF(vec);
+ return (PyObject *)vec;
+#else
+ Py_fvec *copy = (Py_fvec*) PyObject_New (Py_fvec, &Py_fvecType);
+ copy->o = new_fvec(vec->o->length, vec->o->channels);
+ aubio_filter_do_outplace (((Py_filter *)self)->o, vec->o, copy->o);
+ return (PyObject *)copy;
+#endif
+}
+
+static PyObject *
+Py_filter_set_c_weighting (Py_filter * self, PyObject *unused)
+{
+ uint_t err = aubio_filter_set_c_weighting (((Py_filter *)self)->o);
+ if (err > 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "error when setting filter to C-weighting");
+ return NULL;
+ }
+ return Py_None;
+}
+
+static PyObject *
+Py_filter_set_a_weighting (Py_filter * self, PyObject *unused)
+{
+ uint_t err = aubio_filter_set_a_weighting (((Py_filter *)self)->o);
+ if (err > 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "error when setting filter to A-weighting");
+ return NULL;
+ }
+ return Py_None;
+}
+
+static PyMemberDef Py_filter_members[] = {
+ // TODO remove READONLY flag and define getter/setter
+ {"samplerate", T_INT, offsetof (Py_filter, samplerate), READONLY,
+ "sampling rate"},
+ {"order", T_INT, offsetof (Py_filter, order), READONLY,
+ "order of the filter"},
+ {"channels", T_INT, offsetof (Py_filter, channels), READONLY,
+ "number of channels"},
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef Py_filter_methods[] = {
+ {"do", (PyCFunction) Py_filter_do, METH_VARARGS,
+ "filter input vector"},
+ {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_NOARGS,
+ "set filter coefficients to C-weighting"},
+ {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_NOARGS,
+ "set filter coefficients to A-weighting"},
+ {NULL}
+};
+
+PyTypeObject Py_filterType = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /* ob_size */
+ "aubio.digital_filter", /* tp_name */
+ sizeof (Py_filter), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) Py_filter_del, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, //(reprfunc) Py_filter_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)Py_filter_do, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_filter_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Py_filter_methods, /* tp_methods */
+ Py_filter_members, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) Py_filter_init, /* tp_init */
+ 0, /* tp_alloc */
+ Py_filter_new, /* tp_new */
+};