Merge pull request #40 from nphilipp/develop--py3k-fixes
[aubio.git] / python / ext / py-source.c
1 #include "aubiowraphell.h"
2
3 typedef 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
15 static 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
49 static char Py_source_get_samplerate_doc[] = ""
50 "x.get_samplerate() -> source samplerate\n"
51 "\n"
52 "Get samplerate of source.";
53
54 static char Py_source_get_channels_doc[] = ""
55 "x.get_channels() -> number of channels\n"
56 "\n"
57 "Get number of channels in source.";
58
59 static char Py_source_do_doc[] = ""
60 "vec, read = x.do() <==> vec, read = x()\n"
61 "\n"
62 "Read monophonic vector from source.";
63
64 static char Py_source_do_multi_doc[] = ""
65 "mat, read = x.do_multi()\n"
66 "\n"
67 "Read polyphonic vector from source.";
68
69 static char Py_source_close_doc[] = ""
70 "x.close()\n"
71 "\n"
72 "Close this source now.";
73
74 static char Py_source_seek_doc[] = ""
75 "x.seek(position)\n"
76 "\n"
77 "Seek to resampled frame position.";
78
79 static PyObject *
80 Py_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
135 static int
136 Py_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
156 static void
157 Py_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   self->ob_type->tp_free((PyObject *) self);
163 }
164
165
166 /* function Py_source_do */
167 static PyObject *
168 Py_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 = PyList_New(0);
188   PyList_Append( outputs, (PyObject *)PyAubio_CFvecToArray (self->read_to));
189   PyList_Append( outputs, (PyObject *)PyInt_FromLong (read));
190   return outputs;
191 }
192
193 /* function Py_source_do_multi */
194 static PyObject *
195 Py_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 = PyList_New(0);
215   PyList_Append( outputs, (PyObject *)PyAubio_CFmatToArray (self->mread_to));
216   PyList_Append( outputs, (PyObject *)PyInt_FromLong (read));
217   return outputs;
218 }
219
220 AUBIO_MEMBERS_START(source)
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 AUBIO_MEMBERS_STOP(source)
230
231
232 static PyObject *
233 Pyaubio_source_get_samplerate (Py_source *self, PyObject *unused)
234 {
235   uint_t tmp = aubio_source_get_samplerate (self->o);
236   return (PyObject *)PyInt_FromLong (tmp);
237 }
238
239 static PyObject *
240 Pyaubio_source_get_channels (Py_source *self, PyObject *unused)
241 {
242   uint_t tmp = aubio_source_get_channels (self->o);
243   return (PyObject *)PyInt_FromLong (tmp);
244 }
245
246 static PyObject *
247 Pyaubio_source_close (Py_source *self, PyObject *unused)
248 {
249   aubio_source_close (self->o);
250   Py_RETURN_NONE;
251 }
252
253 static PyObject *
254 Pyaubio_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
272 static 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
288 AUBIO_TYPEOBJECT(source, "aubio.source")