#define AUBIO_UNSTABLE 1
#include <aubio.h>
-#define Py_default_vector_length 1024
-#define Py_default_vector_channels 1
+#define Py_default_vector_length 1024
+#define Py_default_vector_height 1
#define Py_aubio_default_samplerate 44100
it.
*/
-#define AUBIO_DO_CASTING 0
typedef struct
{
PyObject_HEAD
fvec_t * o;
uint_t length;
- uint_t channels;
} Py_fvec;
extern PyTypeObject Py_fvecType;
extern PyObject *PyAubio_FvecToArray (Py_fvec * self);
extern PyObject *PyAubio_CFvecToArray (fvec_t * self);
extern Py_fvec *PyAubio_ArrayToFvec (PyObject * self);
+typedef struct
+{
+ PyObject_HEAD
+ fmat_t * o;
+ uint_t length;
+ uint_t height;
+} Py_fmat;
+extern PyTypeObject Py_fmatType;
+extern PyObject *PyAubio_FmatToArray (Py_fmat * self);
+extern PyObject *PyAubio_CFmatToArray (fmat_t * self);
+extern Py_fmat *PyAubio_ArrayToFmat (PyObject * self);
+
typedef struct
{
PyObject_HEAD
int err;
if ((PyType_Ready (&Py_fvecType) < 0)
+ || (PyType_Ready (&Py_fmatType) < 0)
|| (PyType_Ready (&Py_cvecType) < 0)
|| (PyType_Ready (&Py_filterType) < 0)
|| (PyType_Ready (&Py_filterbankType) < 0)
Py_INCREF (&Py_fvecType);
PyModule_AddObject (m, "fvec", (PyObject *) & Py_fvecType);
+ Py_INCREF (&Py_fmatType);
+ PyModule_AddObject (m, "fmat", (PyObject *) & Py_fmatType);
Py_INCREF (&Py_cvecType);
PyModule_AddObject (m, "cvec", (PyObject *) & Py_cvecType);
Py_INCREF (&Py_filterType);
};
// some more helpers
-#define AUBIO_NEW_VEC(name, type, lengthval, channelsval) \
+#define AUBIO_NEW_VEC(name, type, lengthval) \
name = (type *) PyObject_New (type, & type ## Type); \
- name->channels = channelsval; \
name->length = lengthval;
# the important bits: the size of the output for each objects. this data should
# move into the C library at some point.
defaultsizes = {
- 'resampler': ('input->length * self->ratio', 'input->channels'),
- 'specdesc': ('1', 'fftgrain->channels'),
- 'onset': ('1', 'self->channels'),
- 'pitchyin': ('1', 'in->channels'),
- 'pitchyinfft': ('1', 'in->channels'),
- 'pitchschmitt': ('1', 'in->channels'),
- 'pitchmcomb': ('1', 'self->channels'),
- 'pitchfcomb': ('1', 'self->channels'),
- 'pitch': ('1', 'self->channels'),
- 'tss': ('self->hop_size', 'self->channels'),
- 'mfcc': ('self->n_coeffs', 'in->channels'),
- 'beattracking': ('self->hop_size', 'self->channels'),
- 'tempo': ('1', 'self->channels'),
- 'peakpicker': ('1', 'self->channels'),
+ 'resampler': 'input->length * self->ratio',
+ 'specdesc': '1',
+ 'onset': '1',
+ 'pitchyin': '1',
+ 'pitchyinfft': '1',
+ 'pitchschmitt': '1',
+ 'pitchmcomb': '1',
+ 'pitchfcomb': '1',
+ 'pitch': '1',
+ 'tss': 'self->hop_size',
+ 'mfcc': 'self->n_coeffs',
+ 'beattracking': 'self->hop_size',
+ 'tempo': '1',
+ 'peakpicker': '1',
}
# default value for variables
# and here too
'hop_size': 'Py_default_vector_length / 2',
# these should be alright
- 'channels': 'Py_default_vector_channels',
'samplerate': 'Py_aubio_default_samplerate',
# now for the non obvious ones
'n_filters': '40',
def gen_new_init(newfunc, name):
newparams = get_params_types_names(newfunc)
# self->param1, self->param2, self->param3
- selfparams = ', self->'.join([p[1] for p in newparams])
+ if len(newparams):
+ selfparams = ', self->'+', self->'.join([p[1] for p in newparams])
+ else:
+ selfparams = ''
# "param1", "param2", "param3"
paramnames = ", ".join(["\""+p[1]+"\"" for p in newparams])
pyparams = "".join(map(lambda p: aubio2pytypes[p[0]], newparams))
static PyObject *
Py_%(name)s_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
{
+ Py_%(name)s *self;
""" % locals()
for ptype, pname in newparams:
initval = aubioinitvalue[ptype]
%(ptype)s %(pname)s = %(initval)s;
""" % locals()
# now the actual PyArg_Parse
- s += """\
- Py_%(name)s *self;
+ if len(paramnames):
+ s += """\
static char *kwlist[] = { %(paramnames)s, NULL };
if (!PyArg_ParseTupleAndKeywords (args, kwds, "|%(pyparams)s", kwlist,
%(paramrefs)s)) {
return NULL;
}
+""" % locals()
+ s += """\
self = (Py_%(name)s *) pytype->tp_alloc (pytype, 0);
return (PyObject *) self;
}
-AUBIO_INIT(%(name)s, self->%(selfparams)s)
+AUBIO_INIT(%(name)s %(selfparams)s)
AUBIO_DEL(%(name)s)
# "too many output parameters"
outputvecs = "\n ".join([aubio2pyaubio[p[0]]+" * " + p[-1] + ";" for p in outputparams])
outputcreate = "\n ".join(["""\
-AUBIO_NEW_VEC(%(name)s, %(pytype)s, %(length)s, %(channels)s)
- %(name)s->o = new_%(autype)s (%(length)s, %(channels)s);""" % \
+AUBIO_NEW_VEC(%(name)s, %(pytype)s, %(length)s)
+ %(name)s->o = new_%(autype)s (%(length)s);""" % \
{'name': p[-1], 'pytype': aubio2pyaubio[p[0]], 'autype': p[0][:-3],
- 'length': defaultsizes[name][0], 'channels': defaultsizes[name][1]} \
+ 'length': defaultsizes[name]} \
for p in outputparams])
if len(outputparams) > 1:
returnval = "PyObject *outputs = PyList_New(0);\n"
static char Py_fft_doc[] = "fft object";
-AUBIO_DECLARE(fft, uint_t win_s; uint_t channels)
+AUBIO_DECLARE(fft, uint_t win_s)
//AUBIO_NEW(fft)
static PyObject *
Py_fft_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
- int win_s = 0, channels = 0;
+ int win_s = 0;
Py_fft *self;
- static char *kwlist[] = { "win_s", "channels", NULL };
+ static char *kwlist[] = { "win_s", NULL };
- if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
- &win_s, &channels)) {
+ if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist,
+ &win_s)) {
return NULL;
}
}
self->win_s = Py_default_vector_length;
- self->channels = Py_default_vector_channels;
if (self == NULL) {
return NULL;
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_INIT(fft, self->win_s)
AUBIO_DEL(fft)
}
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);
+ output->o = new_cvec(((Py_fft *) self)->win_s);
// compute the function
aubio_fft_do (((Py_fft *)self)->o, vec->o, output->o);
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 *
}
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);
+ output->o = new_fvec(output->length);
// compute the function
aubio_fft_rdo (((Py_fft *)self)->o, vec->o, output->o);
PyObject_HEAD
aubio_filter_t * o;
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 order= 0, channels = 0;
+ int order= 0;
Py_filter *self;
- static char *kwlist[] = { "order", "channels", NULL };
+ static char *kwlist[] = { "order", NULL };
if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
- &order, &channels)) {
+ &order)) {
return NULL;
}
}
self->order = 7;
- self->channels = Py_default_vector_channels;
if (order > 0) {
self->order = 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->order, self->channels);
+ self->o = new_aubio_filter (self->order);
if (self->o == NULL) {
return -1;
}
// compute the function
#if 1
aubio_filter_do (((Py_filter *)self)->o, vec->o);
- Py_INCREF(vec);
+ PyArray_INCREF((PyArrayObject*)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);
+ copy->o = new_fvec(vec->o->length);
aubio_filter_do_outplace (((Py_filter *)self)->o, vec->o, copy->o);
return (PyObject *)copy;
#endif
// TODO remove READONLY flag and define getter/setter
{"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 */
};
}
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);
+ output->o = new_fvec(self->n_filters);
// compute the function
aubio_filterbank_do (self->o, vec->o, output->o);
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;
+ Py_fmat *output = (Py_fmat *) PyObject_New (Py_fmat, &Py_fvecType);
output->o = aubio_filterbank_get_coeffs (self->o);
- return (PyObject *)PyAubio_FvecToArray(output);
+ return (PyObject *)PyAubio_FmatToArray(output);
}
static PyMethodDef Py_filterbank_methods[] = {
--- /dev/null
+#include "aubio-types.h"
+
+/* fmat type definition
+
+class fmat():
+ def __init__(self, length = 1024, height = 1):
+ self.length = length
+ self.height = height
+ self.data = array(length, height)
+
+*/
+
+static char Py_fmat_doc[] = "fmat object";
+
+static PyObject *
+Py_fmat_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
+{
+ int length= 0, height = 0;
+ Py_fmat *self;
+ static char *kwlist[] = { "length", "height", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
+ &length, &height)) {
+ return NULL;
+ }
+
+
+ self = (Py_fmat *) type->tp_alloc (type, 0);
+
+ self->length = Py_default_vector_length;
+ self->height = Py_default_vector_height;
+
+ 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 (height > 0) {
+ self->height = height;
+ } else if (height < 0) {
+ PyErr_SetString (PyExc_ValueError,
+ "can not use negative number of height");
+ return NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int
+Py_fmat_init (Py_fmat * self, PyObject * args, PyObject * kwds)
+{
+ self->o = new_fmat (self->length, self->height);
+ if (self->o == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+Py_fmat_del (Py_fmat * self)
+{
+ del_fmat (self->o);
+ self->ob_type->tp_free ((PyObject *) self);
+}
+
+static PyObject *
+Py_fmat_repr (Py_fmat * self, PyObject * unused)
+{
+ PyObject *format = NULL;
+ PyObject *args = NULL;
+ PyObject *result = NULL;
+
+ format = PyString_FromString ("aubio fmat of %d elements with %d height");
+ if (format == NULL) {
+ goto fail;
+ }
+
+ args = Py_BuildValue ("II", self->length, self->height);
+ if (args == NULL) {
+ goto fail;
+ }
+ fmat_print ( self->o );
+
+ result = PyString_Format (format, args);
+
+fail:
+ Py_XDECREF (format);
+ Py_XDECREF (args);
+
+ return result;
+}
+
+Py_fmat *
+PyAubio_ArrayTofmat (PyObject *input) {
+ PyObject *array;
+ Py_fmat *vec;
+ uint_t i;
+ if (input == NULL) {
+ PyErr_SetString (PyExc_ValueError, "input array is not a python object");
+ goto fail;
+ }
+ // parsing input object into a Py_fmat
+ if (PyObject_TypeCheck (input, &Py_fmatType)) {
+ // input is an fmat, nothing else to do
+ vec = (Py_fmat *) input;
+ } else if (PyArray_Check(input)) {
+
+ // we got an array, convert it to an fmat
+ 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;
+ } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
+ PyErr_SetString (PyExc_ValueError, "input array should be float32");
+ goto fail;
+ } else {
+ // input data type is float32, nothing else to do
+ array = input;
+ }
+
+ // create a new fmat object
+ vec = (Py_fmat*) PyObject_New (Py_fmat, &Py_fmatType);
+ if (PyArray_NDIM (array) == 1) {
+ vec->height = 1;
+ vec->length = PyArray_SIZE (array);
+ } else {
+ vec->height = PyArray_DIM (array, 0);
+ vec->length = PyArray_DIM (array, 1);
+ }
+
+ // no need to really allocate fmat, just its struct member
+ // vec->o = new_fmat (vec->length, vec->height);
+ vec->o = (fmat_t *)malloc(sizeof(fmat_t));
+ vec->o->length = vec->length; vec->o->height = vec->height;
+ vec->o->data = (smpl_t**)malloc(vec->o->height * sizeof(smpl_t*));
+ // hat data[i] point to array line
+ for (i = 0; i < vec->height; i++) {
+ vec->o->data[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
+ }
+
+ } else {
+ PyErr_SetString (PyExc_ValueError, "can only accept array or fmat as input");
+ return NULL;
+ }
+
+ return vec;
+
+fail:
+ return NULL;
+}
+
+PyObject *
+PyAubio_CfmatToArray (fmat_t * self)
+{
+ PyObject *array = NULL;
+ uint_t i;
+ npy_intp dims[] = { self->length, 1 };
+ PyObject *concat = PyList_New (0), *tmp = NULL;
+ for (i = 0; i < self->height; i++) {
+ tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data[i]);
+ PyList_Append (concat, tmp);
+ Py_DECREF (tmp);
+ }
+ array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2);
+ Py_DECREF (concat);
+ return array;
+}
+
+PyObject *
+PyAubio_FmatToArray (Py_fmat * self)
+{
+ PyObject *array = NULL;
+ if (self->height == 1) {
+ npy_intp dims[] = { self->length, 1 };
+ 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->height; i++) {
+ tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[i]);
+ PyList_Append (concat, tmp);
+ Py_DECREF (tmp);
+ }
+ array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2);
+ Py_DECREF (concat);
+ }
+ return array;
+}
+
+static Py_ssize_t
+Py_fmat_get_height (Py_fmat * self)
+{
+ return self->height;
+}
+
+static PyObject *
+Py_fmat_getitem (Py_fmat * self, Py_ssize_t index)
+{
+ PyObject *array;
+
+ if (index < 0 || index >= self->height) {
+ PyErr_SetString (PyExc_IndexError, "no such channel");
+ return NULL;
+ }
+
+ npy_intp dims[] = { self->length, 1 };
+ array = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[index]);
+ return array;
+}
+
+static int
+Py_fmat_setitem (Py_fmat * self, Py_ssize_t index, PyObject * o)
+{
+ PyObject *array;
+
+ if (index < 0 || index >= self->height) {
+ PyErr_SetString (PyExc_IndexError, "no such channel");
+ return -1;
+ }
+
+ array = PyArray_FROM_OT (o, AUBIO_NPY_SMPL);
+ 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 fmat");
+ goto fail;
+ }
+
+ self->o->data[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+static PyMemberDef Py_fmat_members[] = {
+ // TODO remove READONLY flag and define getter/setter
+ {"length", T_INT, offsetof (Py_fmat, length), READONLY,
+ "length attribute"},
+ {"height", T_INT, offsetof (Py_fmat, height), READONLY,
+ "height attribute"},
+ {NULL} /* Sentinel */
+};
+
+static PyMethodDef Py_fmat_methods[] = {
+ {"__array__", (PyCFunction) PyAubio_FmatToArray, METH_NOARGS,
+ "Returns the vector as a numpy array."},
+ {NULL}
+};
+
+static PySequenceMethods Py_fmat_tp_as_sequence = {
+ (lenfunc) Py_fmat_get_height, /* sq_length */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ (ssizeargfunc) Py_fmat_getitem, /* sq_item */
+ 0, /* sq_slice */
+ (ssizeobjargproc) Py_fmat_setitem, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ 0, /* sq_contains */
+ 0, /* sq_inplace_concat */
+ 0, /* sq_inplace_repeat */
+};
+
+
+PyTypeObject Py_fmatType = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /* ob_size */
+ "aubio.fmat", /* tp_name */
+ sizeof (Py_fmat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) Py_fmat_del, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc) Py_fmat_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ &Py_fmat_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_fmat_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Py_fmat_methods, /* tp_methods */
+ Py_fmat_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_fmat_init, /* tp_init */
+ 0, /* tp_alloc */
+ Py_fmat_new, /* tp_new */
+};