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