shithub: aubio

Download patch

ref: 569b363d02577c0445fe78385a94fcbedce8ede7
parent: a35db12f8b28c6d538130b88c65987c2b29d4181
author: Paul Brossier <piem@piem.org>
date: Sun Apr 24 14:23:14 EDT 2016

python/ext: simplify memory allocations, removed unneeded malloc/free calls

--- a/python/ext/aubiomodule.c
+++ b/python/ext/aubiomodule.c
@@ -83,7 +83,7 @@
 Py_alpha_norm (PyObject * self, PyObject * args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
   smpl_t alpha;
   PyObject *result;
 
@@ -95,15 +95,12 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
   // compute the function
-  result = Py_BuildValue ("f", fvec_alpha_norm (vec, alpha));
-  free(vec);
+  result = Py_BuildValue ("f", fvec_alpha_norm (&vec, alpha));
   if (result == NULL) {
     return NULL;
   }
@@ -175,7 +172,7 @@
 Py_zero_crossing_rate (PyObject * self, PyObject * args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
   PyObject *result;
 
   if (!PyArg_ParseTuple (args, "O:zero_crossing_rate", &input)) {
@@ -186,15 +183,12 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
   // compute the function
-  result = Py_BuildValue ("f", aubio_zero_crossing_rate (vec));
-  free(vec);
+  result = Py_BuildValue ("f", aubio_zero_crossing_rate (&vec));
   if (result == NULL) {
     return NULL;
   }
@@ -206,7 +200,7 @@
 Py_min_removal(PyObject * self, PyObject * args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
 
   if (!PyArg_ParseTuple (args, "O:min_removal", &input)) {
     return NULL;
@@ -216,19 +210,17 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
   // compute the function
-  fvec_min_removal (vec);
+  fvec_min_removal (&vec);
 
   // since this function does not return, we could return None
   //Py_RETURN_NONE;
   // however it is convenient to return the modified vector
-  return (PyObject *) PyAubio_CFvecToArray(vec);
+  return (PyObject *) PyAubio_CFvecToArray(&vec);
   // or even without converting it back to an array
   //Py_INCREF(vec);
   //return (PyObject *)vec;
--- a/python/ext/aubioproxy.c
+++ b/python/ext/aubioproxy.c
@@ -143,17 +143,15 @@
     return 0;
   }
 
-  if (mat->height != (uint_t)PyArray_DIM ((PyArrayObject *)input, 0)) {
-    /*
-    free(mat->data);
-    mat->height = (uint_t)PyArray_DIM ((PyArrayObject *)input, 0);
-    mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height);
-    */
-    PyErr_Format(PyExc_ValueError, "too many rows, %d but %ld expected",
-                      mat->height, PyArray_DIM ((PyArrayObject *)input, 0) );
-    return 0;
+  uint_t new_height = (uint_t)PyArray_DIM ((PyArrayObject *)input, 0);
+  if (mat->height != new_height) {
+    if (mat->data) {
+      free(mat->data);
+    }
+    mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * new_height);
   }
 
+  mat->height = new_height;
   mat->length = (uint_t)PyArray_DIM ((PyArrayObject *)input, 1);
   for (i=0; i< mat->height; i++) {
     mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)input, i);
--- a/python/ext/py-fft.c
+++ b/python/ext/py-fft.c
@@ -7,11 +7,14 @@
   PyObject_HEAD
   aubio_fft_t * o;
   uint_t win_s;
-  fvec_t *vecin;
+  // do / rdo input vectors
+  fvec_t vecin;
+  cvec_t cvecin;
+  // do / rdo output results
   cvec_t *out;
-  Py_cvec *py_out;
-  cvec_t *cvecin;
   fvec_t *rout;
+  // bridge for cvec output
+  Py_cvec *py_out;
 } Py_fft;
 
 static PyObject *
@@ -56,9 +59,6 @@
     return -1;
   }
 
-  self->cvecin = (cvec_t *)malloc(sizeof(cvec_t));
-  self->vecin = (fvec_t *)malloc(sizeof(fvec_t));
-
   self->out = new_cvec(self->win_s);
   self->py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
   Py_XINCREF(self->py_out);
@@ -74,8 +74,6 @@
   del_aubio_fft(self->o);
   del_cvec(self->out);
   del_fvec(self->rout);
-  free(self->cvecin);
-  free(self->vecin);
   Py_TYPE(self)->tp_free((PyObject *) self);
 }
 
@@ -88,12 +86,12 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCFvec(input, self->vecin)) {
+  if (!PyAubio_ArrayToCFvec(input, &(self->vecin))) {
     return NULL;
   }
 
   // compute the function
-  aubio_fft_do (((Py_fft *)self)->o, self->vecin, self->out);
+  aubio_fft_do (((Py_fft *)self)->o, &(self->vecin), self->out);
 #if 0
   Py_cvec * py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
   PyObject* output = PyAubio_CCvecToPyCvec(self->out, py_out);
@@ -119,12 +117,12 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCCvec (input, self->cvecin) ) {
+  if (!PyAubio_ArrayToCCvec (input, &(self->cvecin)) ) {
     return NULL;
   }
 
   // compute the function
-  aubio_fft_rdo (self->o, self->cvecin, self->rout);
+  aubio_fft_rdo (self->o, &(self->cvecin), self->rout);
   return PyAubio_CFvecToArray(self->rout);
 }
 
--- a/python/ext/py-filter.c
+++ b/python/ext/py-filter.c
@@ -5,7 +5,7 @@
   PyObject_HEAD
   aubio_filter_t * o;
   uint_t order;
-  fvec_t *vec;
+  fvec_t vec;
   fvec_t *out;
 } Py_filter;
 
@@ -50,7 +50,6 @@
     return -1;
   }
   self->out = new_fvec(Py_default_vector_length);
-  self->vec = (fvec_t *)malloc(sizeof(fvec_t));
   return 0;
 }
 
@@ -59,7 +58,6 @@
 {
   del_fvec(self->out);
   del_aubio_filter (self->o);
-  free(self->vec);
   Py_TYPE(self)->tp_free ((PyObject *) self);
 }
 
@@ -76,17 +74,17 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCFvec(input, self->vec)) {
+  if (!PyAubio_ArrayToCFvec(input, &(self->vec))) {
     return NULL;
   }
 
   // reallocate the output if needed
-  if (self->vec->length != self->out->length) {
+  if (self->vec.length != self->out->length) {
     del_fvec(self->out);
-    self->out = new_fvec(self->vec->length);
+    self->out = new_fvec(self->vec.length);
   }
   // compute the function
-  aubio_filter_do_outplace (self->o, self->vec, self->out);
+  aubio_filter_do_outplace (self->o, &(self->vec), self->out);
   return PyAubio_CFvecToArray(self->out);
 }
 
--- a/python/ext/py-filterbank.c
+++ b/python/ext/py-filterbank.c
@@ -8,10 +8,10 @@
   aubio_filterbank_t * o;
   uint_t n_filters;
   uint_t win_s;
-  cvec_t *vec;
+  cvec_t vec;
+  fvec_t freqs;
+  fmat_t coeffs;
   fvec_t *out;
-  fvec_t *freqs;
-  fmat_t *coeffs;
 } Py_filterbank;
 
 static PyObject *
@@ -66,14 +66,6 @@
   }
   self->out = new_fvec(self->n_filters);
 
-  self->vec = (cvec_t *)malloc(sizeof(cvec_t));
-
-  self->freqs = (fvec_t *)malloc(sizeof(fvec_t));
-
-  self->coeffs = (fmat_t *)malloc(sizeof(fmat_t));
-  self->coeffs->data = (smpl_t **)malloc(sizeof(smpl_t*) * self->n_filters);
-  self->coeffs->height = self->n_filters;
-
   return 0;
 }
 
@@ -82,10 +74,7 @@
 {
   del_aubio_filterbank(self->o);
   del_fvec(self->out);
-  free(self->vec);
-  free(self->freqs);
-  free(self->coeffs->data);
-  free(self->coeffs);
+  free(self->coeffs.data);
   Py_TYPE(self)->tp_free((PyObject *) self);
 }
 
@@ -98,12 +87,12 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCCvec(input, self->vec)) {
+  if (!PyAubio_ArrayToCCvec(input, &(self->vec) )) {
     return NULL;
   }
 
   // compute the function
-  aubio_filterbank_do (self->o, self->vec, self->out);
+  aubio_filterbank_do (self->o, &(self->vec), self->out);
   return (PyObject *)PyAubio_CFvecToArray(self->out);
 }
 
@@ -130,12 +119,12 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCFvec(input, self->freqs)) {
+  if (!PyAubio_ArrayToCFvec(input, &(self->freqs) )) {
     return NULL;
   }
 
   err = aubio_filterbank_set_triangle_bands (self->o,
-      self->freqs, samplerate);
+      &(self->freqs), samplerate);
   if (err > 0) {
     PyErr_SetString (PyExc_ValueError,
         "error when setting filter to A-weighting");
@@ -173,11 +162,11 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCFmat(input, self->coeffs)) {
+  if (!PyAubio_ArrayToCFmat(input, &(self->coeffs))) {
     return NULL;
   }
 
-  err = aubio_filterbank_set_coeffs (self->o, self->coeffs);
+  err = aubio_filterbank_set_coeffs (self->o, &(self->coeffs));
 
   if (err > 0) {
     PyErr_SetString (PyExc_ValueError,
--- a/python/ext/py-musicutils.c
+++ b/python/ext/py-musicutils.c
@@ -25,7 +25,7 @@
 Py_aubio_level_lin(PyObject *self, PyObject *args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
   PyObject *level_lin;
 
   if (!PyArg_ParseTuple (args, "O:level_lin", &input)) {
@@ -37,14 +37,11 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
-  level_lin = Py_BuildValue("f", aubio_level_lin(vec));
-  free(vec);
+  level_lin = Py_BuildValue("f", aubio_level_lin(&vec));
   if (level_lin == NULL) {
     PyErr_SetString (PyExc_ValueError, "failed computing level_lin");
     return NULL;
@@ -57,7 +54,7 @@
 Py_aubio_db_spl(PyObject *self, PyObject *args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
   PyObject *db_spl;
 
   if (!PyArg_ParseTuple (args, "O:db_spl", &input)) {
@@ -69,14 +66,11 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
-  db_spl = Py_BuildValue("f", aubio_db_spl(vec));
-  free(vec);
+  db_spl = Py_BuildValue("f", aubio_db_spl(&vec));
   if (db_spl == NULL) {
     PyErr_SetString (PyExc_ValueError, "failed computing db_spl");
     return NULL;
@@ -89,7 +83,7 @@
 Py_aubio_silence_detection(PyObject *self, PyObject *args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
   PyObject *silence_detection;
   smpl_t threshold;
 
@@ -102,14 +96,11 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
-  silence_detection = Py_BuildValue("I", aubio_silence_detection(vec, threshold));
-  free(vec);
+  silence_detection = Py_BuildValue("I", aubio_silence_detection(&vec, threshold));
   if (silence_detection == NULL) {
     PyErr_SetString (PyExc_ValueError, "failed computing silence_detection");
     return NULL;
@@ -122,7 +113,7 @@
 Py_aubio_level_detection(PyObject *self, PyObject *args)
 {
   PyObject *input;
-  fvec_t *vec;
+  fvec_t vec;
   PyObject *level_detection;
   smpl_t threshold;
 
@@ -135,14 +126,11 @@
     return NULL;
   }
 
-  vec = (fvec_t *)malloc(sizeof(fvec_t));
-  if (!PyAubio_ArrayToCFvec(input, vec)) {
-    free(vec);
+  if (!PyAubio_ArrayToCFvec(input, &vec)) {
     return NULL;
   }
 
-  level_detection = Py_BuildValue("f", aubio_level_detection(vec, threshold));
-  free(vec);
+  level_detection = Py_BuildValue("f", aubio_level_detection(&vec, threshold));
   if (level_detection == NULL) {
     PyErr_SetString (PyExc_ValueError, "failed computing level_detection");
     return NULL;
--- a/python/ext/py-phasevoc.c
+++ b/python/ext/py-phasevoc.c
@@ -1,7 +1,5 @@
 #include "aubio-types.h"
 
-static char Py_pvoc_doc[] = "pvoc object";
-
 typedef struct
 {
   PyObject_HEAD
@@ -8,10 +6,10 @@
   aubio_pvoc_t * o;
   uint_t win_s;
   uint_t hop_s;
-  fvec_t *vecin;
+  fvec_t vecin;
   cvec_t *output;
   Py_cvec *py_out;
-  cvec_t *cvecin;
+  cvec_t cvecin;
   fvec_t *routput;
 } Py_pvoc;
 
@@ -71,9 +69,6 @@
     return -1;
   }
 
-  self->cvecin = (cvec_t *)malloc(sizeof(cvec_t));
-  self->vecin = (fvec_t *)malloc(sizeof(fvec_t));
-
   self->output = new_cvec(self->win_s);
   self->py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
   self->routput = new_fvec(self->hop_s);
@@ -88,8 +83,6 @@
   del_aubio_pvoc(self->o);
   del_cvec(self->output);
   del_fvec(self->routput);
-  free(self->cvecin);
-  free(self->vecin);
   Py_TYPE(self)->tp_free((PyObject *) self);
 }
 
@@ -103,12 +96,12 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCFvec (input, self->vecin)) {
+  if (!PyAubio_ArrayToCFvec (input, &(self->vecin) )) {
     return NULL;
   }
 
   // compute the function
-  aubio_pvoc_do (self->o, self->vecin, self->output);
+  aubio_pvoc_do (self->o, &(self->vecin), self->output);
 #if 0
   Py_cvec * py_out = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType);
   PyObject* output = PyAubio_CCvecToPyCvec(self->output, py_out);
@@ -135,12 +128,12 @@
     return NULL;
   }
 
-  if (!PyAubio_ArrayToCCvec (input, self->cvecin)) {
+  if (!PyAubio_ArrayToCCvec (input, &(self->cvecin) )) {
     return NULL;
   }
 
   // compute the function
-  aubio_pvoc_rdo (self->o, self->cvecin, self->routput);
+  aubio_pvoc_rdo (self->o, &(self->cvecin), self->routput);
   return PyAubio_CFvecToArray(self->routput);
 }
 
--- a/python/ext/py-sink.c
+++ b/python/ext/py-sink.c
@@ -7,8 +7,8 @@
   char_t* uri;
   uint_t samplerate;
   uint_t channels;
-  fvec_t *write_data;
-  fmat_t *mwrite_data;
+  fvec_t write_data;
+  fmat_t mwrite_data;
 } Py_sink;
 
 static char Py_sink_doc[] = ""
@@ -123,10 +123,6 @@
   self->samplerate = aubio_sink_get_samplerate ( self->o );
   self->channels = aubio_sink_get_channels ( self->o );
 
-  self->write_data = (fvec_t *)malloc(sizeof(fvec_t));
-  self->mwrite_data = (fmat_t *)malloc(sizeof(fmat_t));
-  self->mwrite_data->height = self->channels;
-  self->mwrite_data->data = (smpl_t **)malloc(sizeof(smpl_t*) * self->channels);
   return 0;
 }
 
@@ -134,9 +130,7 @@
 Py_sink_del (Py_sink *self, PyObject *unused)
 {
   del_aubio_sink(self->o);
-  free(self->write_data);
-  free(self->mwrite_data->data);
-  free(self->mwrite_data);
+  free(self->mwrite_data.data);
   Py_TYPE(self)->tp_free((PyObject *) self);
 }
 
@@ -156,13 +150,13 @@
   }
 
   /* input vectors parsing */
-  if (!PyAubio_ArrayToCFvec(write_data_obj, self->write_data)) {
+  if (!PyAubio_ArrayToCFvec(write_data_obj, &(self->write_data))) {
     return NULL;
   }
 
 
   /* compute _do function */
-  aubio_sink_do (self->o, self->write_data, write);
+  aubio_sink_do (self->o, &(self->write_data), write);
 
   Py_RETURN_NONE;
 }
@@ -184,12 +178,12 @@
 
 
   /* input vectors parsing */
-  if (!PyAubio_ArrayToCFmat(write_data_obj, self->mwrite_data)) {
+  if (!PyAubio_ArrayToCFmat(write_data_obj, &(self->mwrite_data))) {
     return NULL;
   }
 
   /* compute _do function */
-  aubio_sink_do_multi (self->o, self->mwrite_data, write);
+  aubio_sink_do_multi (self->o, &(self->mwrite_data), write);
   Py_RETURN_NONE;
 }
 
--- a/python/lib/gen_code.py
+++ b/python/lib/gen_code.py
@@ -202,7 +202,9 @@
     {output_results};
 }} Py_{shortname};
 """
-        return out.format(do_inputs_list = "; ".join(get_input_params(self.do_proto)), **self.__dict__)
+        # fmat_t* / fvec_t* / cvec_t* inputs -> full fvec_t /.. struct in Py_{shortname}
+        do_inputs_list = "; ".join(get_input_params(self.do_proto)).replace('fvec_t *','fvec_t').replace('fmat_t *', 'fmat_t').replace('cvec_t *', 'cvec_t')
+        return out.format(do_inputs_list = do_inputs_list, **self.__dict__)
 
     def gen_doc(self):
         out = """
@@ -310,9 +312,6 @@
         out += """
   // TODO get internal params after actual object creation?
 """
-        for input_param in self.do_inputs:
-            out += """
-  self->{0} = ({1})malloc(sizeof({2}));""".format(input_param['name'], input_param['type'], input_param['type'][:-1])
         out += """
   // create outputs{output_create}
 """.format(output_create = output_create)
@@ -342,8 +341,9 @@
 Py_{shortname}_del  (Py_{shortname} * self, PyObject * unused)
 {{""".format(**self.__dict__)
         for input_param in self.do_inputs:
-            out += """
-    free(self->{0[name]});""".format(input_param)
+            if input_param['type'] == 'fmat_t *':
+                out += """
+    free(self->{0[name]}.data);""".format(input_param)
         for o in self.outputs:
             name = o['name']
             del_out = delfromtype_fn[o['type']]
@@ -379,11 +379,11 @@
     }}""".format(refs = refs, pyparamtypes = pyparamtypes, **self.__dict__)
         for p in input_params:
             out += """
-    if (!{pytoaubio}(py_{0[name]}, self->{0[name]})) {{
+    if (!{pytoaubio}(py_{0[name]}, &(self->{0[name]}))) {{
         return NULL;
     }}""".format(input_param, pytoaubio = pytoaubio_fn[input_param['type']])
         do_fn = get_name(self.do_proto)
-        inputs = ", ".join(['self->'+p['name'] for p in input_params])
+        inputs = ", ".join(['&(self->'+p['name']+')' for p in input_params])
         outputs = ", ".join(["self->%s" % p['name'] for p in self.do_outputs])
         out += """