source: python/ext/py-cvec.c @ ceb884d

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since ceb884d was ede5d38, checked in by Paul Brossier <piem@piem.org>, 9 years ago

python/ext/aubio-types.h: add new_py_ functions to create PyObjects? instead of fvec_t, apply to py-fft.c

  • Property mode set to 100644
File size: 9.5 KB
Line 
1#include "aubio-types.h"
2
3/* cvec type definition
4
5class cvec():
6    def __new__(self, length = 1024):
7        self.length = length / 2 + 1
8        self.norm = np.zeros(length / 2 + 1)
9        self.phas = np.zeros(length / 2 + 1)
10
11*/
12
13// special python type for cvec
14typedef struct
15{
16  PyObject_HEAD
17  PyObject *norm;
18  PyObject *phas;
19  uint_t length;
20} Py_cvec;
21
22static char Py_cvec_doc[] = "cvec object";
23
24
25PyObject *
26new_py_cvec(uint_t length) {
27  Py_cvec* vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
28  npy_intp dims[] = { length / 2 + 1, 1 };
29  vec->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
30  vec->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
31  vec->length = length / 2 + 1;
32  return (PyObject*)vec;
33}
34
35PyObject *
36PyAubio_CCvecToPyCvec (cvec_t * input) {
37  if (input == NULL) {
38      PyErr_SetString (PyExc_ValueError, "PyAubio_CCvecToPyCvec got a null cvec!");
39      return NULL;
40  }
41  Py_cvec* vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
42  npy_intp dims[] = { input->length, 1 };
43  vec->norm = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->norm);
44  vec->phas = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->phas);
45  vec->length = input->length;
46  return (PyObject *)vec;
47}
48
49int
50PyAubio_PyCvecToCCvec (PyObject *input, cvec_t *i) {
51  if (PyObject_TypeCheck (input, &Py_cvecType)) {
52      Py_cvec * in = (Py_cvec *)input;
53      i->norm = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->norm), 0);
54      i->phas = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->phas), 0);
55      i->length = ((Py_cvec*)input)->length;
56      return 1;
57  } else {
58      PyErr_SetString (PyExc_ValueError, "input array should be aubio.cvec");
59      return 0;
60  }
61}
62
63static PyObject *
64Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
65{
66  int length= 0;
67  Py_cvec *self;
68  static char *kwlist[] = { "length", NULL };
69
70  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist,
71          &length)) {
72    return NULL;
73  }
74
75  self = (Py_cvec *) type->tp_alloc (type, 0);
76
77  self->length = Py_default_vector_length / 2 + 1;
78
79  if (self == NULL) {
80    return NULL;
81  }
82
83  if (length > 0) {
84    self->length = length / 2 + 1;
85  } else if (length < 0) {
86    PyErr_SetString (PyExc_ValueError,
87        "can not use negative number of elements");
88    return NULL;
89  }
90
91  return (PyObject *) self;
92}
93
94static int
95Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
96{
97  npy_intp dims[] = { self->length, 1 };
98  self->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
99  self->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
100  return 0;
101}
102
103static void
104Py_cvec_del (Py_cvec * self)
105{
106  Py_DECREF(self->norm);
107  Py_DECREF(self->phas);
108  Py_TYPE(self)->tp_free ((PyObject *) self);
109}
110
111static PyObject *
112Py_cvec_repr (Py_cvec * self, PyObject * unused)
113{
114  PyObject *format = NULL;
115  PyObject *args = NULL;
116  PyObject *result = NULL;
117
118  format = PyUnicode_FromString ("aubio cvec of %d elements");
119  if (format == NULL) {
120    goto fail;
121  }
122
123  args = Py_BuildValue ("I", self->length);
124  if (args == NULL) {
125    goto fail;
126  }
127  // hide actual norm / phas content
128
129  result = PyUnicode_Format (format, args);
130
131fail:
132  Py_XDECREF (format);
133  Py_XDECREF (args);
134
135  return result;
136}
137
138PyObject *
139Py_cvec_get_norm (Py_cvec * self, void *closure)
140{
141  // we want self->norm to still exist after our caller return it
142  Py_INCREF(self->norm);
143  return (PyObject*)(self->norm);
144}
145
146PyObject *
147Py_cvec_get_phas (Py_cvec * self, void *closure)
148{
149  // we want self->phas to still exist after our caller return it
150  Py_INCREF(self->phas);
151  return (PyObject *)(self->phas);
152}
153
154static int
155Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure)
156{
157  PyArrayObject * array;
158  if (input == NULL) {
159    PyErr_SetString (PyExc_ValueError, "input array is not a python object");
160    goto fail;
161  }
162  if (PyArray_Check(input)) {
163    // we got an array, convert it to a cvec.norm
164    if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
165      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
166      goto fail;
167    } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
168      PyErr_SetString (PyExc_ValueError,
169          "input array has more than two dimensions");
170      goto fail;
171    }
172
173    if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
174      PyErr_SetString (PyExc_ValueError, "input array should be float");
175      goto fail;
176    } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
177      PyErr_SetString (PyExc_ValueError, "input array should be float32");
178      goto fail;
179    }
180    array = (PyArrayObject *)input;
181
182    // check input array dimensions
183    if (PyArray_NDIM (array) != 1) {
184      PyErr_Format (PyExc_ValueError,
185          "input array has %d dimensions, not 1",
186          PyArray_NDIM (array));
187      goto fail;
188    } else {
189      if (vec->length != PyArray_SIZE (array)) {
190          PyErr_Format (PyExc_ValueError,
191                  "input array has length %d, but cvec has length %d",
192                  (int)PyArray_SIZE (array), vec->length);
193          goto fail;
194      }
195    }
196
197    Py_XDECREF(vec->norm);
198    vec->norm = input;
199    Py_INCREF(vec->norm);
200
201  } else {
202    PyErr_SetString (PyExc_ValueError, "can only accept array as input");
203    return 1;
204  }
205
206  return 0;
207
208fail:
209  return 1;
210}
211
212static int
213Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
214{
215  PyArrayObject * array;
216  if (input == NULL) {
217    PyErr_SetString (PyExc_ValueError, "input array is not a python object");
218    goto fail;
219  }
220  if (PyArray_Check(input)) {
221
222    // we got an array, convert it to a cvec.phas
223    if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
224      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
225      goto fail;
226    } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
227      PyErr_SetString (PyExc_ValueError,
228          "input array has more than two dimensions");
229      goto fail;
230    }
231
232    if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
233      PyErr_SetString (PyExc_ValueError, "input array should be float");
234      goto fail;
235    } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
236      PyErr_SetString (PyExc_ValueError, "input array should be float32");
237      goto fail;
238    }
239    array = (PyArrayObject *)input;
240
241    // check input array dimensions
242    if (PyArray_NDIM (array) != 1) {
243      PyErr_Format (PyExc_ValueError,
244          "input array has %d dimensions, not 1",
245          PyArray_NDIM (array));
246      goto fail;
247    } else {
248      if (vec->length != PyArray_SIZE (array)) {
249          PyErr_Format (PyExc_ValueError,
250                  "input array has length %d, but cvec has length %d",
251                  (int)PyArray_SIZE (array), vec->length);
252          goto fail;
253      }
254    }
255
256    Py_XDECREF(vec->phas);
257    vec->phas = input;
258    Py_INCREF(vec->phas);
259
260  } else {
261    PyErr_SetString (PyExc_ValueError, "can only accept array as input");
262    return 1;
263  }
264
265  return 0;
266
267fail:
268  return 1;
269}
270
271static PyMemberDef Py_cvec_members[] = {
272  // TODO remove READONLY flag and define getter/setter
273  {"length", T_INT, offsetof (Py_cvec, length), READONLY,
274      "length attribute"},
275  {NULL}                        /* Sentinel */
276};
277
278static PyMethodDef Py_cvec_methods[] = {
279  {NULL}
280};
281
282static PyGetSetDef Py_cvec_getseters[] = {
283  {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, 
284      "Numpy vector of shape (length,) containing the magnitude",
285      NULL},
286  {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, 
287      "Numpy vector of shape (length,) containing the phase",
288      NULL},
289  {NULL} /* sentinel */
290};
291
292PyTypeObject Py_cvecType = {
293  PyVarObject_HEAD_INIT(NULL, 0)
294  "aubio.cvec",                 /* tp_name           */
295  sizeof (Py_cvec),             /* tp_basicsize      */
296  0,                            /* tp_itemsize       */
297  (destructor) Py_cvec_del,     /* tp_dealloc        */
298  0,                            /* tp_print          */
299  0,                            /* tp_getattr        */
300  0,                            /* tp_setattr        */
301  0,                            /* tp_compare        */
302  (reprfunc) Py_cvec_repr,      /* tp_repr           */
303  0,                            /* tp_as_number      */
304  0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence    */
305  0,                            /* tp_as_mapping     */
306  0,                            /* tp_hash           */
307  0,                            /* tp_call           */
308  0,                            /* tp_str            */
309  0,                            /* tp_getattro       */
310  0,                            /* tp_setattro       */
311  0,                            /* tp_as_buffer      */
312  Py_TPFLAGS_DEFAULT,           /* tp_flags          */
313  Py_cvec_doc,                  /* tp_doc            */
314  0,                            /* tp_traverse       */
315  0,                            /* tp_clear          */
316  0,                            /* tp_richcompare    */
317  0,                            /* tp_weaklistoffset */
318  0,                            /* tp_iter           */
319  0,                            /* tp_iternext       */
320  Py_cvec_methods,              /* tp_methods        */
321  Py_cvec_members,              /* tp_members        */
322  Py_cvec_getseters,            /* tp_getset         */
323  0,                            /* tp_base           */
324  0,                            /* tp_dict           */
325  0,                            /* tp_descr_get      */
326  0,                            /* tp_descr_set      */
327  0,                            /* tp_dictoffset     */
328  (initproc) Py_cvec_init,      /* tp_init           */
329  0,                            /* tp_alloc          */
330  Py_cvec_new,                  /* tp_new            */
331};
Note: See TracBrowser for help on using the repository browser.