python/ext: simplify memory allocations, removed unneeded malloc/free calls
[aubio.git] / python / ext / py-filter.c
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   fvec_t *out;
10 } Py_filter;
11
12 static char Py_filter_doc[] = "filter object";
13
14 static PyObject *
15 Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
16 {
17   int order= 0;
18   Py_filter *self;
19   static char *kwlist[] = { "order", NULL };
20
21   if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist,
22           &order)) {
23     return NULL;
24   }
25
26   self = (Py_filter *) type->tp_alloc (type, 0);
27
28   if (self == NULL) {
29     return NULL;
30   }
31
32   self->order = 7;
33
34   if (order > 0) {
35     self->order = order;
36   } else if (order < 0) {
37     PyErr_SetString (PyExc_ValueError,
38         "can not use negative order");
39     return NULL;
40   }
41
42   return (PyObject *) self;
43 }
44
45 static int
46 Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds)
47 {
48   self->o = new_aubio_filter (self->order);
49   if (self->o == NULL) {
50     return -1;
51   }
52   self->out = new_fvec(Py_default_vector_length);
53   return 0;
54 }
55
56 static void
57 Py_filter_del (Py_filter * self)
58 {
59   del_fvec(self->out);
60   del_aubio_filter (self->o);
61   Py_TYPE(self)->tp_free ((PyObject *) self);
62 }
63
64 static PyObject * 
65 Py_filter_do(Py_filter * self, PyObject * args)
66 {
67   PyObject *input;
68
69   if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) {
70     return NULL;
71   }
72
73   if (input == NULL) {
74     return NULL;
75   }
76
77   if (!PyAubio_ArrayToCFvec(input, &(self->vec))) {
78     return NULL;
79   }
80
81   // reallocate the output if needed
82   if (self->vec.length != self->out->length) {
83     del_fvec(self->out);
84     self->out = new_fvec(self->vec.length);
85   }
86   // compute the function
87   aubio_filter_do_outplace (self->o, &(self->vec), self->out);
88   return PyAubio_CFvecToArray(self->out);
89 }
90
91 static PyObject * 
92 Py_filter_set_c_weighting (Py_filter * self, PyObject *args)
93 {
94   uint_t err = 0;
95   uint_t samplerate;
96   if (!PyArg_ParseTuple (args, "I", &samplerate)) {
97     return NULL;
98   }
99
100   err = aubio_filter_set_c_weighting (self->o, samplerate);
101   if (err > 0) {
102     PyErr_SetString (PyExc_ValueError,
103         "error when setting filter to C-weighting");
104     return NULL;
105   }
106   Py_RETURN_NONE;
107 }
108
109 static PyObject * 
110 Py_filter_set_a_weighting (Py_filter * self, PyObject *args)
111 {
112   uint_t err = 0;
113   uint_t samplerate;
114   if (!PyArg_ParseTuple (args, "I", &samplerate)) {
115     return NULL;
116   }
117
118   err = aubio_filter_set_a_weighting (self->o, samplerate);
119   if (err > 0) {
120     PyErr_SetString (PyExc_ValueError,
121         "error when setting filter to A-weighting");
122     return NULL;
123   }
124   Py_RETURN_NONE;
125 }
126
127 static PyObject *
128 Py_filter_set_biquad(Py_filter * self, PyObject *args)
129 {
130   uint_t err = 0;
131   lsmp_t b0, b1, b2, a1, a2;
132   if (!PyArg_ParseTuple (args, "ddddd", &b0, &b1, &b2, &a1, &a2)) {
133     return NULL;
134   }
135
136   err = aubio_filter_set_biquad (self->o, b0, b1, b2, a1, a2);
137   if (err > 0) {
138     PyErr_SetString (PyExc_ValueError,
139         "error when setting filter with biquad coefficients");
140     return NULL;
141   }
142   Py_RETURN_NONE;
143 }
144
145 static PyMemberDef Py_filter_members[] = {
146   // TODO remove READONLY flag and define getter/setter
147   {"order", T_INT, offsetof (Py_filter, order), READONLY,
148       "order of the filter"},
149   {NULL}                        /* Sentinel */
150 };
151
152 static PyMethodDef Py_filter_methods[] = {
153   {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_VARARGS,
154       "set filter coefficients to C-weighting"},
155   {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_VARARGS,
156       "set filter coefficients to A-weighting"},
157   {"set_biquad", (PyCFunction) Py_filter_set_biquad, METH_VARARGS,
158       "set b0, b1, b2, a1, a2 biquad coefficients"},
159   {NULL}
160 };
161
162 PyTypeObject Py_filterType = {
163   PyVarObject_HEAD_INIT(NULL, 0)
164   "aubio.digital_filter",       /* tp_name           */
165   sizeof (Py_filter),           /* tp_basicsize      */
166   0,                            /* tp_itemsize       */
167   (destructor) Py_filter_del,   /* tp_dealloc        */
168   0,                            /* tp_print          */
169   0,                            /* tp_getattr        */
170   0,                            /* tp_setattr        */
171   0,                            /* tp_compare        */
172   0, //(reprfunc) Py_filter_repr,    /* tp_repr           */
173   0,                            /* tp_as_number      */
174   0,                            /* tp_as_sequence    */
175   0,                            /* tp_as_mapping     */
176   0,                            /* tp_hash           */
177   (ternaryfunc)Py_filter_do,    /* tp_call           */
178   0,                            /* tp_str            */
179   0,                            /* tp_getattro       */
180   0,                            /* tp_setattro       */
181   0,                            /* tp_as_buffer      */
182   Py_TPFLAGS_DEFAULT,           /* tp_flags          */
183   Py_filter_doc,                /* tp_doc            */
184   0,                            /* tp_traverse       */
185   0,                            /* tp_clear          */
186   0,                            /* tp_richcompare    */
187   0,                            /* tp_weaklistoffset */
188   0,                            /* tp_iter           */
189   0,                            /* tp_iternext       */
190   Py_filter_methods,            /* tp_methods        */
191   Py_filter_members,            /* tp_members        */
192   0,                            /* tp_getset         */
193   0,                            /* tp_base           */
194   0,                            /* tp_dict           */
195   0,                            /* tp_descr_get      */
196   0,                            /* tp_descr_set      */
197   0,                            /* tp_dictoffset     */
198   (initproc) Py_filter_init,    /* tp_init           */
199   0,                            /* tp_alloc          */
200   Py_filter_new,                /* tp_new            */
201 };