python/ext/py-filterbank.c: fix error message formatting, do not delete if not created
[aubio.git] / python / ext / py-filterbank.c
1 #include "aubio-types.h"
2
3 static char Py_filterbank_doc[] = "filterbank object";
4
5 typedef struct
6 {
7   PyObject_HEAD
8   aubio_filterbank_t * o;
9   uint_t n_filters;
10   uint_t win_s;
11   cvec_t vec;
12   fvec_t freqs;
13   fmat_t coeffs;
14   PyObject *out;
15   fvec_t c_out;
16 } Py_filterbank;
17
18 static PyObject *
19 Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
20 {
21   int win_s = 0, n_filters = 0;
22   Py_filterbank *self;
23   static char *kwlist[] = { "n_filters", "win_s", NULL };
24
25   if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist,
26           &n_filters, &win_s)) {
27     return NULL;
28   }
29
30   self = (Py_filterbank *) type->tp_alloc (type, 0);
31
32   if (self == NULL) {
33     return NULL;
34   }
35
36   self->win_s = Py_default_vector_length;
37   if (win_s > 0) {
38     self->win_s = win_s;
39   } else if (win_s < 0) {
40     PyErr_SetString (PyExc_ValueError,
41         "can not use negative window size");
42     return NULL;
43   }
44
45   self->n_filters = 40;
46   if (n_filters > 0) {
47     self->n_filters = n_filters;
48   } else if (n_filters < 0) {
49     PyErr_SetString (PyExc_ValueError,
50         "can not use negative number of filters");
51     return NULL;
52   }
53
54   return (PyObject *) self;
55 }
56
57 static int
58 Py_filterbank_init (Py_filterbank * self, PyObject * args, PyObject * kwds)
59 {
60   self->o = new_aubio_filterbank (self->n_filters, self->win_s);
61   if (self->o == NULL) {
62     PyErr_Format(PyExc_RuntimeError, "error creating filterbank with"
63         " n_filters=%d, win_s=%d", self->n_filters, self->win_s);
64     return -1;
65   }
66   self->out = new_py_fvec(self->n_filters);
67
68   return 0;
69 }
70
71 static void
72 Py_filterbank_del (Py_filterbank *self, PyObject *unused)
73 {
74   if (self->o) {
75     free(self->coeffs.data);
76     del_aubio_filterbank(self->o);
77   }
78   Py_XDECREF(self->out);
79   Py_TYPE(self)->tp_free((PyObject *) self);
80 }
81
82 static PyObject *
83 Py_filterbank_do(Py_filterbank * self, PyObject * args)
84 {
85   PyObject *input;
86
87   if (!PyArg_ParseTuple (args, "O", &input)) {
88     return NULL;
89   }
90
91   if (!PyAubio_PyCvecToCCvec(input, &(self->vec) )) {
92     return NULL;
93   }
94
95   if (self->vec.length != self->win_s / 2 + 1) {
96     PyErr_Format(PyExc_ValueError,
97                  "input cvec has length %d, but fft expects length %d",
98                  self->vec.length, self->win_s / 2 + 1);
99     return NULL;
100   }
101
102   Py_INCREF(self->out);
103   if (!PyAubio_ArrayToCFvec(self->out, &(self->c_out))) {
104     return NULL;
105   }
106   // compute the function
107   aubio_filterbank_do (self->o, &(self->vec), &(self->c_out));
108   return self->out;
109 }
110
111 static PyMemberDef Py_filterbank_members[] = {
112   {"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY,
113     "size of the window"},
114   {"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY,
115     "number of filters"},
116   {NULL} /* sentinel */
117 };
118
119 static PyObject *
120 Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args)
121 {
122   uint_t err = 0;
123
124   PyObject *input;
125   uint_t samplerate;
126   if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) {
127     return NULL;
128   }
129
130   if (input == NULL) {
131     return NULL;
132   }
133
134   if (!PyAubio_ArrayToCFvec(input, &(self->freqs) )) {
135     return NULL;
136   }
137
138   err = aubio_filterbank_set_triangle_bands (self->o,
139       &(self->freqs), samplerate);
140   if (err > 0) {
141     PyErr_SetString (PyExc_ValueError,
142         "error when setting filter to A-weighting");
143     return NULL;
144   }
145   Py_RETURN_NONE;
146 }
147
148 static PyObject *
149 Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args)
150 {
151   uint_t err = 0;
152
153   uint_t samplerate;
154   if (!PyArg_ParseTuple (args, "I", &samplerate)) {
155     return NULL;
156   }
157
158   err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate);
159   if (err > 0) {
160     PyErr_SetString (PyExc_ValueError,
161         "error when setting filter to A-weighting");
162     return NULL;
163   }
164   Py_RETURN_NONE;
165 }
166
167 static PyObject *
168 Py_filterbank_set_coeffs (Py_filterbank * self, PyObject *args)
169 {
170   uint_t err = 0;
171
172   PyObject *input;
173   if (!PyArg_ParseTuple (args, "O", &input)) {
174     return NULL;
175   }
176
177   if (!PyAubio_ArrayToCFmat(input, &(self->coeffs))) {
178     return NULL;
179   }
180
181   err = aubio_filterbank_set_coeffs (self->o, &(self->coeffs));
182
183   if (err > 0) {
184     PyErr_SetString (PyExc_ValueError,
185         "error when setting filter coefficients");
186     return NULL;
187   }
188   Py_RETURN_NONE;
189 }
190
191 static PyObject *
192 Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused)
193 {
194   return (PyObject *)PyAubio_CFmatToArray(
195       aubio_filterbank_get_coeffs (self->o) );
196 }
197
198 static PyMethodDef Py_filterbank_methods[] = {
199   {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands,
200     METH_VARARGS, "set coefficients of filterbanks"},
201   {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney,
202     METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"},
203   {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs,
204     METH_NOARGS, "get coefficients of filterbank"},
205   {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs,
206     METH_VARARGS, "set coefficients of filterbank"},
207   {NULL}
208 };
209
210 PyTypeObject Py_filterbankType = {
211   PyVarObject_HEAD_INIT (NULL, 0)
212   "aubio.filterbank",
213   sizeof (Py_filterbank),
214   0,
215   (destructor) Py_filterbank_del,
216   0,
217   0,
218   0,
219   0,
220   0,
221   0,
222   0,
223   0,
224   0,
225   (ternaryfunc)Py_filterbank_do,
226   0,
227   0,
228   0,
229   0,
230   Py_TPFLAGS_DEFAULT,
231   Py_filterbank_doc,
232   0,
233   0,
234   0,
235   0,
236   0,
237   0,
238   Py_filterbank_methods,
239   Py_filterbank_members,
240   0,
241   0,
242   0,
243   0,
244   0,
245   0,
246   (initproc) Py_filterbank_init,
247   0,
248   Py_filterbank_new,
249   0,
250   0,
251   0,
252   0,
253   0,
254   0,
255   0,
256   0,
257   0,
258 };