Changeset 92a8800


Ignore:
Timestamp:
Apr 28, 2016, 6:59:55 PM (4 years ago)
Author:
Paul Brossier <piem@piem.org>
Branches:
feature/autosink, feature/constantq, feature/pitchshift, feature/pydocstrings, feature/timestretch, master, pitchshift, sampler, timestretch, yinfft+
Children:
6937842
Parents:
1f4d932
Message:

python/ext/py-cvec.c: rewrite and simplify aubio.cvec, safer and better memory usage (see #49)

Location:
python
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • python/ext/aubio-types.h

    r1f4d932 r92a8800  
    5151#endif
    5252
    53 // special python type for cvec
    54 typedef struct
    55 {
    56   PyObject_HEAD
    57   cvec_t * o;
    58   uint_t length;
    59 } Py_cvec;
    6053extern PyTypeObject Py_cvecType;
    6154
     
    6457extern int PyAubio_ArrayToCFvec (PyObject * self, fvec_t *out);
    6558
    66 extern PyObject * PyAubio_CCvecToPyCvec (cvec_t * self, Py_cvec *out);
    67 extern int PyAubio_ArrayToCCvec (PyObject *input, cvec_t *i);
     59extern PyObject * PyAubio_CCvecToPyCvec (cvec_t * self);
     60extern int PyAubio_PyCvecToCCvec (PyObject *input, cvec_t *i);
    6861
    6962extern PyObject *PyAubio_CFmatToArray (fmat_t * self);
  • python/ext/aubioproxy.c

    r1f4d932 r92a8800  
    5454  out->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)input, 0);
    5555  return 1;
    56 }
    57 
    58 PyObject *
    59 PyAubio_CCvecToPyCvec (cvec_t * input, Py_cvec *vec) {
    60   vec->length = input->length;
    61   vec->o = input;
    62   // keep a reference to re-use after returning it
    63   Py_INCREF(vec);
    64   return (PyObject *)vec;
    65 }
    66 
    67 int
    68 PyAubio_ArrayToCCvec (PyObject *input, cvec_t *i) {
    69   if (PyObject_TypeCheck (input, &Py_cvecType)) {
    70       //*i = *(((Py_cvec*)input)->o);
    71       i->norm = ((Py_cvec*)input)->o->norm;
    72       i->phas = ((Py_cvec*)input)->o->phas;
    73       i->length = ((Py_cvec*)input)->o->length;
    74       return 1;
    75   } else {
    76       PyErr_SetString (PyExc_ValueError, "input array should be aubio.cvec");
    77       return 0;
    78   }
    7956}
    8057
  • python/ext/py-cvec.c

    r1f4d932 r92a8800  
    11#include "aubio-types.h"
    22
    3 /* cvec type definition 
     3/* cvec type definition
    44
    55class cvec():
    6     def __init__(self, length = 1024):
    7         self.length = length
    8         self.norm = array(length)
    9         self.phas = array(length)
     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)
    1010
    1111*/
    1212
     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
    1322static char Py_cvec_doc[] = "cvec object";
     23
     24PyObject *
     25PyAubio_CCvecToPyCvec (cvec_t * input) {
     26  if (input == NULL) {
     27      PyErr_SetString (PyExc_ValueError, "PyAubio_CCvecToPyCvec got a null cvec!");
     28      return NULL;
     29  }
     30  Py_cvec* vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
     31  npy_intp dims[] = { input->length, 1 };
     32  vec->norm = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->norm);
     33  vec->phas = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->phas);
     34  vec->length = input->length;
     35  return (PyObject *)vec;
     36}
     37
     38int
     39PyAubio_PyCvecToCCvec (PyObject *input, cvec_t *i) {
     40  if (PyObject_TypeCheck (input, &Py_cvecType)) {
     41      Py_cvec * in = (Py_cvec *)input;
     42      if (in->norm == NULL) {
     43        npy_intp dims[] = { in->length, 1 };
     44        in->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
     45      }
     46      if (in->phas == NULL) {
     47        npy_intp dims[] = { in->length, 1 };
     48        in->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
     49      }
     50      i->norm = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->norm), 0);
     51      i->phas = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)(in->phas), 0);
     52      i->length = ((Py_cvec*)input)->length;
     53      return 1;
     54  } else {
     55      PyErr_SetString (PyExc_ValueError, "input array should be aubio.cvec");
     56      return 0;
     57  }
     58}
    1459
    1560static PyObject *
     
    2469    return NULL;
    2570  }
    26 
    2771
    2872  self = (Py_cvec *) type->tp_alloc (type, 0);
     
    4892Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds)
    4993{
    50   self->o = new_cvec ((self->length - 1) * 2);
    51   if (self->o == NULL) {
    52     return -1;
    53   }
    54 
     94  self->norm = NULL;
     95  self->phas = NULL;
    5596  return 0;
    5697}
     
    59100Py_cvec_del (Py_cvec * self)
    60101{
    61   del_cvec (self->o);
     102  Py_XDECREF(self->norm);
     103  Py_XDECREF(self->phas);
    62104  Py_TYPE(self)->tp_free ((PyObject *) self);
    63105}
     
    79121    goto fail;
    80122  }
    81   cvec_print ( self->o );
     123  // hide actual norm / phas content
    82124
    83125  result = PyUnicode_Format (format, args);
     
    91133
    92134PyObject *
    93 PyAubio_CvecNormToArray (Py_cvec * self)
    94 {
    95   npy_intp dims[] = { self->o->length, 1 };
    96   return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->norm);
    97 }
    98 
    99 
    100 PyObject *
    101 PyAubio_CvecPhasToArray (Py_cvec * self)
    102 {
    103   npy_intp dims[] = { self->o->length, 1 };
    104   return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->o->phas);
    105 }
    106 
    107 PyObject *
    108 PyAubio_ArrayToCvecPhas (PyObject * self)
    109 {
    110   return NULL;
    111 }
    112 
    113 PyObject *
    114135Py_cvec_get_norm (Py_cvec * self, void *closure)
    115136{
    116   return PyAubio_CvecNormToArray(self);
     137  // if it norm hasn't been created, create it now
     138  if (self->norm == NULL) {
     139    npy_intp dims[] = { self->length, 1 };
     140    self->norm = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
     141  }
     142  Py_INCREF(self->norm);
     143  return (PyObject*)(self->norm);
    117144}
    118145
     
    120147Py_cvec_get_phas (Py_cvec * self, void *closure)
    121148{
    122   return PyAubio_CvecPhasToArray(self);
     149  // if it phas hasn't been created, create it now
     150  if (self->phas == NULL) {
     151    npy_intp dims[] = { self->length, 1 };
     152    self->phas = PyArray_ZEROS(1, dims, AUBIO_NPY_SMPL, 0);
     153  }
     154  Py_INCREF(self->phas);
     155  return (PyObject *)(self->phas);
    123156}
    124157
     
    132165  }
    133166  if (PyArray_Check(input)) {
    134 
    135     // we got an array, convert it to a cvec.norm
     167    // we got an array, convert it to a cvec.norm
    136168    if (PyArray_NDIM ((PyArrayObject *)input) == 0) {
    137169      PyErr_SetString (PyExc_ValueError, "input array is a scalar");
     
    159191      goto fail;
    160192    } else {
    161       if (vec->o->length != PyArray_SIZE (array)) {
     193      if (vec->length != PyArray_SIZE (array)) {
    162194          PyErr_Format (PyExc_ValueError,
    163195                  "input array has length %d, but cvec has length %d",
    164                   (int)PyArray_SIZE (array), vec->o->length);
     196                  (int)PyArray_SIZE (array), vec->length);
    165197          goto fail;
    166198      }
    167199    }
    168200
    169     vec->o->norm = (smpl_t *) PyArray_GETPTR1 (array, 0);
     201    Py_XDECREF(vec->norm);
     202    vec->norm = input;
     203    Py_INCREF(vec->norm);
    170204
    171205  } else {
     
    174208  }
    175209
    176   Py_INCREF(array);
    177210  return 0;
    178211
     
    217250      goto fail;
    218251    } else {
    219       if (vec->o->length != PyArray_SIZE (array)) {
     252      if (vec->length != PyArray_SIZE (array)) {
    220253          PyErr_Format (PyExc_ValueError,
    221254                  "input array has length %d, but cvec has length %d",
    222                   (int)PyArray_SIZE (array), vec->o->length);
     255                  (int)PyArray_SIZE (array), vec->length);
    223256          goto fail;
    224257      }
    225258    }
    226259
    227     vec->o->phas = (smpl_t *) PyArray_GETPTR1 (array, 0);
     260    Py_XDECREF(vec->phas);
     261    vec->phas = input;
     262    Py_INCREF(vec->phas);
    228263
    229264  } else {
     
    232267  }
    233268
    234   Py_INCREF(array);
    235269  return 0;
    236270
  • python/ext/py-fft.c

    r1f4d932 r92a8800  
    1414  cvec_t *out;
    1515  fvec_t *rout;
    16   // bridge for cvec output
    17   Py_cvec *py_out;
    1816} Py_fft;
    1917
     
    6159
    6260  self->out = new_cvec(self->win_s);
    63   self->py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
    64   Py_XINCREF(self->py_out);
    6561  self->rout = new_fvec(self->win_s);
    6662
     
    7167Py_fft_del (Py_fft *self, PyObject *unused)
    7268{
    73   Py_XDECREF((PyObject*)(self->py_out));
    7469  del_aubio_fft(self->o);
    7570  del_cvec(self->out);
     
    9388  // compute the function
    9489  aubio_fft_do (((Py_fft *)self)->o, &(self->vecin), self->out);
    95 #if 0
    96   Py_cvec * py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
    97   PyObject* output = PyAubio_CCvecToPyCvec(self->out, py_out);
    98   return output;
    99 #else
    100   // convert cvec to py_cvec, incrementing refcount to keep a copy
    101   return PyAubio_CCvecToPyCvec(self->out, self->py_out);
    102 #endif
     90  // convert cvec to py_cvec
     91  return PyAubio_CCvecToPyCvec(self->out);
    10392}
    10493
     
    118107  }
    119108
    120   if (!PyAubio_ArrayToCCvec (input, &(self->cvecin)) ) {
     109  if (!PyAubio_PyCvecToCCvec (input, &(self->cvecin)) ) {
    121110    return NULL;
    122111  }
  • python/ext/py-filterbank.c

    r1f4d932 r92a8800  
    8888  }
    8989
    90   if (!PyAubio_ArrayToCCvec(input, &(self->vec) )) {
     90  if (!PyAubio_PyCvecToCCvec(input, &(self->vec) )) {
    9191    return NULL;
    9292  }
  • python/ext/py-phasevoc.c

    r1f4d932 r92a8800  
    1111  fvec_t vecin;
    1212  cvec_t *output;
    13   Py_cvec *py_out;
    1413  cvec_t cvecin;
    1514  fvec_t *routput;
     
    7372
    7473  self->output = new_cvec(self->win_s);
    75   self->py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
    7674  self->routput = new_fvec(self->hop_s);
    7775
     
    105103  // compute the function
    106104  aubio_pvoc_do (self->o, &(self->vecin), self->output);
    107 #if 0
    108   Py_cvec * py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
    109   PyObject* output = PyAubio_CCvecToPyCvec(self->output, py_out);
    110   return output;
    111 #else
    112   // convert cvec to py_cvec, incrementing refcount to keep a copy
    113   return PyAubio_CCvecToPyCvec(self->output, self->py_out);
    114 #endif
     105  // convert cvec to py_cvec
     106  return PyAubio_CCvecToPyCvec(self->output);
    115107}
    116108
     
    131123  }
    132124
    133   if (!PyAubio_ArrayToCCvec (input, &(self->cvecin) )) {
     125  if (!PyAubio_PyCvecToCCvec (input, &(self->cvecin) )) {
    134126    return NULL;
    135127  }
  • python/lib/gen_code.py

    r1f4d932 r92a8800  
    3838pytoaubio_fn = {
    3939        'fvec_t*': 'PyAubio_ArrayToCFvec',
    40         'cvec_t*': 'PyAubio_ArrayToCCvec',
     40        'cvec_t*': 'PyAubio_PyCvecToCCvec',
    4141        #'fmat_t*': 'PyAubio_ArrayToCFmat',
    4242        }
Note: See TracChangeset for help on using the changeset viewer.