[py] incref exception type before restoring it
[aubio.git] / python / ext / py-filterbank.c
1 #include "aubio-types.h"
2
3 static char Py_filterbank_doc[] = ""
4 "filterbank(n_filters=40, win_s=1024)\n"
5 "\n"
6 "Create a bank of spectral filters. Each instance is a callable\n"
7 "that holds a matrix of coefficients.\n"
8 "\n"
9 "See also :meth:`set_mel_coeffs`, :meth:`set_mel_coeffs_htk`,\n"
10 ":meth:`set_mel_coeffs_slaney`, :meth:`set_triangle_bands`, and\n"
11 ":meth:`set_coeffs`.\n"
12 "\n"
13 "Parameters\n"
14 "----------\n"
15 "n_filters : int\n"
16 "    Number of filters to create.\n"
17 "win_s : int\n"
18 "    Size of the input spectrum to process.\n"
19 "\n"
20 "Examples\n"
21 "--------\n"
22 ">>> f = aubio.filterbank(128, 1024)\n"
23 ">>> f.set_mel_coeffs(44100, 0, 10000)\n"
24 ">>> c = aubio.cvec(1024)\n"
25 ">>> f(c).shape\n"
26 "(128, )\n"
27 "";
28
29 static char Py_filterbank_set_triangle_bands_doc[] =""
30 "set_triangle_bands(freqs, samplerate)\n"
31 "\n"
32 "Set triangular bands. The coefficients will be set to triangular\n"
33 "overlapping windows using the boundaries specified by `freqs`.\n"
34 "\n"
35 "`freqs` should contain `n_filters + 2` frequencies in Hz, ordered\n"
36 "by value, from smallest to largest. The first element should be greater\n"
37 "or equal to zero; the last element should be smaller or equal to\n"
38 "`samplerate / 2`.\n"
39 "\n"
40 "Parameters\n"
41 "----------\n"
42 "freqs: fvec\n"
43 "    List of frequencies, in Hz.\n"
44 "samplerate : float\n"
45 "    Sampling-rate of the expected input.\n"
46 "\n"
47 "Example\n"
48 "-------\n"
49 ">>> fb = aubio.filterbank(n_filters=100, win_s=2048)\n"
50 ">>> samplerate = 44100; freqs = np.linspace(0, 20200, 102)\n"
51 ">>> fb.set_triangle_bands(aubio.fvec(freqs), samplerate)\n"
52 "";
53
54 static char Py_filterbank_set_mel_coeffs_slaney_doc[] = ""
55 "set_mel_coeffs_slaney(samplerate)\n"
56 "\n"
57 "Set coefficients of filterbank to match Slaney's Auditory Toolbox.\n"
58 "\n"
59 "The filter coefficients will be set as in Malcolm Slaney's\n"
60 "implementation. The filterbank should have been created with\n"
61 "`n_filters = 40`.\n"
62 "\n"
63 "This is approximately equivalent to using :meth:`set_mel_coeffs` with\n"
64 "`fmin = 400./3., fmax = 6853.84`.\n"
65 "\n"
66 "Parameters\n"
67 "----------\n"
68 "samplerate : float\n"
69 "    Sampling-rate of the expected input.\n"
70 "\n"
71 "References\n"
72 "----------\n"
73 "\n"
74 "Malcolm Slaney, `Auditory Toolbox Version 2, Technical Report #1998-010\n"
75 "<https://engineering.purdue.edu/~malcolm/interval/1998-010/>`_\n"
76 "";
77
78 static char Py_filterbank_set_mel_coeffs_doc[] = ""
79 "set_mel_coeffs(samplerate, fmin, fmax)\n"
80 "\n"
81 "Set coefficients of filterbank to linearly spaced mel scale.\n"
82 "\n"
83 "Parameters\n"
84 "----------\n"
85 "samplerate : float\n"
86 "    Sampling-rate of the expected input.\n"
87 "fmin : float\n"
88 "    Lower frequency boundary of the first filter.\n"
89 "fmax : float\n"
90 "    Upper frequency boundary of the last filter.\n"
91 "\n"
92 "See also\n"
93 "--------\n"
94 "hztomel\n"
95 "";
96
97 static char Py_filterbank_set_mel_coeffs_htk_doc[] = ""
98 "set_mel_coeffs_htk(samplerate, fmin, fmax)\n"
99 "\n"
100 "Set coefficients of the filters to be linearly spaced in the HTK mel scale.\n"
101 "\n"
102 "Parameters\n"
103 "----------\n"
104 "samplerate : float\n"
105 "    Sampling-rate of the expected input.\n"
106 "fmin : float\n"
107 "    Lower frequency boundary of the first filter.\n"
108 "fmax : float\n"
109 "    Upper frequency boundary of the last filter.\n"
110 "\n"
111 "See also\n"
112 "--------\n"
113 "hztomel with `htk=True`\n"
114 "";
115
116 static char Py_filterbank_get_coeffs_doc[] = ""
117 "get_coeffs()\n"
118 "\n"
119 "Get coefficients matrix of filterbank.\n"
120 "\n"
121 "Returns\n"
122 "-------\n"
123 "array_like\n"
124 "    Array of shape (n_filters, win_s/2+1) containing the coefficients.\n"
125 "";
126
127 static char Py_filterbank_set_coeffs_doc[] = ""
128 "set_coeffs(coeffs)\n"
129 "\n"
130 "Set coefficients of filterbank.\n"
131 "\n"
132 "Parameters\n"
133 "----------\n"
134 "coeffs : fmat\n"
135 "    Array of shape (n_filters, win_s/2+1) containing the coefficients.\n"
136 "";
137
138 static char Py_filterbank_set_power_doc[] = ""
139 "set_power(power)\n"
140 "\n"
141 "Set power applied to input spectrum of filterbank.\n"
142 "\n"
143 "Parameters\n"
144 "----------\n"
145 "power : float\n"
146 "    Power to raise input spectrum to before computing the filters.\n"
147 "";
148
149 static char Py_filterbank_get_power_doc[] = ""
150 "get_power()\n"
151 "\n"
152 "Get power applied to filterbank.\n"
153 "\n"
154 "Returns\n"
155 "-------\n"
156 "float\n"
157 "    Power parameter.\n"
158 "";
159
160 static char Py_filterbank_set_norm_doc[] = ""
161 "set_norm(norm)\n"
162 "\n"
163 "Set norm parameter. If set to `0`, the filters will not be normalized.\n"
164 "If set to `1`, the filters will be normalized to one. Default to `1`.\n"
165 "\n"
166 "This function should be called *before* :meth:`set_triangle_bands`,\n"
167 ":meth:`set_mel_coeffs`, :meth:`set_mel_coeffs_htk`, or\n"
168 ":meth:`set_mel_coeffs_slaney`.\n"
169 "\n"
170 "Parameters\n"
171 "----------\n"
172 "norm : int\n"
173 "   `0` to disable, `1` to enable\n"
174 "";
175
176 static char Py_filterbank_get_norm_doc[] = ""
177 "get_norm()\n"
178 "\n"
179 "Get norm parameter of filterbank.\n"
180 "\n"
181 "Returns\n"
182 "-------\n"
183 "float\n"
184 "    Norm parameter.\n"
185 "";
186
187 typedef struct
188 {
189   PyObject_HEAD
190   aubio_filterbank_t * o;
191   uint_t n_filters;
192   uint_t win_s;
193   cvec_t vec;
194   fvec_t freqs;
195   fmat_t coeffs;
196   PyObject *out;
197   fvec_t c_out;
198 } Py_filterbank;
199
200 static PyObject *
201 Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
202 {
203   int win_s = 0, n_filters = 0;
204   Py_filterbank *self;
205   static char *kwlist[] = { "n_filters", "win_s", NULL };
206
207   if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
208           &n_filters, &win_s)) {
209     return NULL;
210   }
211
212   self = (Py_filterbank *) type->tp_alloc (type, 0);
213
214   if (self == NULL) {
215     return NULL;
216   }
217
218   self->win_s = Py_default_vector_length;
219   if (win_s > 0) {
220     self->win_s = win_s;
221   } else if (win_s < 0) {
222     PyErr_SetString (PyExc_ValueError,
223         "can not use negative window size");
224     return NULL;
225   }
226
227   self->n_filters = 40;
228   if (n_filters > 0) {
229     self->n_filters = n_filters;
230   } else if (n_filters < 0) {
231     PyErr_SetString (PyExc_ValueError,
232         "can not use negative number of filters");
233     return NULL;
234   }
235
236   return (PyObject *) self;
237 }
238
239 static int
240 Py_filterbank_init (Py_filterbank * self, PyObject * args, PyObject * kwds)
241 {
242   self->o = new_aubio_filterbank (self->n_filters, self->win_s);
243   if (self->o == NULL) {
244     PyErr_Format(PyExc_RuntimeError, "error creating filterbank with"
245         " n_filters=%d, win_s=%d", self->n_filters, self->win_s);
246     return -1;
247   }
248   self->out = new_py_fvec(self->n_filters);
249
250   return 0;
251 }
252
253 static void
254 Py_filterbank_del (Py_filterbank *self, PyObject *unused)
255 {
256   if (self->o) {
257     free(self->coeffs.data);
258     del_aubio_filterbank(self->o);
259   }
260   Py_XDECREF(self->out);
261   Py_TYPE(self)->tp_free((PyObject *) self);
262 }
263
264 static PyObject *
265 Py_filterbank_do(Py_filterbank * self, PyObject * args)
266 {
267   PyObject *input;
268
269   if (!PyArg_ParseTuple (args, "O", &input)) {
270     return NULL;
271   }
272
273   if (!PyAubio_PyCvecToCCvec(input, &(self->vec) )) {
274     return NULL;
275   }
276
277   if (self->vec.length != self->win_s / 2 + 1) {
278     PyErr_Format(PyExc_ValueError,
279                  "input cvec has length %d, but filterbank expects length %d",
280                  self->vec.length, self->win_s / 2 + 1);
281     return NULL;
282   }
283
284   Py_INCREF(self->out);
285   if (!PyAubio_ArrayToCFvec(self->out, &(self->c_out))) {
286     return NULL;
287   }
288   // compute the function
289   aubio_filterbank_do (self->o, &(self->vec), &(self->c_out));
290   return self->out;
291 }
292
293 static PyMemberDef Py_filterbank_members[] = {
294   {"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY,
295     "size of the window"},
296   {"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY,
297     "number of filters"},
298   {NULL} /* sentinel */
299 };
300
301 static PyObject *
302 Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args)
303 {
304   uint_t err = 0;
305
306   PyObject *input;
307   smpl_t samplerate;
308   if (!PyArg_ParseTuple (args, "O" AUBIO_NPY_SMPL_CHR, &input, &samplerate)) {
309     return NULL;
310   }
311
312   if (input == NULL) {
313     return NULL;
314   }
315
316   if (!PyAubio_ArrayToCFvec(input, &(self->freqs) )) {
317     return NULL;
318   }
319
320   err = aubio_filterbank_set_triangle_bands (self->o,
321       &(self->freqs), samplerate);
322   if (err > 0) {
323     if (PyErr_Occurred() == NULL) {
324       PyErr_SetString (PyExc_ValueError, "error running set_triangle_bands");
325     } else {
326       // change the RuntimeError into ValueError
327       PyObject *type, *value, *traceback;
328       PyErr_Fetch(&type, &value, &traceback);
329       Py_XDECREF(type);
330       type = PyExc_ValueError;
331       Py_XINCREF(type);
332       PyErr_Restore(type, value, traceback);
333     }
334     return NULL;
335   }
336   Py_RETURN_NONE;
337 }
338
339 static PyObject *
340 Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args)
341 {
342   uint_t err = 0;
343
344   smpl_t samplerate;
345   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &samplerate)) {
346     return NULL;
347   }
348
349   err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate);
350   if (err > 0) {
351     if (PyErr_Occurred() == NULL) {
352       PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs_slaney");
353     } else {
354       // change the RuntimeError into ValueError
355       PyObject *type, *value, *traceback;
356       PyErr_Fetch(&type, &value, &traceback);
357       Py_XDECREF(type);
358       type = PyExc_ValueError;
359       Py_XINCREF(type);
360       PyErr_Restore(type, value, traceback);
361     }
362     return NULL;
363   }
364   Py_RETURN_NONE;
365 }
366
367 static PyObject *
368 Py_filterbank_set_mel_coeffs (Py_filterbank * self, PyObject *args)
369 {
370   uint_t err = 0;
371
372   smpl_t samplerate;
373   smpl_t freq_min;
374   smpl_t freq_max;
375   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR
376         AUBIO_NPY_SMPL_CHR, &samplerate, &freq_min, &freq_max)) {
377     return NULL;
378   }
379
380   err = aubio_filterbank_set_mel_coeffs (self->o, samplerate,
381       freq_min, freq_max);
382   if (err > 0) {
383     if (PyErr_Occurred() == NULL) {
384       PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs");
385     } else {
386       // change the RuntimeError into ValueError
387       PyObject *type, *value, *traceback;
388       PyErr_Fetch(&type, &value, &traceback);
389       Py_XDECREF(type);
390       type = PyExc_ValueError;
391       Py_XINCREF(type);
392       PyErr_Restore(type, value, traceback);
393     }
394     return NULL;
395   }
396   Py_RETURN_NONE;
397 }
398
399 static PyObject *
400 Py_filterbank_set_mel_coeffs_htk (Py_filterbank * self, PyObject *args)
401 {
402   uint_t err = 0;
403
404   smpl_t samplerate;
405   smpl_t freq_min;
406   smpl_t freq_max;
407   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR
408         AUBIO_NPY_SMPL_CHR, &samplerate, &freq_min, &freq_max)) {
409     return NULL;
410   }
411
412   err = aubio_filterbank_set_mel_coeffs_htk (self->o, samplerate,
413       freq_min, freq_max);
414   if (err > 0) {
415     if (PyErr_Occurred() == NULL) {
416       PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs_htk");
417     } else {
418       // change the RuntimeError into ValueError
419       PyObject *type, *value, *traceback;
420       PyErr_Fetch(&type, &value, &traceback);
421       Py_XDECREF(type);
422       type = PyExc_ValueError;
423       Py_XINCREF(type);
424       PyErr_Restore(type, value, traceback);
425     }
426     return NULL;
427   }
428   Py_RETURN_NONE;
429 }
430
431 static PyObject *
432 Py_filterbank_set_coeffs (Py_filterbank * self, PyObject *args)
433 {
434   uint_t err = 0;
435
436   PyObject *input;
437   if (!PyArg_ParseTuple (args, "O", &input)) {
438     return NULL;
439   }
440
441   if (!PyAubio_ArrayToCFmat(input, &(self->coeffs))) {
442     return NULL;
443   }
444
445   err = aubio_filterbank_set_coeffs (self->o, &(self->coeffs));
446
447   if (err > 0) {
448     PyErr_SetString (PyExc_ValueError,
449         "error when setting filter coefficients");
450     return NULL;
451   }
452   Py_RETURN_NONE;
453 }
454
455 static PyObject *
456 Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused)
457 {
458   return (PyObject *)PyAubio_CFmatToArray(
459       aubio_filterbank_get_coeffs (self->o) );
460 }
461
462 static PyObject *
463 Py_filterbank_set_power(Py_filterbank *self, PyObject *args)
464 {
465   smpl_t power;
466
467   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &power)) {
468     return NULL;
469   }
470   if(aubio_filterbank_set_power (self->o, power)) {
471     if (PyErr_Occurred() == NULL) {
472       PyErr_SetString (PyExc_ValueError,
473           "error running filterbank.set_power");
474     } else {
475       // change the RuntimeError into ValueError
476       PyObject *type, *value, *traceback;
477       PyErr_Fetch(&type, &value, &traceback);
478       Py_XDECREF(type);
479       type = PyExc_ValueError;
480       Py_XINCREF(type);
481       PyErr_Restore(type, value, traceback);
482     }
483     return NULL;
484   }
485   Py_RETURN_NONE;
486 }
487
488 static PyObject *
489 Py_filterbank_get_power (Py_filterbank * self, PyObject *unused)
490 {
491   smpl_t power = aubio_filterbank_get_power(self->o);
492   return (PyObject *)PyFloat_FromDouble (power);
493 }
494
495 static PyObject *
496 Py_filterbank_set_norm(Py_filterbank *self, PyObject *args)
497 {
498   smpl_t norm;
499
500   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &norm)) {
501     return NULL;
502   }
503   if(aubio_filterbank_set_norm (self->o, norm)) {
504     if (PyErr_Occurred() == NULL) {
505       PyErr_SetString (PyExc_ValueError,
506           "error running filterbank.set_power");
507     } else {
508       // change the RuntimeError into ValueError
509       PyObject *type, *value, *traceback;
510       PyErr_Fetch(&type, &value, &traceback);
511       Py_XDECREF(type);
512       type = PyExc_ValueError;
513       Py_XINCREF(type);
514       PyErr_Restore(type, value, traceback);
515     }
516     return NULL;
517   }
518   Py_RETURN_NONE;
519 }
520
521 static PyObject *
522 Py_filterbank_get_norm (Py_filterbank * self, PyObject *unused)
523 {
524   smpl_t norm = aubio_filterbank_get_norm(self->o);
525   return (PyObject *)PyFloat_FromDouble (norm);
526 }
527
528 static PyMethodDef Py_filterbank_methods[] = {
529   {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands,
530     METH_VARARGS, Py_filterbank_set_triangle_bands_doc},
531   {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney,
532     METH_VARARGS, Py_filterbank_set_mel_coeffs_slaney_doc},
533   {"set_mel_coeffs", (PyCFunction) Py_filterbank_set_mel_coeffs,
534     METH_VARARGS, Py_filterbank_set_mel_coeffs_doc},
535   {"set_mel_coeffs_htk", (PyCFunction) Py_filterbank_set_mel_coeffs_htk,
536     METH_VARARGS, Py_filterbank_set_mel_coeffs_htk_doc},
537   {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs,
538     METH_NOARGS, Py_filterbank_get_coeffs_doc},
539   {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs,
540     METH_VARARGS, Py_filterbank_set_coeffs_doc},
541   {"set_power", (PyCFunction) Py_filterbank_set_power,
542     METH_VARARGS, Py_filterbank_set_power_doc},
543   {"get_power", (PyCFunction) Py_filterbank_get_power,
544     METH_NOARGS, Py_filterbank_get_power_doc},
545   {"set_norm", (PyCFunction) Py_filterbank_set_norm,
546     METH_VARARGS, Py_filterbank_set_norm_doc},
547   {"get_norm", (PyCFunction) Py_filterbank_get_norm,
548     METH_NOARGS, Py_filterbank_get_norm_doc},
549   {NULL}
550 };
551
552 PyTypeObject Py_filterbankType = {
553   PyVarObject_HEAD_INIT (NULL, 0)
554   "aubio.filterbank",
555   sizeof (Py_filterbank),
556   0,
557   (destructor) Py_filterbank_del,
558   0,
559   0,
560   0,
561   0,
562   0,
563   0,
564   0,
565   0,
566   0,
567   (ternaryfunc)Py_filterbank_do,
568   0,
569   0,
570   0,
571   0,
572   Py_TPFLAGS_DEFAULT,
573   Py_filterbank_doc,
574   0,
575   0,
576   0,
577   0,
578   0,
579   0,
580   Py_filterbank_methods,
581   Py_filterbank_members,
582   0,
583   0,
584   0,
585   0,
586   0,
587   0,
588   (initproc) Py_filterbank_init,
589   0,
590   Py_filterbank_new,
591   0,
592   0,
593   0,
594   0,
595   0,
596   0,
597   0,
598   0,
599   0,
600 };