source: python/ext/py-filterbank.c @ 8389694

feature/crepe_org
Last change on this file since 8389694 was e5efa0f, checked in by Paul Brossier <piem@piem.org>, 6 years ago

[py] add get_norm/power and documentation to filterbank

  • Property mode set to 100644
File size: 14.2 KB
Line 
1#include "aubio-types.h"
2
3static 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
29static 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
54static 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
78static 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
97static 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
116static 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
127static 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
138static 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
149static 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
160static 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
176static 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
187typedef 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
200static PyObject *
201Py_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
239static int
240Py_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
253static void
254Py_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
264static PyObject *
265Py_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
293static 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
301static PyObject *
302Py_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
336static PyObject *
337Py_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
361static PyObject *
362Py_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
390static PyObject *
391Py_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
419static PyObject *
420Py_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
443static PyObject *
444Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused)
445{
446  return (PyObject *)PyAubio_CFmatToArray(
447      aubio_filterbank_get_coeffs (self->o) );
448}
449
450static PyObject *
451Py_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
473static PyObject *
474Py_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
480static PyObject *
481Py_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
503static PyObject *
504Py_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
510static 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
534PyTypeObject 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};
Note: See TracBrowser for help on using the repository browser.