python/ext/py-source.c: __exit__ to close once
[aubio.git] / python / ext / aubiomodule.c
1 #define PY_AUBIO_MODULE_MAIN
2 #include "aubio-types.h"
3 #include "py-musicutils.h"
4
5 // this dummy macro is used to convince windows that a string passed as -D flag
6 // is just that, a string, and not a double.
7 #define REDEFINESTRING(x) #x
8 #define DEFINEDSTRING(x) REDEFINESTRING(x)
9
10 static char aubio_module_doc[] = "Python module for the aubio library";
11
12 static char Py_alpha_norm_doc[] = ""
13 "alpha_norm(fvec, integer) -> float\n"
14 "\n"
15 "Compute alpha normalisation factor on vector, given alpha\n"
16 "\n"
17 "Example\n"
18 "-------\n"
19 "\n"
20 ">>> b = alpha_norm(a, 9)";
21
22 static char Py_bintomidi_doc[] = ""
23 "bintomidi(float, samplerate = integer, fftsize = integer) -> float\n"
24 "\n"
25 "Convert bin (float) to midi (float), given the sampling rate and the FFT size\n"
26 "\n"
27 "Example\n"
28 "-------\n"
29 "\n"
30 ">>> midi = bintomidi(float, samplerate = 44100, fftsize = 1024)";
31
32 static char Py_miditobin_doc[] = ""
33 "miditobin(float, samplerate = integer, fftsize = integer) -> float\n"
34 "\n"
35 "Convert midi (float) to bin (float), given the sampling rate and the FFT size\n"
36 "\n"
37 "Example\n"
38 "-------\n"
39 "\n"
40 ">>> bin = miditobin(midi, samplerate = 44100, fftsize = 1024)";
41
42 static char Py_bintofreq_doc[] = ""
43 "bintofreq(float, samplerate = integer, fftsize = integer) -> float\n"
44 "\n"
45 "Convert bin number (float) in frequency (Hz), given the sampling rate and the FFT size\n"
46 "\n"
47 "Example\n"
48 "-------\n"
49 "\n"
50 ">>> freq = bintofreq(bin, samplerate = 44100, fftsize = 1024)";
51
52 static char Py_freqtobin_doc[] = ""
53 "freqtobin(float, samplerate = integer, fftsize = integer) -> float\n"
54 "\n"
55 "Convert frequency (Hz) in bin number (float), given the sampling rate and the FFT size\n"
56 "\n"
57 "Example\n"
58 "-------\n"
59 "\n"
60 ">>> bin = freqtobin(freq, samplerate = 44100, fftsize = 1024)";
61
62 static char Py_zero_crossing_rate_doc[] = ""
63 "zero_crossing_rate(fvec) -> float\n"
64 "\n"
65 "Compute Zero crossing rate of a vector\n"
66 "\n"
67 "Example\n"
68 "-------\n"
69 "\n"
70 ">>> z = zero_crossing_rate(a)";
71
72 static char Py_min_removal_doc[] = ""
73 "min_removal(fvec) -> float\n"
74 "\n"
75 "Remove the minimum value of a vector, in-place modification\n"
76 "\n"
77 "Example\n"
78 "-------\n"
79 "\n"
80 ">>> min_removal(a)";
81
82 extern void add_ufuncs ( PyObject *m );
83 extern int generated_types_ready(void);
84
85 static PyObject *
86 Py_alpha_norm (PyObject * self, PyObject * args)
87 {
88   PyObject *input;
89   fvec_t vec;
90   smpl_t alpha;
91   PyObject *result;
92
93   if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR ":alpha_norm", &input, &alpha)) {
94     return NULL;
95   }
96
97   if (input == NULL) {
98     return NULL;
99   }
100
101   if (!PyAubio_ArrayToCFvec(input, &vec)) {
102     return NULL;
103   }
104
105   // compute the function
106   result = Py_BuildValue (AUBIO_NPY_SMPL_CHR, fvec_alpha_norm (&vec, alpha));
107   if (result == NULL) {
108     return NULL;
109   }
110
111   return result;
112 }
113
114 static PyObject *
115 Py_bintomidi (PyObject * self, PyObject * args)
116 {
117   smpl_t input, samplerate, fftsize;
118   smpl_t output;
119
120   if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) {
121     return NULL;
122   }
123
124   output = aubio_bintomidi (input, samplerate, fftsize);
125
126   return (PyObject *)PyFloat_FromDouble (output);
127 }
128
129 static PyObject *
130 Py_miditobin (PyObject * self, PyObject * args)
131 {
132   smpl_t input, samplerate, fftsize;
133   smpl_t output;
134
135   if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) {
136     return NULL;
137   }
138
139   output = aubio_miditobin (input, samplerate, fftsize);
140
141   return (PyObject *)PyFloat_FromDouble (output);
142 }
143
144 static PyObject *
145 Py_bintofreq (PyObject * self, PyObject * args)
146 {
147   smpl_t input, samplerate, fftsize;
148   smpl_t output;
149
150   if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) {
151     return NULL;
152   }
153
154   output = aubio_bintofreq (input, samplerate, fftsize);
155
156   return (PyObject *)PyFloat_FromDouble (output);
157 }
158
159 static PyObject *
160 Py_freqtobin (PyObject * self, PyObject * args)
161 {
162   smpl_t input, samplerate, fftsize;
163   smpl_t output;
164
165   if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) {
166     return NULL;
167   }
168
169   output = aubio_freqtobin (input, samplerate, fftsize);
170
171   return (PyObject *)PyFloat_FromDouble (output);
172 }
173
174 static PyObject *
175 Py_zero_crossing_rate (PyObject * self, PyObject * args)
176 {
177   PyObject *input;
178   fvec_t vec;
179   PyObject *result;
180
181   if (!PyArg_ParseTuple (args, "O:zero_crossing_rate", &input)) {
182     return NULL;
183   }
184
185   if (input == NULL) {
186     return NULL;
187   }
188
189   if (!PyAubio_ArrayToCFvec(input, &vec)) {
190     return NULL;
191   }
192
193   // compute the function
194   result = Py_BuildValue (AUBIO_NPY_SMPL_CHR, aubio_zero_crossing_rate (&vec));
195   if (result == NULL) {
196     return NULL;
197   }
198
199   return result;
200 }
201
202 static PyObject *
203 Py_min_removal(PyObject * self, PyObject * args)
204 {
205   PyObject *input;
206   fvec_t vec;
207
208   if (!PyArg_ParseTuple (args, "O:min_removal", &input)) {
209     return NULL;
210   }
211
212   if (input == NULL) {
213     return NULL;
214   }
215
216   if (!PyAubio_ArrayToCFvec(input, &vec)) {
217     return NULL;
218   }
219
220   // compute the function
221   fvec_min_removal (&vec);
222
223   // since this function does not return, we could return None
224   //Py_RETURN_NONE;
225   // however it is convenient to return the modified vector
226   return (PyObject *) PyAubio_CFvecToArray(&vec);
227   // or even without converting it back to an array
228   //Py_INCREF(vec);
229   //return (PyObject *)vec;
230 }
231
232 static PyMethodDef aubio_methods[] = {
233   {"bintomidi", Py_bintomidi, METH_VARARGS, Py_bintomidi_doc},
234   {"miditobin", Py_miditobin, METH_VARARGS, Py_miditobin_doc},
235   {"bintofreq", Py_bintofreq, METH_VARARGS, Py_bintofreq_doc},
236   {"freqtobin", Py_freqtobin, METH_VARARGS, Py_freqtobin_doc},
237   {"alpha_norm", Py_alpha_norm, METH_VARARGS, Py_alpha_norm_doc},
238   {"zero_crossing_rate", Py_zero_crossing_rate, METH_VARARGS, Py_zero_crossing_rate_doc},
239   {"min_removal", Py_min_removal, METH_VARARGS, Py_min_removal_doc},
240   {"level_lin", Py_aubio_level_lin, METH_VARARGS, Py_aubio_level_lin_doc},
241   {"db_spl", Py_aubio_db_spl, METH_VARARGS, Py_aubio_db_spl_doc},
242   {"silence_detection", Py_aubio_silence_detection, METH_VARARGS, Py_aubio_silence_detection_doc},
243   {"level_detection", Py_aubio_level_detection, METH_VARARGS, Py_aubio_level_detection_doc},
244   {"window", Py_aubio_window, METH_VARARGS, Py_aubio_window_doc},
245   {NULL, NULL, 0, NULL} /* Sentinel */
246 };
247
248 #if PY_MAJOR_VERSION >= 3
249 // Python3 module definition
250 static struct PyModuleDef moduledef = {
251    PyModuleDef_HEAD_INIT,
252    "_aubio",          /* m_name */
253    aubio_module_doc,  /* m_doc */
254    -1,                /* m_size */
255    aubio_methods,     /* m_methods */
256    NULL,              /* m_reload */
257    NULL,              /* m_traverse */
258    NULL,              /* m_clear */
259    NULL,              /* m_free */
260 };
261 #endif
262
263 void
264 aubio_log_function(int level, const char *message, void *data)
265 {
266   // remove trailing \n
267   char *pos;
268   if ((pos=strchr(message, '\n')) != NULL) {
269         *pos = '\0';
270   }
271   // warning or error
272   if (level == AUBIO_LOG_ERR) {
273     PyErr_Format(PyExc_RuntimeError, "%s", message);
274   } else {
275     PyErr_WarnEx(PyExc_UserWarning, message, 1);
276   }
277 }
278
279 static PyObject *
280 initaubio (void)
281 {
282   PyObject *m = NULL;
283   int err;
284
285   // fvec is defined in __init__.py
286   if (   (PyType_Ready (&Py_cvecType) < 0)
287       || (PyType_Ready (&Py_filterType) < 0)
288       || (PyType_Ready (&Py_filterbankType) < 0)
289       || (PyType_Ready (&Py_fftType) < 0)
290       || (PyType_Ready (&Py_pvocType) < 0)
291       || (PyType_Ready (&Py_sourceType) < 0)
292       || (PyType_Ready (&Py_sinkType) < 0)
293       // generated objects
294       || (generated_types_ready() < 0 )
295   ) {
296     return m;
297   }
298
299 #if PY_MAJOR_VERSION >= 3
300   m = PyModule_Create(&moduledef);
301 #else
302   m = Py_InitModule3 ("_aubio", aubio_methods, aubio_module_doc);
303 #endif
304
305   if (m == NULL) {
306     return m;
307   }
308
309   err = _import_array ();
310   if (err != 0) {
311     fprintf (stderr,
312         "Unable to import Numpy array from aubio module (error %d)\n", err);
313   }
314
315   Py_INCREF (&Py_cvecType);
316   PyModule_AddObject (m, "cvec", (PyObject *) & Py_cvecType);
317   Py_INCREF (&Py_filterType);
318   PyModule_AddObject (m, "digital_filter", (PyObject *) & Py_filterType);
319   Py_INCREF (&Py_filterbankType);
320   PyModule_AddObject (m, "filterbank", (PyObject *) & Py_filterbankType);
321   Py_INCREF (&Py_fftType);
322   PyModule_AddObject (m, "fft", (PyObject *) & Py_fftType);
323   Py_INCREF (&Py_pvocType);
324   PyModule_AddObject (m, "pvoc", (PyObject *) & Py_pvocType);
325   Py_INCREF (&Py_sourceType);
326   PyModule_AddObject (m, "source", (PyObject *) & Py_sourceType);
327   Py_INCREF (&Py_sinkType);
328   PyModule_AddObject (m, "sink", (PyObject *) & Py_sinkType);
329
330   PyModule_AddStringConstant(m, "float_type", AUBIO_NPY_SMPL_STR);
331   PyModule_AddStringConstant(m, "__version__", DEFINEDSTRING(AUBIO_VERSION));
332
333   // add generated objects
334   add_generated_objects(m);
335
336   // add ufunc
337   add_ufuncs(m);
338
339   aubio_log_set_level_function(AUBIO_LOG_ERR, aubio_log_function, NULL);
340   aubio_log_set_level_function(AUBIO_LOG_WRN, aubio_log_function, NULL);
341   return m;
342 }
343
344 #if PY_MAJOR_VERSION >= 3
345     // Python3 init
346     PyMODINIT_FUNC PyInit__aubio(void)
347     {
348         return initaubio();
349     }
350 #else
351     // Python 2 init
352     PyMODINIT_FUNC init_aubio(void)
353     {
354         initaubio();
355     }
356 #endif