4fc514f26a2207fdec0b404f077b61eafd544441
[aubio.git] / python / ext / py-sink.c
1 #include "aubio-types.h"
2
3 typedef struct
4 {
5   PyObject_HEAD
6   aubio_sink_t * o;
7   char_t* uri;
8   uint_t samplerate;
9   uint_t channels;
10   fvec_t write_data;
11   fmat_t mwrite_data;
12 } Py_sink;
13
14 static char Py_sink_doc[] = ""
15 "sink(path, samplerate=44100, channels=1)\n"
16 "\n"
17 "Write audio samples to file.\n"
18 "\n"
19 "Parameters\n"
20 "----------\n"
21 "path : str\n"
22 "   Pathname of the file to be opened for writing.\n"
23 "samplerate : int\n"
24 "   Sampling rate of the file, in Hz.\n"
25 "channels : int\n"
26 "   Number of channels to create the file with.\n"
27 "\n"
28 "Examples\n"
29 "--------\n"
30 "\n"
31 "Create a new sink at 44100Hz, mono:\n"
32 "\n"
33 ">>> snk = aubio.sink('out.wav')\n"
34 "\n"
35 "Create a new sink at 32000Hz, stereo, write 100 samples into it:\n"
36 "\n"
37 ">>> snk = aubio.sink('out.wav', samplerate=16000, channels=3)\n"
38 ">>> snk(aubio.fvec(100), 100)\n"
39 "\n"
40 "Open a new sink at 48000Hz, stereo, write `1234` samples into it:\n"
41 "\n"
42 ">>> with aubio.sink('out.wav', samplerate=48000, channels=2) as src:\n"
43 "...     snk(aubio.fvec(1024), 1024)\n"
44 "...     snk(aubio.fvec(210), 210)\n"
45 "...\n"
46 "\n"
47 "See also\n"
48 "--------\n"
49 "source: read audio samples from a file.\n"
50 "\n";
51
52 static char Py_sink_do_doc[] = ""
53 "do(vec, write)\n"
54 "\n"
55 "Write a single channel vector to sink.\n"
56 "\n"
57 "Parameters\n"
58 "----------\n"
59 "vec : fvec\n"
60 "   input vector `(n,)` where `n >= 0`.\n"
61 "write : int\n"
62 "   Number of samples to write.\n"
63 "";
64
65 static char Py_sink_do_multi_doc[] = ""
66 "do_multi(mat, write)\n"
67 "\n"
68 "Write a matrix containing vectors from multiple channels to sink.\n"
69 "\n"
70 "Parameters\n"
71 "----------\n"
72 "mat : numpy.ndarray\n"
73 "   input matrix of shape `(channels, n)`, where `n >= 0`.\n"
74 "write : int\n"
75 "   Number of frames to write.\n"
76 "";
77
78 static char Py_sink_close_doc[] = ""
79 "close()\n"
80 "\n"
81 "Close this sink now.\n"
82 "\n"
83 "By default, the sink will be closed before being deleted.\n"
84 "Explicitely closing a sink can be useful to control the number\n"
85 "of files simultaneously opened.\n"
86 "";
87
88 static PyObject *
89 Py_sink_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
90 {
91   Py_sink *self;
92   char_t* uri = NULL;
93   uint_t samplerate = 0;
94   uint_t channels = 0;
95   static char *kwlist[] = { "uri", "samplerate", "channels", NULL };
96
97   if (!PyArg_ParseTupleAndKeywords (args, kwds, "|sII", kwlist,
98           &uri, &samplerate, &channels)) {
99     return NULL;
100   }
101
102   self = (Py_sink *) pytype->tp_alloc (pytype, 0);
103
104   if (self == NULL) {
105     return NULL;
106   }
107
108   self->uri = NULL;
109   if (uri != NULL) {
110     self->uri = (char_t *)malloc(sizeof(char_t) * (strnlen(uri, PATH_MAX) + 1));
111     strncpy(self->uri, uri, strnlen(uri, PATH_MAX) + 1);
112   }
113
114   self->samplerate = Py_aubio_default_samplerate;
115   if (samplerate != 0) {
116     self->samplerate = samplerate;
117   }
118
119   self->channels = 1;
120   if (channels != 0) {
121     self->channels = channels;
122   }
123
124   return (PyObject *) self;
125 }
126
127 static int
128 Py_sink_init (Py_sink * self, PyObject * args, PyObject * kwds)
129 {
130   self->o = new_aubio_sink ( self->uri, 0 );
131   if (self->o == NULL) {
132     // error string was set in new_aubio_sink
133     return -1;
134   }
135   if (aubio_sink_preset_channels(self->o, self->channels) != 0) {
136     // error string was set in aubio_sink_preset_channels
137     return -1;
138   }
139   if (aubio_sink_preset_samplerate(self->o, self->samplerate) != 0) {
140     // error string was set in aubio_sink_preset_samplerate
141     return -1;
142   }
143
144   self->samplerate = aubio_sink_get_samplerate ( self->o );
145   self->channels = aubio_sink_get_channels ( self->o );
146
147   return 0;
148 }
149
150 static void
151 Py_sink_del (Py_sink *self, PyObject *unused)
152 {
153   if (self->o) {
154     del_aubio_sink(self->o);
155     free(self->mwrite_data.data);
156   }
157   if (self->uri) {
158     free(self->uri);
159   }
160   Py_TYPE(self)->tp_free((PyObject *) self);
161 }
162
163 /* function Py_sink_do */
164 static PyObject *
165 Py_sink_do(Py_sink * self, PyObject * args)
166 {
167   /* input vectors python prototypes */
168   PyObject * write_data_obj;
169
170   /* input vectors prototypes */
171   uint_t write;
172
173
174   if (!PyArg_ParseTuple (args, "OI", &write_data_obj, &write)) {
175     return NULL;
176   }
177
178   /* input vectors parsing */
179   if (!PyAubio_ArrayToCFvec(write_data_obj, &(self->write_data))) {
180     return NULL;
181   }
182
183
184   /* compute _do function */
185   aubio_sink_do (self->o, &(self->write_data), write);
186
187   Py_RETURN_NONE;
188 }
189
190 /* function Py_sink_do_multi */
191 static PyObject *
192 Py_sink_do_multi(Py_sink * self, PyObject * args)
193 {
194   /* input vectors python prototypes */
195   PyObject * write_data_obj;
196
197   /* input vectors prototypes */
198   uint_t write;
199
200
201   if (!PyArg_ParseTuple (args, "OI", &write_data_obj, &write)) {
202     return NULL;
203   }
204
205
206   /* input vectors parsing */
207   if (!PyAubio_ArrayToCFmat(write_data_obj, &(self->mwrite_data))) {
208     return NULL;
209   }
210
211   /* compute _do function */
212   aubio_sink_do_multi (self->o, &(self->mwrite_data), write);
213   Py_RETURN_NONE;
214 }
215
216 static PyMemberDef Py_sink_members[] = {
217   {"uri", T_STRING, offsetof (Py_sink, uri), READONLY,
218     "str (read-only): Path at which the sink was created."},
219   {"samplerate", T_INT, offsetof (Py_sink, samplerate), READONLY,
220     "int (read-only): Samplerate at which the sink was created."},
221   {"channels", T_INT, offsetof (Py_sink, channels), READONLY,
222     "int (read-only): Number of channels with which the sink was created."},
223   { NULL } // sentinel
224 };
225
226 static PyObject *
227 Pyaubio_sink_close (Py_sink *self, PyObject *unused)
228 {
229   aubio_sink_close (self->o);
230   Py_RETURN_NONE;
231 }
232
233 static char Pyaubio_sink_enter_doc[] = "";
234 static PyObject* Pyaubio_sink_enter(Py_sink *self, PyObject *unused) {
235   Py_INCREF(self);
236   return (PyObject*)self;
237 }
238
239 static char Pyaubio_sink_exit_doc[] = "";
240 static PyObject* Pyaubio_sink_exit(Py_sink *self, PyObject *unused) {
241   return Pyaubio_sink_close(self, unused);
242 }
243
244 static PyMethodDef Py_sink_methods[] = {
245   {"do", (PyCFunction) Py_sink_do, METH_VARARGS, Py_sink_do_doc},
246   {"do_multi", (PyCFunction) Py_sink_do_multi, METH_VARARGS, Py_sink_do_multi_doc},
247   {"close", (PyCFunction) Pyaubio_sink_close, METH_NOARGS, Py_sink_close_doc},
248   {"__enter__", (PyCFunction)Pyaubio_sink_enter, METH_NOARGS,
249     Pyaubio_sink_enter_doc},
250   {"__exit__",  (PyCFunction)Pyaubio_sink_exit, METH_VARARGS,
251     Pyaubio_sink_exit_doc},
252   {NULL} /* sentinel */
253 };
254
255 PyTypeObject Py_sinkType = {
256   PyVarObject_HEAD_INIT (NULL, 0)
257   "aubio.sink",
258   sizeof (Py_sink),
259   0,
260   (destructor) Py_sink_del,
261   0,
262   0,
263   0,
264   0,
265   0,
266   0,
267   0,
268   0,
269   0,
270   (ternaryfunc)Py_sink_do,
271   0,
272   0,
273   0,
274   0,
275   Py_TPFLAGS_DEFAULT,
276   Py_sink_doc,
277   0,
278   0,
279   0,
280   0,
281   0,
282   0,
283   Py_sink_methods,
284   Py_sink_members,
285   0,
286   0,
287   0,
288   0,
289   0,
290   0,
291   (initproc) Py_sink_init,
292   0,
293   Py_sink_new,
294   0,
295   0,
296   0,
297   0,
298   0,
299   0,
300   0,
301   0,
302   0,
303 };