From: Paul Brossier Date: Thu, 21 Apr 2016 19:30:28 +0000 (+0200) Subject: ext/aubio-types.h: rewrite array to fvec conversions to reduce memory allocations X-Git-Tag: 0.4.4~300^2~285 X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=bfe8256155757161c8d96033b2c000685a63e001;p=aubio.git ext/aubio-types.h: rewrite array to fvec conversions to reduce memory allocations --- diff --git a/python/ext/aubio-types.h b/python/ext/aubio-types.h index edce6d6e..b77abc6a 100644 --- a/python/ext/aubio-types.h +++ b/python/ext/aubio-types.h @@ -55,13 +55,13 @@ extern PyTypeObject Py_cvecType; // defined in aubio-proxy.c extern PyObject *PyAubio_CFvecToArray (fvec_t * self); -extern fvec_t *PyAubio_ArrayToCFvec (PyObject * self); +extern int PyAubio_ArrayToCFvec (PyObject * self, fvec_t *out); -extern Py_cvec *PyAubio_CCvecToPyCvec (cvec_t * self); -extern cvec_t *PyAubio_ArrayToCCvec (PyObject *input); +extern PyObject * PyAubio_CCvecToPyCvec (cvec_t * self, Py_cvec *out); +extern int PyAubio_ArrayToCCvec (PyObject *input, cvec_t *i); extern PyObject *PyAubio_CFmatToArray (fmat_t * self); -extern fmat_t *PyAubio_ArrayToCFmat (PyObject *input); +extern int PyAubio_ArrayToCFmat (PyObject *input, fmat_t *out); // hand written wrappers extern PyTypeObject Py_filterType; diff --git a/python/ext/aubioproxy.c b/python/ext/aubioproxy.c index d3c00949..8a02a35c 100644 --- a/python/ext/aubioproxy.c +++ b/python/ext/aubioproxy.c @@ -1,12 +1,17 @@ #include "aubio-types.h" -fvec_t * -PyAubio_ArrayToCFvec (PyObject *input) { - PyObject *array; - fvec_t *vec; +PyObject * +PyAubio_CFvecToArray (fvec_t * self) +{ + npy_intp dims[] = { self->length, 1 }; + return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data); +} + +int +PyAubio_ArrayToCFvec (PyObject *input, fvec_t *out) { if (input == NULL) { PyErr_SetString (PyExc_ValueError, "input array is not a python object"); - goto fail; + return 0; } // parsing input object into a Py_fvec if (PyArray_Check(input)) { @@ -14,73 +19,62 @@ PyAubio_ArrayToCFvec (PyObject *input) { // we got an array, convert it to an fvec if (PyArray_NDIM ((PyArrayObject *)input) == 0) { PyErr_SetString (PyExc_ValueError, "input array is a scalar"); - goto fail; + return 0; } else if (PyArray_NDIM ((PyArrayObject *)input) > 1) { PyErr_SetString (PyExc_ValueError, "input array has more than one dimensions"); - goto fail; + return 0; } if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { PyErr_SetString (PyExc_ValueError, "input array should be float"); - goto fail; + return 0; } else if (PyArray_TYPE ((PyArrayObject *)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; + return 0; } // vec = new_fvec (vec->length); // no need to really allocate fvec, just its struct member - vec = (fvec_t *)malloc(sizeof(fvec_t)); - long length = PyArray_SIZE ((PyArrayObject *)array); - if (length > 0) { - vec->length = (uint_t)length; - } else { + long length = PyArray_SIZE ((PyArrayObject *)input); + if (length <= 0) { PyErr_SetString (PyExc_ValueError, "input array size should be greater than 0"); - goto fail; + return 0; } - vec->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)array, 0); } else if (PyObject_TypeCheck (input, &PyList_Type)) { PyErr_SetString (PyExc_ValueError, "does not convert from list yet"); - return NULL; + return 0; } else { PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input"); - return NULL; + return 0; } - return vec; - -fail: - return NULL; + out->length = (uint_t) PyArray_SIZE ((PyArrayObject *)input); + out->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)input, 0); + return 1; } PyObject * -PyAubio_CFvecToArray (fvec_t * self) -{ - npy_intp dims[] = { self->length, 1 }; - return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data); -} - -Py_cvec * -PyAubio_CCvecToPyCvec (cvec_t * input) { - Py_cvec *vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); +PyAubio_CCvecToPyCvec (cvec_t * input, Py_cvec *vec) { vec->length = input->length; vec->o = input; + // keep a reference to re-use after returning it Py_INCREF(vec); - return vec; + return (PyObject *)vec; } -cvec_t * -PyAubio_ArrayToCCvec (PyObject *input) { +int +PyAubio_ArrayToCCvec (PyObject *input, cvec_t *i) { if (PyObject_TypeCheck (input, &Py_cvecType)) { - return ((Py_cvec*)input)->o; + //*i = *(((Py_cvec*)input)->o); + i->norm = ((Py_cvec*)input)->o->norm; + i->phas = ((Py_cvec*)input)->o->phas; + i->length = ((Py_cvec*)input)->o->length; + return 1; } else { PyErr_SetString (PyExc_ValueError, "input array should be float32"); - return NULL; + return 0; } } @@ -101,14 +95,12 @@ PyAubio_CFmatToArray (fmat_t * input) return array; } -fmat_t * -PyAubio_ArrayToCFmat (PyObject *input) { - PyObject *array; - fmat_t *mat; +int +PyAubio_ArrayToCFmat (PyObject *input, fmat_t *mat) { uint_t i; if (input == NULL) { PyErr_SetString (PyExc_ValueError, "input array is not a python object"); - goto fail; + return 0; } // parsing input object into a Py_fvec if (PyArray_Check(input)) { @@ -116,56 +108,55 @@ PyAubio_ArrayToCFmat (PyObject *input) { // we got an array, convert it to an fvec if (PyArray_NDIM ((PyArrayObject *)input) == 0) { PyErr_SetString (PyExc_ValueError, "input array is a scalar"); - goto fail; + return 0; } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { PyErr_SetString (PyExc_ValueError, "input array has more than two dimensions"); - goto fail; + return 0; } if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { PyErr_SetString (PyExc_ValueError, "input array should be float"); - goto fail; + return 0; } else if (PyArray_TYPE ((PyArrayObject *)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; + return 0; } // no need to really allocate fvec, just its struct member - mat = (fmat_t *)malloc(sizeof(fmat_t)); - long length = PyArray_DIM ((PyArrayObject *)array, 1); - if (length > 0) { - mat->length = (uint_t)length; - } else { + long length = PyArray_DIM ((PyArrayObject *)input, 1); + if (length <= 0) { PyErr_SetString (PyExc_ValueError, "input array dimension 1 should be greater than 0"); - goto fail; + return 0; } - long height = PyArray_DIM ((PyArrayObject *)array, 0); - if (height > 0) { - mat->height = (uint_t)height; - } else { + long height = PyArray_DIM ((PyArrayObject *)input, 0); + if (height <= 0) { PyErr_SetString (PyExc_ValueError, "input array dimension 0 should be greater than 0"); - goto fail; - } - mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height); - for (i=0; i< mat->height; i++) { - mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)array, i); + return 0; } } else if (PyObject_TypeCheck (input, &PyList_Type)) { PyErr_SetString (PyExc_ValueError, "can not convert list to fmat"); - return NULL; + return 0; } else { PyErr_SetString (PyExc_ValueError, "can only accept matrix of float as input"); - return NULL; + return 0; } - return mat; + if (mat->height != (uint_t)PyArray_DIM ((PyArrayObject *)input, 0)) { + /* + free(mat->data); + mat->height = (uint_t)PyArray_DIM ((PyArrayObject *)input, 0); + mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height); + */ + PyErr_Format(PyExc_ValueError, "too many rows, %d but %ld expected", + mat->height, PyArray_DIM ((PyArrayObject *)input, 0) ); + return 0; + } -fail: - return NULL; + mat->length = (uint_t)PyArray_DIM ((PyArrayObject *)input, 1); + for (i=0; i< mat->height; i++) { + mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)input, i); + } + return 1; } -