source: interfaces/python/aubiomodule.c @ 0a6c211

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

added new python interface draft, work in progress

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