Merge branch 'feature/cdocstrings' into feature/docstrings
[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 "Open `path` to write a WAV 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   del_aubio_sink(self->o);
154   free(self->mwrite_data.data);
155   if (self->uri) {
156     free(self->uri);
157   }
158   Py_TYPE(self)->tp_free((PyObject *) self);
159 }
160
161 /* function Py_sink_do */
162 static PyObject *
163 Py_sink_do(Py_sink * self, PyObject * args)
164 {
165   /* input vectors python prototypes */
166   PyObject * write_data_obj;
167
168   /* input vectors prototypes */
169   uint_t write;
170
171
172   if (!PyArg_ParseTuple (args, "OI", &write_data_obj, &write)) {
173     return NULL;
174   }
175
176   /* input vectors parsing */
177   if (!PyAubio_ArrayToCFvec(write_data_obj, &(self->write_data))) {
178     return NULL;
179   }
180
181
182   /* compute _do function */
183   aubio_sink_do (self->o, &(self->write_data), write);
184
185   Py_RETURN_NONE;
186 }
187
188 /* function Py_sink_do_multi */
189 static PyObject *
190 Py_sink_do_multi(Py_sink * self, PyObject * args)
191 {
192   /* input vectors python prototypes */
193   PyObject * write_data_obj;
194
195   /* input vectors prototypes */
196   uint_t write;
197
198
199   if (!PyArg_ParseTuple (args, "OI", &write_data_obj, &write)) {
200     return NULL;
201   }
202
203
204   /* input vectors parsing */
205   if (!PyAubio_ArrayToCFmat(write_data_obj, &(self->mwrite_data))) {
206     return NULL;
207   }
208
209   /* compute _do function */
210   aubio_sink_do_multi (self->o, &(self->mwrite_data), write);
211   Py_RETURN_NONE;
212 }
213
214 static PyMemberDef Py_sink_members[] = {
215   {"uri", T_STRING, offsetof (Py_sink, uri), READONLY,
216     "str (read-only): Path at which the sink was created."},
217   {"samplerate", T_INT, offsetof (Py_sink, samplerate), READONLY,
218     "int (read-only): Samplerate at which the sink was created."},
219   {"channels", T_INT, offsetof (Py_sink, channels), READONLY,
220     "int (read-only): Number of channels with which the sink was created."},
221   { NULL } // sentinel
222 };
223
224 static PyObject *
225 Pyaubio_sink_close (Py_sink *self, PyObject *unused)
226 {
227   aubio_sink_close (self->o);
228   Py_RETURN_NONE;
229 }
230
231 static char Pyaubio_sink_enter_doc[] = "";
232 static PyObject* Pyaubio_sink_enter(Py_sink *self, PyObject *unused) {
233   Py_INCREF(self);
234   return (PyObject*)self;
235 }
236
237 static char Pyaubio_sink_exit_doc[] = "";
238 static PyObject* Pyaubio_sink_exit(Py_sink *self, PyObject *unused) {
239   return Pyaubio_sink_close(self, unused);
240 }
241
242 static PyMethodDef Py_sink_methods[] = {
243   {"do", (PyCFunction) Py_sink_do, METH_VARARGS, Py_sink_do_doc},
244   {"do_multi", (PyCFunction) Py_sink_do_multi, METH_VARARGS, Py_sink_do_multi_doc},
245   {"close", (PyCFunction) Pyaubio_sink_close, METH_NOARGS, Py_sink_close_doc},
246   {"__enter__", (PyCFunction)Pyaubio_sink_enter, METH_NOARGS,
247     Pyaubio_sink_enter_doc},
248   {"__exit__",  (PyCFunction)Pyaubio_sink_exit, METH_VARARGS,
249     Pyaubio_sink_exit_doc},
250   {NULL} /* sentinel */
251 };
252
253 PyTypeObject Py_sinkType = {
254   PyVarObject_HEAD_INIT (NULL, 0)
255   "aubio.sink",
256   sizeof (Py_sink),
257   0,
258   (destructor) Py_sink_del,
259   0,
260   0,
261   0,
262   0,
263   0,
264   0,
265   0,
266   0,
267   0,
268   (ternaryfunc)Py_sink_do,
269   0,
270   0,
271   0,
272   0,
273   Py_TPFLAGS_DEFAULT,
274   Py_sink_doc,
275   0,
276   0,
277   0,
278   0,
279   0,
280   0,
281   Py_sink_methods,
282   Py_sink_members,
283   0,
284   0,
285   0,
286   0,
287   0,
288   0,
289   (initproc) Py_sink_init,
290   0,
291   Py_sink_new,
292   0,
293   0,
294   0,
295   0,
296   0,
297   0,
298   0,
299   0,
300   0,
301 };