source: python/ext/py-filterbank.c @ 918b764

Last change on this file since 918b764 was 843b22f, checked in by Paul Brossier <piem@piem.org>, 5 years ago

[py] incref exception type before restoring it

  • Property mode set to 100644
File size: 14.6 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      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
339static PyObject *
340Py_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
367static PyObject *
368Py_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
399static PyObject *
400Py_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
431static PyObject *
432Py_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
455static PyObject *
456Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused)
457{
458  return (PyObject *)PyAubio_CFmatToArray(
459      aubio_filterbank_get_coeffs (self->o) );
460}
461
462static PyObject *
463Py_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
488static PyObject *
489Py_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
495static PyObject *
496Py_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
521static PyObject *
522Py_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
528static 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
552PyTypeObject 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};
Note: See TracBrowser for help on using the repository browser.