source: interfaces/python/py-cvec.c @ 970bced

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 970bced was f826349, 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.5 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
14typedef struct
15{
16  PyObject_HEAD
17  cvec_t * o;
18  uint_t length;
19  uint_t channels;
20} Py_cvec;
21
22static char Py_cvec_doc[] = "cvec object";
23
24static PyObject *
25Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
26{
27  int length= 0, channels = 0;
28  Py_cvec *self;
29  static char *kwlist[] = { "length", "channels", NULL };
30
31  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
32          &length, &channels)) {
33    return NULL;
34  }
35
36
37  self = (Py_cvec *) type->tp_alloc (type, 0);
38
39  self->length = Py_default_vector_length;
40  self->channels = Py_default_vector_channels;
41
42  if (self == NULL) {
43    return NULL;
44  }
45
46  if (length > 0) {
47    self->length = length;
48  } else if (length < 0) {
49    PyErr_SetString (PyExc_ValueError,
50        "can not use negative number of elements");
51    return NULL;
52  }
53
54  if (channels > 0) {
55    self->channels = channels;
56  } else if (channels < 0) {
57    PyErr_SetString (PyExc_ValueError,
58        "can not use negative number of channels");
59    return NULL;
60  }
61
62  return (PyObject *) self;
63}
64
65static int
66Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
67{
68  self->o = new_cvec (self->length, self->channels);
69  if (self->o == NULL) {
70    return -1;
71  }
72
73  return 0;
74}
75
76static void
77Py_cvec_del (Py_cvec * self)
78{
79  del_cvec (self->o);
80  self->ob_type->tp_free ((PyObject *) self);
81}
82
83static PyObject *
84Py_cvec_repr (Py_cvec * self, PyObject * unused)
85{
86  PyObject *format = NULL;
87  PyObject *args = NULL;
88  PyObject *result = NULL;
89
90  format = PyString_FromString ("aubio cvec of %d elements with %d channels");
91  if (format == NULL) {
92    goto fail;
93  }
94
95  args = Py_BuildValue ("II", self->length, self->channels);
96  if (args == NULL) {
97    goto fail;
98  }
99  cvec_print ( self->o );
100
101  result = PyString_Format (format, args);
102
103fail:
104  Py_XDECREF (format);
105  Py_XDECREF (args);
106
107  return result;
108}
109
110Py_cvec *
111PyAubio_ArrayToCvec (PyObject *input) {
112  PyObject *array;
113  Py_cvec *vec;
114  uint_t i;
115  // parsing input object into a Py_cvec
116  if (PyObject_TypeCheck (input, &Py_cvecType)) {
117    // input is an cvec, nothing else to do
118    vec = (Py_cvec *) input;
119  } else if (PyArray_Check(input)) {
120
121    // we got an array, convert it to an cvec
122    if (PyArray_NDIM (input) == 0) {
123      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
124      goto fail;
125    } else if (PyArray_NDIM (input) > 2) {
126      PyErr_SetString (PyExc_ValueError,
127          "input array has more than two dimensions");
128      goto fail;
129    }
130
131    if (!PyArray_ISFLOAT (input)) {
132      PyErr_SetString (PyExc_ValueError, "input array should be float");
133      goto fail;
134#if AUBIO_DO_CASTING
135    } else if (PyArray_TYPE (input) != AUBIO_FLOAT) {
136      // input data type is not float32, casting
137      array = PyArray_Cast ( (PyArrayObject*) input, AUBIO_FLOAT);
138      if (array == NULL) {
139        PyErr_SetString (PyExc_IndexError, "failed converting to NPY_FLOAT");
140        goto fail;
141      }
142#else
143    } else if (PyArray_TYPE (input) != AUBIO_FLOAT) {
144      PyErr_SetString (PyExc_ValueError, "input array should be float32");
145      goto fail;
146#endif
147    } else {
148      // input data type is float32, nothing else to do
149      array = input;
150    }
151
152    // create a new cvec object
153    vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); 
154    if (PyArray_NDIM (array) == 1) {
155      vec->channels = 1;
156      vec->length = PyArray_SIZE (array);
157    } else {
158      vec->channels = PyArray_DIM (array, 0);
159      vec->length = PyArray_DIM (array, 1);
160    }
161
162    // no need to really allocate cvec, just its struct member
163    // vec->o = new_cvec (vec->length, vec->channels);
164    vec->o = (cvec_t *)malloc(sizeof(cvec_t));
165    vec->o->length = vec->length; vec->o->channels = vec->channels;
166    vec->o->norm = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
167    vec->o->phas = (smpl_t**)malloc(vec->o->channels * sizeof(smpl_t*));
168    // hat data[i] point to array line
169    for (i = 0; i < vec->channels; i++) {
170      vec->o->norm[i] = (smpl_t *) PyArray_GETPTR1 (array, i);
171    }
172
173  } else {
174    PyErr_SetString (PyExc_ValueError, "can only accept array or cvec as input");
175    return NULL;
176  }
177
178  return vec;
179
180fail:
181  return NULL;
182}
183
184PyObject *
185PyAubio_CvecToArray (Py_cvec * self)
186{
187  PyObject *array = NULL;
188  if (self->channels == 1) {
189    npy_intp dims[] = { self->length, 1 };
190    array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[0]);
191  } else {
192    uint_t i;
193    npy_intp dims[] = { self->length, 1 };
194    PyObject *concat = PyList_New (0), *tmp = NULL;
195    for (i = 0; i < self->channels; i++) {
196      tmp = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[i]);
197      PyList_Append (concat, tmp);
198      Py_DECREF (tmp);
199    }
200    array = PyArray_FromObject (concat, NPY_FLOAT, 2, 2);
201    Py_DECREF (concat);
202  }
203  return array;
204}
205
206static Py_ssize_t
207Py_cvec_getchannels (Py_cvec * self)
208{
209  return self->channels;
210}
211
212static PyObject *
213Py_cvec_getitem (Py_cvec * self, Py_ssize_t index)
214{
215  PyObject *array;
216
217  if (index < 0 || index >= self->channels) {
218    PyErr_SetString (PyExc_IndexError, "no such channel");
219    return NULL;
220  }
221
222  npy_intp dims[] = { self->length, 1 };
223  array = PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm[index]);
224  return array;
225}
226
227static int
228Py_cvec_setitem (Py_cvec * self, Py_ssize_t index, PyObject * o)
229{
230  PyObject *array;
231
232  if (index < 0 || index >= self->channels) {
233    PyErr_SetString (PyExc_IndexError, "no such channel");
234    return -1;
235  }
236
237  array = PyArray_FROM_OT (o, NPY_FLOAT);
238  if (array == NULL) {
239    PyErr_SetString (PyExc_ValueError, "should be an array of float");
240    goto fail;
241  }
242
243  if (PyArray_NDIM (array) != 1) {
244    PyErr_SetString (PyExc_ValueError, "should be a one-dimensional array");
245    goto fail;
246  }
247
248  if (PyArray_SIZE (array) != self->length) {
249    PyErr_SetString (PyExc_ValueError,
250        "should be an array of same length as target cvec");
251    goto fail;
252  }
253
254  self->o->norm[index] = (smpl_t *) PyArray_GETPTR1 (array, 0);
255
256  return 0;
257
258fail:
259  return -1;
260}
261
262static PyMemberDef Py_cvec_members[] = {
263  // TODO remove READONLY flag and define getter/setter
264  {"length", T_INT, offsetof (Py_cvec, length), READONLY,
265      "length attribute"},
266  {"channels", T_INT, offsetof (Py_cvec, channels), READONLY,
267      "channels attribute"},
268  {NULL}                        /* Sentinel */
269};
270
271static PyMethodDef Py_cvec_methods[] = {
272  {"__array__", (PyCFunction) PyAubio_FvecToArray, METH_NOARGS,
273      "Returns the first channel as a numpy array."},
274  {NULL}
275};
276
277static PySequenceMethods Py_cvec_tp_as_sequence = {
278  (lenfunc) Py_cvec_getchannels,        /* sq_length         */
279  0,                                    /* sq_concat         */
280  0,                                    /* sq_repeat         */
281  (ssizeargfunc) Py_cvec_getitem,       /* sq_item           */
282  0,                                    /* sq_slice          */
283  (ssizeobjargproc) Py_cvec_setitem,    /* sq_ass_item       */
284  0,                                    /* sq_ass_slice      */
285  0,                                    /* sq_contains       */
286  0,                                    /* sq_inplace_concat */
287  0,                                    /* sq_inplace_repeat */
288};
289
290
291PyTypeObject Py_cvecType = {
292  PyObject_HEAD_INIT (NULL)
293  0,                            /* ob_size           */
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  &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  0,                            /* 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.