python/ext/{aubioproxy,py-cvec}.c: use npy_intp, not long
[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   if (!PyAubio_IsValidVector(input)) {
144     return 1;
145   }
146   npy_intp length = PyArray_SIZE ((PyArrayObject *)input);
147   if (length != vec->length) {
148     PyErr_Format (PyExc_ValueError,
149         "input array has length %ld, but cvec has length %d", length,
150         vec->length);
151     return 1;
152   }
153
154   Py_XDECREF(vec->norm);
155   vec->norm = input;
156   Py_INCREF(vec->norm);
157   return 0;
158 }
159
160 static int
161 Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure)
162 {
163   if (!PyAubio_IsValidVector(input)) {
164     return 1;
165   }
166   npy_intp length = PyArray_SIZE ((PyArrayObject *)input);
167   if (length != vec->length) {
168     PyErr_Format (PyExc_ValueError,
169         "input array has length %ld, but cvec has length %d", length,
170         vec->length);
171     return 1;
172   }
173
174   Py_XDECREF(vec->phas);
175   vec->phas = input;
176   Py_INCREF(vec->phas);
177   return 0;
178 }
179
180 static PyMemberDef Py_cvec_members[] = {
181   // TODO remove READONLY flag and define getter/setter
182   {"length", T_INT, offsetof (Py_cvec, length), READONLY,
183       "length attribute"},
184   {NULL}                        /* Sentinel */
185 };
186
187 static PyMethodDef Py_cvec_methods[] = {
188   {NULL}
189 };
190
191 static PyGetSetDef Py_cvec_getseters[] = {
192   {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, 
193       "Numpy vector of shape (length,) containing the magnitude",
194       NULL},
195   {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, 
196       "Numpy vector of shape (length,) containing the phase",
197       NULL},
198   {NULL} /* sentinel */
199 };
200
201 PyTypeObject Py_cvecType = {
202   PyVarObject_HEAD_INIT(NULL, 0)
203   "aubio.cvec",                 /* tp_name           */
204   sizeof (Py_cvec),             /* tp_basicsize      */
205   0,                            /* tp_itemsize       */
206   (destructor) Py_cvec_del,     /* tp_dealloc        */
207   0,                            /* tp_print          */
208   0,                            /* tp_getattr        */
209   0,                            /* tp_setattr        */
210   0,                            /* tp_compare        */
211   (reprfunc) Py_cvec_repr,      /* tp_repr           */
212   0,                            /* tp_as_number      */
213   0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence    */
214   0,                            /* tp_as_mapping     */
215   0,                            /* tp_hash           */
216   0,                            /* tp_call           */
217   0,                            /* tp_str            */
218   0,                            /* tp_getattro       */
219   0,                            /* tp_setattro       */
220   0,                            /* tp_as_buffer      */
221   Py_TPFLAGS_DEFAULT,           /* tp_flags          */
222   Py_cvec_doc,                  /* tp_doc            */
223   0,                            /* tp_traverse       */
224   0,                            /* tp_clear          */
225   0,                            /* tp_richcompare    */
226   0,                            /* tp_weaklistoffset */
227   0,                            /* tp_iter           */
228   0,                            /* tp_iternext       */
229   Py_cvec_methods,              /* tp_methods        */
230   Py_cvec_members,              /* tp_members        */
231   Py_cvec_getseters,            /* tp_getset         */
232   0,                            /* tp_base           */
233   0,                            /* tp_dict           */
234   0,                            /* tp_descr_get      */
235   0,                            /* tp_descr_set      */
236   0,                            /* tp_dictoffset     */
237   (initproc) Py_cvec_init,      /* tp_init           */
238   0,                            /* tp_alloc          */
239   Py_cvec_new,                  /* tp_new            */
240 };