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

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

python/aubiomodule.c: move PyAubio_ArrayToFvec to py-fvec.c

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