shithub: aubio

Download patch

ref: ccb9fb565a315f676cd028cde7fa2da4ac26879f
parent: fbd7c80e36a2b490316585eeb07e5e467056903d
author: Paul Brossier <piem@piem.org>
date: Mon Apr 18 21:36:13 EDT 2016

lib/gen_external.py: rewrote wrapper

--- /dev/null
+++ b/python/lib/gen_code.py
@@ -1,0 +1,487 @@
+aubiodefvalue = {
+    # we have some clean up to do
+    'buf_size': 'Py_default_vector_length',
+    'win_s': 'Py_default_vector_length',
+    # and here too
+    'hop_size': 'Py_default_vector_length / 2',
+    'hop_s': 'Py_default_vector_length / 2',
+    # these should be alright
+    'samplerate': 'Py_aubio_default_samplerate',
+    # now for the non obvious ones
+    'n_filters': '40',
+    'n_coeffs': '13',
+    'nelems': '10',
+    'flow': '0.',
+    'fhig': '1.',
+    'ilow': '0.',
+    'ihig': '1.',
+    'thrs': '0.5',
+    'ratio': '0.5',
+    'method': '"default"',
+    'uri': '"none"',
+    }
+
+member_types = {
+        'name': 'type',
+        'char_t*': 'T_STRING',
+        'uint_t': 'T_INT',
+        'smpl_t': 'T_FLOAT',
+        }
+
+pyfromtype_fn = {
+        'smpl_t': 'PyFloat_FromDouble',
+        'uint_t': 'PyLong_FromLong', # was: 'PyInt_FromLong',
+        'fvec_t*': 'PyAubio_CFvecToArray',
+        'fmat_t*': 'PyAubio_CFmatToArray',
+        }
+
+pytoaubio_fn = {
+        'fvec_t*': 'PyAubio_ArrayToCFvec',
+        'cvec_t*': 'PyAubio_ArrayToCCvec',
+        'fmat_t*': 'PyAubio_ArrayToCFmat',
+        }
+
+pyfromaubio_fn = {
+        'fvec_t*': 'PyAubio_CFvecToArray',
+        'cvec_t*': 'PyAubio_CCvecToArray',
+        'fmat_t*': 'PyAubio_CFmatToArray',
+        }
+
+newfromtype_fn = {
+        'fvec_t*': 'new_fvec',
+        'fmat_t*': 'new_fmat',
+        'cvec_t*': 'new_cvec',
+        }
+
+delfromtype_fn = {
+        'fvec_t*': 'del_fvec',
+        'fmat_t*': 'del_fmat',
+        'cvec_t*': 'del_cvec',
+        }
+
+param_init = {
+        'char_t*': 'NULL',
+        'uint_t': '0',
+        'sint_t': 0,
+        'smpl_t': 0.,
+        'lsmp_t': 0.,
+        }
+
+pyargparse_chars = {
+        'smpl_t': 'f',
+        'uint_t': 'I',
+        'sint_t': 'I',
+        'char_t*': 's',
+        'fmat_t*': 'O',
+        'fvec_t*': 'O',
+        }
+
+objoutsize = {
+        'onset': '1',
+        'pitch': '1',
+        'wavetable': 'self->hop_size',
+        'sampler': 'self->hop_size',
+        'mfcc': 'self->n_coeffs',
+        'specdesc': '1',
+        'tempo': '1',
+        'filterbank': 'self->n_filters',
+        }
+
+def get_name(proto):
+    name = proto.replace(' *', '* ').split()[1].split('(')[0]
+    name = name.replace('*','')
+    if name == '': raise ValueError(proto + "gave empty name")
+    return name
+
+def get_return_type(proto):
+    import re
+    paramregex = re.compile('(\w+ ?\*?).*')
+    outputs = paramregex.findall(proto)
+    assert len(outputs) == 1
+    return outputs[0].replace(' ', '')
+
+def split_type(arg):
+    """ arg = 'foo *name' 
+        return ['foo*', 'name'] """
+    l = arg.split()
+    type_arg = {'type': l[0], 'name': l[1]}
+    # ['foo', '*name'] -> ['foo*', 'name']
+    if l[-1].startswith('*'):
+        #return [l[0]+'*', l[1][1:]]
+        type_arg['type'] = l[0] + '*'
+        type_arg['name'] = l[1][1:]
+    # ['foo', '*', 'name'] -> ['foo*', 'name']
+    if len(l) == 3:
+        #return [l[0]+l[1], l[2]]
+        type_arg['type'] = l[0]+l[1]
+        type_arg['name'] = l[2]
+    else:
+        #return l
+        pass
+    return type_arg
+
+def get_params(proto):
+    """ get the list of parameters from a function prototype
+    example: proto = "int main (int argc, char ** argv)"
+    returns: ['int argc', 'char ** argv']
+    """
+    import re
+    paramregex = re.compile('[\(, ](\w+ \*?\*? ?\w+)[, \)]')
+    return paramregex.findall(proto)
+
+def get_params_types_names(proto):
+    """ get the list of parameters from a function prototype
+    example: proto = "int main (int argc, char ** argv)"
+    returns: [['int', 'argc'], ['char **','argv']]
+    """
+    return list(map(split_type, get_params(proto)))
+
+
+class MappedObject(object):
+
+    def __init__(self, prototypes):
+        self.prototypes = prototypes
+
+        self.shortname = prototypes['shortname']
+        self.longname = prototypes['longname']
+        self.new_proto = prototypes['new'][0]
+        self.del_proto = prototypes['del'][0]
+        self.do_proto = prototypes['do'][0]
+        self.input_params = get_params_types_names(self.new_proto)
+        self.input_params_list = "; ".join(get_params(self.new_proto))
+        self.outputs = get_params_types_names(self.do_proto)[2:]
+        self.outputs_flat = get_params(self.do_proto)[2:]
+        self.output_results = ", ".join(self.outputs_flat)
+
+    def gen_code(self):
+        out = ""
+        out += self.gen_struct()
+        out += self.gen_doc()
+        out += self.gen_new()
+        out += self.gen_init()
+        out += self.gen_del()
+        out += self.gen_do()
+        out += self.gen_memberdef()
+        out += self.gen_set()
+        out += self.gen_get()
+        out += self.gen_methodef()
+        out += self.gen_typeobject()
+        return out
+
+    def gen_struct(self):
+        out = """
+// {shortname} structure
+typedef struct{{
+    PyObject_HEAD
+    // pointer to aubio object
+    {longname} *o;
+    // input parameters
+    {input_params_list};
+    // output results
+    {output_results};
+}} Py_{shortname};
+"""
+        return out.format(**self.__dict__)
+
+    def gen_doc(self):
+        out = """
+// TODO: add documentation
+static char Py_{shortname}_doc[] = \"undefined\";
+    """
+        return out.format(**self.__dict__)
+
+    def gen_new(self):
+        out = """
+// new {shortname}
+static PyObject *
+Py_{shortname}_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
+{{
+    Py_{shortname} *self;
+""".format(**self.__dict__)
+        params = self.input_params
+        for p in params:
+            out += """
+    {type} {name} = {defval};""".format(defval = param_init[p['type']], **p)
+        plist = ", ".join(["\"%s\"" % p['name'] for p in params])
+        out += """
+    static char *kwlist[] = {{ {plist}, NULL }};""".format(plist = plist)
+        argchars = "".join([pyargparse_chars[p['type']] for p in params])
+        arglist = ", ".join(["&%s" % p['name'] for p in params])
+        out += """
+    if (!PyArg_ParseTupleAndKeywords (args, kwds, "|{argchars}", kwlist,
+              {arglist})) {{
+        return NULL;
+    }}
+""".format(argchars = argchars, arglist = arglist)
+        out += """
+    self = (Py_{shortname} *) pytype->tp_alloc (pytype, 0);
+    if (self == NULL) {{
+        return NULL;
+    }}
+""".format(**self.__dict__)
+        params = self.input_params
+        for p in params:
+            out += self.check_valid(p) 
+        out += """
+    return (PyObject *)self;
+}
+"""
+        return out
+
+    def check_valid(self, p):
+        if p['type'] == 'uint_t':
+            return self.check_valid_uint(p)
+        if p['type'] == 'char_t*':
+            return self.check_valid_char(p)
+        else:
+            print ("ERROR, no idea how to check %s for validity" % p['type'])
+
+    def check_valid_uint(self, p):
+        name = p['name']
+        return """
+    self->{name} = {defval};
+    if ((sint_t){name} > 0) {{
+        self->{name} = {name};
+    }} else if ((sint_t){name} < 0) {{
+        PyErr_SetString (PyExc_ValueError, "can not use negative value for {name}");
+        return NULL;
+    }}
+""".format(defval = aubiodefvalue[name], name = name)
+
+    def check_valid_char(self, p):
+        name = p['name']
+        return """
+    self->{name} = {defval};
+    if ({name} != NULL) {{
+        self->{name} = {name};
+    }}
+""".format(defval = aubiodefvalue[name], name = name)
+
+    def gen_init(self):
+        out = """
+// init {shortname}
+static int
+Py_{shortname}_init (Py_{shortname} * self, PyObject * args, PyObject * kwds)
+{{
+""".format(**self.__dict__)
+        new_name = get_name(self.new_proto)
+        new_params = ", ".join(["self->%s" % s['name'] for s in self.input_params])
+        out += """
+  self->o = {new_name}({new_params});
+""".format(new_name = new_name, new_params = new_params)
+        paramchars = "%s"
+        paramvals = "self->method"
+        out += """
+  // return -1 and set error string on failure
+  if (self->o == NULL) {{
+    //char_t errstr[30 + strlen(self->uri)];
+    //sprintf(errstr, "error creating {shortname} with params {paramchars}", {paramvals});
+    char_t errstr[60];
+    sprintf(errstr, "error creating {shortname} with given params");
+    PyErr_SetString (PyExc_Exception, errstr);
+    return -1;
+  }}
+""".format(paramchars = paramchars, paramvals = paramvals, **self.__dict__)
+        output_create = ""
+        for o in self.outputs:
+            output_create += """
+  self->{name} = {create_fn}({output_size});""".format(name = o['name'], create_fn = newfromtype_fn[o['type']], output_size = objoutsize[self.shortname])
+        out += """
+  // TODO get internal params after actual object creation?
+"""
+        out += """
+  // create outputs{output_create}
+""".format(output_create = output_create)
+        out += """
+  return 0;
+}
+"""
+        return out
+
+    def gen_memberdef(self):
+        out = """
+static PyMemberDef Py_{shortname}_members[] = {{
+""".format(**self.__dict__)
+        for p in get_params_types_names(self.new_proto):
+            tmp = "  {{\"{name}\", {ttype}, offsetof (Py_{shortname}, {name}), READONLY, \"TODO documentation\"}},\n"
+            pytype = member_types[p['type']]
+            out += tmp.format(name = p['name'], ttype = pytype, shortname = self.shortname)
+        out += """  {NULL}, // sentinel
+};
+"""
+        return out
+
+    def gen_del(self):
+        out = """
+// del {shortname}
+static void
+Py_{shortname}_del  (Py_{shortname} * self, PyObject * unused)
+{{""".format(**self.__dict__)
+        for o in self.outputs:
+            name = o['name']
+            del_out = delfromtype_fn[o['type']]
+            out += """
+    {del_out}(self->{name});""".format(del_out = del_out, name = name)
+        del_fn = get_name(self.del_proto)
+        out += """
+    {del_fn}(self->o);
+    Py_TYPE(self)->tp_free((PyObject *) self);
+}}
+""".format(del_fn = del_fn)
+        return out
+
+    def gen_do(self):
+        do_fn = get_name(self.do_proto)
+        input_param = get_params_types_names(self.do_proto)[1];
+        pytoaubio = pytoaubio_fn[input_param['type']]
+        output = self.outputs[0]
+        out = """
+// do {shortname}
+static PyObject*
+Py_{shortname}_do  (Py_{shortname} * self, PyObject * args)
+{{
+    PyObject * in_obj;
+    {input_type} {input_name};
+
+    if (!PyArg_ParseTuple (args, "O", &in_obj)) {{
+        return NULL;
+    }}
+    {input_name} = {pytoaubio} (in_obj); 
+    if ({input_name} == NULL) {{
+        return NULL;
+    }}
+
+    {do_fn}(self->o, {input_name}, {outputs});
+
+    return (PyObject *) {aubiotonumpy} ({outputs});
+}}
+"""
+        return out.format(do_fn = do_fn,
+                shortname = self.prototypes['shortname'],
+                input_name = input_param['name'],
+                input_type= input_param['type'],
+                pytoaubio = pytoaubio,
+                outputs = ", ".join(["self->%s" % p['name'] for p in self.outputs]),
+                aubiotonumpy = pyfromaubio_fn[output['type']], 
+                )
+
+    def gen_set(self):
+        out = """
+// {shortname} setters
+""".format(**self.__dict__)
+        for set_param in self.prototypes['set']:
+            params = get_params_types_names(set_param)[1]
+            paramtype = params['type']
+            method_name = get_name(set_param)
+            param = method_name.split('aubio_'+self.shortname+'_set_')[-1]
+            pyparamtype = pyargparse_chars[paramtype]
+            out += """
+static PyObject *
+Pyaubio_{shortname}_set_{param} (Py_{shortname} *self, PyObject *args)
+{{
+  uint_t err = 0;
+  {paramtype} {param};
+
+  if (!PyArg_ParseTuple (args, "{pyparamtype}", &{param})) {{
+    return NULL;
+  }}
+  err = aubio_{shortname}_set_{param} (self->o, {param});
+
+  if (err > 0) {{
+    PyErr_SetString (PyExc_ValueError, "error running aubio_{shortname}_set_{param}");
+    return NULL;
+  }}
+  Py_RETURN_NONE;
+}}
+""".format(param = param, paramtype = paramtype, pyparamtype = pyparamtype, **self.__dict__)
+        return out
+
+    def gen_get(self):
+        out = """
+// {shortname} getters
+""".format(**self.__dict__)
+        for method in self.prototypes['get']:
+            params = get_params_types_names(method)
+            method_name = get_name(method)
+            assert len(params) == 1, \
+                "get method has more than one parameter %s" % params
+            param = method_name.split('aubio_'+self.shortname+'_get_')[-1]
+            paramtype = get_return_type(method)
+            ptypeconv = pyfromtype_fn[paramtype]
+            out += """
+static PyObject *
+Pyaubio_{shortname}_get_{param} (Py_{shortname} *self, PyObject *unused)
+{{
+  {ptype} {param} = aubio_{shortname}_get_{param} (self->o);
+  return (PyObject *){ptypeconv} ({param});
+}}
+""".format(param = param, ptype = paramtype, ptypeconv = ptypeconv,
+        **self.__dict__)
+        return out
+
+    def gen_methodef(self):
+        out = """
+static PyMethodDef Py_{shortname}_methods[] = {{""".format(**self.__dict__)
+        for m in self.prototypes['set']:
+            name = get_name(m)
+            shortname = name.replace('aubio_%s_' % self.shortname, '')
+            out += """
+  {{"{shortname}", (PyCFunction) Py{name},
+    METH_VARARGS, ""}},""".format(name = name, shortname = shortname)
+        for m in self.prototypes['get']:
+            name = get_name(m)
+            shortname = name.replace('aubio_%s_' % self.shortname, '')
+            out += """
+  {{"{shortname}", (PyCFunction) Py{name},
+    METH_NOARGS, ""}},""".format(name = name, shortname = shortname)
+        out += """
+  {NULL} /* sentinel */
+};
+"""
+        return out
+
+    def gen_typeobject(self):
+        return """
+PyTypeObject Py_{shortname}Type = {{
+  //PyObject_HEAD_INIT (NULL)
+  //0,
+  PyVarObject_HEAD_INIT (NULL, 0)
+  "aubio.{shortname}",
+  sizeof (Py_{shortname}),
+  0,
+  (destructor) Py_{shortname}_del,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  (ternaryfunc)Py_{shortname}_do,
+  0,
+  0,
+  0,
+  0,
+  Py_TPFLAGS_DEFAULT,
+  Py_{shortname}_doc,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  Py_{shortname}_methods,
+  Py_{shortname}_members,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  (initproc) Py_{shortname}_init,
+  0,
+  Py_{shortname}_new,
+}};
+""".format(**self.__dict__)
--- /dev/null
+++ b/python/lib/gen_external.py
@@ -1,0 +1,182 @@
+import os
+
+header = """// this file is generated! do not modify
+#include "aubio-types.h"
+"""
+
+skip_objects = [
+  # already in ext/
+  'fft',
+  'pvoc',
+  'filter',
+  'filterbank',
+  #'resampler',
+  # AUBIO_UNSTABLE
+  'hist',
+  'parameter',
+  'scale',
+  'beattracking',
+  'resampler',
+  'peakpicker',
+  'pitchfcomb',
+  'pitchmcomb',
+  'pitchschmitt',
+  'pitchspecacf',
+  'pitchyin',
+  'pitchyinfft',
+  'sink',
+  'sink_apple_audio',
+  'sink_sndfile',
+  'sink_wavwrite',
+  #'mfcc',
+  'source',
+  'source_apple_audio',
+  'source_sndfile',
+  'source_avcodec',
+  'source_wavread',
+  #'sampler',
+  'audio_unit',
+
+  'tss',
+  ]
+
+
+def get_cpp_objects():
+
+    cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=1 -I../build/src ../src/aubio.h').readlines()]
+    #cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=0 -I../build/src ../src/onset/onset.h').readlines()]
+    #cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=0 -I../build/src ../src/pitch/pitch.h').readlines()]
+
+    cpp_output = filter(lambda y: len(y) > 1, cpp_output)
+    cpp_output = filter(lambda y: not y.startswith('#'), cpp_output)
+    cpp_output = list(cpp_output)
+
+    i = 1
+    while 1:
+        if i >= len(cpp_output): break
+        if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
+            cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
+            cpp_output.pop(i-1)
+        else:
+            i += 1
+
+    typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
+
+    cpp_objects = [a.split()[3][:-1] for a in typedefs]
+
+    return cpp_output, cpp_objects
+
+def generate_external(output_path):
+    os.mkdir(output_path)
+    sources_list = []
+    cpp_output, cpp_objects = get_cpp_objects()
+    lib = {}
+
+    for o in cpp_objects:
+        if o[:6] != 'aubio_':
+            continue
+        shortname = o[6:-2]
+        if shortname in skip_objects:
+            continue
+        lib[shortname] = {'struct': [], 'new': [], 'del': [], 'do': [], 'get': [], 'set': [], 'other': []}
+        lib[shortname]['longname'] = o
+        lib[shortname]['shortname'] = shortname
+        for fn in cpp_output:
+            if o[:-1] in fn:
+                #print "found", o[:-1], "in", fn
+                if 'typedef struct ' in fn:
+                    lib[shortname]['struct'].append(fn)
+                elif '_do' in fn:
+                    lib[shortname]['do'].append(fn)
+                elif 'new_' in fn:
+                    lib[shortname]['new'].append(fn)
+                elif 'del_' in fn:
+                    lib[shortname]['del'].append(fn)
+                elif '_get_' in fn:
+                    lib[shortname]['get'].append(fn)
+                elif '_set_' in fn:
+                    lib[shortname]['set'].append(fn)
+                else:
+                    #print "no idea what to do about", fn
+                    lib[shortname]['other'].append(fn)
+
+    """
+    for fn in cpp_output:
+        found = 0
+        for o in lib:
+            for family in lib[o]:
+                if fn in lib[o][family]:
+                    found = 1
+        if found == 0:
+            print "missing", fn
+
+    for o in lib:
+        for family in lib[o]:
+            if type(lib[o][family]) == str:
+                print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family] ) )
+            elif len(lib[o][family]) == 1:
+                print ( "{:15s} {:10s} {:s}".format(o, family, lib[o][family][0] ) )
+            else:                                             
+                print ( "{:15s} {:10s} {:d}".format(o, family, len(lib[o][family]) ) )
+    """
+
+    from .gen_code import MappedObject
+    for o in lib:
+        out = header
+        mapped = MappedObject(lib[o])
+        out += mapped.gen_code()
+        output_file = os.path.join(output_path, 'gen-%s.c' % o)
+        with open(output_file, 'w') as f:
+            f.write(out)
+            print ("wrote %s" % output_file )
+            sources_list.append(output_file)
+
+    out = header
+    out += "#include \"aubio-generated.h\""
+    check_types = "\n     ||  ".join(["PyType_Ready(&Py_%sType) < 0" % o for o in lib])
+    out += """
+
+int generated_types_ready (void)
+{{
+  return ({pycheck_types});
+}}
+""".format(pycheck_types = check_types)
+
+    add_types = "".join(["""
+  Py_INCREF (&Py_{name}Type);
+  PyModule_AddObject(m, "{name}", (PyObject *) & Py_{name}Type);""".format(name = o) for o in lib])
+    out += """
+
+void add_generated_objects ( PyObject *m )
+{{
+{add_types}
+}}
+""".format(add_types = add_types)
+
+    output_file = os.path.join(output_path, 'aubio-generated.c')
+    with open(output_file, 'w') as f:
+        f.write(out)
+        print ("wrote %s" % output_file )
+        sources_list.append(output_file)
+    
+    objlist = "".join(["extern PyTypeObject Py_%sType;\n" % p for p in lib])
+    out = """
+// generated list of objects created with gen_external.py
+#include <Python.h>
+
+{objlist}
+int generated_objects ( void );
+void add_generated_objects( PyObject *m );
+""".format(objlist = objlist)
+
+    output_file = os.path.join(output_path, 'aubio-generated.h')
+    with open(output_file, 'w') as f:
+        f.write(out)
+        print ("wrote %s" % output_file )
+        # no need to add header to list of sources
+
+    return sources_list
+
+if __name__ == '__main__':
+    output_path = 'gen'
+    generate_external(output_path)
--- a/python/lib/gen_pyobject.py
+++ /dev/null
@@ -1,531 +1,0 @@
-#! /usr/bin/python
-
-""" This madness of code is used to generate the C code of the python interface
-to aubio. Don't try this at home.
-
-The list of typedefs and functions is obtained from the command line 'cpp
-aubio.h'. This list is then used to parse all the functions about this object.
-
-I hear the ones asking "why not use swig, or cython, or something like that?"
-
-The requirements for this extension are the following:
-
-    - aubio vectors can be viewed as numpy arrays, and vice versa
-    - aubio 'object' should be python classes, not just a bunch of functions
-
-I haven't met any python interface generator that can meet both these
-requirements. If you know of one, please let me know, it will spare me
-maintaining this bizarre file.
-"""
-
-param_numbers = {
-  'source': [0, 2],
-  'sink':   [2, 0],
-  'sampler': [1, 1],
-}
-
-# TODO
-# do function: for now, only the following pattern is supported:
-# void aubio_<foo>_do (aubio_foo_t * o, 
-#       [input1_t * input, [output1_t * output, ..., output3_t * output]]);
-# There is no way of knowing that output1 is actually input2. In the future,
-# const could be used for the inputs in the C prototypes.
-
-def write_msg(*args):
-  pass
-  # uncomment out for debugging
-  #print args
-
-def split_type(arg):
-    """ arg = 'foo *name' 
-        return ['foo*', 'name'] """
-    l = arg.split()
-    type_arg = {'type': l[0], 'name': l[1]}
-    # ['foo', '*name'] -> ['foo*', 'name']
-    if l[-1].startswith('*'):
-        #return [l[0]+'*', l[1][1:]]
-        type_arg['type'] = l[0] + '*'
-        type_arg['name'] = l[1][1:]
-    # ['foo', '*', 'name'] -> ['foo*', 'name']
-    if len(l) == 3:
-        #return [l[0]+l[1], l[2]]
-        type_arg['type'] = l[0]+l[1]
-        type_arg['name'] = l[2]
-    else:
-        #return l
-        pass
-    return type_arg
-
-def get_params(proto):
-    """ get the list of parameters from a function prototype
-    example: proto = "int main (int argc, char ** argv)"
-    returns: ['int argc', 'char ** argv']
-    """
-    import re
-    paramregex = re.compile('[\(, ](\w+ \*?\*? ?\w+)[, \)]')
-    return paramregex.findall(proto)
-
-def get_params_types_names(proto):
-    """ get the list of parameters from a function prototype
-    example: proto = "int main (int argc, char ** argv)"
-    returns: [['int', 'argc'], ['char **','argv']]
-    """
-    return list(map(split_type, get_params(proto)))
-
-def get_return_type(proto):
-    import re
-    paramregex = re.compile('(\w+ ?\*?).*')
-    outputs = paramregex.findall(proto)
-    assert len(outputs) == 1
-    return outputs[0].replace(' ', '')
-
-def get_name(proto):
-    name = proto.split()[1].split('(')[0]
-    return name.replace('*','')
-
-# the important bits: the size of the output for each objects. this data should
-# move into the C library at some point.
-defaultsizes = {
-    'resampler':    ['input->length * self->ratio'],
-    'specdesc':     ['1'],
-    'onset':        ['1'],
-    'pitchyin':     ['1'],
-    'pitchyinfft':  ['1'],
-    'pitchschmitt': ['1'],
-    'pitchmcomb':   ['1'],
-    'pitchfcomb':   ['1'],
-    'pitch':        ['1'],
-    'tss':          ['self->buf_size', 'self->buf_size'],
-    'mfcc':         ['self->n_coeffs'],
-    'beattracking': ['self->hop_size'],
-    'tempo':        ['1'],
-    'peakpicker':   ['1'],
-    'source':       ['self->hop_size', '1'],
-    'sampler':      ['self->hop_size'],
-    'wavetable':    ['self->hop_size'],
-}
-
-# default value for variables
-aubioinitvalue = {
-    'uint_t': 0,
-    'sint_t': 0,
-    'smpl_t': 0,
-    'lsmp_t': 0.,
-    'char_t*': 'NULL',
-    }
-
-aubiodefvalue = {
-    # we have some clean up to do
-    'buf_size': 'Py_default_vector_length', 
-    # and here too
-    'hop_size': 'Py_default_vector_length / 2', 
-    # these should be alright
-    'samplerate': 'Py_aubio_default_samplerate', 
-    # now for the non obvious ones
-    'n_filters': '40', 
-    'n_coeffs': '13', 
-    'nelems': '10',
-    'flow': '0.', 
-    'fhig': '1.', 
-    'ilow': '0.', 
-    'ihig': '1.', 
-    'thrs': '0.5',
-    'ratio': '0.5',
-    'method': '"default"',
-    'uri': '"none"',
-    }
-
-# aubio to python
-aubio2pytypes = {
-    'uint_t': 'I',
-    'sint_t': 'I',
-    'smpl_t': 'f',
-    'lsmp_t': 'd',
-    'fvec_t*': 'O',
-    'cvec_t*': 'O',
-    'char_t*': 's',
-}
-
-# python to aubio
-aubiovecfrompyobj = {
-    'fvec_t*': 'PyAubio_ArrayToCFvec',
-    'cvec_t*': 'PyAubio_ArrayToCCvec',
-    'uint_t': '(uint_t)PyLong_AsLong',
-}
-
-# aubio to python
-aubiovectopyobj = {
-    'fvec_t*': 'PyAubio_CFvecToArray',
-    'cvec_t*': 'PyAubio_CCvecToPyCvec',
-    'smpl_t': 'PyFloat_FromDouble',
-    'uint_t*': 'PyLong_FromLong',
-    'uint_t': 'PyLong_FromLong',
-}
-
-def gen_new_init(newfunc, name):
-    newparams = get_params_types_names(newfunc)
-    # self->param1, self->param2, self->param3
-    if len(newparams):
-        selfparams = ', self->'+', self->'.join([p['name'] for p in newparams])
-    else:
-        selfparams = '' 
-    # "param1", "param2", "param3"
-    paramnames = ", ".join(["\""+p['name']+"\"" for p in newparams])
-    pyparams = "".join([aubio2pytypes[p['type']] for p in newparams])
-    paramrefs = ", ".join(["&" + p['name'] for p in newparams])
-    s = """\
-// WARNING: this file is generated, DO NOT EDIT
-
-// WARNING: if you haven't read the first line yet, please do so
-#include "aubiowraphell.h"
-
-typedef struct
-{
-  PyObject_HEAD
-  aubio_%(name)s_t * o;
-""" % locals()
-    for p in newparams:
-        ptype = p['type']
-        pname = p['name']
-        s += """\
-  %(ptype)s %(pname)s;
-""" % locals()
-    s += """\
-} Py_%(name)s;
-
-static char Py_%(name)s_doc[] = "%(name)s object";
-
-static PyObject *
-Py_%(name)s_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds)
-{
-  Py_%(name)s *self;
-""" % locals()
-    for p in newparams:
-        ptype = p['type']
-        pname = p['name']
-        initval = aubioinitvalue[ptype]
-        s += """\
-  %(ptype)s %(pname)s = %(initval)s;
-""" % locals()
-    # now the actual PyArg_Parse
-    if len(paramnames):
-        s += """\
-  static char *kwlist[] = { %(paramnames)s, NULL };
-
-  if (!PyArg_ParseTupleAndKeywords (args, kwds, "|%(pyparams)s", kwlist,
-          %(paramrefs)s)) {
-    return NULL;
-  }
-""" % locals()
-    s += """\
-
-  self = (Py_%(name)s *) pytype->tp_alloc (pytype, 0);
-
-  if (self == NULL) {
-    return NULL;
-  }
-""" % locals()
-    for p in newparams:
-        ptype = p['type']
-        pname = p['name']
-        defval = aubiodefvalue[pname]
-        if ptype == 'char_t*':
-            s += """\
-
-  self->%(pname)s = %(defval)s;
-  if (%(pname)s != NULL) {
-    self->%(pname)s = %(pname)s;
-  }
-""" % locals()
-        elif ptype == 'uint_t':
-            s += """\
-
-  self->%(pname)s = %(defval)s;
-  if ((sint_t)%(pname)s > 0) {
-    self->%(pname)s = %(pname)s;
-  } else if ((sint_t)%(pname)s < 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "can not use negative value for %(pname)s");
-    return NULL;
-  }
-""" % locals()
-        elif ptype == 'smpl_t':
-            s += """\
-
-  self->%(pname)s = %(defval)s;
-  if (%(pname)s != %(defval)s) {
-    self->%(pname)s = %(pname)s;
-  }
-""" % locals()
-        else:
-            write_msg ("ERROR, unknown type of parameter %s %s" % (ptype, pname) )
-    s += """\
-
-  return (PyObject *) self;
-}
-
-AUBIO_INIT(%(name)s %(selfparams)s)
-
-AUBIO_DEL(%(name)s)
-
-""" % locals()
-    return s
-
-def gen_do_input_params(inputparams):
-  inputdefs = ''
-  parseinput = ''
-  inputrefs = ''
-  inputvecs = ''
-  pytypes = ''
-
-  if len(inputparams):
-    # build the parsing string for PyArg_ParseTuple
-    pytypes = "".join([aubio2pytypes[p['type']] for p in inputparams])
-
-    inputdefs = "  /* input vectors python prototypes */\n"
-    for p in inputparams:
-      if p['type'] != 'uint_t':
-        inputdefs += "  PyObject * " + p['name'] + "_obj;\n"
-
-    inputvecs = "  /* input vectors prototypes */\n  "
-    inputvecs += "\n  ".join([ p['type'] + ' ' + p['name'] + ";" for p in inputparams])
-
-    parseinput = "  /* input vectors parsing */\n  "
-    for p in inputparams:
-        inputvec = p['name']
-        if p['type'] != 'uint_t':
-          inputdef = p['name'] + "_obj"
-        else:
-          inputdef = p['name']
-        converter = aubiovecfrompyobj[p['type']]
-        if p['type'] != 'uint_t':
-          parseinput += """%(inputvec)s = %(converter)s (%(inputdef)s);
-
-  if (%(inputvec)s == NULL) {
-    return NULL;
-  }
-
-  """ % locals()
-
-    # build the string for the input objects references
-    inputreflist = []
-    for p in inputparams:
-      if p['type'] != 'uint_t':
-        inputreflist += [ "&" + p['name'] + "_obj" ]
-      else:
-        inputreflist += [ "&" + p['name'] ]
-    inputrefs = ", ".join(inputreflist)
-    # end of inputs strings
-  return inputdefs, parseinput, inputrefs, inputvecs, pytypes
-
-def gen_do_output_params(outputparams, name):
-  outputvecs = ""
-  outputcreate = ""
-  if len(outputparams):
-    outputvecs = "  /* output vectors prototypes */\n"
-    for p in outputparams:
-      params = {
-        'name': p['name'], 'pytype': p['type'], 'autype': p['type'][:-3],
-        'length': defaultsizes[name].pop(0) }
-      if (p['type'] == 'uint_t*'):
-        outputvecs += '  uint_t' + ' ' + p['name'] + ";\n"
-        outputcreate += "  %(name)s = 0;\n" % params
-      else:
-        outputvecs += "  " + p['type'] + ' ' + p['name'] + ";\n"
-        outputcreate += "  /* creating output %(name)s as a new_%(autype)s of length %(length)s */\n" % params
-        outputcreate += "  %(name)s = new_%(autype)s (%(length)s);\n" % params
-
-  returnval = "";
-  if len(outputparams) > 1:
-    returnval += "  PyObject *outputs = PyList_New(0);\n"
-    for p in outputparams:
-      returnval += "  PyList_Append( outputs, (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" +");\n"
-    returnval += "  return outputs;"
-  elif len(outputparams) == 1:
-    if defaultsizes[name] == '1':
-      returnval += "  return (PyObject *)PyFloat_FromDouble(" + p['name'] + "->data[0])"
-    else:
-      returnval += "  return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")"
-  else:
-    returnval += "  Py_RETURN_NONE"
-  # end of output strings
-  return outputvecs, outputcreate, returnval
-
-def gen_do(dofunc, name):
-    funcname = dofunc.split()[1].split('(')[0]
-    doparams = get_params_types_names(dofunc) 
-    # make sure the first parameter is the object
-    assert doparams[0]['type'] == "aubio_"+name+"_t*", \
-        "method is not in 'aubio_<name>_t"
-    # and remove it
-    doparams = doparams[1:]
-
-    n_param = len(doparams)
-
-    if name in list(param_numbers.keys()):
-      n_input_param, n_output_param = param_numbers[name]
-    else:
-      n_input_param, n_output_param = 1, n_param - 1
-
-    assert n_output_param + n_input_param == n_param, "n_output_param + n_input_param != n_param for %s" % name
-
-    inputparams = doparams[:n_input_param]
-    outputparams = doparams[n_input_param:n_input_param + n_output_param]
-
-    inputdefs, parseinput, inputrefs, inputvecs, pytypes = gen_do_input_params(inputparams);
-    outputvecs, outputcreate, returnval = gen_do_output_params(outputparams, name)
-
-    # build strings for outputs
-    # build the parameters for the  _do() call
-    doparams_string = "self->o"
-    for p in doparams:
-      if p['type'] == 'uint_t*':
-        doparams_string += ", &" + p['name']
-      else:
-        doparams_string += ", " + p['name']
-
-    if n_input_param:
-      arg_parse_tuple = """\
-  if (!PyArg_ParseTuple (args, "%(pytypes)s", %(inputrefs)s)) {
-    return NULL;
-  }
-""" % locals()
-    else:
-      arg_parse_tuple = ""
-    # put it all together
-    s = """\
-/* function Py_%(name)s_do */
-static PyObject * 
-Py_%(name)s_do(Py_%(name)s * self, PyObject * args)
-{
-%(inputdefs)s
-%(inputvecs)s
-%(outputvecs)s
-
-%(arg_parse_tuple)s
-
-%(parseinput)s
-  
-%(outputcreate)s
-
-  /* compute _do function */
-  %(funcname)s (%(doparams_string)s);
-
-%(returnval)s;
-}
-""" % locals()
-    return s
-
-def gen_members(new_method, name):
-    newparams = get_params_types_names(new_method)
-    s = """
-AUBIO_MEMBERS_START(%(name)s)""" % locals()
-    for param in newparams:
-        if param['type'] == 'char_t*':
-            s += """
-  {"%(pname)s", T_STRING, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \
-        % { 'pname': param['name'], 'ptype': param['type'], 'name': name}
-        elif param['type'] == 'uint_t':
-            s += """
-  {"%(pname)s", T_INT, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \
-        % { 'pname': param['name'], 'ptype': param['type'], 'name': name}
-        elif param['type'] == 'smpl_t':
-            s += """
-  {"%(pname)s", T_FLOAT, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \
-        % { 'pname': param['name'], 'ptype': param['type'], 'name': name}
-        else:
-            write_msg ("-- ERROR, unknown member type ", param )
-    s += """
-AUBIO_MEMBERS_STOP(%(name)s)
-
-""" % locals()
-    return s
-
-
-def gen_methods(get_methods, set_methods, name):
-    s = ""
-    method_defs = ""
-    for method in set_methods:
-        method_name = get_name(method)
-        params = get_params_types_names(method)
-        out_type = get_return_type(method)
-        assert params[0]['type'] == "aubio_"+name+"_t*", \
-            "get method is not in 'aubio_<name>_t"
-        write_msg (method )
-        write_msg (params[1:])
-        setter_args = "self->o, " +",".join([p['name'] for p in params[1:]])
-        parse_args = ""
-        for p in params[1:]:
-            parse_args += p['type'] + " " + p['name'] + ";\n"
-        argmap = "".join([aubio2pytypes[p['type']] for p in params[1:]])
-        arglist = ", ".join(["&"+p['name'] for p in params[1:]])
-        parse_args += """
-  if (!PyArg_ParseTuple (args, "%(argmap)s", %(arglist)s)) {
-    return NULL;
-  } """ % locals()
-        s += """
-static PyObject *
-Py%(funcname)s (Py_%(objname)s *self, PyObject *args)
-{
-  uint_t err = 0;
-
-  %(parse_args)s
-
-  err = %(funcname)s (%(setter_args)s);
-
-  if (err > 0) {
-    PyErr_SetString (PyExc_ValueError,
-        "error running %(funcname)s");
-    return NULL;
-  }
-  Py_RETURN_NONE;
-}
-""" % {'funcname': method_name, 'objname': name, 
-        'out_type': out_type, 'setter_args': setter_args, 'parse_args': parse_args }
-        shortname = method_name.split('aubio_'+name+'_')[-1]
-        method_defs += """\
-  {"%(shortname)s", (PyCFunction) Py%(method_name)s,
-    METH_VARARGS, ""},
-""" % locals()
-
-    for method in get_methods:
-        method_name = get_name(method)
-        params = get_params_types_names(method)
-        out_type = get_return_type(method)
-        assert params[0]['type'] == "aubio_"+name+"_t*", \
-            "get method is not in 'aubio_<name>_t %s" % params[0]['type']
-        assert len(params) == 1, \
-            "get method has more than one parameter %s" % params
-        getter_args = "self->o" 
-        returnval = "(PyObject *)" + aubiovectopyobj[out_type] + " (tmp)"
-        shortname = method_name.split('aubio_'+name+'_')[-1]
-        method_defs += """\
-  {"%(shortname)s", (PyCFunction) Py%(method_name)s,
-    METH_NOARGS, ""},
-""" % locals()
-        s += """
-static PyObject *
-Py%(funcname)s (Py_%(objname)s *self, PyObject *unused)
-{
-  %(out_type)s tmp = %(funcname)s (%(getter_args)s);
-  return %(returnval)s;
-}
-""" % {'funcname': method_name, 'objname': name, 
-        'out_type': out_type, 'getter_args': getter_args, 'returnval': returnval }
-
-    s += """
-static PyMethodDef Py_%(name)s_methods[] = {
-""" % locals() 
-    s += method_defs 
-    s += """\
-  {NULL} /* sentinel */
-};
-""" % locals() 
-    return s
-
-def gen_finish(name):
-    s = """\
-
-AUBIO_TYPEOBJECT(%(name)s, "aubio.%(name)s")
-""" % locals()
-    return s
--- a/python/lib/generator.py
+++ /dev/null
@@ -1,233 +1,0 @@
-#! /usr/bin/python
-
-""" This file generates a c file from a list of cpp prototypes. """
-
-import os, sys, shutil
-from .gen_pyobject import write_msg, gen_new_init, gen_do, gen_members, gen_methods, gen_finish
-
-def get_cpp_objects():
-
-  cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=1 -I../build/src ../src/aubio.h').readlines()]
-
-  cpp_output = filter(lambda y: len(y) > 1, cpp_output)
-  cpp_output = filter(lambda y: not y.startswith('#'), cpp_output)
-  cpp_output = list(cpp_output)
-
-  i = 1
-  while 1:
-      if i >= len(cpp_output): break
-      if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'):
-          cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i]
-          cpp_output.pop(i-1)
-      else:
-          i += 1
-
-  typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output)
-  typedefs = list(typedefs)
-
-  cpp_objects = [a.split()[3][:-1] for a in typedefs]
-
-  return cpp_output, cpp_objects
-
-def generate_object_files(output_path):
-  if os.path.isdir(output_path): shutil.rmtree(output_path)
-  os.mkdir(output_path)
-
-  generated_objects = []
-  cpp_output, cpp_objects = get_cpp_objects()
-  skip_objects = [
-      # already in ext/
-      'fft',
-      'pvoc',
-      'filter',
-      'filterbank',
-      #'resampler',
-      # AUBIO_UNSTABLE
-      'hist',
-      'parameter',
-      'scale',
-      'beattracking',
-      'resampler',
-      'sndfile',
-      'peakpicker',
-      'pitchfcomb',
-      'pitchmcomb',
-      'pitchschmitt',
-      'pitchspecacf',
-      'pitchyin',
-      'pitchyinfft',
-      'sink',
-      'sink_apple_audio',
-      'sink_sndfile',
-      'sink_wavwrite',
-      'source',
-      'source_apple_audio',
-      'source_sndfile',
-      'source_avcodec',
-      'source_wavread',
-      #'sampler',
-      'audio_unit',
-      ]
-
-  write_msg("-- INFO: %d objects in total" % len(cpp_objects))
-
-  for this_object in cpp_objects:
-      lint = 0
-
-      if this_object[-2:] == '_t':
-          object_name = this_object[:-2]
-      else:
-          object_name = this_object
-          write_msg("-- WARNING: %s does not end in _t" % this_object)
-
-      if object_name[:len('aubio_')] != 'aubio_':
-          write_msg("-- WARNING: %s does not start n aubio_" % this_object)
-
-      write_msg("-- INFO: looking at", object_name)
-      object_methods = filter(lambda x: this_object in x, cpp_output)
-      object_methods = [a.strip() for a in object_methods]
-      object_methods = filter(lambda x: not x.startswith('typedef'), object_methods)
-      object_methods = list(object_methods)
-      #for method in object_methods:
-      #    write_msg(method)
-      new_methods = list(filter(
-          lambda x: 'new_'+object_name in x, object_methods))
-      if len(new_methods) > 1:
-          write_msg("-- WARNING: more than one new method for", object_name)
-          for method in new_methods:
-              write_msg(method)
-      elif len(new_methods) < 1:
-          write_msg("-- WARNING: no new method for", object_name)
-      elif 0:
-          for method in new_methods:
-              write_msg(method)
-
-      del_methods = list(filter(
-          lambda x: 'del_'+object_name in x, object_methods))
-      if len(del_methods) > 1:
-          write_msg("-- WARNING: more than one del method for", object_name)
-          for method in del_methods:
-              write_msg(method)
-      elif len(del_methods) < 1:
-          write_msg("-- WARNING: no del method for", object_name)
-
-      do_methods = list(filter(
-          lambda x: object_name+'_do' in x, object_methods))
-      if len(do_methods) > 1:
-          pass
-          #write_msg("-- WARNING: more than one do method for", object_name)
-          #for method in do_methods:
-          #    write_msg(method)
-      elif len(do_methods) < 1:
-          write_msg("-- WARNING: no do method for", object_name)
-      elif 0:
-          for method in do_methods:
-              write_msg(method)
-
-      # check do methods return void
-      for method in do_methods:
-          if (method.split()[0] != 'void'):
-              write_msg("-- ERROR: _do method does not return void:", method )
-
-      get_methods = filter(lambda x: object_name+'_get_' in x, object_methods)
-
-      set_methods = filter(lambda x: object_name+'_set_' in x, object_methods)
-      for method in set_methods:
-          if (method.split()[0] != 'uint_t'):
-              write_msg("-- ERROR: _set method does not return uint_t:", method )
-
-      other_methods = filter(lambda x: x not in new_methods, object_methods)
-      other_methods = filter(lambda x: x not in del_methods, other_methods)
-      other_methods = filter(lambda x: x not in    do_methods, other_methods)
-      other_methods = filter(lambda x: x not in get_methods, other_methods)
-      other_methods = filter(lambda x: x not in set_methods, other_methods)
-      other_methods = list(other_methods)
-
-      if len(other_methods) > 0:
-          write_msg("-- WARNING: some methods for", object_name, "were unidentified")
-          for method in other_methods:
-              write_msg(method)
-
-
-      # generate this_object
-      short_name = object_name[len('aubio_'):]
-      if short_name in skip_objects:
-              write_msg("-- INFO: skipping object", short_name )
-              continue
-      if 1: #try:
-          s = gen_new_init(new_methods[0], short_name)
-          s += gen_do(do_methods[0], short_name)
-          s += gen_members(new_methods[0], short_name)
-          s += gen_methods(get_methods, set_methods, short_name)
-          s += gen_finish(short_name)
-          generated_filepath = os.path.join(output_path,'gen-'+short_name+'.c')
-          fd = open(generated_filepath, 'w')
-          fd.write(s)
-      #except Exception, e:
-      #        write_msg("-- ERROR:", type(e), str(e), "in", short_name)
-      #        continue
-      generated_objects += [this_object]
-
-  s = """// generated list of objects created with generator.py
-
-"""
-
-  types_ready = []
-  for each in generated_objects:
-      types_ready.append("  PyType_Ready (&Py_%sType) < 0" % \
-              each.replace('aubio_','').replace('_t','') )
-
-  s = """// generated list of objects created with generator.py
-
-#include "aubio-generated.h"
-"""
-
-  s += """
-int generated_types_ready (void)
-{
-  return (
-"""
-  s += ('\n     ||').join(types_ready)
-  s += """);
-}
-"""
-
-  s += """
-void add_generated_objects ( PyObject *m )
-{"""
-  for each in generated_objects:
-    s += """
-  Py_INCREF (&Py_%(name)sType);
-  PyModule_AddObject (m, "%(name)s", (PyObject *) & Py_%(name)sType);""" % \
-          { 'name': ( each.replace('aubio_','').replace('_t','') ) }
-
-  s += """
-}"""
-
-  fd = open(os.path.join(output_path,'aubio-generated.c'), 'w')
-  fd.write(s)
-
-  s = """// generated list of objects created with generator.py
-
-#include <Python.h>
-
-"""
-
-  for each in generated_objects:
-      s += "extern PyTypeObject Py_%sType;\n" % \
-              each.replace('aubio_','').replace('_t','')
-
-  s+= "int generated_objects ( void );\n"
-  s+= "void add_generated_objects( PyObject *m );\n"
-
-  fd = open(os.path.join(output_path,'aubio-generated.h'), 'w')
-  fd.write(s)
-
-  from os import listdir
-  generated_files = listdir(output_path)
-  generated_files = filter(lambda x: x.endswith('.c'), generated_files)
-  generated_files = [output_path+'/'+f for f in generated_files]
-  return generated_files
-
-if __name__ == '__main__':
-  generate_object_files('gen')