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 *
Py_filterbank_new(PyTypeObject * type,PyObject * args,PyObject * kwds)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
Py_filterbank_init(Py_filterbank * self,PyObject * args,PyObject * kwds)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
Py_filterbank_del(Py_filterbank * self,PyObject * unused)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 *
Py_filterbank_do(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_set_triangle_bands(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_set_mel_coeffs_slaney(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_set_mel_coeffs(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_set_mel_coeffs_htk(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_set_coeffs(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_get_coeffs(Py_filterbank * self,PyObject * unused)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 *
Py_filterbank_set_power(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_get_power(Py_filterbank * self,PyObject * unused)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 *
Py_filterbank_set_norm(Py_filterbank * self,PyObject * args)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 *
Py_filterbank_get_norm(Py_filterbank * self,PyObject * unused)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 };
583