1 #include "aubio-types.h"
2
3 typedef struct
4 {
5 PyObject_HEAD
6 aubio_filter_t * o;
7 uint_t order;
8 fvec_t vec;
9 PyObject *out;
10 fvec_t c_out;
11 } Py_filter;
12
13 static char Py_filter_doc[] = ""
14 "digital_filter(order=7)\n"
15 "\n"
16 "Create a digital filter.\n"
17 "";
18
19 static char Py_filter_set_c_weighting_doc[] = ""
20 "set_c_weighting(samplerate)\n"
21 "\n"
22 "Set filter coefficients to C-weighting.\n"
23 "\n"
24 "`samplerate` should be one of 8000, 11025, 16000, 22050, 24000, 32000,\n"
25 "44100, 48000, 88200, 96000, or 192000. `order` of the filter should be 5.\n"
26 "\n"
27 "Parameters\n"
28 "----------\n"
29 "samplerate : int\n"
30 " Sampling-rate of the input signal, in Hz.\n"
31 "";
32
33 static char Py_filter_set_a_weighting_doc[] = ""
34 "set_a_weighting(samplerate)\n"
35 "\n"
36 "Set filter coefficients to A-weighting.\n"
37 "\n"
38 "`samplerate` should be one of 8000, 11025, 16000, 22050, 24000, 32000,\n"
39 "44100, 48000, 88200, 96000, or 192000. `order` of the filter should be 7.\n"
40 "\n"
41 "Parameters\n"
42 "----------\n"
43 "samplerate : int\n"
44 " Sampling-rate of the input signal.\n"
45 "";
46
47 static char Py_filter_set_biquad_doc[] = ""
48 "set_biquad(b0, b1, b2, a1, a2)\n"
49 "\n"
50 "Set biquad coefficients. `order` of the filter should be 3.\n"
51 "\n"
52 "Parameters\n"
53 "----------\n"
54 "b0 : float\n"
55 " Forward filter coefficient.\n"
56 "b1 : float\n"
57 " Forward filter coefficient.\n"
58 "b2 : float\n"
59 " Forward filter coefficient.\n"
60 "a1 : float\n"
61 " Feedback filter coefficient.\n"
62 "a2 : float\n"
63 " Feedback filter coefficient.\n"
64 "";
65
66 static PyObject *
Py_filter_new(PyTypeObject * type,PyObject * args,PyObject * kwds)67 Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
68 {
69 int order= 0;
70 Py_filter *self;
71 static char *kwlist[] = { "order", NULL };
72
73 if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist,
74 &order)) {
75 return NULL;
76 }
77
78 self = (Py_filter *) type->tp_alloc (type, 0);
79
80 if (self == NULL) {
81 return NULL;
82 }
83
84 self->order = 7;
85
86 if (order > 0) {
87 self->order = order;
88 } else if (order < 0) {
89 PyErr_SetString (PyExc_ValueError,
90 "can not use negative order");
91 return NULL;
92 }
93
94 return (PyObject *) self;
95 }
96
97 static int
Py_filter_init(Py_filter * self,PyObject * args,PyObject * kwds)98 Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds)
99 {
100 self->o = new_aubio_filter (self->order);
101 if (self->o == NULL) {
102 return -1;
103 }
104 self->out = NULL;
105 return 0;
106 }
107
108 static void
Py_filter_del(Py_filter * self)109 Py_filter_del (Py_filter * self)
110 {
111 Py_XDECREF(self->out);
112 if (self->o)
113 del_aubio_filter (self->o);
114 Py_TYPE(self)->tp_free ((PyObject *) self);
115 }
116
117 static PyObject *
Py_filter_do(Py_filter * self,PyObject * args)118 Py_filter_do(Py_filter * self, PyObject * args)
119 {
120 PyObject *input;
121
122 if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) {
123 return NULL;
124 }
125
126 if (input == NULL) {
127 return NULL;
128 }
129
130 if (!PyAubio_ArrayToCFvec(input, &(self->vec))) {
131 return NULL;
132 }
133
134 // initialize output now
135 if (self->out == NULL) {
136 self->out = new_py_fvec(self->vec.length);
137 }
138
139 Py_INCREF(self->out);
140 if (!PyAubio_ArrayToCFvec(self->out, &(self->c_out)) ) {
141 return NULL;
142 }
143 // compute the function
144 aubio_filter_do_outplace (self->o, &(self->vec), &(self->c_out));
145 return self->out;
146 }
147
148 static PyObject *
Py_filter_set_c_weighting(Py_filter * self,PyObject * args)149 Py_filter_set_c_weighting (Py_filter * self, PyObject *args)
150 {
151 uint_t err = 0;
152 uint_t samplerate;
153 if (!PyArg_ParseTuple (args, "I", &samplerate)) {
154 return NULL;
155 }
156
157 err = aubio_filter_set_c_weighting (self->o, samplerate);
158 if (err > 0) {
159 PyErr_SetString (PyExc_ValueError,
160 "error when setting filter to C-weighting");
161 return NULL;
162 }
163 Py_RETURN_NONE;
164 }
165
166 static PyObject *
Py_filter_set_a_weighting(Py_filter * self,PyObject * args)167 Py_filter_set_a_weighting (Py_filter * self, PyObject *args)
168 {
169 uint_t err = 0;
170 uint_t samplerate;
171 if (!PyArg_ParseTuple (args, "I", &samplerate)) {
172 return NULL;
173 }
174
175 err = aubio_filter_set_a_weighting (self->o, samplerate);
176 if (err > 0) {
177 PyErr_SetString (PyExc_ValueError,
178 "error when setting filter to A-weighting");
179 return NULL;
180 }
181 Py_RETURN_NONE;
182 }
183
184 static PyObject *
Py_filter_set_biquad(Py_filter * self,PyObject * args)185 Py_filter_set_biquad(Py_filter * self, PyObject *args)
186 {
187 uint_t err = 0;
188 lsmp_t b0, b1, b2, a1, a2;
189 if (!PyArg_ParseTuple (args, "ddddd", &b0, &b1, &b2, &a1, &a2)) {
190 return NULL;
191 }
192
193 err = aubio_filter_set_biquad (self->o, b0, b1, b2, a1, a2);
194 if (err > 0) {
195 PyErr_SetString (PyExc_ValueError,
196 "error when setting filter with biquad coefficients");
197 return NULL;
198 }
199 Py_RETURN_NONE;
200 }
201
202 static PyMemberDef Py_filter_members[] = {
203 // TODO remove READONLY flag and define getter/setter
204 {"order", T_INT, offsetof (Py_filter, order), READONLY,
205 "order of the filter"},
206 {NULL} /* Sentinel */
207 };
208
209 static PyMethodDef Py_filter_methods[] = {
210 {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_VARARGS,
211 Py_filter_set_c_weighting_doc},
212 {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_VARARGS,
213 Py_filter_set_a_weighting_doc},
214 {"set_biquad", (PyCFunction) Py_filter_set_biquad, METH_VARARGS,
215 Py_filter_set_biquad_doc},
216 {NULL}
217 };
218
219 PyTypeObject Py_filterType = {
220 PyVarObject_HEAD_INIT(NULL, 0)
221 "aubio.digital_filter", /* tp_name */
222 sizeof (Py_filter), /* tp_basicsize */
223 0, /* tp_itemsize */
224 (destructor) Py_filter_del, /* tp_dealloc */
225 0, /* tp_print */
226 0, /* tp_getattr */
227 0, /* tp_setattr */
228 0, /* tp_compare */
229 0, //(reprfunc) Py_filter_repr, /* tp_repr */
230 0, /* tp_as_number */
231 0, /* tp_as_sequence */
232 0, /* tp_as_mapping */
233 0, /* tp_hash */
234 (ternaryfunc)Py_filter_do, /* tp_call */
235 0, /* tp_str */
236 0, /* tp_getattro */
237 0, /* tp_setattro */
238 0, /* tp_as_buffer */
239 Py_TPFLAGS_DEFAULT, /* tp_flags */
240 Py_filter_doc, /* tp_doc */
241 0, /* tp_traverse */
242 0, /* tp_clear */
243 0, /* tp_richcompare */
244 0, /* tp_weaklistoffset */
245 0, /* tp_iter */
246 0, /* tp_iternext */
247 Py_filter_methods, /* tp_methods */
248 Py_filter_members, /* tp_members */
249 0, /* tp_getset */
250 0, /* tp_base */
251 0, /* tp_dict */
252 0, /* tp_descr_get */
253 0, /* tp_descr_set */
254 0, /* tp_dictoffset */
255 (initproc) Py_filter_init, /* tp_init */
256 0, /* tp_alloc */
257 Py_filter_new, /* tp_new */
258 0,
259 0,
260 0,
261 0,
262 0,
263 0,
264 0,
265 0,
266 0,
267 };
268