python/ext/py-source.c: add seek, thanks @davebrent for the heads up
[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 } Py_source;
12
13 static char Py_source_doc[] = ""
14 "   __new__(path, samplerate = 0, hop_size = 512, channels = 1)\n"
15 "\n"
16 "       Create a new source, opening the given path for reading.\n"
17 "\n"
18 "       Examples\n"
19 "       --------\n"
20 "\n"
21 "       Create a new source, using the original samplerate, with hop_size = 512:\n"
22 "\n"
23 "       >>> source('/tmp/t.wav')\n"
24 "\n"
25 "       Create a new source, resampling the original to 8000Hz:\n"
26 "\n"
27 "       >>> source('/tmp/t.wav', samplerate = 8000)\n"
28 "\n"
29 "       Create a new source, resampling it at 32000Hz, hop_size = 32:\n"
30 "\n"
31 "       >>> source('/tmp/t.wav', samplerate = 32000, hop_size = 32)\n"
32 "\n"
33 "       Create a new source, using its original samplerate:\n"
34 "\n"
35 "       >>> source('/tmp/t.wav', samplerate = 0)\n"
36 "\n"
37 "   __call__()\n"
38 "       vec, read = x() <==> vec, read = x.do()\n"
39 "\n"
40 "       Read vector from source.\n"
41 "\n"
42 "       See also\n"
43 "       --------\n"
44 "       aubio.source.do\n"
45 "\n";
46
47 static char Py_source_get_samplerate_doc[] = ""
48 "x.get_samplerate() -> source samplerate\n"
49 "\n"
50 "Get samplerate of source.";
51
52 static char Py_source_get_channels_doc[] = ""
53 "x.get_channels() -> number of channels\n"
54 "\n"
55 "Get number of channels in source.";
56
57 static char Py_source_do_doc[] = ""
58 "vec, read = x.do() <==> vec, read = x()\n"
59 "\n"
60 "Read monophonic vector from source.";
61
62 static char Py_source_do_multi_doc[] = ""
63 "mat, read = x.do_multi()\n"
64 "\n"
65 "Read polyphonic vector from source.";
66
67 static char Py_source_close_doc[] = ""
68 "x.close()\n"
69 "\n"
70 "Close this source now.";
71
72 static char Py_source_seek_doc[] = ""
73 "x.seek(position)\n"
74 "\n"
75 "Seek to resampled frame position.";
76
77 static PyObject *
78 Py_source_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
79 {
80   Py_source *self;
81   char_t* uri = NULL;
82   uint_t samplerate = 0;
83   uint_t hop_size = 0;
84   uint_t channels = 0;
85   static char *kwlist[] = { "uri", "samplerate", "hop_size", "channels", NULL };
86
87   if (!PyArg_ParseTupleAndKeywords (args, kwds, "|sIII", kwlist,
88           &uri, &samplerate, &hop_size, &channels)) {
89     return NULL;
90   }
91
92   self = (Py_source *) pytype->tp_alloc (pytype, 0);
93
94   if (self == NULL) {
95     return NULL;
96   }
97
98   self->uri = "none";
99   if (uri != NULL) {
100     self->uri = uri;
101   }
102
103   self->samplerate = 0;
104   if ((sint_t)samplerate > 0) {
105     self->samplerate = samplerate;
106   } else if ((sint_t)samplerate < 0) {
107     PyErr_SetString (PyExc_ValueError,
108         "can not use negative value for samplerate");
109     return NULL;
110   }
111
112   self->hop_size = Py_default_vector_length / 2;
113   if ((sint_t)hop_size > 0) {
114     self->hop_size = hop_size;
115   } else if ((sint_t)hop_size < 0) {
116     PyErr_SetString (PyExc_ValueError,
117         "can not use negative value for hop_size");
118     return NULL;
119   }
120
121   self->channels = 1;
122   if ((sint_t)channels >= 0) {
123     self->channels = channels;
124   } else if ((sint_t)channels < 0) {
125     PyErr_SetString (PyExc_ValueError,
126         "can not use negative value for channels");
127     return NULL;
128   }
129
130   return (PyObject *) self;
131 }
132
133 static int
134 Py_source_init (Py_source * self, PyObject * args, PyObject * kwds)
135 {
136   self->o = new_aubio_source ( self->uri, self->samplerate, self->hop_size );
137   if (self->o == NULL) {
138     char_t errstr[30 + strlen(self->uri)];
139     sprintf(errstr, "error creating source with %s", self->uri);
140     PyErr_SetString (PyExc_StandardError, errstr);
141     return -1;
142   }
143   self->samplerate = aubio_source_get_samplerate ( self->o );
144   if (self->channels == 0) {
145     self->channels = aubio_source_get_channels ( self->o );
146   }
147
148   return 0;
149 }
150
151 AUBIO_DEL(source)
152
153 /* function Py_source_do */
154 static PyObject *
155 Py_source_do(Py_source * self, PyObject * args)
156 {
157
158
159   /* output vectors prototypes */
160   fvec_t* read_to;
161   uint_t read;
162
163
164
165
166
167
168   /* creating output read_to as a new_fvec of length self->hop_size */
169   read_to = new_fvec (self->hop_size);
170   read = 0;
171
172
173   /* compute _do function */
174   aubio_source_do (self->o, read_to, &read);
175
176   PyObject *outputs = PyList_New(0);
177   PyList_Append( outputs, (PyObject *)PyAubio_CFvecToArray (read_to));
178   //del_fvec (read_to);
179   PyList_Append( outputs, (PyObject *)PyInt_FromLong (read));
180   return outputs;
181 }
182
183 /* function Py_source_do_multi */
184 static PyObject *
185 Py_source_do_multi(Py_source * self, PyObject * args)
186 {
187
188
189   /* output vectors prototypes */
190   fmat_t* read_to;
191   uint_t read;
192
193
194
195
196
197
198   /* creating output read_to as a new_fvec of length self->hop_size */
199   read_to = new_fmat (self->channels, self->hop_size);
200   read = 0;
201
202
203   /* compute _do function */
204   aubio_source_do_multi (self->o, read_to, &read);
205
206   PyObject *outputs = PyList_New(0);
207   PyList_Append( outputs, (PyObject *)PyAubio_CFmatToArray (read_to));
208   //del_fvec (read_to);
209   PyList_Append( outputs, (PyObject *)PyInt_FromLong (read));
210   return outputs;
211 }
212
213 AUBIO_MEMBERS_START(source)
214   {"uri", T_STRING, offsetof (Py_source, uri), READONLY,
215     "path at which the source was created"},
216   {"samplerate", T_INT, offsetof (Py_source, samplerate), READONLY,
217     "samplerate at which the source is viewed"},
218   {"channels", T_INT, offsetof (Py_source, channels), READONLY,
219     "number of channels found in the source"},
220   {"hop_size", T_INT, offsetof (Py_source, hop_size), READONLY,
221     "number of consecutive frames that will be read at each do or do_multi call"},
222 AUBIO_MEMBERS_STOP(source)
223
224
225 static PyObject *
226 Pyaubio_source_get_samplerate (Py_source *self, PyObject *unused)
227 {
228   uint_t tmp = aubio_source_get_samplerate (self->o);
229   return (PyObject *)PyInt_FromLong (tmp);
230 }
231
232 static PyObject *
233 Pyaubio_source_get_channels (Py_source *self, PyObject *unused)
234 {
235   uint_t tmp = aubio_source_get_channels (self->o);
236   return (PyObject *)PyInt_FromLong (tmp);
237 }
238
239 static PyObject *
240 Pyaubio_source_close (Py_source *self, PyObject *unused)
241 {
242   aubio_source_close (self->o);
243   Py_RETURN_NONE;
244 }
245
246 static PyObject *
247 Pyaubio_source_seek (Py_source *self, PyObject *args)
248 {
249   uint_t err = 0;
250
251   uint_t position;
252   if (!PyArg_ParseTuple (args, "I", &position)) {
253     return NULL;
254   }
255
256   err = aubio_source_seek(self->o, position);
257   if (err != 0) {
258     PyErr_SetString (PyExc_ValueError,
259         "error when seeking in source");
260     return NULL;
261   }
262   Py_RETURN_NONE;
263 }
264
265 static PyMethodDef Py_source_methods[] = {
266   {"get_samplerate", (PyCFunction) Pyaubio_source_get_samplerate,
267     METH_NOARGS, Py_source_get_samplerate_doc},
268   {"get_channels", (PyCFunction) Pyaubio_source_get_channels,
269     METH_NOARGS, Py_source_get_channels_doc},
270   {"do", (PyCFunction) Py_source_do,
271     METH_NOARGS, Py_source_do_doc},
272   {"do_multi", (PyCFunction) Py_source_do_multi,
273     METH_NOARGS, Py_source_do_multi_doc},
274   {"close", (PyCFunction) Pyaubio_source_close,
275     METH_NOARGS, Py_source_close_doc},
276   {"seek", (PyCFunction) Pyaubio_source_seek,
277     METH_VARARGS, Py_source_seek_doc},
278   {NULL} /* sentinel */
279 };
280
281 AUBIO_TYPEOBJECT(source, "aubio.source")