source: python/ext/py-cvec.c @ 4deb255

feature/autosinkfeature/constantqfeature/pitchshiftfeature/pydocstringsfeature/timestretch
Last change on this file since 4deb255 was 4deb255, checked in by Paul Brossier <piem@piem.org>, 3 years ago

python/ext/py-cvec.c: setters to return a negative value on error (closes #17)

  • Property mode set to 100644
File size: 6.7 KB
Line 
1#include "aubio-types.h"
2
3/* cvec type definition
4
5class 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
14typedef struct
15{
16  PyObject_HEAD
17  PyObject *norm;
18  PyObject *phas;
19  uint_t length;
20} Py_cvec;
21
22static char Py_cvec_doc[] = "cvec object";
23
24
25PyObject *
26new_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
35int
36PyAubio_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
49static PyObject *
50Py_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
80static int
81Py_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
89static void
90Py_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
97static PyObject *
98Py_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
117fail:
118  Py_XDECREF (format);
119  Py_XDECREF (args);
120
121  return result;
122}
123
124PyObject *
125Py_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
132PyObject *
133Py_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
140static int
141Py_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 %" NPY_INTP_FMT ", 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
161static int
162Py_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 %" NPY_INTP_FMT ", 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
182static 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
189static PyMethodDef Py_cvec_methods[] = {
190  {NULL}
191};
192
193static 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
203PyTypeObject 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};
Note: See TracBrowser for help on using the repository browser.