ChangeLog: update for 0.4.3
[aubio.git] / python / ext / py-cvec.c
1 #include "aubio-types.h"
2
3 /* cvec type definition
4
5 class cvec():
6     def __new__(self, length = 1024):
7         self.length = length / 2 + 1
8         self.norm = np.zeros(length / 2 + 1)
9         self.phas = np.zeros(length / 2 + 1)
10
11 */
12
13 // special python type for cvec
14 typedef struct
15 {
16   PyObject_HEAD
17   PyObject *norm;
18   PyObject *phas;
19   uint_t length;
20 } Py_cvec;
21
22 static char Py_cvec_doc[] = "cvec object";
23
24
25 PyObject *
26 new_py_cvec(uint_t length) {
27   Py_cvec* vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
28   npy_intp dims[] = { length / 2 + 1, 1 };
29   vec->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
30   vec->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
31   vec->length = length / 2 + 1;
32   return (PyObject*)vec;
33 }
34
35 int
36 PyAubio_PyCvecToCCvec (PyObject *input, cvec_t *i) {
37   if (PyObject_TypeCheck (input, &Py_cvecType)) {
38       Py_cvec * in = (Py_cvec *)input;
39       i->norm = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->norm), 0);
40       i->phas = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->phas), 0);
41       i->length = ((Py_cvec*)input)->length;
42       return 1;
43   } else {
44       PyErr_SetString (PyExc_ValueError, "input array should be aubio.cvec");
45       return 0;
46   }
47 }
48
49 static PyObject *
50 Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds)
51 {
52   int length= 0;
53   Py_cvec *self;
54   static char *kwlist[] = { "length", NULL };
55
56   if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist,
57           &length)) {
58     return NULL;
59   }
60
61   self = (Py_cvec *) type->tp_alloc (type, 0);
62
63   self->length = Py_default_vector_length / 2 + 1;
64
65   if (self == NULL) {
66     return NULL;
67   }
68
69   if (length > 0) {
70     self->length = length / 2 + 1;
71   } else if (length < 0) {
72     PyErr_SetString (PyExc_ValueError,
73         "can not use negative number of elements");
74     return NULL;
75   }
76
77   return (PyObject *) self;
78 }
79
80 static int
81 Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
82 {
83   npy_intp dims[] = { self->length, 1 };
84   self->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
85   self->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
86   return 0;
87 }
88
89 static void
90 Py_cvec_del (Py_cvec * self)
91 {
92   Py_DECREF(self->norm);
93   Py_DECREF(self->phas);
94   Py_TYPE(self)->tp_free ((PyObject *) self);
95 }
96
97 static PyObject *
98 Py_cvec_repr (Py_cvec * self, PyObject * unused)
99 {
100   PyObject *format = NULL;
101   PyObject *args = NULL;
102   PyObject *result = NULL;
103
104   format = PyUnicode_FromString ("aubio cvec of %d elements");
105   if (format == NULL) {
106     goto fail;
107   }
108
109   args = Py_BuildValue ("I", self->length);
110   if (args == NULL) {
111     goto fail;
112   }
113   // hide actual norm / phas content
114
115   result = PyUnicode_Format (format, args);
116
117 fail:
118   Py_XDECREF (format);
119   Py_XDECREF (args);
120
121   return result;
122 }
123
124 PyObject *
125 Py_cvec_get_norm (Py_cvec * self, void *closure)
126 {
127   // we want self->norm to still exist after our caller return it
128   Py_INCREF(self->norm);
129   return (PyObject*)(self->norm);
130 }
131
132 PyObject *
133 Py_cvec_get_phas (Py_cvec * self, void *closure)
134 {
135   // we want self->phas to still exist after our caller return it
136   Py_INCREF(self->phas);
137   return (PyObject *)(self->phas);
138 }
139
140 static int
141 Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure)
142 {
143   npy_intp length;
144   if (!PyAubio_IsValidVector(input)) {
145     return 1;
146   }
147   length = PyArray_SIZE ((PyArrayObject *)input);
148   if (length != vec->length) {
149     PyErr_Format (PyExc_ValueError,
150         "input array has length %ld, but cvec has length %d", length,
151         vec->length);
152     return 1;
153   }
154
155   Py_XDECREF(vec->norm);
156   vec->norm = input;
157   Py_INCREF(vec->norm);
158   return 0;
159 }
160
161 static int
162 Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
163 {
164   npy_intp length;
165   if (!PyAubio_IsValidVector(input)) {
166     return 1;
167   }
168   length = PyArray_SIZE ((PyArrayObject *)input);
169   if (length != vec->length) {
170     PyErr_Format (PyExc_ValueError,
171         "input array has length %ld, but cvec has length %d", length,
172         vec->length);
173     return 1;
174   }
175
176   Py_XDECREF(vec->phas);
177   vec->phas = input;
178   Py_INCREF(vec->phas);
179   return 0;
180 }
181
182 static PyMemberDef Py_cvec_members[] = {
183   // TODO remove READONLY flag and define getter/setter
184   {"length", T_INT, offsetof (Py_cvec, length), READONLY,
185       "length attribute"},
186   {NULL}                        /* Sentinel */
187 };
188
189 static PyMethodDef Py_cvec_methods[] = {
190   {NULL}
191 };
192
193 static PyGetSetDef Py_cvec_getseters[] = {
194   {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, 
195       "Numpy vector of shape (length,) containing the magnitude",
196       NULL},
197   {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, 
198       "Numpy vector of shape (length,) containing the phase",
199       NULL},
200   {NULL} /* sentinel */
201 };
202
203 PyTypeObject Py_cvecType = {
204   PyVarObject_HEAD_INIT(NULL, 0)
205   "aubio.cvec",                 /* tp_name           */
206   sizeof (Py_cvec),             /* tp_basicsize      */
207   0,                            /* tp_itemsize       */
208   (destructor) Py_cvec_del,     /* tp_dealloc        */
209   0,                            /* tp_print          */
210   0,                            /* tp_getattr        */
211   0,                            /* tp_setattr        */
212   0,                            /* tp_compare        */
213   (reprfunc) Py_cvec_repr,      /* tp_repr           */
214   0,                            /* tp_as_number      */
215   0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence    */
216   0,                            /* tp_as_mapping     */
217   0,                            /* tp_hash           */
218   0,                            /* tp_call           */
219   0,                            /* tp_str            */
220   0,                            /* tp_getattro       */
221   0,                            /* tp_setattro       */
222   0,                            /* tp_as_buffer      */
223   Py_TPFLAGS_DEFAULT,           /* tp_flags          */
224   Py_cvec_doc,                  /* tp_doc            */
225   0,                            /* tp_traverse       */
226   0,                            /* tp_clear          */
227   0,                            /* tp_richcompare    */
228   0,                            /* tp_weaklistoffset */
229   0,                            /* tp_iter           */
230   0,                            /* tp_iternext       */
231   Py_cvec_methods,              /* tp_methods        */
232   Py_cvec_members,              /* tp_members        */
233   Py_cvec_getseters,            /* tp_getset         */
234   0,                            /* tp_base           */
235   0,                            /* tp_dict           */
236   0,                            /* tp_descr_get      */
237   0,                            /* tp_descr_set      */
238   0,                            /* tp_dictoffset     */
239   (initproc) Py_cvec_init,      /* tp_init           */
240   0,                            /* tp_alloc          */
241   Py_cvec_new,                  /* tp_new            */
242   0,
243   0,
244   0,
245   0,
246   0,
247   0,
248   0,
249   0,
250   0,
251 };