From 0b2892fa076aea21f128617f7d21b826f53797a8 Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Fri, 13 Jul 2012 19:39:07 -0600 Subject: [PATCH] gen_pyobject.py: improve, also parse io/source --- interfaces/python/gen_pyobject.py | 183 ++++++++++++++++++------------ 1 file changed, 109 insertions(+), 74 deletions(-) diff --git a/interfaces/python/gen_pyobject.py b/interfaces/python/gen_pyobject.py index d6159c18..a14735b5 100644 --- a/interfaces/python/gen_pyobject.py +++ b/interfaces/python/gen_pyobject.py @@ -18,6 +18,10 @@ requirements. If you know of one, please let me know, it will spare me maintaining this bizarre file. """ +param_numbers = { + 'source': [0, 2], +} + # TODO # do function: for now, only the following pattern is supported: # void aubio__do (aubio_foo_t * o, @@ -80,20 +84,21 @@ def get_name(proto): # 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->hop_size', - 'mfcc': 'self->n_coeffs', - 'beattracking': 'self->hop_size', - 'tempo': '1', - 'peakpicker': '1', + 'resampler': ['input->length * self->ratio'], + 'specdesc': ['1'], + 'onset': ['1'], + 'pitchyin': ['1'], + 'pitchyinfft': ['1'], + 'pitchschmitt': ['1'], + 'pitchmcomb': ['1'], + 'pitchfcomb': ['1'], + 'pitch': ['1'], + 'tss': ['self->hop_size', 'self->hop_size'], + 'mfcc': ['self->n_coeffs'], + 'beattracking': ['self->hop_size'], + 'tempo': ['1'], + 'peakpicker': ['1'], + 'source': ['self->hop_size', '1'], } # default value for variables @@ -122,6 +127,7 @@ aubiodefvalue = { 'thrs': '0.5', 'ratio': '0.5', 'method': '"default"', + 'uri': '"none"', } # aubio to python @@ -145,6 +151,7 @@ aubiovectopyobj = { 'fvec_t*': 'PyAubio_CFvecToArray', 'cvec_t*': 'PyAubio_CCvecToPyCvec', 'smpl_t': 'PyFloat_FromDouble', + 'uint_t*': 'PyInt_FromLong', } def gen_new_init(newfunc, name): @@ -256,24 +263,16 @@ AUBIO_DEL(%(name)s) """ % locals() return s -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__t" - # and remove it - doparams = doparams[1:] - # guess the input/output params, assuming we have less than 3 - assert len(doparams) > 0, \ - "no parameters for function do in object %s" % name - #assert (len(doparams) <= 2), \ - # "more than 3 parameters for do in object %s" % name - - # build strings for inputs, assuming there is only one input - inputparams = [doparams[0]] +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 doparams[0:1]]) + pytypes = "".join([aubio2pytypes[p['type']] for p in inputparams]) inputdefs = "/* input vectors python prototypes */\n " inputdefs += "\n ".join(["PyObject * " + p['name'] + "_obj;" for p in inputparams]) @@ -295,66 +294,102 @@ def gen_do(dofunc, name): # build the string for the input objects references inputrefs = ", ".join(["&" + p['name'] + "_obj" for p in inputparams]) # 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 = " return Py_None;"; + # end of output strings + return outputvecs, outputcreate, returnval - # build strings for outputs - outputparams = doparams[1:] - if len(outputparams) >= 1: - #assert len(outputparams) == 1, \ - # "too many output parameters" - outputvecs = "\n /* output vectors prototypes */\n " - outputvecs += "\n ".join([p['type'] + ' ' + p['name'] + ";" for p in outputparams]) - params = { - 'name': p['name'], 'pytype': p['type'], 'autype': p['type'][:-3], - 'length': defaultsizes[name]} - outputcreate = "\n ".join(["""/* creating output %(name)s as a new_%(autype)s of length %(length)s */""" % \ - params for p in outputparams]) - outputcreate += "\n" - outputcreate += "\n ".join([""" %(name)s = new_%(autype)s (%(length)s);""" % \ - params for p in outputparams]) - 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;" - else: - if defaultsizes[name] == '1': - returnval += "return (PyObject *)PyFloat_FromDouble(" + p['name'] + "->data[0])" - else: - returnval += "return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" +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__t" + # and remove it + doparams = doparams[1:] + + n_param = len(doparams) + + if name in param_numbers.keys(): + n_input_param, n_output_param = param_numbers[name] else: - # no output - outputvecs = "" - outputcreate = "" - #returnval = "Py_None"; - returnval = "return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" - # end of output strings + n_input_param, n_output_param = 1, n_param - 1 - # build the parameters for the _do() call - doparams_string = "self->o, " + ", ".join([p['name'] for p in doparams]) + 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 +%(inputdefs)s +%(inputvecs)s +%(outputvecs)s - if (!PyArg_ParseTuple (args, "%(pytypes)s", %(inputrefs)s)) { - return NULL; - } +%(arg_parse_tuple)s - %(parseinput)s +%(parseinput)s - %(outputcreate)s +%(outputcreate)s /* compute _do function */ %(funcname)s (%(doparams_string)s); - %(returnval)s; +%(returnval)s; } """ % locals() return s -- 2.26.2