ref: 9d3fa49dd788dc6fd01cc81081b64241bf3837f8
dir: /interfaces/python/py-cvec.c/
#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)
*/
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_NPY_SMPL) {
// input data type is not float32, casting
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_NPY_SMPL) {
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) {
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) / 2;
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+=2) {
vec->o->norm[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
vec->o->phas[i] = (smpl_t *) PyArray_GETPTR1 (array, i+1);
}
} 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;
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_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 * vec, PyObject *input, void * closure)
{
uint_t i;
PyObject * array;
if (input == NULL) {
PyErr_SetString (PyExc_ValueError, "input array is not a python object");
goto fail;
}
if (PyArray_Check(input)) {
// we got an array, convert it to a cvec.norm
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;
}
array = input;
// check input array dimensions
if (PyArray_NDIM (array) == 1) {
if (vec->channels != 1) {
PyErr_SetString (PyExc_ValueError,
"input array should have more than one channel");
goto fail;
}
if (vec->o->length != PyArray_SIZE (array)) {
PyErr_Format (PyExc_ValueError,
"input array has length %d, but cvec has length %d",
PyArray_SIZE (array), vec->o->length);
goto fail;
}
} else {
if (vec->channels != PyArray_DIM (array, 0)) {
PyErr_Format (PyExc_ValueError,
"input array has %d channels, but vector has %d channels",
PyArray_DIM (array, 0), vec->channels);
goto fail;
}
if (vec->o->length != PyArray_DIM (array, 1)) {
PyErr_Format (PyExc_ValueError,
"input array has length %d, but vector has length %d",
PyArray_DIM (array, 1), vec->o->length);
goto fail;
}
}
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 as input");
return 1;
}
Py_INCREF(array);
return 0;
fail:
return 1;
}
static int
Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
{
uint_t i;
PyObject * array;
if (input == NULL) {
PyErr_SetString (PyExc_ValueError, "input array is not a python object");
goto fail;
}
if (PyArray_Check(input)) {
// we got an array, convert it to a cvec.phas
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;
}
array = input;
// check input array dimensions
if (PyArray_NDIM (array) == 1) {
if (vec->channels != 1) {
PyErr_SetString (PyExc_ValueError,
"input array should have more than one channel");
goto fail;
}
if (vec->o->length != PyArray_SIZE (array)) {
PyErr_Format (PyExc_ValueError,
"input array has length %d, but cvec has length %d",
PyArray_SIZE (array), vec->o->length);
goto fail;
}
} else {
if (vec->channels != PyArray_DIM (array, 0)) {
PyErr_Format (PyExc_ValueError,
"input array has %d channels, but vector has %d channels",
PyArray_DIM (array, 0), vec->channels);
goto fail;
}
if (vec->o->length != PyArray_DIM (array, 1)) {
PyErr_Format (PyExc_ValueError,
"input array has length %d, but vector has length %d",
PyArray_DIM (array, 1), vec->o->length);
goto fail;
}
}
for (i = 0; i < vec->channels; i++) {
vec->o->phas[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
}
} else {
PyErr_SetString (PyExc_ValueError, "can only accept array as input");
return 1;
}
Py_INCREF(array);
return 0;
fail:
return 1;
}
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_CvecToArray, METH_NOARGS,
"Returns the content 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 */
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 */
Py_cvec_getseters, /* 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 */
};