[py] fix reference counting of exception types (thanks @wackou)
[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       PyErr_Restore(PyExc_ValueError, value, traceback);
330     }
331     return NULL;
332   }
333   Py_RETURN_NONE;
334 }
335
336 static PyObject *
337 Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args)
338 {
339   uint_t err = 0;
340
341   smpl_t samplerate;
342   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &samplerate)) {
343     return NULL;
344   }
345
346   err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate);
347   if (err > 0) {
348     if (PyErr_Occurred() == NULL) {
349       PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs_slaney");
350     } else {
351       // change the RuntimeError into ValueError
352       PyObject *type, *value, *traceback;
353       PyErr_Fetch(&type, &value, &traceback);
354       PyErr_Restore(PyExc_ValueError, value, traceback);
355     }
356     return NULL;
357   }
358   Py_RETURN_NONE;
359 }
360
361 static PyObject *
362 Py_filterbank_set_mel_coeffs (Py_filterbank * self, PyObject *args)
363 {
364   uint_t err = 0;
365
366   smpl_t samplerate;
367   smpl_t freq_min;
368   smpl_t freq_max;
369   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR
370         AUBIO_NPY_SMPL_CHR, &samplerate, &freq_min, &freq_max)) {
371     return NULL;
372   }
373
374   err = aubio_filterbank_set_mel_coeffs (self->o, samplerate,
375       freq_min, freq_max);
376   if (err > 0) {
377     if (PyErr_Occurred() == NULL) {
378       PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs");
379     } else {
380       // change the RuntimeError into ValueError
381       PyObject *type, *value, *traceback;
382       PyErr_Fetch(&type, &value, &traceback);
383       PyErr_Restore(PyExc_ValueError, value, traceback);
384     }
385     return NULL;
386   }
387   Py_RETURN_NONE;
388 }
389
390 static PyObject *
391 Py_filterbank_set_mel_coeffs_htk (Py_filterbank * self, PyObject *args)
392 {
393   uint_t err = 0;
394
395   smpl_t samplerate;
396   smpl_t freq_min;
397   smpl_t freq_max;
398   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR
399         AUBIO_NPY_SMPL_CHR, &samplerate, &freq_min, &freq_max)) {
400     return NULL;
401   }
402
403   err = aubio_filterbank_set_mel_coeffs_htk (self->o, samplerate,
404       freq_min, freq_max);
405   if (err > 0) {
406     if (PyErr_Occurred() == NULL) {
407       PyErr_SetString (PyExc_ValueError, "error running set_mel_coeffs_htk");
408     } else {
409       // change the RuntimeError into ValueError
410       PyObject *type, *value, *traceback;
411       PyErr_Fetch(&type, &value, &traceback);
412       PyErr_Restore(PyExc_ValueError, value, traceback);
413     }
414     return NULL;
415   }
416   Py_RETURN_NONE;
417 }
418
419 static PyObject *
420 Py_filterbank_set_coeffs (Py_filterbank * self, PyObject *args)
421 {
422   uint_t err = 0;
423
424   PyObject *input;
425   if (!PyArg_ParseTuple (args, "O", &input)) {
426     return NULL;
427   }
428
429   if (!PyAubio_ArrayToCFmat(input, &(self->coeffs))) {
430     return NULL;
431   }
432
433   err = aubio_filterbank_set_coeffs (self->o, &(self->coeffs));
434
435   if (err > 0) {
436     PyErr_SetString (PyExc_ValueError,
437         "error when setting filter coefficients");
438     return NULL;
439   }
440   Py_RETURN_NONE;
441 }
442
443 static PyObject *
444 Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused)
445 {
446   return (PyObject *)PyAubio_CFmatToArray(
447       aubio_filterbank_get_coeffs (self->o) );
448 }
449
450 static PyObject *
451 Py_filterbank_set_power(Py_filterbank *self, PyObject *args)
452 {
453   smpl_t power;
454
455   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &power)) {
456     return NULL;
457   }
458   if(aubio_filterbank_set_power (self->o, power)) {
459     if (PyErr_Occurred() == NULL) {
460       PyErr_SetString (PyExc_ValueError,
461           "error running filterbank.set_power");
462     } else {
463       // change the RuntimeError into ValueError
464       PyObject *type, *value, *traceback;
465       PyErr_Fetch(&type, &value, &traceback);
466       PyErr_Restore(PyExc_ValueError, value, traceback);
467     }
468     return NULL;
469   }
470   Py_RETURN_NONE;
471 }
472
473 static PyObject *
474 Py_filterbank_get_power (Py_filterbank * self, PyObject *unused)
475 {
476   smpl_t power = aubio_filterbank_get_power(self->o);
477   return (PyObject *)PyFloat_FromDouble (power);
478 }
479
480 static PyObject *
481 Py_filterbank_set_norm(Py_filterbank *self, PyObject *args)
482 {
483   smpl_t norm;
484
485   if (!PyArg_ParseTuple (args, AUBIO_NPY_SMPL_CHR, &norm)) {
486     return NULL;
487   }
488   if(aubio_filterbank_set_norm (self->o, norm)) {
489     if (PyErr_Occurred() == NULL) {
490       PyErr_SetString (PyExc_ValueError,
491           "error running filterbank.set_power");
492     } else {
493       // change the RuntimeError into ValueError
494       PyObject *type, *value, *traceback;
495       PyErr_Fetch(&type, &value, &traceback);
496       PyErr_Restore(PyExc_ValueError, value, traceback);
497     }
498     return NULL;
499   }
500   Py_RETURN_NONE;
501 }
502
503 static PyObject *
504 Py_filterbank_get_norm (Py_filterbank * self, PyObject *unused)
505 {
506   smpl_t norm = aubio_filterbank_get_norm(self->o);
507   return (PyObject *)PyFloat_FromDouble (norm);
508 }
509
510 static PyMethodDef Py_filterbank_methods[] = {
511   {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands,
512     METH_VARARGS, Py_filterbank_set_triangle_bands_doc},
513   {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney,
514     METH_VARARGS, Py_filterbank_set_mel_coeffs_slaney_doc},
515   {"set_mel_coeffs", (PyCFunction) Py_filterbank_set_mel_coeffs,
516     METH_VARARGS, Py_filterbank_set_mel_coeffs_doc},
517   {"set_mel_coeffs_htk", (PyCFunction) Py_filterbank_set_mel_coeffs_htk,
518     METH_VARARGS, Py_filterbank_set_mel_coeffs_htk_doc},
519   {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs,
520     METH_NOARGS, Py_filterbank_get_coeffs_doc},
521   {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs,
522     METH_VARARGS, Py_filterbank_set_coeffs_doc},
523   {"set_power", (PyCFunction) Py_filterbank_set_power,
524     METH_VARARGS, Py_filterbank_set_power_doc},
525   {"get_power", (PyCFunction) Py_filterbank_get_power,
526     METH_NOARGS, Py_filterbank_get_power_doc},
527   {"set_norm", (PyCFunction) Py_filterbank_set_norm,
528     METH_VARARGS, Py_filterbank_set_norm_doc},
529   {"get_norm", (PyCFunction) Py_filterbank_get_norm,
530     METH_NOARGS, Py_filterbank_get_norm_doc},
531   {NULL}
532 };
533
534 PyTypeObject Py_filterbankType = {
535   PyVarObject_HEAD_INIT (NULL, 0)
536   "aubio.filterbank",
537   sizeof (Py_filterbank),
538   0,
539   (destructor) Py_filterbank_del,
540   0,
541   0,
542   0,
543   0,
544   0,
545   0,
546   0,
547   0,
548   0,
549   (ternaryfunc)Py_filterbank_do,
550   0,
551   0,
552   0,
553   0,
554   Py_TPFLAGS_DEFAULT,
555   Py_filterbank_doc,
556   0,
557   0,
558   0,
559   0,
560   0,
561   0,
562   Py_filterbank_methods,
563   Py_filterbank_members,
564   0,
565   0,
566   0,
567   0,
568   0,
569   0,
570   (initproc) Py_filterbank_init,
571   0,
572   Py_filterbank_new,
573   0,
574   0,
575   0,
576   0,
577   0,
578   0,
579   0,
580   0,
581   0,
582 };