source: python/ext/py-source.c @ 26eb6d0

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretchpitchshiftsamplertimestretchyinfft+
Last change on this file since 26eb6d0 was 26eb6d0, checked in by Paul Brossier <piem@piem.org>, 4 years ago

python/ext/py-source.c: fix memory leak (see #18)

  • Property mode set to 100644
File size: 7.4 KB
Line 
1#include "aubio-types.h"
2
3typedef struct
4{
5  PyObject_HEAD
6  aubio_source_t * o;
7  char_t* uri;
8  uint_t samplerate;
9  uint_t channels;
10  uint_t hop_size;
11  fvec_t *read_to;
12  fmat_t *mread_to;
13} Py_source;
14
15static char Py_source_doc[] = ""
16"   __new__(path, samplerate = 0, hop_size = 512, channels = 1)\n"
17"\n"
18"       Create a new source, opening the given path for reading.\n"
19"\n"
20"       Examples\n"
21"       --------\n"
22"\n"
23"       Create a new source, using the original samplerate, with hop_size = 512:\n"
24"\n"
25"       >>> source('/tmp/t.wav')\n"
26"\n"
27"       Create a new source, resampling the original to 8000Hz:\n"
28"\n"
29"       >>> source('/tmp/t.wav', samplerate = 8000)\n"
30"\n"
31"       Create a new source, resampling it at 32000Hz, hop_size = 32:\n"
32"\n"
33"       >>> source('/tmp/t.wav', samplerate = 32000, hop_size = 32)\n"
34"\n"
35"       Create a new source, using its original samplerate:\n"
36"\n"
37"       >>> source('/tmp/t.wav', samplerate = 0)\n"
38"\n"
39"   __call__()\n"
40"       vec, read = x() <==> vec, read = x.do()\n"
41"\n"
42"       Read vector from source.\n"
43"\n"
44"       See also\n"
45"       --------\n"
46"       aubio.source.do\n"
47"\n";
48
49static char Py_source_get_samplerate_doc[] = ""
50"x.get_samplerate() -> source samplerate\n"
51"\n"
52"Get samplerate of source.";
53
54static char Py_source_get_channels_doc[] = ""
55"x.get_channels() -> number of channels\n"
56"\n"
57"Get number of channels in source.";
58
59static char Py_source_do_doc[] = ""
60"vec, read = x.do() <==> vec, read = x()\n"
61"\n"
62"Read monophonic vector from source.";
63
64static char Py_source_do_multi_doc[] = ""
65"mat, read = x.do_multi()\n"
66"\n"
67"Read polyphonic vector from source.";
68
69static char Py_source_close_doc[] = ""
70"x.close()\n"
71"\n"
72"Close this source now.";
73
74static char Py_source_seek_doc[] = ""
75"x.seek(position)\n"
76"\n"
77"Seek to resampled frame position.";
78
79static PyObject *
80Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
81{
82  Py_source *self;
83  char_t* uri = NULL;
84  uint_t samplerate = 0;
85  uint_t hop_size = 0;
86  uint_t channels = 0;
87  static char *kwlist[] = { "uri", "samplerate", "hop_size", "channels", NULL };
88
89  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|sIII", kwlist,
90          &uri, &samplerate, &hop_size, &channels)) {
91    return NULL;
92  }
93
94  self = (Py_source *) pytype->tp_alloc (pytype, 0);
95
96  if (self == NULL) {
97    return NULL;
98  }
99
100  self->uri = "none";
101  if (uri != NULL) {
102    self->uri = uri;
103  }
104
105  self->samplerate = 0;
106  if ((sint_t)samplerate > 0) {
107    self->samplerate = samplerate;
108  } else if ((sint_t)samplerate < 0) {
109    PyErr_SetString (PyExc_ValueError,
110        "can not use negative value for samplerate");
111    return NULL;
112  }
113
114  self->hop_size = Py_default_vector_length / 2;
115  if ((sint_t)hop_size > 0) {
116    self->hop_size = hop_size;
117  } else if ((sint_t)hop_size < 0) {
118    PyErr_SetString (PyExc_ValueError,
119        "can not use negative value for hop_size");
120    return NULL;
121  }
122
123  self->channels = 1;
124  if ((sint_t)channels >= 0) {
125    self->channels = channels;
126  } else if ((sint_t)channels < 0) {
127    PyErr_SetString (PyExc_ValueError,
128        "can not use negative value for channels");
129    return NULL;
130  }
131
132  return (PyObject *) self;
133}
134
135static int
136Py_source_init (Py_source * self, PyObject * args, PyObject * kwds)
137{
138  self->o = new_aubio_source ( self->uri, self->samplerate, self->hop_size );
139  if (self->o == NULL) {
140    char_t errstr[30 + strlen(self->uri)];
141    sprintf(errstr, "error creating source with %s", self->uri);
142    PyErr_SetString (PyExc_RuntimeError, errstr);
143    return -1;
144  }
145  self->samplerate = aubio_source_get_samplerate ( self->o );
146  if (self->channels == 0) {
147    self->channels = aubio_source_get_channels ( self->o );
148  }
149
150  self->read_to = new_fvec(self->hop_size);
151  self->mread_to = new_fmat (self->channels, self->hop_size);
152
153  return 0;
154}
155
156static void
157Py_source_del (Py_source *self, PyObject *unused)
158{
159  del_aubio_source(self->o);
160  del_fvec(self->read_to);
161  del_fmat(self->mread_to);
162  Py_TYPE(self)->tp_free((PyObject *) self);
163}
164
165
166/* function Py_source_do */
167static PyObject *
168Py_source_do(Py_source * self, PyObject * args)
169{
170
171
172  /* output vectors prototypes */
173  uint_t read;
174
175
176
177
178
179
180  /* creating output read_to as a new_fvec of length self->hop_size */
181  read = 0;
182
183
184  /* compute _do function */
185  aubio_source_do (self->o, self->read_to, &read);
186
187  PyObject *outputs = PyTuple_New(2);
188  PyTuple_SetItem( outputs, 0, (PyObject *)PyAubio_CFvecToArray (self->read_to) );
189  PyTuple_SetItem( outputs, 1, (PyObject *)PyLong_FromLong(read));
190  return outputs;
191}
192
193/* function Py_source_do_multi */
194static PyObject *
195Py_source_do_multi(Py_source * self, PyObject * args)
196{
197
198
199  /* output vectors prototypes */
200  uint_t read;
201
202
203
204
205
206
207  /* creating output mread_to as a new_fvec of length self->hop_size */
208  read = 0;
209
210
211  /* compute _do function */
212  aubio_source_do_multi (self->o, self->mread_to, &read);
213
214  PyObject *outputs = PyTuple_New(2);
215  PyTuple_SetItem( outputs, 0, (PyObject *)PyAubio_CFmatToArray (self->mread_to));
216  PyTuple_SetItem( outputs, 1, (PyObject *)PyLong_FromLong(read));
217  return outputs;
218}
219
220static PyMemberDef Py_source_members[] = {
221  {"uri", T_STRING, offsetof (Py_source, uri), READONLY,
222    "path at which the source was created"},
223  {"samplerate", T_INT, offsetof (Py_source, samplerate), READONLY,
224    "samplerate at which the source is viewed"},
225  {"channels", T_INT, offsetof (Py_source, channels), READONLY,
226    "number of channels found in the source"},
227  {"hop_size", T_INT, offsetof (Py_source, hop_size), READONLY,
228    "number of consecutive frames that will be read at each do or do_multi call"},
229  { NULL } // sentinel
230};
231
232static PyObject *
233Pyaubio_source_get_samplerate (Py_source *self, PyObject *unused)
234{
235  uint_t tmp = aubio_source_get_samplerate (self->o);
236  return (PyObject *)PyLong_FromLong (tmp);
237}
238
239static PyObject *
240Pyaubio_source_get_channels (Py_source *self, PyObject *unused)
241{
242  uint_t tmp = aubio_source_get_channels (self->o);
243  return (PyObject *)PyLong_FromLong (tmp);
244}
245
246static PyObject *
247Pyaubio_source_close (Py_source *self, PyObject *unused)
248{
249  aubio_source_close (self->o);
250  Py_RETURN_NONE;
251}
252
253static PyObject *
254Pyaubio_source_seek (Py_source *self, PyObject *args)
255{
256  uint_t err = 0;
257
258  uint_t position;
259  if (!PyArg_ParseTuple (args, "I", &position)) {
260    return NULL;
261  }
262
263  err = aubio_source_seek(self->o, position);
264  if (err != 0) {
265    PyErr_SetString (PyExc_ValueError,
266        "error when seeking in source");
267    return NULL;
268  }
269  Py_RETURN_NONE;
270}
271
272static PyMethodDef Py_source_methods[] = {
273  {"get_samplerate", (PyCFunction) Pyaubio_source_get_samplerate,
274    METH_NOARGS, Py_source_get_samplerate_doc},
275  {"get_channels", (PyCFunction) Pyaubio_source_get_channels,
276    METH_NOARGS, Py_source_get_channels_doc},
277  {"do", (PyCFunction) Py_source_do,
278    METH_NOARGS, Py_source_do_doc},
279  {"do_multi", (PyCFunction) Py_source_do_multi,
280    METH_NOARGS, Py_source_do_multi_doc},
281  {"close", (PyCFunction) Pyaubio_source_close,
282    METH_NOARGS, Py_source_close_doc},
283  {"seek", (PyCFunction) Pyaubio_source_seek,
284    METH_VARARGS, Py_source_seek_doc},
285  {NULL} /* sentinel */
286};
287
288PyTypeObject Py_sourceType = {
289  PyVarObject_HEAD_INIT (NULL, 0)
290  "aubio.source",
291  sizeof (Py_source),
292  0,
293  (destructor) Py_source_del,
294  0,
295  0,
296  0,
297  0,
298  0,
299  0,
300  0,
301  0,
302  0,
303  (ternaryfunc)Py_source_do,
304  0,
305  0,
306  0,
307  0,
308  Py_TPFLAGS_DEFAULT,
309  Py_source_doc,
310  0,
311  0,
312  0,
313  0,
314  0,
315  0,
316  Py_source_methods,
317  Py_source_members,
318  0,
319  0,
320  0,
321  0,
322  0,
323  0,
324  (initproc) Py_source_init,
325  0,
326  Py_source_new,
327};
Note: See TracBrowser for help on using the repository browser.