python/ext/py-cvec.c: rewrite and simplify aubio.cvec, safer and better memory usage...
[aubio.git] / python / ext / aubioproxy.c
1 #include "aubio-types.h"
2
3 PyObject *
4 PyAubio_CFvecToArray (fvec_t * self)
5 {
6   npy_intp dims[] = { self->length, 1 };
7   return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data);
8 }
9
10 int
11 PyAubio_ArrayToCFvec (PyObject *input, fvec_t *out) {
12   if (input == NULL) {
13     PyErr_SetString (PyExc_ValueError, "input array is not a python object");
14     return 0;
15   }
16   // parsing input object into a Py_fvec
17   if (PyArray_Check(input)) {
18
19     // we got an array, convert it to an fvec
20     if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
21       PyErr_SetString (PyExc_ValueError, "input array is a scalar");
22       return 0;
23     } else if (PyArray_NDIM ((PyArrayObject *)input) > 1) {
24       PyErr_SetString (PyExc_ValueError,
25           "input array has more than one dimensions");
26       return 0;
27     }
28
29     if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
30       PyErr_SetString (PyExc_ValueError, "input array should be float");
31       return 0;
32     } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
33       PyErr_SetString (PyExc_ValueError, "input array should be " AUBIO_NPY_SMPL_STR);
34       return 0;
35     }
36
37     // vec = new_fvec (vec->length);
38     // no need to really allocate fvec, just its struct member
39     long length = PyArray_SIZE ((PyArrayObject *)input);
40     if (length <= 0) {
41       PyErr_SetString (PyExc_ValueError, "input array size should be greater than 0");
42       return 0;
43     }
44
45   } else if (PyObject_TypeCheck (input, &PyList_Type)) {
46     PyErr_SetString (PyExc_ValueError, "does not convert from list yet");
47     return 0;
48   } else {
49     PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input");
50     return 0;
51   }
52
53   out->length = (uint_t) PyArray_SIZE ((PyArrayObject *)input);
54   out->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)input, 0);
55   return 1;
56 }
57
58 PyObject *
59 PyAubio_CFmatToArray (fmat_t * input)
60 {
61   PyObject *array = NULL;
62   uint_t i;
63   npy_intp dims[] = { input->length, 1 };
64   PyObject *concat = PyList_New (0), *tmp = NULL;
65   for (i = 0; i < input->height; i++) {
66     tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->data[i]);
67     PyList_Append (concat, tmp);
68     Py_DECREF (tmp);
69   }
70   array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2);
71   Py_DECREF (concat);
72   return array;
73 }
74
75 int
76 PyAubio_ArrayToCFmat (PyObject *input, fmat_t *mat) {
77   uint_t i;
78   if (input == NULL) {
79     PyErr_SetString (PyExc_ValueError, "input array is not a python object");
80     return 0;
81   }
82   // parsing input object into a Py_fvec
83   if (PyArray_Check(input)) {
84
85     // we got an array, convert it to an fvec
86     if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
87       PyErr_SetString (PyExc_ValueError, "input array is a scalar");
88       return 0;
89     } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
90       PyErr_SetString (PyExc_ValueError,
91           "input array has more than two dimensions");
92       return 0;
93     }
94
95     if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
96       PyErr_SetString (PyExc_ValueError, "input array should be float");
97       return 0;
98     } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
99       PyErr_SetString (PyExc_ValueError, "input array should be " AUBIO_NPY_SMPL_STR);
100       return 0;
101     }
102
103     // no need to really allocate fvec, just its struct member
104     long length = PyArray_DIM ((PyArrayObject *)input, 1);
105     if (length <= 0) {
106       PyErr_SetString (PyExc_ValueError, "input array dimension 1 should be greater than 0");
107       return 0;
108     }
109     long height = PyArray_DIM ((PyArrayObject *)input, 0);
110     if (height <= 0) {
111       PyErr_SetString (PyExc_ValueError, "input array dimension 0 should be greater than 0");
112       return 0;
113     }
114
115   } else if (PyObject_TypeCheck (input, &PyList_Type)) {
116     PyErr_SetString (PyExc_ValueError, "can not convert list to fmat");
117     return 0;
118   } else {
119     PyErr_SetString (PyExc_ValueError, "can only accept matrix of float as input");
120     return 0;
121   }
122
123   uint_t new_height = (uint_t)PyArray_DIM ((PyArrayObject *)input, 0);
124   if (mat->height != new_height) {
125     if (mat->data) {
126       free(mat->data);
127     }
128     mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * new_height);
129   }
130
131   mat->height = new_height;
132   mat->length = (uint_t)PyArray_DIM ((PyArrayObject *)input, 1);
133   for (i=0; i< mat->height; i++) {
134     mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)input, i);
135   }
136   return 1;
137 }