source: interfaces/python/py-cvec.c @ 68607fd

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

interfaces/python/py-cvec.c: write setters for norm and phas

  • Property mode set to 100644
File size: 15.4 KB
Line 
1#include "aubio-types.h"
2
3/* cvec type definition
4
5class cvec():
6    def __init__(self, length = 1024, channels = 1):
7        self.length = length
8        self.channels = channels
9        self.norm = array(length, channels)
10        self.phas = array(length, channels)
11*/
12
13
14static char Py_cvec_doc[] = "cvec object";
15
16static PyObject *
17Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
18{
19  int length= 0, channels = 0;
20  Py_cvec *self;
21  static char *kwlist[] = { "length", "channels", NULL };
22
23  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
24          &length, &channels)) {
25    return NULL;
26  }
27
28
29  self = (Py_cvec *) type->tp_alloc (type, 0);
30
31  self->length = Py_default_vector_length;
32  self->channels = Py_default_vector_channels;
33
34  if (self == NULL) {
35    return NULL;
36  }
37
38  if (length > 0) {
39    self->length = length;
40  } else if (length < 0) {
41    PyErr_SetString (PyExc_ValueError,
42        "can not use negative number of elements");
43    return NULL;
44  }
45
46  if (channels > 0) {
47    self->channels = channels;
48  } else if (channels < 0) {
49    PyErr_SetString (PyExc_ValueError,
50        "can not use negative number of channels");
51    return NULL;
52  }
53
54  return (PyObject *) self;
55}
56
57static int
58Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
59{
60  self->o = new_cvec (self->length, self->channels);
61  if (self->o == NULL) {
62    return -1;
63  }
64
65  return 0;
66}
67
68static void
69Py_cvec_del (Py_cvec * self)
70{
71  del_cvec (self->o);
72  self->ob_type->tp_free ((PyObject *) self);
73}
74
75static PyObject *
76Py_cvec_repr (Py_cvec * self, PyObject * unused)
77{
78  PyObject *format = NULL;
79  PyObject *args = NULL;
80  PyObject *result = NULL;
81
82  format = PyString_FromString ("aubio cvec of %d elements with %d channels");
83  if (format == NULL) {
84    goto fail;
85  }
86
87  args = Py_BuildValue ("II", self->length, self->channels);
88  if (args == NULL) {
89    goto fail;
90  }
91  //cvec_print ( self->o );
92
93  result = PyString_Format (format, args);
94
95fail:
96  Py_XDECREF (format);
97  Py_XDECREF (args);
98
99  return result;
100}
101
102Py_cvec *
103PyAubio_ArrayToCvec (PyObject *input) {
104  PyObject *array;
105  Py_cvec *vec;
106  uint_t i;
107  // parsing input object into a Py_cvec
108  if (PyObject_TypeCheck (input, &Py_cvecType)) {
109    // input is an cvec, nothing else to do
110    vec = (Py_cvec *) input;
111  } else if (PyArray_Check(input)) {
112
113    // we got an array, convert it to an cvec
114    if (PyArray_NDIM (input) == 0) {
115      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
116      goto fail;
117    } else if (PyArray_NDIM (input) > 2) {
118      PyErr_SetString (PyExc_ValueError,
119          "input array has more than two dimensions");
120      goto fail;
121    }
122
123    if (!PyArray_ISFLOAT (input)) {
124      PyErr_SetString (PyExc_ValueError, "input array should be float");
125      goto fail;
126#if AUBIO_DO_CASTING
127    } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
128      // input data type is not float32, casting
129      array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_NPY_SMPL);
130      if (array == NULL) {
131        PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT");
132        goto fail;
133      }
134#else
135    } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
136      PyErr_SetString (PyExc_ValueError, "input array should be float32");
137      goto fail;
138#endif
139    } else {
140      // input data type is float32, nothing else to do
141      array = input;
142    }
143
144    // create a new cvec object
145    vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); 
146    if (PyArray_NDIM (array) == 1) {
147      PyErr_SetString (PyExc_ValueError,
148          "input array should be have at least two rows for norm and phas");
149      goto fail;
150    } else if (PyArray_NDIM (array) == 2) {
151      vec->channels = 1;
152      vec->length = PyArray_SIZE (array);
153    } else {
154      vec->channels = PyArray_DIM (array, 0) / 2;
155      vec->length = PyArray_DIM (array, 1);
156    }
157
158    // no need to really allocate cvec, just its struct member
159    // vec->o = new_cvec (vec->length, vec->channels);
160    vec->o = (cvec_t *)malloc(sizeof(cvec_t));
161    vec->o->length = vec->length; vec->o->channels = vec->channels;
162    vec->o->norm = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
163    vec->o->phas = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
164    // hat data[i] point to array line
165    for (i = 0; i < vec->channels; i+=2) {
166      vec->o->norm[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
167      vec->o->phas[i] = (smpl_t *) PyArray_GETPTR1 (array, i+1);
168    }
169
170  } else {
171    PyErr_SetString (PyExc_ValueError, "can only accept array or cvec as input");
172    return NULL;
173  }
174
175  return vec;
176
177fail:
178  return NULL;
179}
180
181PyObject *
182PyAubio_CvecToArray (Py_cvec * self)
183{
184  PyObject *array = NULL;
185  uint_t i;
186  npy_intp dims[] = { self->o->length, 1 };
187  PyObject *concat = PyList_New (0), *tmp = NULL;
188  for (i = 0; i < self->channels; i++) {
189    tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[i]);
190    PyList_Append (concat, tmp);
191    Py_DECREF (tmp);
192    tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas[i]);
193    PyList_Append (concat, tmp);
194    Py_DECREF (tmp);
195  }
196  array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
197  Py_DECREF (concat);
198  return array;
199}
200
201PyObject *
202PyAubio_CvecNormToArray (Py_cvec * self)
203{
204  PyObject *array = NULL;
205  uint_t i;
206  npy_intp dims[] = { self->o->length, 1 };
207  PyObject *concat = PyList_New (0), *tmp = NULL;
208  for (i = 0; i < self->channels; i++) {
209    tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[i]);
210    PyList_Append (concat, tmp);
211    Py_DECREF (tmp);
212  }
213  array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
214  Py_DECREF (concat);
215  return array;
216}
217
218
219PyObject *
220PyAubio_CvecPhasToArray (Py_cvec * self)
221{
222  PyObject *array = NULL;
223  uint_t i;
224  npy_intp dims[] = { self->o->length, 1 };
225  PyObject *concat = PyList_New (0), *tmp = NULL;
226  for (i = 0; i < self->channels; i++) {
227    tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas[i]);
228    PyList_Append (concat, tmp);
229    Py_DECREF (tmp);
230  }
231  array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
232  Py_DECREF (concat);
233  return array;
234}
235
236PyObject *
237PyAubio_ArrayToCvecPhas (PyObject * self)
238{
239  return NULL;
240}
241
242PyObject *
243Py_cvec_get_norm (Py_cvec * self, void *closure)
244{
245  return PyAubio_CvecNormToArray(self);
246}
247
248PyObject *
249Py_cvec_get_phas (Py_cvec * self, void *closure)
250{
251  return PyAubio_CvecPhasToArray(self);
252}
253
254static int
255Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure)
256{
257  uint_t i;
258  PyObject * array;
259  if (input == NULL) {
260    PyErr_SetString (PyExc_ValueError, "input array is not a python object");
261    goto fail;
262  }
263  if (PyArray_Check(input)) {
264
265    // we got an array, convert it to a cvec.norm
266    if (PyArray_NDIM (input) == 0) {
267      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
268      goto fail;
269    } else if (PyArray_NDIM (input) > 2) {
270      PyErr_SetString (PyExc_ValueError,
271          "input array has more than two dimensions");
272      goto fail;
273    }
274
275    if (!PyArray_ISFLOAT (input)) {
276      PyErr_SetString (PyExc_ValueError, "input array should be float");
277      goto fail;
278    } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
279      PyErr_SetString (PyExc_ValueError, "input array should be float32");
280      goto fail;
281    }
282    array = input;
283
284    // check input array dimensions
285    if (PyArray_NDIM (array) == 1) {
286      if (vec->channels != 1) {
287          PyErr_SetString (PyExc_ValueError,
288                  "input array should have more than one channel");
289          goto fail;
290      }
291      if (vec->o->length != PyArray_SIZE (array)) {
292          PyErr_Format (PyExc_ValueError,
293                  "input array has length %d, but cvec has length %d",
294                  PyArray_SIZE (array), vec->o->length);
295          goto fail;
296      }
297    } else {
298      if (vec->channels != PyArray_DIM (array, 0)) {
299          PyErr_Format (PyExc_ValueError,
300                  "input array has %d channels, but vector has %d channels",
301                  PyArray_DIM (array, 0), vec->channels);
302          goto fail;
303      }
304      if (vec->o->length != PyArray_DIM (array, 1)) {
305          PyErr_Format (PyExc_ValueError,
306                  "input array has length %d, but vector has length %d",
307                  PyArray_DIM (array, 1), vec->o->length);
308          goto fail;
309      }
310    }
311
312    for (i = 0; i < vec->channels; i++) {
313      vec->o->norm[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
314    }
315
316  } else {
317    PyErr_SetString (PyExc_ValueError, "can only accept array as input");
318    return 1;
319  }
320
321  Py_INCREF(array);
322  return 0;
323
324fail:
325  return 1;
326}
327
328static int
329Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
330{
331  uint_t i;
332  PyObject * array;
333  if (input == NULL) {
334    PyErr_SetString (PyExc_ValueError, "input array is not a python object");
335    goto fail;
336  }
337  if (PyArray_Check(input)) {
338
339    // we got an array, convert it to a cvec.phas
340    if (PyArray_NDIM (input) == 0) {
341      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
342      goto fail;
343    } else if (PyArray_NDIM (input) > 2) {
344      PyErr_SetString (PyExc_ValueError,
345          "input array has more than two dimensions");
346      goto fail;
347    }
348
349    if (!PyArray_ISFLOAT (input)) {
350      PyErr_SetString (PyExc_ValueError, "input array should be float");
351      goto fail;
352    } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
353      PyErr_SetString (PyExc_ValueError, "input array should be float32");
354      goto fail;
355    }
356    array = input;
357
358    // check input array dimensions
359    if (PyArray_NDIM (array) == 1) {
360      if (vec->channels != 1) {
361          PyErr_SetString (PyExc_ValueError,
362                  "input array should have more than one channel");
363          goto fail;
364      }
365      if (vec->o->length != PyArray_SIZE (array)) {
366          PyErr_Format (PyExc_ValueError,
367                  "input array has length %d, but cvec has length %d",
368                  PyArray_SIZE (array), vec->o->length);
369          goto fail;
370      }
371    } else {
372      if (vec->channels != PyArray_DIM (array, 0)) {
373          PyErr_Format (PyExc_ValueError,
374                  "input array has %d channels, but vector has %d channels",
375                  PyArray_DIM (array, 0), vec->channels);
376          goto fail;
377      }
378      if (vec->o->length != PyArray_DIM (array, 1)) {
379          PyErr_Format (PyExc_ValueError,
380                  "input array has length %d, but vector has length %d",
381                  PyArray_DIM (array, 1), vec->o->length);
382          goto fail;
383      }
384    }
385
386    for (i = 0; i < vec->channels; i++) {
387      vec->o->phas[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
388    }
389
390  } else {
391    PyErr_SetString (PyExc_ValueError, "can only accept array as input");
392    return 1;
393  }
394
395  Py_INCREF(array);
396  return 0;
397
398fail:
399  return 1;
400}
401
402static Py_ssize_t
403Py_cvec_getchannels (Py_cvec * self)
404{
405  return self->channels;
406}
407
408static PyObject *
409Py_cvec_getitem (Py_cvec * self, Py_ssize_t index)
410{
411  PyObject *array;
412
413  if (index < 0 || index >= self->channels) {
414    PyErr_SetString (PyExc_IndexError, "no such channel");
415    return NULL;
416  }
417
418  npy_intp dims[] = { self->length, 1 };
419  array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[index]);
420  return array;
421}
422
423static int
424Py_cvec_setitem (Py_cvec * self, Py_ssize_t index, PyObject * o)
425{
426  PyObject *array;
427
428  if (index < 0 || index >= self->channels) {
429    PyErr_SetString (PyExc_IndexError, "no such channel");
430    return -1;
431  }
432
433  array = PyArray_FROM_OT (o, NPY_FLOAT);
434  if (array == NULL) {
435    PyErr_SetString (PyExc_ValueError, "should be an array of float");
436    goto fail;
437  }
438
439  if (PyArray_NDIM (array) != 1) {
440    PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
441    goto fail;
442  }
443
444  if (PyArray_SIZE (array) != self->length) {
445    PyErr_SetString (PyExc_ValueError,
446        "should be an array of same length as target cvec");
447    goto fail;
448  }
449
450  self->o->norm[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
451
452  return 0;
453
454fail:
455  return -1;
456}
457
458static PyMemberDef Py_cvec_members[] = {
459  // TODO remove READONLY flag and define getter/setter
460  {"length", T_INT, offsetof (Py_cvec, length), READONLY,
461      "length attribute"},
462  {"channels", T_INT, offsetof (Py_cvec, channels), READONLY,
463      "channels attribute"},
464  {NULL}                        /* Sentinel */
465};
466
467static PyMethodDef Py_cvec_methods[] = {
468  {"__array__", (PyCFunction) PyAubio_CvecToArray, METH_NOARGS,
469      "Returns the content of this cvec as a numpy array"},
470  {NULL}
471};
472
473static PyGetSetDef Py_cvec_getseters[] = {
474  {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, 
475      "Content of the magnitude of this cvec",
476      NULL},
477  {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, 
478      "Content of the magnitude of this cvec",
479      NULL},
480  {NULL} /* sentinel */
481};
482
483static PySequenceMethods Py_cvec_tp_as_sequence = {
484  (lenfunc) Py_cvec_getchannels,        /* sq_length         */
485  0,                                    /* sq_concat         */
486  0,                                    /* sq_repeat         */
487  (ssizeargfunc) Py_cvec_getitem,       /* sq_item           */
488  0,                                    /* sq_slice          */
489  (ssizeobjargproc) Py_cvec_setitem,    /* sq_ass_item       */
490  0,                                    /* sq_ass_slice      */
491  0,                                    /* sq_contains       */
492  0,                                    /* sq_inplace_concat */
493  0,                                    /* sq_inplace_repeat */
494};
495
496
497PyTypeObject Py_cvecType = {
498  PyObject_HEAD_INIT (NULL)
499  0,                            /* ob_size           */
500  "aubio.cvec",                 /* tp_name           */
501  sizeof (Py_cvec),             /* tp_basicsize      */
502  0,                            /* tp_itemsize       */
503  (destructor) Py_cvec_del,     /* tp_dealloc        */
504  0,                            /* tp_print          */
505  0,                            /* tp_getattr        */
506  0,                            /* tp_setattr        */
507  0,                            /* tp_compare        */
508  (reprfunc) Py_cvec_repr,      /* tp_repr           */
509  0,                            /* tp_as_number      */
510  &Py_cvec_tp_as_sequence,      /* tp_as_sequence    */
511  0,                            /* tp_as_mapping     */
512  0,                            /* tp_hash           */
513  0,                            /* tp_call           */
514  0,                            /* tp_str            */
515  0,                            /* tp_getattro       */
516  0,                            /* tp_setattro       */
517  0,                            /* tp_as_buffer      */
518  Py_TPFLAGS_DEFAULT,           /* tp_flags          */
519  Py_cvec_doc,                  /* tp_doc            */
520  0,                            /* tp_traverse       */
521  0,                            /* tp_clear          */
522  0,                            /* tp_richcompare    */
523  0,                            /* tp_weaklistoffset */
524  0,                            /* tp_iter           */
525  0,                            /* tp_iternext       */
526  Py_cvec_methods,              /* tp_methods        */
527  Py_cvec_members,              /* tp_members        */
528  Py_cvec_getseters,            /* tp_getset         */
529  0,                            /* tp_base           */
530  0,                            /* tp_dict           */
531  0,                            /* tp_descr_get      */
532  0,                            /* tp_descr_set      */
533  0,                            /* tp_dictoffset     */
534  (initproc) Py_cvec_init,      /* tp_init           */
535  0,                            /* tp_alloc          */
536  Py_cvec_new,                  /* tp_new            */
537};
Note: See TracBrowser for help on using the repository browser.