source: interfaces/python/py-fvec.c @ f826349

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

interfaces/python: add cvec and filter types

  • Property mode set to 100644
File size: 9.4 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_FLOAT) {
131      // input data type is not float32, casting
132      array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_FLOAT);
133      if (array == NULL) {
134        PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT");
135        goto fail;
136      }
137#else
138    } else if (PyArray_TYPE (input) != AUBIO_FLOAT) {
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_FvecToArray (Py_fvec * self)
180{
181  PyObject *array = NULL;
182  if (self->channels == 1) {
183    npy_intp dims[] = { self->length, 1 };
184    array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[0]);
185  } else {
186    uint_t i;
187    npy_intp dims[] = { self->length, 1 };
188    PyObject *concat = PyList_New (0), *tmp = NULL;
189    for (i = 0; i < self->channels; i++) {
190      tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[i]);
191      PyList_Append (concat, tmp);
192      Py_DECREF (tmp);
193    }
194    array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
195    Py_DECREF (concat);
196  }
197  return array;
198}
199
200static Py_ssize_t
201Py_fvec_getchannels (Py_fvec * self)
202{
203  return self->channels;
204}
205
206static PyObject *
207Py_fvec_getitem (Py_fvec * self, Py_ssize_t index)
208{
209  PyObject *array;
210
211  if (index < 0 || index >= self->channels) {
212    PyErr_SetString (PyExc_IndexError, "no such channel");
213    return NULL;
214  }
215
216  npy_intp dims[] = { self->length, 1 };
217  array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->data[index]);
218  return array;
219}
220
221static int
222Py_fvec_setitem (Py_fvec * self, Py_ssize_t index, PyObject * o)
223{
224  PyObject *array;
225
226  if (index < 0 || index >= self->channels) {
227    PyErr_SetString (PyExc_IndexError, "no such channel");
228    return -1;
229  }
230
231  array = PyArray_FROM_OT (o, NPY_FLOAT);
232  if (array == NULL) {
233    PyErr_SetString (PyExc_ValueError, "should be an array of float");
234    goto fail;
235  }
236
237  if (PyArray_NDIM (array) != 1) {
238    PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
239    goto fail;
240  }
241
242  if (PyArray_SIZE (array) != self->length) {
243    PyErr_SetString (PyExc_ValueError,
244        "should be an array of same length as target fvec");
245    goto fail;
246  }
247
248  self->o->data[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
249
250  return 0;
251
252fail:
253  return -1;
254}
255
256static PyMemberDef Py_fvec_members[] = {
257  // TODO remove READONLY flag and define getter/setter
258  {"length", T_INT, offsetof (Py_fvec, length), READONLY,
259      "length attribute"},
260  {"channels", T_INT, offsetof (Py_fvec, channels), READONLY,
261      "channels attribute"},
262  {NULL}                        /* Sentinel */
263};
264
265static PyMethodDef Py_fvec_methods[] = {
266  {"__array__", (PyCFunction) PyAubio_FvecToArray, METH_NOARGS,
267      "Returns the first channel as a numpy array."},
268  {NULL}
269};
270
271static PySequenceMethods Py_fvec_tp_as_sequence = {
272  (lenfunc) Py_fvec_getchannels,        /* sq_length         */
273  0,                                    /* sq_concat         */
274  0,                                    /* sq_repeat         */
275  (ssizeargfunc) Py_fvec_getitem,       /* sq_item           */
276  0,                                    /* sq_slice          */
277  (ssizeobjargproc) Py_fvec_setitem,    /* sq_ass_item       */
278  0,                                    /* sq_ass_slice      */
279  0,                                    /* sq_contains       */
280  0,                                    /* sq_inplace_concat */
281  0,                                    /* sq_inplace_repeat */
282};
283
284
285PyTypeObject Py_fvecType = {
286  PyObject_HEAD_INIT (NULL)
287  0,                            /* ob_size           */
288  "aubio.fvec",                 /* tp_name           */
289  sizeof (Py_fvec),             /* tp_basicsize      */
290  0,                            /* tp_itemsize       */
291  (destructor) Py_fvec_del,     /* tp_dealloc        */
292  0,                            /* tp_print          */
293  0,                            /* tp_getattr        */
294  0,                            /* tp_setattr        */
295  0,                            /* tp_compare        */
296  (reprfunc) Py_fvec_repr,      /* tp_repr           */
297  0,                            /* tp_as_number      */
298  &Py_fvec_tp_as_sequence,      /* tp_as_sequence    */
299  0,                            /* tp_as_mapping     */
300  0,                            /* tp_hash           */
301  0,                            /* tp_call           */
302  0,                            /* tp_str            */
303  0,                            /* tp_getattro       */
304  0,                            /* tp_setattro       */
305  0,                            /* tp_as_buffer      */
306  Py_TPFLAGS_DEFAULT,           /* tp_flags          */
307  Py_fvec_doc,                  /* tp_doc            */
308  0,                            /* tp_traverse       */
309  0,                            /* tp_clear          */
310  0,                            /* tp_richcompare    */
311  0,                            /* tp_weaklistoffset */
312  0,                            /* tp_iter           */
313  0,                            /* tp_iternext       */
314  Py_fvec_methods,              /* tp_methods        */
315  Py_fvec_members,              /* tp_members        */
316  0,                            /* tp_getset         */
317  0,                            /* tp_base           */
318  0,                            /* tp_dict           */
319  0,                            /* tp_descr_get      */
320  0,                            /* tp_descr_set      */
321  0,                            /* tp_dictoffset     */
322  (initproc) Py_fvec_init,      /* tp_init           */
323  0,                            /* tp_alloc          */
324  Py_fvec_new,                  /* tp_new            */
325};
Note: See TracBrowser for help on using the repository browser.