source: python/ext/py-cvec.c @ 1e4d90f

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 1e4d90f was ede5d38, checked in by Paul Brossier <piem@piem.org>, 8 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
RevLine 
[f826349]1#include "aubio-types.h"
2
[92a8800]3/* cvec type definition
[f826349]4
5class cvec():
[92a8800]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)
[f826349]10
[7a7b00f]11*/
[f826349]12
[92a8800]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
[f826349]22static char Py_cvec_doc[] = "cvec object";
23
[ede5d38]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
[92a8800]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
[f826349]63static PyObject *
64Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
65{
[7a7b00f]66  int length= 0;
[f826349]67  Py_cvec *self;
[7a7b00f]68  static char *kwlist[] = { "length", NULL };
[f826349]69
[7a7b00f]70  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist,
71          &length)) {
[f826349]72    return NULL;
73  }
74
75  self = (Py_cvec *) type->tp_alloc (type, 0);
76
[eb93592]77  self->length = Py_default_vector_length / 2 + 1;
[f826349]78
79  if (self == NULL) {
80    return NULL;
81  }
82
83  if (length > 0) {
[eb93592]84    self->length = length / 2 + 1;
[f826349]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{
[ede5d38]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);
[f826349]100  return 0;
101}
102
103static void
104Py_cvec_del (Py_cvec * self)
105{
[ede5d38]106  Py_DECREF(self->norm);
107  Py_DECREF(self->phas);
[770b9e7]108  Py_TYPE(self)->tp_free ((PyObject *) self);
[f826349]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
[5c1200a]118  format = PyUnicode_FromString ("aubio cvec of %d elements");
[f826349]119  if (format == NULL) {
120    goto fail;
121  }
122
[7a7b00f]123  args = Py_BuildValue ("I", self->length);
[f826349]124  if (args == NULL) {
125    goto fail;
126  }
[92a8800]127  // hide actual norm / phas content
[f826349]128
[5c1200a]129  result = PyUnicode_Format (format, args);
[f826349]130
131fail:
132  Py_XDECREF (format);
133  Py_XDECREF (args);
134
135  return result;
136}
137
[615ac7d]138PyObject *
139Py_cvec_get_norm (Py_cvec * self, void *closure)
140{
[ede5d38]141  // we want self->norm to still exist after our caller return it
[92a8800]142  Py_INCREF(self->norm);
143  return (PyObject*)(self->norm);
[615ac7d]144}
145
146PyObject *
147Py_cvec_get_phas (Py_cvec * self, void *closure)
148{
[ede5d38]149  // we want self->phas to still exist after our caller return it
[92a8800]150  Py_INCREF(self->phas);
151  return (PyObject *)(self->phas);
[615ac7d]152}
153
154static int
[a8aaef3]155Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure)
[615ac7d]156{
[1458de5]157  PyArrayObject * array;
[a8aaef3]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)) {
[92a8800]163    // we got an array, convert it to a cvec.norm
[1458de5]164    if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
[a8aaef3]165      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
166      goto fail;
[1458de5]167    } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
[a8aaef3]168      PyErr_SetString (PyExc_ValueError,
169          "input array has more than two dimensions");
170      goto fail;
171    }
172
[1458de5]173    if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
[a8aaef3]174      PyErr_SetString (PyExc_ValueError, "input array should be float");
175      goto fail;
[1458de5]176    } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
[a8aaef3]177      PyErr_SetString (PyExc_ValueError, "input array should be float32");
178      goto fail;
179    }
[1458de5]180    array = (PyArrayObject *)input;
[a8aaef3]181
182    // check input array dimensions
[7a7b00f]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 {
[92a8800]189      if (vec->length != PyArray_SIZE (array)) {
[a8aaef3]190          PyErr_Format (PyExc_ValueError,
191                  "input array has length %d, but cvec has length %d",
[92a8800]192                  (int)PyArray_SIZE (array), vec->length);
[a8aaef3]193          goto fail;
194      }
195    }
196
[92a8800]197    Py_XDECREF(vec->norm);
198    vec->norm = input;
199    Py_INCREF(vec->norm);
[a8aaef3]200
201  } else {
202    PyErr_SetString (PyExc_ValueError, "can only accept array as input");
203    return 1;
204  }
205
[615ac7d]206  return 0;
[a8aaef3]207
208fail:
209  return 1;
[615ac7d]210}
211
212static int
[a8aaef3]213Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
[615ac7d]214{
[1458de5]215  PyArrayObject * array;
[a8aaef3]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
[1458de5]223    if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
[a8aaef3]224      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
225      goto fail;
[1458de5]226    } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) {
[a8aaef3]227      PyErr_SetString (PyExc_ValueError,
228          "input array has more than two dimensions");
229      goto fail;
230    }
231
[1458de5]232    if (!PyArray_ISFLOAT ((PyArrayObject *)input)) {
[a8aaef3]233      PyErr_SetString (PyExc_ValueError, "input array should be float");
234      goto fail;
[1458de5]235    } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) {
[a8aaef3]236      PyErr_SetString (PyExc_ValueError, "input array should be float32");
237      goto fail;
238    }
[1458de5]239    array = (PyArrayObject *)input;
[a8aaef3]240
241    // check input array dimensions
[7a7b00f]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 {
[92a8800]248      if (vec->length != PyArray_SIZE (array)) {
[a8aaef3]249          PyErr_Format (PyExc_ValueError,
250                  "input array has length %d, but cvec has length %d",
[92a8800]251                  (int)PyArray_SIZE (array), vec->length);
[a8aaef3]252          goto fail;
253      }
254    }
255
[92a8800]256    Py_XDECREF(vec->phas);
257    vec->phas = input;
258    Py_INCREF(vec->phas);
[a8aaef3]259
260  } else {
261    PyErr_SetString (PyExc_ValueError, "can only accept array as input");
262    return 1;
263  }
264
[615ac7d]265  return 0;
[a8aaef3]266
267fail:
268  return 1;
[615ac7d]269}
270
[f826349]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
[615ac7d]282static PyGetSetDef Py_cvec_getseters[] = {
283  {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, 
[474f297]284      "Numpy vector of shape (length,) containing the magnitude",
[615ac7d]285      NULL},
286  {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, 
[474f297]287      "Numpy vector of shape (length,) containing the phase",
[615ac7d]288      NULL},
289  {NULL} /* sentinel */
290};
291
[f826349]292PyTypeObject Py_cvecType = {
[5c1200a]293  PyVarObject_HEAD_INIT(NULL, 0)
[f826349]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      */
[f2ce0fc]304  0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence    */
[f826349]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        */
[615ac7d]322  Py_cvec_getseters,            /* tp_getset         */
[f826349]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.