source: interfaces/python/py-fvec.c @ 1dd137b

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

py-fvec.c: add PyAubio_CFvecToArray

  • Property mode set to 100644
File size: 9.9 KB
Line 
1#include "aubio-types.h"
2
3/* fvec type definition
4
5class fvec():
6    def __init__(self, length = 1024, channels = 1):
7        self.length = length
8        self.channels = channels
9        self.data = array(length, channels)
10
11*/
12
13static char Py_fvec_doc[] = "fvec object";
14
15static PyObject *
16Py_fvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
17{
18  int length= 0, channels = 0;
19  Py_fvec *self;
20  static char *kwlist[] = { "length", "channels", NULL };
21
22  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
23          &length, &channels)) {
24    return NULL;
25  }
26
27
28  self = (Py_fvec *) type->tp_alloc (type, 0);
29
30  self->length = Py_default_vector_length;
31  self->channels = Py_default_vector_channels;
32
33  if (self == NULL) {
34    return NULL;
35  }
36
37  if (length > 0) {
38    self->length = length;
39  } else if (length < 0) {
40    PyErr_SetString (PyExc_ValueError,
41        "can not use negative number of elements");
42    return NULL;
43  }
44
45  if (channels > 0) {
46    self->channels = channels;
47  } else if (channels < 0) {
48    PyErr_SetString (PyExc_ValueError,
49        "can not use negative number of channels");
50    return NULL;
51  }
52
53  return (PyObject *) self;
54}
55
56static int
57Py_fvec_init (Py_fvec * self, PyObject * args, PyObject * kwds)
58{
59  self->o = new_fvec (self->length, self->channels);
60  if (self->o == NULL) {
61    return -1;
62  }
63
64  return 0;
65}
66
67static void
68Py_fvec_del (Py_fvec * self)
69{
70  del_fvec (self->o);
71  self->ob_type->tp_free ((PyObject *) self);
72}
73
74static PyObject *
75Py_fvec_repr (Py_fvec * self, PyObject * unused)
76{
77  PyObject *format = NULL;
78  PyObject *args = NULL;
79  PyObject *result = NULL;
80
81  format = PyString_FromString ("aubio fvec of %d elements with %d channels");
82  if (format == NULL) {
83    goto fail;
84  }
85
86  args = Py_BuildValue ("II", self->length, self->channels);
87  if (args == NULL) {
88    goto fail;
89  }
90  fvec_print ( self->o );
91
92  result = PyString_Format (format, args);
93
94fail:
95  Py_XDECREF (format);
96  Py_XDECREF (args);
97
98  return result;
99}
100
101Py_fvec *
102PyAubio_ArrayToFvec (PyObject *input) {
103  PyObject *array;
104  Py_fvec *vec;
105  uint_t i;
106  if (input == NULL) {
107    PyErr_SetString (PyExc_ValueError, "input array is not a python object");
108    goto fail;
109  }
110  // parsing input object into a Py_fvec
111  if (PyObject_TypeCheck (input, &Py_fvecType)) {
112    // input is an fvec, nothing else to do
113    vec = (Py_fvec *) input;
114  } else if (PyArray_Check(input)) {
115
116    // we got an array, convert it to an fvec
117    if (PyArray_NDIM (input) == 0) {
118      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
119      goto fail;
120    } else if (PyArray_NDIM (input) > 2) {
121      PyErr_SetString (PyExc_ValueError,
122          "input array has more than two dimensions");
123      goto fail;
124    }
125
126    if (!PyArray_ISFLOAT (input)) {
127      PyErr_SetString (PyExc_ValueError, "input array should be float");
128      goto fail;
129#if AUBIO_DO_CASTING
130    } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
131      // input data type is not float32, casting
132      array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_NPY_SMPL);
133      if (array == NULL) {
134        PyErr_SetString (PyExc_IndexError, "failed converting to AUBIO_NPY_SMPL");
135        goto fail;
136      }
137#else
138    } else if (PyArray_TYPE (input) != AUBIO_NPY_SMPL) {
139      PyErr_SetString (PyExc_ValueError, "input array should be float32");
140      goto fail;
141#endif
142    } else {
143      // input data type is float32, nothing else to do
144      array = input;
145    }
146
147    // create a new fvec object
148    vec = (Py_fvec*) PyObject_New (Py_fvec, &Py_fvecType); 
149    if (PyArray_NDIM (array) == 1) {
150      vec->channels = 1;
151      vec->length = PyArray_SIZE (array);
152    } else {
153      vec->channels = PyArray_DIM (array, 0);
154      vec->length = PyArray_DIM (array, 1);
155    }
156
157    // no need to really allocate fvec, just its struct member
158    // vec->o = new_fvec (vec->length, vec->channels);
159    vec->o = (fvec_t *)malloc(sizeof(fvec_t));
160    vec->o->length = vec->length; vec->o->channels = vec->channels;
161    vec->o->data = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
162    // hat data[i] point to array line
163    for (i = 0; i < vec->channels; i++) {
164      vec->o->data[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
165    }
166
167  } else {
168    PyErr_SetString (PyExc_ValueError, "can only accept array or fvec as input");
169    return NULL;
170  }
171
172  return vec;
173
174fail:
175  return NULL;
176}
177
178PyObject *
179PyAubio_CFvecToArray (fvec_t * self)
180{
181  PyObject *array = NULL;
182  uint_t i;
183  npy_intp dims[] = { self->length, 1 };
184  PyObject *concat = PyList_New (0), *tmp = NULL;
185  for (i = 0; i < self->channels; i++) {
186    tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data[i]);
187    PyList_Append (concat, tmp);
188    Py_DECREF (tmp);
189  }
190  array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2);
191  Py_DECREF (concat);
192  return array;
193}
194
195PyObject *
196PyAubio_FvecToArray (Py_fvec * self)
197{
198  PyObject *array = NULL;
199  if (self->channels == 1) {
200    npy_intp dims[] = { self->length, 1 };
201    array = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[0]);
202  } else {
203    uint_t i;
204    npy_intp dims[] = { self->length, 1 };
205    PyObject *concat = PyList_New (0), *tmp = NULL;
206    for (i = 0; i < self->channels; i++) {
207      tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[i]);
208      PyList_Append (concat, tmp);
209      Py_DECREF (tmp);
210    }
211    array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2);
212    Py_DECREF (concat);
213  }
214  return array;
215}
216
217static Py_ssize_t
218Py_fvec_getchannels (Py_fvec * self)
219{
220  return self->channels;
221}
222
223static PyObject *
224Py_fvec_getitem (Py_fvec * self, Py_ssize_t index)
225{
226  PyObject *array;
227
228  if (index < 0 || index >= self->channels) {
229    PyErr_SetString (PyExc_IndexError, "no such channel");
230    return NULL;
231  }
232
233  npy_intp dims[] = { self->length, 1 };
234  array = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->data[index]);
235  return array;
236}
237
238static int
239Py_fvec_setitem (Py_fvec * self, Py_ssize_t index, PyObject * o)
240{
241  PyObject *array;
242
243  if (index < 0 || index >= self->channels) {
244    PyErr_SetString (PyExc_IndexError, "no such channel");
245    return -1;
246  }
247
248  array = PyArray_FROM_OT (o, AUBIO_NPY_SMPL);
249  if (array == NULL) {
250    PyErr_SetString (PyExc_ValueError, "should be an array of float");
251    goto fail;
252  }
253
254  if (PyArray_NDIM (array) != 1) {
255    PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
256    goto fail;
257  }
258
259  if (PyArray_SIZE (array) != self->length) {
260    PyErr_SetString (PyExc_ValueError,
261        "should be an array of same length as target fvec");
262    goto fail;
263  }
264
265  self->o->data[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
266
267  return 0;
268
269fail:
270  return -1;
271}
272
273static PyMemberDef Py_fvec_members[] = {
274  // TODO remove READONLY flag and define getter/setter
275  {"length", T_INT, offsetof (Py_fvec, length), READONLY,
276      "length attribute"},
277  {"channels", T_INT, offsetof (Py_fvec, channels), READONLY,
278      "channels attribute"},
279  {NULL}                        /* Sentinel */
280};
281
282static PyMethodDef Py_fvec_methods[] = {
283  {"__array__", (PyCFunction) PyAubio_FvecToArray, METH_NOARGS,
284      "Returns the vector as a numpy array."},
285  {NULL}
286};
287
288static PySequenceMethods Py_fvec_tp_as_sequence = {
289  (lenfunc) Py_fvec_getchannels,        /* sq_length         */
290  0,                                    /* sq_concat         */
291  0,                                    /* sq_repeat         */
292  (ssizeargfunc) Py_fvec_getitem,       /* sq_item           */
293  0,                                    /* sq_slice          */
294  (ssizeobjargproc) Py_fvec_setitem,    /* sq_ass_item       */
295  0,                                    /* sq_ass_slice      */
296  0,                                    /* sq_contains       */
297  0,                                    /* sq_inplace_concat */
298  0,                                    /* sq_inplace_repeat */
299};
300
301
302PyTypeObject Py_fvecType = {
303  PyObject_HEAD_INIT (NULL)
304  0,                            /* ob_size           */
305  "aubio.fvec",                 /* tp_name           */
306  sizeof (Py_fvec),             /* tp_basicsize      */
307  0,                            /* tp_itemsize       */
308  (destructor) Py_fvec_del,     /* tp_dealloc        */
309  0,                            /* tp_print          */
310  0,                            /* tp_getattr        */
311  0,                            /* tp_setattr        */
312  0,                            /* tp_compare        */
313  (reprfunc) Py_fvec_repr,      /* tp_repr           */
314  0,                            /* tp_as_number      */
315  &Py_fvec_tp_as_sequence,      /* tp_as_sequence    */
316  0,                            /* tp_as_mapping     */
317  0,                            /* tp_hash           */
318  0,                            /* tp_call           */
319  0,                            /* tp_str            */
320  0,                            /* tp_getattro       */
321  0,                            /* tp_setattro       */
322  0,                            /* tp_as_buffer      */
323  Py_TPFLAGS_DEFAULT,           /* tp_flags          */
324  Py_fvec_doc,                  /* tp_doc            */
325  0,                            /* tp_traverse       */
326  0,                            /* tp_clear          */
327  0,                            /* tp_richcompare    */
328  0,                            /* tp_weaklistoffset */
329  0,                            /* tp_iter           */
330  0,                            /* tp_iternext       */
331  Py_fvec_methods,              /* tp_methods        */
332  Py_fvec_members,              /* tp_members        */
333  0,                            /* tp_getset         */
334  0,                            /* tp_base           */
335  0,                            /* tp_dict           */
336  0,                            /* tp_descr_get      */
337  0,                            /* tp_descr_set      */
338  0,                            /* tp_dictoffset     */
339  (initproc) Py_fvec_init,      /* tp_init           */
340  0,                            /* tp_alloc          */
341  Py_fvec_new,                  /* tp_new            */
342};
Note: See TracBrowser for help on using the repository browser.