From 615ac7dde5b64cec5df54025d9efe96273d00a17 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Mon, 19 Oct 2009 15:08:43 +0200 Subject: [PATCH] . --- interfaces/python/aubio-types.h | 24 ++++- interfaces/python/aubiomodule.c | 17 +++- interfaces/python/py-cvec.c | 143 +++++++++++++++++++++------ interfaces/python/py-fft.c | 126 ++++++++++++++++++++++++ interfaces/python/py-filter.c | 50 +++++----- interfaces/python/py-filterbank.c | 157 ++++++++++++++++++++++++++++++ interfaces/python/py-fvec.c | 18 ++-- interfaces/python/py-phasevoc.c | 137 ++++++++++++++++++++++++++ interfaces/python/setup.py | 17 +++- interfaces/python/test_filter.py | 18 ++-- 10 files changed, 622 insertions(+), 85 deletions(-) create mode 100644 interfaces/python/py-fft.c create mode 100644 interfaces/python/py-filterbank.c create mode 100644 interfaces/python/py-phasevoc.c diff --git a/interfaces/python/aubio-types.h b/interfaces/python/aubio-types.h index d5609e7b..cbab5a0b 100644 --- a/interfaces/python/aubio-types.h +++ b/interfaces/python/aubio-types.h @@ -9,10 +9,11 @@ #define Py_aubio_default_samplerate 44100 -#ifdef HAVE_AUBIO_DOUBLE -#define AUBIO_FLOAT NPY_FLOAT +#if HAVE_AUBIO_DOUBLE +#error "Ouch! Python interface for aubio has not been much tested yet." +#define AUBIO_NPY_SMPL NPY_DOUBLE #else -#define AUBIO_FLOAT NPY_LONG +#define AUBIO_NPY_SMPL NPY_FLOAT #endif /** @@ -32,11 +33,24 @@ typedef struct uint_t channels; } Py_fvec; extern PyTypeObject Py_fvecType; +extern PyObject *PyAubio_FvecToArray (Py_fvec * self); +extern Py_fvec *PyAubio_ArrayToFvec (PyObject * self); +typedef struct +{ + PyObject_HEAD + cvec_t * o; + uint_t length; + uint_t channels; +} Py_cvec; extern PyTypeObject Py_cvecType; +extern PyObject *PyAubio_CvecToArray (Py_cvec * self); +extern Py_cvec *PyAubio_ArrayToCvec (PyObject * self); extern PyTypeObject Py_filterType; -extern PyObject *PyAubio_FvecToArray (Py_fvec * self); +extern PyTypeObject Py_filterbankType; -extern Py_fvec *PyAubio_ArrayToFvec (PyObject * self); +extern PyTypeObject Py_fftType; + +extern PyTypeObject Py_pvocType; diff --git a/interfaces/python/aubiomodule.c b/interfaces/python/aubiomodule.c index 4bd665f5..5dcac23f 100644 --- a/interfaces/python/aubiomodule.c +++ b/interfaces/python/aubiomodule.c @@ -93,6 +93,7 @@ Py_min_removal(PyObject * self, PyObject * args) // compute the function fvec_min_removal (vec->o); + // since this function does not return, we could return None //return Py_None; // however it is convenient to return the modified vector @@ -118,9 +119,13 @@ init_aubio (void) PyObject *m; int err; - if ((PyType_Ready (&Py_fvecType) < 0) || - (PyType_Ready (&Py_cvecType) < 0) || - (PyType_Ready (&Py_filterType) < 0)) { + if ((PyType_Ready (&Py_fvecType) < 0) + || (PyType_Ready (&Py_cvecType) < 0) + || (PyType_Ready (&Py_filterType) < 0) + || (PyType_Ready (&Py_filterbankType) < 0) + || (PyType_Ready (&Py_fftType) < 0) + || (PyType_Ready (&Py_pvocType) < 0) + ) { return; } @@ -143,4 +148,10 @@ init_aubio (void) PyModule_AddObject (m, "cvec", (PyObject *) & Py_cvecType); Py_INCREF (&Py_filterType); PyModule_AddObject (m, "digital_filter", (PyObject *) & Py_filterType); + Py_INCREF (&Py_filterbankType); + PyModule_AddObject (m, "filterbank", (PyObject *) & Py_filterbankType); + Py_INCREF (&Py_fftType); + PyModule_AddObject (m, "fft", (PyObject *) & Py_fftType); + Py_INCREF (&Py_pvocType); + PyModule_AddObject (m, "pvoc", (PyObject *) & Py_pvocType); } diff --git a/interfaces/python/py-cvec.c b/interfaces/python/py-cvec.c index ec25546d..5472a937 100644 --- a/interfaces/python/py-cvec.c +++ b/interfaces/python/py-cvec.c @@ -8,16 +8,8 @@ class cvec(): 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"; @@ -96,7 +88,7 @@ Py_cvec_repr (Py_cvec * self, PyObject * unused) if (args == NULL) { goto fail; } - cvec_print ( self->o ); + //cvec_print ( self->o ); result = PyString_Format (format, args); @@ -132,15 +124,15 @@ PyAubio_ArrayToCvec (PyObject *input) { PyErr_SetString (PyExc_ValueError, "input array should be float"); goto fail; #if AUBIO_DO_CASTING - } else if (PyArray_TYPE (input) != AUBIO_FLOAT) { + } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) { // input data type is not float32, casting - array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_FLOAT); + array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_NPY_SMPL); if (array == NULL) { PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT"); goto fail; } #else - } else if (PyArray_TYPE (input) != AUBIO_FLOAT) { + } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) { PyErr_SetString (PyExc_ValueError, "input array should be float32"); goto fail; #endif @@ -152,10 +144,14 @@ PyAubio_ArrayToCvec (PyObject *input) { // create a new cvec object vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); if (PyArray_NDIM (array) == 1) { + PyErr_SetString (PyExc_ValueError, + "input array should be have at least two rows for norm and phas"); + goto fail; + } else if (PyArray_NDIM (array) == 2) { vec->channels = 1; vec->length = PyArray_SIZE (array); } else { - vec->channels = PyArray_DIM (array, 0); + vec->channels = PyArray_DIM (array, 0) / 2; vec->length = PyArray_DIM (array, 1); } @@ -166,8 +162,9 @@ PyAubio_ArrayToCvec (PyObject *input) { 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++) { + for (i = 0; i < vec->channels; i+=2) { vec->o->norm[i] = (smpl_t *) PyArray_GETPTR1 (array, i); + vec->o->phas[i] = (smpl_t *) PyArray_GETPTR1 (array, i+1); } } else { @@ -185,24 +182,92 @@ 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); + uint_t i; + npy_intp dims[] = { self->o->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); + tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas[i]); + PyList_Append (concat, tmp); + Py_DECREF (tmp); + } + array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2); + Py_DECREF (concat); + return array; +} + +PyObject * +PyAubio_CvecNormToArray (Py_cvec * self) +{ + PyObject *array = NULL; + uint_t i; + npy_intp dims[] = { self->o->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; +} + +PyObject * +PyAubio_ArrayToCvecNorm (PyObject * self) +{ + return NULL; +} + +PyObject * +PyAubio_CvecPhasToArray (Py_cvec * self) +{ + PyObject *array = NULL; + uint_t i; + npy_intp dims[] = { self->o->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->phas[i]); + PyList_Append (concat, tmp); + Py_DECREF (tmp); } + array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2); + Py_DECREF (concat); return array; } +PyObject * +PyAubio_ArrayToCvecPhas (PyObject * self) +{ + return NULL; +} + +PyObject * +Py_cvec_get_norm (Py_cvec * self, void *closure) +{ + return PyAubio_CvecNormToArray(self); +} + +PyObject * +Py_cvec_get_phas (Py_cvec * self, void *closure) +{ + return PyAubio_CvecPhasToArray(self); +} + +static int +Py_cvec_set_norm (Py_cvec * self, PyObject *value, void * closure) +{ + return 0; +} + +static int +Py_cvec_set_phas (Py_cvec * self, PyObject *value, void * closure) +{ + return 0; +} + static Py_ssize_t Py_cvec_getchannels (Py_cvec * self) { @@ -269,11 +334,27 @@ static PyMemberDef Py_cvec_members[] = { }; static PyMethodDef Py_cvec_methods[] = { - {"__array__", (PyCFunction) PyAubio_FvecToArray, METH_NOARGS, - "Returns the first channel as a numpy array."}, + {"__array__", (PyCFunction) PyAubio_CvecToArray, METH_NOARGS, + "Returns the content of this cvec as a numpy array"}, +/* + {"norm", (PyCFunction) PyAubio_CvecNormToArray, METH_NOARGS, + "Returns the content of the magnitude of this cvec as a numpy array."}, + {"phas", (PyCFunction) PyAubio_CvecPhasToArray, METH_NOARGS, + "Returns the content of the phase of this cvec as a numpy array."}, +*/ {NULL} }; +static PyGetSetDef Py_cvec_getseters[] = { + {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, + "Content of the magnitude of this cvec", + NULL}, + {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, + "Content of the magnitude of this cvec", + NULL}, + {NULL} /* sentinel */ +}; + static PySequenceMethods Py_cvec_tp_as_sequence = { (lenfunc) Py_cvec_getchannels, /* sq_length */ 0, /* sq_concat */ @@ -319,7 +400,7 @@ PyTypeObject Py_cvecType = { 0, /* tp_iternext */ Py_cvec_methods, /* tp_methods */ Py_cvec_members, /* tp_members */ - 0, /* tp_getset */ + Py_cvec_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ diff --git a/interfaces/python/py-fft.c b/interfaces/python/py-fft.c new file mode 100644 index 00000000..acbeb67c --- /dev/null +++ b/interfaces/python/py-fft.c @@ -0,0 +1,126 @@ +#include "aubiowraphell.h" + +static char Py_fft_doc[] = "fft object"; + +AUBIO_DECLARE(fft, uint_t win_s; uint_t channels) + +//AUBIO_NEW(fft) +static PyObject * +Py_fft_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int win_s = 0, channels = 0; + Py_fft *self; + static char *kwlist[] = { "win_s", "channels", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, + &win_s, &channels)) { + return NULL; + } + + self = (Py_fft *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->win_s = Py_default_vector_length; + self->channels = Py_default_vector_channels; + + if (self == NULL) { + return NULL; + } + + if (win_s > 0) { + self->win_s = win_s; + } else if (win_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative window size"); + return NULL; + } + + if (channels > 0) { + self->channels = channels; + } else if (channels < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative number of filters"); + return NULL; + } + + return (PyObject *) self; +} + + +AUBIO_INIT(fft, self->win_s, self->channels) + +AUBIO_DEL(fft) + +static PyObject * +Py_fft_do(PyObject * self, PyObject * args) +{ + PyObject *input; + Py_fvec *vec; + Py_cvec *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToFvec (input); + + if (vec == NULL) { + return NULL; + } + + output = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); + output->channels = vec->channels; + output->length = ((Py_fft *) self)->win_s; + output->o = new_cvec(((Py_fft *) self)->win_s, vec->channels); + + // compute the function + aubio_fft_do (((Py_fft *)self)->o, vec->o, output->o); + Py_INCREF(output); + return (PyObject *)output; + //return (PyObject *)PyAubio_CvecToArray(output); +} + +AUBIO_MEMBERS_START(fft) + {"win_s", T_INT, offsetof (Py_fft, win_s), READONLY, + "size of the window"}, + {"channels", T_INT, offsetof (Py_fft, channels), READONLY, + "number of channels"}, +AUBIO_MEMBERS_STOP(fft) + +static PyObject * +Py_fft_rdo(PyObject * self, PyObject * args) +{ + PyObject *input; + Py_cvec *vec; + Py_fvec *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCvec (input); + + if (vec == NULL) { + return NULL; + } + + output = (Py_fvec*) PyObject_New (Py_fvec, &Py_fvecType); + output->channels = vec->channels; + output->length = ((Py_fft *) self)->win_s; + output->o = new_fvec(output->length, output->channels); + + // compute the function + aubio_fft_rdo (((Py_fft *)self)->o, vec->o, output->o); + return (PyObject *)PyAubio_FvecToArray(output); +} + +static PyMethodDef Py_fft_methods[] = { + {"rdo", (PyCFunction) Py_fft_rdo, METH_VARARGS, + "synthesis of spectral grain"}, + {NULL} +}; + +AUBIO_TYPEOBJECT(fft, "aubio.fft") diff --git a/interfaces/python/py-filter.c b/interfaces/python/py-filter.c index b7d4e86c..8d24a072 100644 --- a/interfaces/python/py-filter.c +++ b/interfaces/python/py-filter.c @@ -4,7 +4,6 @@ typedef struct { PyObject_HEAD aubio_filter_t * o; - uint_t samplerate; uint_t order; uint_t channels; } Py_filter; @@ -14,32 +13,23 @@ 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; + int order= 0, channels = 0; Py_filter *self; - static char *kwlist[] = { "samplerate", "order", "channels", NULL }; + static char *kwlist[] = { "order", "channels", NULL }; - if (!PyArg_ParseTupleAndKeywords (args, kwds, "|III", kwlist, - &samplerate, &order, &channels)) { + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, + &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; - } + self->order = 7; + self->channels = Py_default_vector_channels; if (order > 0) { self->order = order; @@ -63,7 +53,7 @@ Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds) static int Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds) { - self->o = new_aubio_filter (self->samplerate, self->order, self->channels); + self->o = new_aubio_filter (self->order, self->channels); if (self->o == NULL) { return -1; } @@ -112,21 +102,33 @@ Py_filter_do(PyObject * self, PyObject * args) } static PyObject * -Py_filter_set_c_weighting (Py_filter * self, PyObject *unused) +Py_filter_set_c_weighting (Py_filter * self, PyObject *args) { - uint_t err = aubio_filter_set_c_weighting (((Py_filter *)self)->o); + uint_t err = 0; + uint_t samplerate; + if (!PyArg_ParseTuple (args, "I", &samplerate)) { + return NULL; + } + + err = aubio_filter_set_c_weighting (self->o, samplerate); if (err > 0) { PyErr_SetString (PyExc_ValueError, - "error when setting filter to C-weighting"); + "error when setting filter to A-weighting"); return NULL; } return Py_None; } static PyObject * -Py_filter_set_a_weighting (Py_filter * self, PyObject *unused) +Py_filter_set_a_weighting (Py_filter * self, PyObject *args) { - uint_t err = aubio_filter_set_a_weighting (((Py_filter *)self)->o); + uint_t err = 0; + uint_t samplerate; + if (!PyArg_ParseTuple (args, "I", &samplerate)) { + return NULL; + } + + err = aubio_filter_set_a_weighting (self->o, samplerate); if (err > 0) { PyErr_SetString (PyExc_ValueError, "error when setting filter to A-weighting"); @@ -137,8 +139,6 @@ Py_filter_set_a_weighting (Py_filter * self, PyObject *unused) 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, @@ -147,8 +147,6 @@ static PyMemberDef Py_filter_members[] = { }; 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, diff --git a/interfaces/python/py-filterbank.c b/interfaces/python/py-filterbank.c new file mode 100644 index 00000000..f8a1307e --- /dev/null +++ b/interfaces/python/py-filterbank.c @@ -0,0 +1,157 @@ +#include "aubiowraphell.h" + +static char Py_filterbank_doc[] = "filterbank object"; + +AUBIO_DECLARE(filterbank, uint_t n_filters; uint_t win_s) + +//AUBIO_NEW(filterbank) +static PyObject * +Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int win_s = 0, n_filters = 0; + Py_filterbank *self; + static char *kwlist[] = { "n_filters", "win_s", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, + &n_filters, &win_s)) { + return NULL; + } + + self = (Py_filterbank *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->win_s = Py_default_vector_length; + if (win_s > 0) { + self->win_s = win_s; + } else if (win_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative window size"); + return NULL; + } + + self->n_filters = 40; + if (n_filters > 0) { + self->n_filters = n_filters; + } else if (n_filters < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative number of filters"); + return NULL; + } + + return (PyObject *) self; +} + + +AUBIO_INIT(filterbank, self->n_filters, self->win_s) + +AUBIO_DEL(filterbank) + +static PyObject * +Py_filterbank_do(Py_filterbank * self, PyObject * args) +{ + PyObject *input; + Py_cvec *vec; + Py_fvec *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCvec (input); + + if (vec == NULL) { + return NULL; + } + + output = (Py_fvec*) PyObject_New (Py_fvec, &Py_fvecType); + output->channels = vec->channels; + output->length = self->n_filters; + output->o = new_fvec(self->n_filters, vec->channels); + + // compute the function + aubio_filterbank_do (self->o, vec->o, output->o); + return (PyObject *)PyAubio_FvecToArray(output); +} + +AUBIO_MEMBERS_START(filterbank) + {"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY, + "size of the window"}, + {"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY, + "number of filters"}, +AUBIO_MEMBERS_STOP(filterbank) + +static PyObject * +Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) +{ + uint_t err = 0; + + PyObject *input; + uint_t samplerate; + Py_fvec *freqs; + if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) { + return NULL; + } + + if (input == NULL) { + return NULL; + } + + freqs = PyAubio_ArrayToFvec (input); + + if (freqs == NULL) { + return NULL; + } + + err = aubio_filterbank_set_triangle_bands (self->o, + freqs->o, samplerate); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter to A-weighting"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) +{ + uint_t err = 0; + + uint_t samplerate; + if (!PyArg_ParseTuple (args, "I", &samplerate)) { + return NULL; + } + + err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter to A-weighting"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused) +{ + Py_fvec *output = (Py_fvec *) PyObject_New (Py_fvec, &Py_fvecType); + output->channels = self->n_filters; + output->length = self->win_s / 2 + 1; + output->o = aubio_filterbank_get_coeffs (self->o); + return (PyObject *)PyAubio_FvecToArray(output); +} + +static PyMethodDef Py_filterbank_methods[] = { + {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands, + METH_VARARGS, "set coefficients of filterbanks"}, + {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney, + METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"}, + {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs, + METH_NOARGS, "get coefficients of filterbank"}, + {NULL} +}; + +AUBIO_TYPEOBJECT(filterbank, "aubio.filterbank") diff --git a/interfaces/python/py-fvec.c b/interfaces/python/py-fvec.c index 88b131b7..bb68df33 100644 --- a/interfaces/python/py-fvec.c +++ b/interfaces/python/py-fvec.c @@ -127,15 +127,15 @@ PyAubio_ArrayToFvec (PyObject *input) { PyErr_SetString (PyExc_ValueError, "input array should be float"); goto fail; #if AUBIO_DO_CASTING - } else if (PyArray_TYPE (input) != AUBIO_FLOAT) { + } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) { // input data type is not float32, casting - array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_FLOAT); + array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_NPY_SMPL); if (array == NULL) { - PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT"); + PyErr_SetString (PyExc_IndexError, "failed converting to AUBIO_NPY_SMPL"); goto fail; } #else - } else if (PyArray_TYPE (input) != AUBIO_FLOAT) { + } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) { PyErr_SetString (PyExc_ValueError, "input array should be float32"); goto fail; #endif @@ -181,17 +181,17 @@ PyAubio_FvecToArray (Py_fvec * self) PyObject *array = NULL; if (self->channels == 1) { npy_intp dims[] = { self->length, 1 }; - array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[0]); + array = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[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->data[i]); + tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[i]); PyList_Append (concat, tmp); Py_DECREF (tmp); } - array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2); + array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2); Py_DECREF (concat); } return array; @@ -214,7 +214,7 @@ Py_fvec_getitem (Py_fvec * self, Py_ssize_t index) } npy_intp dims[] = { self->length, 1 }; - array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[index]); + array = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[index]); return array; } @@ -228,7 +228,7 @@ Py_fvec_setitem (Py_fvec * self, Py_ssize_t index, PyObject * o) return -1; } - array = PyArray_FROM_OT (o, NPY_FLOAT); + array = PyArray_FROM_OT (o, AUBIO_NPY_SMPL); if (array == NULL) { PyErr_SetString (PyExc_ValueError, "should be an array of float"); goto fail; diff --git a/interfaces/python/py-phasevoc.c b/interfaces/python/py-phasevoc.c new file mode 100644 index 00000000..245152c0 --- /dev/null +++ b/interfaces/python/py-phasevoc.c @@ -0,0 +1,137 @@ +#include "aubiowraphell.h" + +static char Py_pvoc_doc[] = "pvoc object"; + +AUBIO_DECLARE(pvoc, uint_t win_s; uint_t hop_s; uint_t channels) + +//AUBIO_NEW(pvoc) +static PyObject * +Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int win_s = 0, hop_s = 0, channels = 0; + Py_pvoc *self; + static char *kwlist[] = { "win_s", "hop_s", "channels", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|III", kwlist, + &win_s, &hop_s, &channels)) { + return NULL; + } + + self = (Py_pvoc *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->win_s = Py_default_vector_length; + self->hop_s = Py_default_vector_length/2; + self->channels = Py_default_vector_channels; + + if (self == NULL) { + return NULL; + } + + if (win_s > 0) { + self->win_s = win_s; + } else if (win_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative window size"); + return NULL; + } + + if (hop_s > 0) { + self->hop_s = hop_s; + } else if (hop_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative hop size"); + return NULL; + } + + if (channels > 0) { + self->channels = channels; + } else if (channels < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative number of filters"); + return NULL; + } + + return (PyObject *) self; +} + + +AUBIO_INIT(pvoc, self->win_s, self->hop_s, self->channels) + +AUBIO_DEL(pvoc) + +static PyObject * +Py_pvoc_do(PyObject * self, PyObject * args) +{ + PyObject *input; + Py_fvec *vec; + Py_cvec *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToFvec (input); + + if (vec == NULL) { + return NULL; + } + + output = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); + output->channels = vec->channels; + output->length = ((Py_pvoc *) self)->win_s; + output->o = new_cvec(((Py_pvoc *) self)->win_s, vec->channels); + + // compute the function + aubio_pvoc_do (((Py_pvoc *)self)->o, vec->o, output->o); + Py_INCREF(output); + return (PyObject *)output; + //return (PyObject *)PyAubio_CvecToArray(output); +} + +AUBIO_MEMBERS_START(pvoc) + {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY, + "size of the window"}, + {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY, + "size of the hop"}, + {"channels", T_INT, offsetof (Py_pvoc, channels), READONLY, + "number of channels"}, +AUBIO_MEMBERS_STOP(pvoc) + +static PyObject * +Py_pvoc_rdo(PyObject * self, PyObject * args) +{ + PyObject *input; + Py_cvec *vec; + Py_fvec *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCvec (input); + + if (vec == NULL) { + return NULL; + } + + output = (Py_fvec*) PyObject_New (Py_fvec, &Py_fvecType); + output->channels = vec->channels; + output->length = ((Py_pvoc *) self)->hop_s; + output->o = new_fvec(output->length, output->channels); + + // compute the function + aubio_pvoc_rdo (((Py_pvoc *)self)->o, vec->o, output->o); + return (PyObject *)PyAubio_FvecToArray(output); +} + +static PyMethodDef Py_pvoc_methods[] = { + {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS, + "synthesis of spectral grain"}, + {NULL} +}; + +AUBIO_TYPEOBJECT(pvoc, "aubio.pvoc") diff --git a/interfaces/python/setup.py b/interfaces/python/setup.py index 6645bcf0..d9f392f2 100644 --- a/interfaces/python/setup.py +++ b/interfaces/python/setup.py @@ -1,10 +1,23 @@ from distutils.core import setup, Extension +from os import listdir +generated_files = listdir('generated') +generated_files = ['generated/'+f for f in generated_files] + setup(name="_aubio", version="1.0", ext_modules = [ Extension("_aubio", - ["aubiomodule.c", "py-fvec.c", "py-cvec.c", "py-filter.c"], - include_dirs=['../../build/default/src', '../../src' ], + ["aubiomodule.c", + "py-fvec.c", + "py-cvec.c", + "py-filter.c", + # macroised + "py-filterbank.c", + "py-fft.c", + "py-phasevoc.c", + # generated files + ] + generated_files, + include_dirs=['../../build/default/src', '../../src', '.' ], library_dirs=['../../build/default/src', '../../src/.libs' ], libraries=['aubio'])]) diff --git a/interfaces/python/test_filter.py b/interfaces/python/test_filter.py index 23964c04..3007a987 100644 --- a/interfaces/python/test_filter.py +++ b/interfaces/python/test_filter.py @@ -11,9 +11,9 @@ class aubio_filter_test_case(TestCase): def test_members(self): f = digital_filter() - assert_equal ([f.channels, f.order, f.samplerate], [1, 7, 44100]) - f = digital_filter(48000, 5, 2) - assert_equal ([f.channels, f.order, f.samplerate], [2, 5, 48000]) + assert_equal ([f.channels, f.order], [1, 7]) + f = digital_filter(5, 2) + assert_equal ([f.channels, f.order], [2, 5]) f(fvec()) def test_cweighting_error(self): @@ -32,8 +32,8 @@ class aubio_filter_test_case(TestCase): def test_c_weighting(self): expected = array_from_text_file('c_weighting_test_simple.expected') - f = digital_filter(44100, 5, 1) - f.set_c_weighting() + f = digital_filter(5, 1) + f.set_c_weighting(44100) v = fvec(32) v[0][12] = .5 u = f(v) @@ -41,8 +41,8 @@ class aubio_filter_test_case(TestCase): def test_a_weighting(self): expected = array_from_text_file('a_weighting_test_simple.expected') - f = digital_filter(44100, 7, 1) - f.set_a_weighting() + f = digital_filter(7, 1) + f.set_a_weighting(44100) v = fvec(32) v[0][12] = .5 u = f(v) @@ -50,8 +50,8 @@ class aubio_filter_test_case(TestCase): def test_a_weighting_parted(self): expected = array_from_text_file('a_weighting_test_simple.expected') - f = digital_filter(44100, 7, 1) - f.set_a_weighting() + f = digital_filter(7, 1) + f.set_a_weighting(44100) v = fvec(16) v[0][12] = .5 u = f(v) -- 2.26.2