From: Paul Brossier Date: Sun, 10 Feb 2013 01:10:12 +0000 (-0500) Subject: move new python module to the top X-Git-Tag: 0.4.0-beta1~335^2~23 X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=25c9f9ac65ef6d0c66a90795f9b1fd6835e28d2c;p=aubio.git move new python module to the top --- diff --git a/interfaces/python/README.md b/interfaces/python/README.md deleted file mode 100644 index f0054369..00000000 --- a/interfaces/python/README.md +++ /dev/null @@ -1,24 +0,0 @@ -Python aubio module -=================== - -This module wraps the aubio library for python using the numpy module. - -See the [Python/C API Reference -Manual] (http://docs.python.org/c-api/index.html) and the [Numpy/C API -Reference](http://docs.scipy.org/doc/numpy/reference/c-api.html) - -Compiling python aubio on Mac OS X ----------------------------------- - -You should now be able to build the aubio python module out of the box on a -recent version of OS X (10.8.x). Make sure the variables are correct in the -file `build_osx` before running it: - - $ ./build_osx - -Additionally, you can fetch tools such [matplotlib](http://matplotlib.org/) to -use the demo scripts. One easy way to do it is to fetch the fully fledged -[Scipy superpack](http://fonnesbeck.github.com/ScipySuperpack/) - - $ curl -O https://raw.github.com/fonnesbeck/ScipySuperpack/master/install_superpack.sh - $ sh install_superpack.sh diff --git a/interfaces/python/a_weighting_test_simple.expected b/interfaces/python/a_weighting_test_simple.expected deleted file mode 100644 index 6cd3ff3d..00000000 --- a/interfaces/python/a_weighting_test_simple.expected +++ /dev/null @@ -1,2 +0,0 @@ - 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 5.00000000e-01 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 - 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.27870563e-01 2.58244342e-01 1.18719361e-01 -4.02623805e-02 -5.61812129e-02 -5.24739734e-02 -4.72329276e-02 -4.23394349e-02 -3.79219586e-02 -3.39473148e-02 -3.03724479e-02 -2.71574847e-02 -2.42664433e-02 -2.16669285e-02 -1.93297810e-02 -1.72287543e-02 -1.53402241e-02 -1.36429261e-02 -1.21177207e-02 -1.07473802e-02 diff --git a/interfaces/python/aubio-types.h b/interfaces/python/aubio-types.h deleted file mode 100644 index d63bbcd4..00000000 --- a/interfaces/python/aubio-types.h +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#define NO_IMPORT_ARRAY -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include -#define AUBIO_UNSTABLE 1 -#include - -#define Py_default_vector_length 1024 -#define Py_default_vector_height 1 - -#define Py_aubio_default_samplerate 44100 - -#if HAVE_AUBIO_DOUBLE -#error "Ouch! Python interface for aubio has not been much tested yet." -#define AUBIO_NPY_SMPL NPY_DOUBLE -#else -#define AUBIO_NPY_SMPL NPY_FLOAT -#endif - -// special python type for cvec -typedef struct -{ - PyObject_HEAD - cvec_t * o; - uint_t length; - uint_t channels; -} Py_cvec; -extern PyTypeObject Py_cvecType; - -// defined in aubio-proxy.c -extern PyObject *PyAubio_CFvecToArray (fvec_t * self); -extern fvec_t *PyAubio_ArrayToCFvec (PyObject * self); - -extern Py_cvec *PyAubio_CCvecToPyCvec (cvec_t * self); -extern cvec_t *PyAubio_ArrayToCCvec (PyObject *input); - -extern PyObject *PyAubio_CFmatToArray (fmat_t * self); -extern fmat_t *PyAubio_ArrayToCFmat (PyObject *input); - -// hand written wrappers -extern PyTypeObject Py_filterType; - -extern PyTypeObject Py_filterbankType; - -extern PyTypeObject Py_fftType; - -extern PyTypeObject Py_pvocType; - diff --git a/interfaces/python/aubio/__init__.py b/interfaces/python/aubio/__init__.py deleted file mode 100644 index 136848b1..00000000 --- a/interfaces/python/aubio/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -import numpy -from _aubio import * - -class fvec(numpy.ndarray): - - def __new__(self, length = 1024, **kwargs): - if type(length) == type([]): - return numpy.array(length, dtype='float32', **kwargs) - return numpy.zeros(length, dtype='float32', **kwargs) diff --git a/interfaces/python/aubioinput.py b/interfaces/python/aubioinput.py deleted file mode 100644 index 80bc9e4b..00000000 --- a/interfaces/python/aubioinput.py +++ /dev/null @@ -1,141 +0,0 @@ -#! /usr/bin/python - -import pygst -pygst.require('0.10') -import gst -import gobject -gobject.threads_init () - -def gst_buffer_to_numpy_array(buffer, chan): - import numpy - samples = numpy.frombuffer(buffer.data, dtype=numpy.float32) - if chan == 1: - return samples.T - else: - samples.resize([len(samples)/chan, chan]) - return samples.T - -class AubioSink(gst.BaseSink): - _caps = gst.caps_from_string('audio/x-raw-float, \ - rate=[ 1, 2147483647 ], \ - channels=[ 1, 2147483647 ], \ - endianness={ 1234, 4321 }, \ - width=32') - - __gsttemplates__ = ( - gst.PadTemplate ("sink", - gst.PAD_SINK, - gst.PAD_ALWAYS, - _caps), - ) - - def __init__(self, name, process): - self.__gobject_init__() - self.set_name(name) - self.process = process - self.adapter = gst.Adapter() - self.set_property('sync', False) - self.pos = 0 - - def set_property(self, name, value): - if name == 'hopsize': - # blocksize is in byte, convert from hopsize - from struct import calcsize - self.set_property('blocksize', value * calcsize('f')) - else: - super(gst.BaseSink, self).set_property(name, value) - - def do_render(self, buffer): - blocksize = self.get_property('blocksize') - caps = buffer.get_caps() - chan = caps[0]['channels'] - self.adapter.push(buffer) - while self.adapter.available() >= blocksize: - block = self.adapter.take_buffer(blocksize) - v = gst_buffer_to_numpy_array(block, chan) - if self.process: - self.process(v, self.pos) - self.pos += 1 - remaining = self.adapter.available() - if remaining < blocksize and remaining > 0: - block = self.adapter.take_buffer(remaining) - v = gst_buffer_to_numpy_array(block, chan) - if self.process: - self.process(v, self.pos) - self.pos += 1 - return gst.FLOW_OK - -gobject.type_register(AubioSink) - -class aubioinput(gst.Bin): - - ret = 0 - - def __init__(self, uri, process = None, hopsize = 512, - caps = None): - if uri.startswith('/'): - from urllib import quote - uri = 'file://'+quote(uri) - src = gst.element_factory_make('uridecodebin') - src.set_property('uri', uri) - src.connect('pad-added', self.source_pad_added_cb) - conv = gst.element_factory_make('audioconvert') - self.conv = conv - rsmpl = gst.element_factory_make('audioresample') - capsfilter = gst.element_factory_make('capsfilter') - if caps: - capsfilter.set_property('caps', gst.caps_from_string(caps)) - sink = AubioSink("AubioSink", process = process) - sink.set_property('hopsize', hopsize) # * calcsize('f')) - - self.pipeline = gst.Pipeline() - - self.bus = self.pipeline.get_bus() - self.bus.add_signal_watch() - self.bus.connect('message', self.on_eos) - - self.apad = conv.get_pad('sink') - - self.pipeline.add(src, conv, rsmpl, capsfilter, sink) - - gst.element_link_many(conv, rsmpl, capsfilter, sink) - - self.mainloop = gobject.MainLoop() - self.pipeline.set_state(gst.STATE_PLAYING) - - def run(self): - self.mainloop.run() - return self.ret - - def source_pad_added_cb(self, src, pad): - name = pad.get_caps()[0].get_name() - if name == 'audio/x-raw-float' or name == 'audio/x-raw-int': - pad.link(self.conv.get_pad("sink")) - - def source_pad_removed_cb(self, src, pad): - pad.unlink(self.conv.get_pad("sink")) - - def on_eos(self, bus, msg): - if msg.type == gst.MESSAGE_EOS: - self.bus.remove_signal_watch() - self.pipeline.set_state(gst.STATE_PAUSED) - self.mainloop.quit() - elif msg.type == gst.MESSAGE_ERROR: - print "ERROR", msg.parse_error() - self.bus.remove_signal_watch() - self.pipeline.set_state(gst.STATE_PAUSED) - self.mainloop.quit() - self.ret = 1 # set return value to 1 in case of error - -if __name__ == '__main__': - import sys - if len(sys.argv) < 2: - print "Usage: %s " % sys.argv[0] - sys.exit(1) - for filename in sys.argv[1:]: - peak = [0.] # use a mutable - def process(buf, hop): - peak[0] = max( peak[0], abs(buf.max()) ) - a = aubioinput(filename, process = process, hopsize = 512) - if a.run() == 0: # only display the results if no - print "Finished reading %s, peak value is %f" % (filename, max(peak)) diff --git a/interfaces/python/aubiomodule.c b/interfaces/python/aubiomodule.c deleted file mode 100644 index df5787e1..00000000 --- a/interfaces/python/aubiomodule.c +++ /dev/null @@ -1,161 +0,0 @@ -#include -#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include - -#include "aubio-types.h" -#include "generated/aubio-generated.h" - -static char Py_alpha_norm_doc[] = "compute alpha normalisation factor"; - -static PyObject * -Py_alpha_norm (PyObject * self, PyObject * args) -{ - PyObject *input; - fvec_t *vec; - smpl_t alpha; - PyObject *result; - - if (!PyArg_ParseTuple (args, "Of:alpha_norm", &input, &alpha)) { - return NULL; - } - - if (input == NULL) { - return NULL; - } - - vec = PyAubio_ArrayToCFvec (input); - - if (vec == NULL) { - return NULL; - } - - // compute the function - result = Py_BuildValue ("f", fvec_alpha_norm (vec, alpha)); - if (result == NULL) { - return NULL; - } - - return result; -} - -static char Py_zero_crossing_rate_doc[] = "compute zero crossing rate"; - -static PyObject * -Py_zero_crossing_rate (PyObject * self, PyObject * args) -{ - PyObject *input; - fvec_t *vec; - PyObject *result; - - if (!PyArg_ParseTuple (args, "O:zero_crossing_rate", &input)) { - return NULL; - } - - if (input == NULL) { - return NULL; - } - - vec = PyAubio_ArrayToCFvec (input); - - if (vec == NULL) { - return NULL; - } - - // compute the function - result = Py_BuildValue ("f", aubio_zero_crossing_rate (vec)); - if (result == NULL) { - return NULL; - } - - return result; -} - -static char Py_min_removal_doc[] = "compute zero crossing rate"; - -static PyObject * -Py_min_removal(PyObject * self, PyObject * args) -{ - PyObject *input; - fvec_t *vec; - - if (!PyArg_ParseTuple (args, "O:min_removal", &input)) { - return NULL; - } - - if (input == NULL) { - return NULL; - } - - vec = PyAubio_ArrayToCFvec (input); - - if (vec == NULL) { - return NULL; - } - - // compute the function - fvec_min_removal (vec); - - // since this function does not return, we could return None - //return Py_None; - // however it is convenient to return the modified vector - return (PyObject *) PyAubio_CFvecToArray(vec); - // or even without converting it back to an array - //Py_INCREF(vec); - //return (PyObject *)vec; -} - -static PyMethodDef aubio_methods[] = { - {"alpha_norm", Py_alpha_norm, METH_VARARGS, Py_alpha_norm_doc}, - {"zero_crossing_rate", Py_zero_crossing_rate, METH_VARARGS, - Py_zero_crossing_rate_doc}, - {"min_removal", Py_min_removal, METH_VARARGS, Py_min_removal_doc}, - {NULL, NULL} /* Sentinel */ -}; - -static char aubio_module_doc[] = "Python module for the aubio library"; - -PyMODINIT_FUNC -init_aubio (void) -{ - PyObject *m; - int err; - - if ( (PyType_Ready (&Py_cvecType) < 0) - || (PyType_Ready (&Py_filterType) < 0) - || (PyType_Ready (&Py_filterbankType) < 0) - || (PyType_Ready (&Py_fftType) < 0) - || (PyType_Ready (&Py_pvocType) < 0) - // generated objects - || (generated_types_ready() < 0 ) - ) { - return; - } - - m = Py_InitModule3 ("_aubio", aubio_methods, aubio_module_doc); - - if (m == NULL) { - return; - } - - err = _import_array (); - - if (err != 0) { - fprintf (stderr, - "Unable to import Numpy C API from aubio module (error %d)\n", err); - } - - Py_INCREF (&Py_cvecType); - PyModule_AddObject (m, "cvec", (PyObject *) & Py_cvecType); - Py_INCREF (&Py_filterType); - PyModule_AddObject (m, "digital_filter", (PyObject *) & Py_filterType); - Py_INCREF (&Py_filterbankType); - PyModule_AddObject (m, "filterbank", (PyObject *) & Py_filterbankType); - Py_INCREF (&Py_fftType); - PyModule_AddObject (m, "fft", (PyObject *) & Py_fftType); - Py_INCREF (&Py_pvocType); - PyModule_AddObject (m, "pvoc", (PyObject *) & Py_pvocType); - - // generated objects - add_generated_objects(m); -} diff --git a/interfaces/python/aubioproxy.c b/interfaces/python/aubioproxy.c deleted file mode 100644 index 9b7f9179..00000000 --- a/interfaces/python/aubioproxy.c +++ /dev/null @@ -1,153 +0,0 @@ -#include "aubio-types.h" - -fvec_t * -PyAubio_ArrayToCFvec (PyObject *input) { - PyObject *array; - fvec_t *vec; - if (input == NULL) { - PyErr_SetString (PyExc_ValueError, "input array is not a python object"); - goto fail; - } - // parsing input object into a Py_fvec - if (PyArray_Check(input)) { - - // we got an array, convert it to an fvec - if (PyArray_NDIM ((PyArrayObject *)input) == 0) { - PyErr_SetString (PyExc_ValueError, "input array is a scalar"); - goto fail; - } else if (PyArray_NDIM ((PyArrayObject *)input) > 1) { - PyErr_SetString (PyExc_ValueError, - "input array has more than one dimensions"); - goto fail; - } - - if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { - PyErr_SetString (PyExc_ValueError, "input array should be float"); - goto fail; - } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { - PyErr_SetString (PyExc_ValueError, "input array should be float32"); - goto fail; - } else { - // input data type is float32, nothing else to do - array = input; - } - - // vec = new_fvec (vec->length); - // no need to really allocate fvec, just its struct member - vec = (fvec_t *)malloc(sizeof(fvec_t)); - vec->length = PyArray_SIZE ((PyArrayObject *)array); - vec->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)array, 0); - - } else if (PyObject_TypeCheck (input, &PyList_Type)) { - PyErr_SetString (PyExc_ValueError, "does not convert from list yet"); - return NULL; - } else { - PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input"); - return NULL; - } - - return vec; - -fail: - return NULL; -} - -PyObject * -PyAubio_CFvecToArray (fvec_t * self) -{ - npy_intp dims[] = { self->length, 1 }; - return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data); -} - -Py_cvec * -PyAubio_CCvecToPyCvec (cvec_t * input) { - Py_cvec *vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); - vec->length = input->length; - vec->o = input; - Py_INCREF(vec); - return vec; -} - -cvec_t * -PyAubio_ArrayToCCvec (PyObject *input) { - if (PyObject_TypeCheck (input, &Py_cvecType)) { - return ((Py_cvec*)input)->o; - } else { - PyErr_SetString (PyExc_ValueError, "input array should be float32"); - return NULL; - } -} - -PyObject * -PyAubio_CFmatToArray (fmat_t * input) -{ - PyObject *array = NULL; - uint_t i; - npy_intp dims[] = { input->length, 1 }; - PyObject *concat = PyList_New (0), *tmp = NULL; - for (i = 0; i < input->height; i++) { - tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->data[i]); - PyList_Append (concat, tmp); - Py_DECREF (tmp); - } - array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2); - Py_DECREF (concat); - return array; -} - -fmat_t * -PyAubio_ArrayToCFmat (PyObject *input) { - PyObject *array; - fmat_t *mat; - uint_t i; - if (input == NULL) { - PyErr_SetString (PyExc_ValueError, "input array is not a python object"); - goto fail; - } - // parsing input object into a Py_fvec - if (PyArray_Check(input)) { - - // we got an array, convert it to an fvec - if (PyArray_NDIM ((PyArrayObject *)input) == 0) { - PyErr_SetString (PyExc_ValueError, "input array is a scalar"); - goto fail; - } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { - PyErr_SetString (PyExc_ValueError, - "input array has more than two dimensions"); - goto fail; - } - - if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { - PyErr_SetString (PyExc_ValueError, "input array should be float"); - goto fail; - } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { - PyErr_SetString (PyExc_ValueError, "input array should be float32"); - goto fail; - } else { - // input data type is float32, nothing else to do - array = input; - } - - // no need to really allocate fvec, just its struct member - mat = (fmat_t *)malloc(sizeof(fmat_t)); - mat->length = PyArray_DIM ((PyArrayObject *)array, 1); - mat->height = PyArray_DIM ((PyArrayObject *)array, 0); - mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height); - for (i=0; i< mat->height; i++) { - mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)array, i); - } - - } else if (PyObject_TypeCheck (input, &PyList_Type)) { - PyErr_SetString (PyExc_ValueError, "can not convert list to fmat"); - return NULL; - } else { - PyErr_SetString (PyExc_ValueError, "can only accept matrix of float as input"); - return NULL; - } - - return mat; - -fail: - return NULL; -} - diff --git a/interfaces/python/aubiowraphell.h b/interfaces/python/aubiowraphell.h deleted file mode 100644 index d60cc30a..00000000 --- a/interfaces/python/aubiowraphell.h +++ /dev/null @@ -1,90 +0,0 @@ -#include "aubio-types.h" - -#define AUBIO_DECLARE(NAME, PARAMS...) \ -typedef struct { \ - PyObject_HEAD \ - aubio_ ## NAME ## _t * o; \ - PARAMS; \ -} Py_## NAME; - -#define AUBIO_INIT(NAME, PARAMS... ) \ -static int \ -Py_ ## NAME ## _init (Py_ ## NAME * self, PyObject * args, PyObject * kwds) \ -{ \ - self->o = new_aubio_## NAME ( PARAMS ); \ - if (self->o == NULL) { \ - PyErr_SetString (PyExc_StandardError, "error creating object"); \ - return -1; \ - } \ -\ - return 0; \ -} - -#define AUBIO_DEL(NAME) \ -static void \ -Py_ ## NAME ## _del ( Py_ ## NAME * self) \ -{ \ - del_aubio_ ## NAME (self->o); \ - self->ob_type->tp_free ((PyObject *) self); \ -} - -#define AUBIO_MEMBERS_START(NAME) \ -static PyMemberDef Py_ ## NAME ## _members[] = { - -#define AUBIO_MEMBERS_STOP(NAME) \ - {NULL} \ -}; - -#define AUBIO_METHODS(NAME) \ -static PyMethodDef Py_ ## NAME ## _methods[] = { \ - {NULL} \ -}; - - -#define AUBIO_TYPEOBJECT(NAME, PYNAME) \ -PyTypeObject Py_ ## NAME ## Type = { \ - PyObject_HEAD_INIT (NULL) \ - 0, \ - PYNAME, \ - sizeof (Py_ ## NAME), \ - 0, \ - (destructor) Py_ ## NAME ## _del, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - (ternaryfunc)Py_ ## NAME ## _do, \ - 0, \ - 0, \ - 0, \ - 0, \ - Py_TPFLAGS_DEFAULT, \ - Py_ ## NAME ## _doc, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - Py_ ## NAME ## _methods, \ - Py_ ## NAME ## _members, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - (initproc) Py_ ## NAME ## _init, \ - 0, \ - Py_ ## NAME ## _new, \ -}; - -// some more helpers -#define AUBIO_NEW_VEC(name, type, lengthval) \ - name = (type *) PyObject_New (type, & type ## Type); \ - name->length = lengthval; diff --git a/interfaces/python/build_linux b/interfaces/python/build_linux deleted file mode 100755 index 05c97ecb..00000000 --- a/interfaces/python/build_linux +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh - -set -e -set -x - -python setup.py clean build -export PYTHONPATH=./build/lib.linux-x86_64-2.7/ -export LD_LIBRARY_PATH=../../build/src/ -./run_all_tests --verbose diff --git a/interfaces/python/build_osx b/interfaces/python/build_osx deleted file mode 100755 index 7f5cc3b6..00000000 --- a/interfaces/python/build_osx +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh - -set -e -set -x - -python setup.py clean build -export PYTHONPATH=./build/lib.macosx-10.6-intel-2.7:$PYTHONPATH -export DYLD_LIBRARY_PATH=../../build/src -./run_all_tests --verbose diff --git a/interfaces/python/c_weighting_test_simple.expected b/interfaces/python/c_weighting_test_simple.expected deleted file mode 100644 index 70e2b159..00000000 --- a/interfaces/python/c_weighting_test_simple.expected +++ /dev/null @@ -1,2 +0,0 @@ - 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 5.00000000e-01 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 - 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.08504281e-01 2.31621372e-01 1.38614617e-01 1.58040475e-02 -9.84900252e-04 -2.72686896e-03 -2.87772967e-03 -2.87932142e-03 -2.86783482e-03 -2.85529016e-03 -2.84270413e-03 -2.83016008e-03 -2.81766458e-03 -2.80521796e-03 -2.79282009e-03 -2.78047079e-03 -2.76816989e-03 -2.75591721e-03 -2.74371257e-03 -2.73155579e-03 diff --git a/interfaces/python/demo_beats_and_tempo.py b/interfaces/python/demo_beats_and_tempo.py deleted file mode 100755 index 2b33bb19..00000000 --- a/interfaces/python/demo_beats_and_tempo.py +++ /dev/null @@ -1,39 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import tempo, source - -win_s = 512 # fft size -hop_s = win_s / 2 # hop size -samplerate = 44100 - -if len(sys.argv) < 2: - print "Usage: %s " % sys.argv[0] - sys.exit(1) - -filename = sys.argv[1] -beats = [] - -s = source(filename, samplerate, hop_s) -t = tempo("default", win_s, hop_s) - -block_read = 0 -while True: - samples, read = s() - isbeat = t(samples) - if isbeat: - thisbeat = (block_read * hop_s + isbeat[0]) / samplerate - print "%.4f" % thisbeat - beats.append (thisbeat) - block_read += 1 - if read < hop_s: break - -periods = [60./(b - a) for a,b in zip(beats[:-1],beats[1:])] - -from numpy import mean, median -print 'mean period:', mean(periods), 'bpm' -print 'median period:', median(periods), 'bpm' - -from pylab import plot, show -plot(beats[1:], periods) -show() diff --git a/interfaces/python/demo_filterbank_slaney.py b/interfaces/python/demo_filterbank_slaney.py deleted file mode 100755 index 636dc809..00000000 --- a/interfaces/python/demo_filterbank_slaney.py +++ /dev/null @@ -1,21 +0,0 @@ -#! /usr/bin/env python - -from aubio import filterbank -from numpy import array, arange, vstack - -win_s = 8192 -samplerate = 16000 - -f = filterbank(40, win_s) -f.set_mel_coeffs_slaney(samplerate) - -from pylab import loglog, title, show, xlim, ylim, xlabel, ylabel -xlim([0,samplerate / 2]) -times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * 40) -loglog(times.T, f.get_coeffs().T, '.-') -title('Mel frequency bands coefficients') -xlim([100, 7500]) -ylim([1.0e-3, 2.0e-2]) -xlabel('Frequency (Hz)') -ylabel('Amplitude') -show() diff --git a/interfaces/python/demo_filterbank_triangle_bands.py b/interfaces/python/demo_filterbank_triangle_bands.py deleted file mode 100755 index 7b02e7d9..00000000 --- a/interfaces/python/demo_filterbank_triangle_bands.py +++ /dev/null @@ -1,47 +0,0 @@ -#! /usr/bin/env python - -from aubio import filterbank, fvec -from pylab import loglog, show, subplot, xlim, ylim, xlabel, ylabel, title -from numpy import vstack, arange - -win_s = 2048 -samplerate = 48000 - -freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000] -n_filters = len(freq_list) - 2 - -f = filterbank(n_filters, win_s) -freqs = fvec(freq_list) -f.set_triangle_bands(freqs, samplerate) - -subplot(211) -title('Examples of filterbank built with set_triangle_bands and set_coeffs') -times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters) -loglog(times.T, f.get_coeffs().T, '.-') -xlim([50, samplerate/2]) -ylim([1.0e-6, 2.0e-2]) -ylabel('Amplitude') - -## build a new filterbank - -freq_list = [60, 80, 200, 400, 800, 1200, 1600, 3200, 6400, 10000, 15000, 24000] -n_filters = len(freq_list) - 2 - -f = filterbank(n_filters, win_s) -freqs = fvec(freq_list) -f.set_triangle_bands(freqs, samplerate) - -coeffs = f.get_coeffs() -coeffs[4] *= 5. - -f.set_coeffs(coeffs) - -subplot(212) -times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters) -loglog(times.T, f.get_coeffs().T, '.-') -xlim([50, samplerate/2]) -ylim([1.0e-6, 2.0e-2]) -xlabel('Frequency (Hz)') -ylabel('Amplitude') - -show() diff --git a/interfaces/python/demo_onset_sinusoid.py b/interfaces/python/demo_onset_sinusoid.py deleted file mode 100755 index 97f9231d..00000000 --- a/interfaces/python/demo_onset_sinusoid.py +++ /dev/null @@ -1,84 +0,0 @@ -#! /usr/bin/env python - -from numpy import random, sin, arange, ones, zeros -from math import pi -from aubio import fvec, onset - -def build_sinusoid(length, freqs, samplerate): - return sin( 2. * pi * arange(length) * freqs / samplerate) - -def run_onset(p, input_vec): - f = fvec (p.hop_size) - cands = [] - count = 0 - for vec_slice in input_vec.reshape((-1, p.hop_size)): - f[:] = vec_slice - cands.append(o(f)) - return cands - -methods = ['default', - 'energy', - 'complex', - 'phase', - 'specdiff', - 'kl', - 'mkl', - 'specflux', - 'centroid', - 'spread', - 'skewness', - 'kurtosis', - 'slope', - 'decrease', - 'rolloff', - ] - -cands = {} -buf_size = 2048 -hop_size = 512 -samplerate = 44100 -sin_length = (samplerate * 10) % 512 * 512 -freqs = zeros(sin_length) - -partition = sin_length / 8 -pointer = 0 - -pointer += partition -freqs[pointer: pointer + partition] = 440 - -pointer += partition -pointer += partition -freqs[ pointer : pointer + partition ] = 740 - -pointer += partition -freqs[ pointer : pointer + partition ] = 1480 - -pointer += partition -pointer += partition -freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8) - -a = build_sinusoid(sin_length, freqs, samplerate) - -for method in methods: - o = onset(method, buf_size, hop_size, samplerate) - cands[method] = run_onset(o, a) - -print "done computing" - -if 1: - from pylab import plot, show, xlabel, ylabel, legend, ylim, subplot - subplot (211) - legend(methods+['ground truth'], 'upper right') - xlabel('time (s)') - ylabel('amplitude') - ramp = arange(0, sin_length).astype('float') / samplerate - plot(ramp, a, ':') - subplot (212) - ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate - for method in methods: - plot(ramp, cands[method],'.-') - legend(methods, 'upper right') - xlabel('time (s)') - ylabel('spectral descriptor value') - show() - diff --git a/interfaces/python/demo_pitch_sinusoid.py b/interfaces/python/demo_pitch_sinusoid.py deleted file mode 100755 index 6407e586..00000000 --- a/interfaces/python/demo_pitch_sinusoid.py +++ /dev/null @@ -1,68 +0,0 @@ -#! /usr/bin/env python - -from numpy import random, sin, arange, ones, zeros -from math import pi -from aubio import fvec, pitch - -def build_sinusoid(length, freqs, samplerate): - return sin( 2. * pi * arange(length) * freqs / samplerate) - -def run_pitch(p, input_vec): - f = fvec (p.hop_size) - cands = [] - count = 0 - for vec_slice in input_vec.reshape((-1, p.hop_size)): - f[:] = vec_slice - cands.append(p(f)) - return cands - -methods = ['default', 'schmitt', 'fcomb', 'mcomb', 'yin', 'yinfft'] - -cands = {} -buf_size = 2048 -hop_size = 512 -samplerate = 44100 -sin_length = (samplerate * 10) % 512 * 512 -freqs = zeros(sin_length) - -partition = sin_length / 8 -pointer = 0 - -pointer += partition -freqs[pointer: pointer + partition] = 440 - -pointer += partition -pointer += partition -freqs[ pointer : pointer + partition ] = 740 - -pointer += partition -freqs[ pointer : pointer + partition ] = 1480 - -pointer += partition -pointer += partition -freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8) - -a = build_sinusoid(sin_length, freqs, samplerate) - -for method in methods: - p = pitch(method, buf_size, hop_size, samplerate) - cands[method] = run_pitch(p, a) - -print "done computing" - -if 1: - from pylab import plot, show, xlabel, ylabel, legend, ylim - ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate - for method in methods: - plot(ramp, cands[method],'.-') - - # plot ground truth - ramp = arange(0, sin_length).astype('float') / samplerate - plot(ramp, freqs, ':') - - legend(methods+['ground truth'], 'upper right') - xlabel('time (s)') - ylabel('frequency (Hz)') - ylim([0,2000]) - show() - diff --git a/interfaces/python/demo_simple_robot_voice.py b/interfaces/python/demo_simple_robot_voice.py deleted file mode 100755 index 84c9c6ec..00000000 --- a/interfaces/python/demo_simple_robot_voice.py +++ /dev/null @@ -1,29 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import source, sink, pvoc - -if __name__ == '__main__': - if len(sys.argv) < 2: - print 'usage: %s ' % sys.argv[0] - sys.exit(1) - samplerate = 44100 - f = source(sys.argv[1], samplerate, 256) - g = sink(sys.argv[2], samplerate) - total_frames, read = 0, 256 - - win_s = 512 # fft size - hop_s = win_s / 2 # hop size - pv = pvoc(win_s, hop_s) # phase vocoder - - while read: - samples, read = f() - spectrum = pv(samples) # compute spectrum - spectrum.phas[:] = 0. # zero phase - new_samples = pv.rdo(spectrum) # compute modified samples - g(new_samples, read) # write to output - total_frames += read - - print "wrote", total_frames, "from", f.uri, "to", g.uri - - diff --git a/interfaces/python/demo_sink.py b/interfaces/python/demo_sink.py deleted file mode 100755 index 702838c5..00000000 --- a/interfaces/python/demo_sink.py +++ /dev/null @@ -1,17 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import source, sink - -if __name__ == '__main__': - if len(sys.argv) < 3: - print 'usage: %s ' % sys.argv[0] - sys.exit(1) - f = source(sys.argv[1], 8000, 256) - g = sink(sys.argv[2], 8000) - total_frames, read = 0, 256 - while read: - vec, read = f() - g(vec, read) - total_frames += read - print "read", total_frames / float(f.samplerate), "seconds from", f.uri diff --git a/interfaces/python/demo_source.py b/interfaces/python/demo_source.py deleted file mode 100755 index 65925fc0..00000000 --- a/interfaces/python/demo_source.py +++ /dev/null @@ -1,15 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import source - -if __name__ == '__main__': - if len(sys.argv) < 2: - print 'usage: %s ' % sys.argv[0] - sys.exit(1) - f = source(sys.argv[1], 8000, 256) - total_frames, read = 0, 256 - while read: - vec, read = f() - total_frames += read - print "read", total_frames / float(f.samplerate), "seconds from", f.uri diff --git a/interfaces/python/demo_spectrogram.py b/interfaces/python/demo_spectrogram.py deleted file mode 100755 index 16bd69ef..00000000 --- a/interfaces/python/demo_spectrogram.py +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import pvoc, source -from numpy import array, arange, zeros, shape, log10, vstack -from pylab import imshow, show, cm, axis, ylabel, xlabel, xticks, yticks - -def get_spectrogram(filename): - samplerate = 44100 - win_s = 512 # fft window size - hop_s = win_s / 2 # hop size - fft_s = win_s / 2 + 1 # spectrum bins - - a = source(filename, samplerate, hop_s) # source file - pv = pvoc(win_s, hop_s) # phase vocoder - specgram = zeros([0, fft_s], dtype='float32') # numpy array to store spectrogram - - # analysis - while True: - samples, read = a() # read file - specgram = vstack((specgram,pv(samples).norm)) # store new norm vector - if read < a.hop_size: break - - # plotting - imshow(log10(specgram.T + .001), origin = 'bottom', aspect = 'auto', cmap=cm.gray_r) - axis([0, len(specgram), 0, len(specgram[0])]) - # show axes in Hz and seconds - time_step = hop_s / float(samplerate) - total_time = len(specgram) * time_step - print "total time: %0.2fs" % total_time, - print ", samplerate: %.2fkHz" % (samplerate / 1000.) - n_xticks = 10 - n_yticks = 10 - - def get_rounded_ticks( top_pos, step, n_ticks ): - top_label = top_pos * step - # get the first label - ticks_first_label = top_pos * step / n_ticks - # round to the closest .1 - ticks_first_label = round ( ticks_first_label * 10. ) / 10. - # compute all labels from the first rounded one - ticks_labels = [ ticks_first_label * n for n in range(n_ticks) ] + [ top_label ] - # get the corresponding positions - ticks_positions = [ ticks_labels[n] / step for n in range(n_ticks) ] + [ top_pos ] - # convert to string - ticks_labels = [ "%.1f" % x for x in ticks_labels ] - # return position, label tuple to use with x/yticks - return ticks_positions, ticks_labels - - # apply to the axis - xticks( *get_rounded_ticks ( len(specgram), time_step, n_xticks ) ) - yticks( *get_rounded_ticks ( len(specgram[0]), (samplerate / 2. / 1000.) / len(specgram[0]), n_yticks ) ) - ylabel('Frequency (kHz)') - xlabel('Time (s)') - -if __name__ == '__main__': - if len(sys.argv) < 2: - print "Usage: %s " % sys.argv[0] - else: - for soundfile in sys.argv[1:]: - get_spectrogram(soundfile) - # display graph - show() diff --git a/interfaces/python/demo_tss.py b/interfaces/python/demo_tss.py deleted file mode 100755 index 0d670ce1..00000000 --- a/interfaces/python/demo_tss.py +++ /dev/null @@ -1,47 +0,0 @@ -#! /usr/bin/env python - -import sys -from aubio import source, sink, pvoc, tss - -if __name__ == '__main__': - if len(sys.argv) < 2: - print 'usage: %s ' % sys.argv[0] - sys.exit(1) - - samplerate = 44100 - win_s = 512 # fft size - hop_s = win_s / 2 # block size - threshold = 0.26 - - f = source(sys.argv[1], samplerate, hop_s) - g = sink(sys.argv[2], samplerate) - h = sink(sys.argv[3], samplerate) - - pv = pvoc(win_s, hop_s) # phase vocoder - pw = pvoc(win_s, hop_s) # another phase vocoder - t = tss(win_s, hop_s) # transient steady state separation - - t.set_threshold(threshold) - - read = hop_s - - while read: - samples, read = f() # read file - spec = pv(samples) # compute spectrum - trans_spec, stead_spec = t(spec) # transient steady-state separation - transients = pv.rdo(trans_spec) # overlap-add synthesis of transients - steadstate = pw.rdo(stead_spec) # overlap-add synthesis of steady states - g(transients, read) # write transients to output - h(steadstate, read) # write steady states to output - - del f, g, h # finish writing the files now - - from demo_spectrogram import get_spectrogram - from pylab import subplot, show - subplot(311) - get_spectrogram(sys.argv[1]) - subplot(312) - get_spectrogram(sys.argv[2]) - subplot(313) - get_spectrogram(sys.argv[3]) - show() diff --git a/interfaces/python/gen_pyobject.py b/interfaces/python/gen_pyobject.py deleted file mode 100644 index 20f4534a..00000000 --- a/interfaces/python/gen_pyobject.py +++ /dev/null @@ -1,526 +0,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], -} - -# TODO -# do function: for now, only the following pattern is supported: -# void aubio__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 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'], -} - -# default value for variables -aubioinitvalue = { - 'uint_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', - '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)PyInt_AsLong', -} - -# aubio to python -aubiovectopyobj = { - 'fvec_t*': 'PyAubio_CFvecToArray', - 'cvec_t*': 'PyAubio_CCvecToPyCvec', - 'smpl_t': 'PyFloat_FromDouble', - 'uint_t*': 'PyInt_FromLong', - 'uint_t': 'PyInt_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(map(lambda p: aubio2pytypes[p['type']], 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 (%(pname)s > 0) { - self->%(pname)s = %(pname)s; - } else if (%(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(map(lambda p: p['type'] + ' ' + p['name'] + ";", 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 = " return Py_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__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: - 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__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; - } - return Py_None; -} -""" % {'funcname': method_name, 'objname': name, - 'out_type': out_type, 'setter_args': setter_args, 'parse_args': parse_args } - shortname = method_name.split(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__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(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 diff --git a/interfaces/python/generator.py b/interfaces/python/generator.py deleted file mode 100755 index 0bbd20e4..00000000 --- a/interfaces/python/generator.py +++ /dev/null @@ -1,187 +0,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) - - 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_object_files(): - if os.path.isdir('generated'): shutil.rmtree('generated') - os.mkdir('generated') - - generated_objects = [] - cpp_output, cpp_objects = get_cpp_objects() - skip_objects = ['fft', - 'pvoc', - 'filter', - 'filterbank', - 'resampler', - 'sndfile', - 'sink_apple_audio', - 'sink_sndfile', - 'source_apple_audio', - 'source_sndfile'] - - 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) - #for method in object_methods: - # write_msg(method) - new_methods = 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 = 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 = 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) - - 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 = 'generated/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 - -""" - - for each in generated_objects: - s += "extern PyTypeObject Py_%sType;\n" % \ - each.replace('aubio_','').replace('_t','') - - types_ready = [] - for each in generated_objects: - types_ready.append(" PyType_Ready (&Py_%sType) < 0" % \ - each.replace('aubio_','').replace('_t','') ) - - 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('generated/aubio-generated.h', 'w') - fd.write(s) - - from os import listdir - generated_files = listdir('generated') - generated_files = filter(lambda x: x.endswith('.c'), generated_files) - generated_files = ['generated/'+f for f in generated_files] - return generated_files - -if __name__ == '__main__': - generate_object_files() diff --git a/interfaces/python/py-cvec.c b/interfaces/python/py-cvec.c deleted file mode 100644 index 940508fb..00000000 --- a/interfaces/python/py-cvec.c +++ /dev/null @@ -1,302 +0,0 @@ -#include "aubio-types.h" - -/* cvec type definition - -class cvec(): - def __init__(self, length = 1024): - self.length = length - self.norm = array(length) - self.phas = array(length) - -*/ - -static char Py_cvec_doc[] = "cvec object"; - -static PyObject * -Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds) -{ - int length= 0; - Py_cvec *self; - static char *kwlist[] = { "length", NULL }; - - if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, - &length)) { - return NULL; - } - - - self = (Py_cvec *) type->tp_alloc (type, 0); - - self->length = Py_default_vector_length / 2 + 1; - - if (self == NULL) { - return NULL; - } - - if (length > 0) { - self->length = length / 2 + 1; - } else if (length < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative number of elements"); - return NULL; - } - - return (PyObject *) self; -} - -static int -Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds) -{ - self->o = new_cvec ((self->length - 1) * 2); - if (self->o == NULL) { - return -1; - } - - return 0; -} - -static void -Py_cvec_del (Py_cvec * self) -{ - del_cvec (self->o); - self->ob_type->tp_free ((PyObject *) self); -} - -static PyObject * -Py_cvec_repr (Py_cvec * self, PyObject * unused) -{ - PyObject *format = NULL; - PyObject *args = NULL; - PyObject *result = NULL; - - format = PyString_FromString ("aubio cvec of %d elements"); - if (format == NULL) { - goto fail; - } - - args = Py_BuildValue ("I", self->length); - if (args == NULL) { - goto fail; - } - cvec_print ( self->o ); - - result = PyString_Format (format, args); - -fail: - Py_XDECREF (format); - Py_XDECREF (args); - - return result; -} - -PyObject * -PyAubio_CvecNormToArray (Py_cvec * self) -{ - npy_intp dims[] = { self->o->length, 1 }; - return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm); -} - - -PyObject * -PyAubio_CvecPhasToArray (Py_cvec * self) -{ - npy_intp dims[] = { self->o->length, 1 }; - return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas); -} - -PyObject * -PyAubio_ArrayToCvecPhas (PyObject * self) -{ - return NULL; -} - -PyObject * -Py_cvec_get_norm (Py_cvec * self, void *closure) -{ - return PyAubio_CvecNormToArray(self); -} - -PyObject * -Py_cvec_get_phas (Py_cvec * self, void *closure) -{ - return PyAubio_CvecPhasToArray(self); -} - -static int -Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure) -{ - PyArrayObject * array; - if (input == NULL) { - PyErr_SetString (PyExc_ValueError, "input array is not a python object"); - goto fail; - } - if (PyArray_Check(input)) { - - // we got an array, convert it to a cvec.norm - if (PyArray_NDIM ((PyArrayObject *)input) == 0) { - PyErr_SetString (PyExc_ValueError, "input array is a scalar"); - goto fail; - } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { - PyErr_SetString (PyExc_ValueError, - "input array has more than two dimensions"); - goto fail; - } - - if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { - PyErr_SetString (PyExc_ValueError, "input array should be float"); - goto fail; - } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { - PyErr_SetString (PyExc_ValueError, "input array should be float32"); - goto fail; - } - array = (PyArrayObject *)input; - - // check input array dimensions - if (PyArray_NDIM (array) != 1) { - PyErr_Format (PyExc_ValueError, - "input array has %d dimensions, not 1", - PyArray_NDIM (array)); - goto fail; - } else { - if (vec->o->length != PyArray_SIZE (array)) { - PyErr_Format (PyExc_ValueError, - "input array has length %d, but cvec has length %d", - (int)PyArray_SIZE (array), vec->o->length); - goto fail; - } - } - - vec->o->norm = (smpl_t *) PyArray_GETPTR1 (array, 0); - - } else { - PyErr_SetString (PyExc_ValueError, "can only accept array as input"); - return 1; - } - - Py_INCREF(array); - return 0; - -fail: - return 1; -} - -static int -Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) -{ - PyArrayObject * array; - if (input == NULL) { - PyErr_SetString (PyExc_ValueError, "input array is not a python object"); - goto fail; - } - if (PyArray_Check(input)) { - - // we got an array, convert it to a cvec.phas - if (PyArray_NDIM ((PyArrayObject *)input) == 0) { - PyErr_SetString (PyExc_ValueError, "input array is a scalar"); - goto fail; - } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { - PyErr_SetString (PyExc_ValueError, - "input array has more than two dimensions"); - goto fail; - } - - if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { - PyErr_SetString (PyExc_ValueError, "input array should be float"); - goto fail; - } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { - PyErr_SetString (PyExc_ValueError, "input array should be float32"); - goto fail; - } - array = (PyArrayObject *)input; - - // check input array dimensions - if (PyArray_NDIM (array) != 1) { - PyErr_Format (PyExc_ValueError, - "input array has %d dimensions, not 1", - PyArray_NDIM (array)); - goto fail; - } else { - if (vec->o->length != PyArray_SIZE (array)) { - PyErr_Format (PyExc_ValueError, - "input array has length %d, but cvec has length %d", - (int)PyArray_SIZE (array), vec->o->length); - goto fail; - } - } - - vec->o->phas = (smpl_t *) PyArray_GETPTR1 (array, 0); - - } else { - PyErr_SetString (PyExc_ValueError, "can only accept array as input"); - return 1; - } - - Py_INCREF(array); - return 0; - -fail: - return 1; -} - -static PyMemberDef Py_cvec_members[] = { - // TODO remove READONLY flag and define getter/setter - {"length", T_INT, offsetof (Py_cvec, length), READONLY, - "length attribute"}, - {NULL} /* Sentinel */ -}; - -static PyMethodDef Py_cvec_methods[] = { - {NULL} -}; - -static PyGetSetDef Py_cvec_getseters[] = { - {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, - "Numpy vector of shape (length,) containing the magnitude", - NULL}, - {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, - "Numpy vector of shape (length,) containing the phase", - NULL}, - {NULL} /* sentinel */ -}; - -PyTypeObject Py_cvecType = { - PyObject_HEAD_INIT (NULL) - 0, /* ob_size */ - "aubio.cvec", /* tp_name */ - sizeof (Py_cvec), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) Py_cvec_del, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc) Py_cvec_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - Py_cvec_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Py_cvec_methods, /* tp_methods */ - Py_cvec_members, /* tp_members */ - Py_cvec_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc) Py_cvec_init, /* tp_init */ - 0, /* tp_alloc */ - Py_cvec_new, /* tp_new */ -}; diff --git a/interfaces/python/py-fft.c b/interfaces/python/py-fft.c deleted file mode 100644 index 19d7b49b..00000000 --- a/interfaces/python/py-fft.c +++ /dev/null @@ -1,107 +0,0 @@ -#include "aubiowraphell.h" - -static char Py_fft_doc[] = "fft object"; - -AUBIO_DECLARE(fft, uint_t win_s) - -//AUBIO_NEW(fft) -static PyObject * -Py_fft_new (PyTypeObject * type, PyObject * args, PyObject * kwds) -{ - int win_s = 0; - Py_fft *self; - static char *kwlist[] = { "win_s", NULL }; - - if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, - &win_s)) { - return NULL; - } - - self = (Py_fft *) type->tp_alloc (type, 0); - - if (self == NULL) { - return NULL; - } - - self->win_s = Py_default_vector_length; - - if (self == NULL) { - return NULL; - } - - if (win_s > 0) { - self->win_s = win_s; - } else if (win_s < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative window size"); - return NULL; - } - - return (PyObject *) self; -} - - -AUBIO_INIT(fft, self->win_s) - -AUBIO_DEL(fft) - -static PyObject * -Py_fft_do(PyObject * self, PyObject * args) -{ - PyObject *input; - fvec_t *vec; - cvec_t *output; - - if (!PyArg_ParseTuple (args, "O", &input)) { - return NULL; - } - - vec = PyAubio_ArrayToCFvec (input); - - if (vec == NULL) { - return NULL; - } - - output = new_cvec(((Py_fft *) self)->win_s); - - // compute the function - aubio_fft_do (((Py_fft *)self)->o, vec, output); - return (PyObject *)PyAubio_CCvecToPyCvec(output); -} - -AUBIO_MEMBERS_START(fft) - {"win_s", T_INT, offsetof (Py_fft, win_s), READONLY, - "size of the window"}, -AUBIO_MEMBERS_STOP(fft) - -static PyObject * -Py_fft_rdo(Py_fft * self, PyObject * args) -{ - PyObject *input; - cvec_t *vec; - fvec_t *output; - - if (!PyArg_ParseTuple (args, "O", &input)) { - return NULL; - } - - vec = PyAubio_ArrayToCCvec (input); - - if (vec == NULL) { - return NULL; - } - - output = new_fvec(self->win_s); - - // compute the function - aubio_fft_rdo (((Py_fft *)self)->o, vec, output); - return (PyObject *)PyAubio_CFvecToArray(output); -} - -static PyMethodDef Py_fft_methods[] = { - {"rdo", (PyCFunction) Py_fft_rdo, METH_VARARGS, - "synthesis of spectral grain"}, - {NULL} -}; - -AUBIO_TYPEOBJECT(fft, "aubio.fft") diff --git a/interfaces/python/py-filter.c b/interfaces/python/py-filter.c deleted file mode 100644 index 5b9fee64..00000000 --- a/interfaces/python/py-filter.c +++ /dev/null @@ -1,198 +0,0 @@ -#include "aubio-types.h" - -typedef struct -{ - PyObject_HEAD - aubio_filter_t * o; - uint_t order; -} Py_filter; - -static char Py_filter_doc[] = "filter object"; - -static PyObject * -Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds) -{ - int order= 0; - Py_filter *self; - static char *kwlist[] = { "order", NULL }; - - if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, - &order)) { - return NULL; - } - - self = (Py_filter *) type->tp_alloc (type, 0); - - if (self == NULL) { - return NULL; - } - - self->order = 7; - - if (order > 0) { - self->order = order; - } else if (order < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative order"); - return NULL; - } - - return (PyObject *) self; -} - -static int -Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds) -{ - self->o = new_aubio_filter (self->order); - if (self->o == NULL) { - return -1; - } - - return 0; -} - -static void -Py_filter_del (Py_filter * self) -{ - del_aubio_filter (self->o); - self->ob_type->tp_free ((PyObject *) self); -} - -static PyObject * -Py_filter_do(Py_filter * self, PyObject * args) -{ - PyObject *input; - fvec_t *vec; - - if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) { - return NULL; - } - - if (input == NULL) { - return NULL; - } - - vec = PyAubio_ArrayToCFvec (input); - - if (vec == NULL) { - return NULL; - } - - // compute the function - fvec_t * out = new_fvec(vec->length); - aubio_filter_do_outplace (self->o, vec, out); - return PyAubio_CFvecToArray(out); -} - -static PyObject * -Py_filter_set_c_weighting (Py_filter * self, PyObject *args) -{ - uint_t err = 0; - uint_t samplerate; - if (!PyArg_ParseTuple (args, "I", &samplerate)) { - return NULL; - } - - err = aubio_filter_set_c_weighting (self->o, samplerate); - if (err > 0) { - PyErr_SetString (PyExc_ValueError, - "error when setting filter to C-weighting"); - return NULL; - } - return Py_None; -} - -static PyObject * -Py_filter_set_a_weighting (Py_filter * self, PyObject *args) -{ - uint_t err = 0; - uint_t samplerate; - if (!PyArg_ParseTuple (args, "I", &samplerate)) { - return NULL; - } - - err = aubio_filter_set_a_weighting (self->o, samplerate); - if (err > 0) { - PyErr_SetString (PyExc_ValueError, - "error when setting filter to A-weighting"); - return NULL; - } - return Py_None; -} - -static PyObject * -Py_filter_set_biquad(Py_filter * self, PyObject *args) -{ - uint_t err = 0; - lsmp_t b0, b1, b2, a1, a2; - if (!PyArg_ParseTuple (args, "ddddd", &b0, &b1, &b2, &a1, &a2)) { - return NULL; - } - - err = aubio_filter_set_biquad (self->o, b0, b1, b2, a1, a2); - if (err > 0) { - PyErr_SetString (PyExc_ValueError, - "error when setting filter with biquad coefficients"); - return NULL; - } - return Py_None; -} - -static PyMemberDef Py_filter_members[] = { - // TODO remove READONLY flag and define getter/setter - {"order", T_INT, offsetof (Py_filter, order), READONLY, - "order of the filter"}, - {NULL} /* Sentinel */ -}; - -static PyMethodDef Py_filter_methods[] = { - {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_VARARGS, - "set filter coefficients to C-weighting"}, - {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_VARARGS, - "set filter coefficients to A-weighting"}, - {"set_biquad", (PyCFunction) Py_filter_set_biquad, METH_VARARGS, - "set b0, b1, b2, a1, a2 biquad coefficients"}, - {NULL} -}; - -PyTypeObject Py_filterType = { - PyObject_HEAD_INIT (NULL) - 0, /* ob_size */ - "aubio.digital_filter", /* tp_name */ - sizeof (Py_filter), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor) Py_filter_del, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, //(reprfunc) Py_filter_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)Py_filter_do, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - Py_filter_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Py_filter_methods, /* tp_methods */ - Py_filter_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc) Py_filter_init, /* tp_init */ - 0, /* tp_alloc */ - Py_filter_new, /* tp_new */ -}; diff --git a/interfaces/python/py-filterbank.c b/interfaces/python/py-filterbank.c deleted file mode 100644 index cc0da481..00000000 --- a/interfaces/python/py-filterbank.c +++ /dev/null @@ -1,183 +0,0 @@ -#include "aubiowraphell.h" - -static char Py_filterbank_doc[] = "filterbank object"; - -AUBIO_DECLARE(filterbank, uint_t n_filters; uint_t win_s) - -//AUBIO_NEW(filterbank) -static PyObject * -Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds) -{ - int win_s = 0, n_filters = 0; - Py_filterbank *self; - static char *kwlist[] = { "n_filters", "win_s", NULL }; - - if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, - &n_filters, &win_s)) { - return NULL; - } - - self = (Py_filterbank *) type->tp_alloc (type, 0); - - if (self == NULL) { - return NULL; - } - - self->win_s = Py_default_vector_length; - if (win_s > 0) { - self->win_s = win_s; - } else if (win_s < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative window size"); - return NULL; - } - - self->n_filters = 40; - if (n_filters > 0) { - self->n_filters = n_filters; - } else if (n_filters < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative number of filters"); - return NULL; - } - - return (PyObject *) self; -} - - -AUBIO_INIT(filterbank, self->n_filters, self->win_s) - -AUBIO_DEL(filterbank) - -static PyObject * -Py_filterbank_do(Py_filterbank * self, PyObject * args) -{ - PyObject *input; - cvec_t *vec; - fvec_t *out; - - if (!PyArg_ParseTuple (args, "O", &input)) { - return NULL; - } - - vec = PyAubio_ArrayToCCvec (input); - - if (vec == NULL) { - return NULL; - } - - out = new_fvec (self->n_filters); - - // compute the function - aubio_filterbank_do (self->o, vec, out); - return (PyObject *)PyAubio_CFvecToArray(out); -} - -AUBIO_MEMBERS_START(filterbank) - {"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY, - "size of the window"}, - {"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY, - "number of filters"}, -AUBIO_MEMBERS_STOP(filterbank) - -static PyObject * -Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) -{ - uint_t err = 0; - - PyObject *input; - uint_t samplerate; - fvec_t *freqs; - if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) { - return NULL; - } - - if (input == NULL) { - return NULL; - } - - freqs = PyAubio_ArrayToCFvec (input); - - if (freqs == NULL) { - return NULL; - } - - err = aubio_filterbank_set_triangle_bands (self->o, - freqs, samplerate); - if (err > 0) { - PyErr_SetString (PyExc_ValueError, - "error when setting filter to A-weighting"); - return NULL; - } - return Py_None; -} - -static PyObject * -Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) -{ - uint_t err = 0; - - uint_t samplerate; - if (!PyArg_ParseTuple (args, "I", &samplerate)) { - return NULL; - } - - err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate); - if (err > 0) { - PyErr_SetString (PyExc_ValueError, - "error when setting filter to A-weighting"); - return NULL; - } - return Py_None; -} - -static PyObject * -Py_filterbank_set_coeffs (Py_filterbank * self, PyObject *args) -{ - uint_t err = 0; - - PyObject *input; - fmat_t *coeffs; - - if (!PyArg_ParseTuple (args, "O", &input)) { - return NULL; - } - - coeffs = PyAubio_ArrayToCFmat (input); - - if (coeffs == NULL) { - PyErr_SetString (PyExc_ValueError, - "unable to parse input array"); - return NULL; - } - - err = aubio_filterbank_set_coeffs (self->o, coeffs); - - if (err > 0) { - PyErr_SetString (PyExc_ValueError, - "error when setting filter coefficients"); - return NULL; - } - return Py_None; -} - -static PyObject * -Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused) -{ - return (PyObject *)PyAubio_CFmatToArray( - aubio_filterbank_get_coeffs (self->o) ); -} - -static PyMethodDef Py_filterbank_methods[] = { - {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands, - METH_VARARGS, "set coefficients of filterbanks"}, - {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney, - METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"}, - {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs, - METH_NOARGS, "get coefficients of filterbank"}, - {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs, - METH_VARARGS, "set coefficients of filterbank"}, - {NULL} -}; - -AUBIO_TYPEOBJECT(filterbank, "aubio.filterbank") diff --git a/interfaces/python/py-phasevoc.c b/interfaces/python/py-phasevoc.c deleted file mode 100644 index 6767e921..00000000 --- a/interfaces/python/py-phasevoc.c +++ /dev/null @@ -1,118 +0,0 @@ -#include "aubiowraphell.h" - -static char Py_pvoc_doc[] = "pvoc object"; - -AUBIO_DECLARE(pvoc, uint_t win_s; uint_t hop_s) - -//AUBIO_NEW(pvoc) -static PyObject * -Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) -{ - int win_s = 0, hop_s = 0; - Py_pvoc *self; - static char *kwlist[] = { "win_s", "hop_s", NULL }; - - if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, - &win_s, &hop_s)) { - return NULL; - } - - self = (Py_pvoc *) type->tp_alloc (type, 0); - - if (self == NULL) { - return NULL; - } - - self->win_s = Py_default_vector_length; - self->hop_s = Py_default_vector_length/2; - - if (self == NULL) { - return NULL; - } - - if (win_s > 0) { - self->win_s = win_s; - } else if (win_s < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative window size"); - return NULL; - } - - if (hop_s > 0) { - self->hop_s = hop_s; - } else if (hop_s < 0) { - PyErr_SetString (PyExc_ValueError, - "can not use negative hop size"); - return NULL; - } - - return (PyObject *) self; -} - - -AUBIO_INIT(pvoc, self->win_s, self->hop_s) - -AUBIO_DEL(pvoc) - -static PyObject * -Py_pvoc_do(Py_pvoc * self, PyObject * args) -{ - PyObject *input; - fvec_t *vec; - cvec_t *output; - - if (!PyArg_ParseTuple (args, "O", &input)) { - return NULL; - } - - vec = PyAubio_ArrayToCFvec (input); - - if (vec == NULL) { - return NULL; - } - - output = new_cvec(self->win_s); - - // compute the function - aubio_pvoc_do (self->o, vec, output); - return (PyObject *)PyAubio_CCvecToPyCvec(output); -} - -AUBIO_MEMBERS_START(pvoc) - {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY, - "size of the window"}, - {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY, - "size of the hop"}, -AUBIO_MEMBERS_STOP(pvoc) - -static PyObject * -Py_pvoc_rdo(Py_pvoc * self, PyObject * args) -{ - PyObject *input; - cvec_t *vec; - fvec_t *output; - - if (!PyArg_ParseTuple (args, "O", &input)) { - return NULL; - } - - vec = PyAubio_ArrayToCCvec (input); - - if (vec == NULL) { - return NULL; - } - - output = new_fvec(self->hop_s); - - // compute the function - aubio_pvoc_rdo (self->o, vec, output); - return (PyObject *)PyAubio_CFvecToArray(output); -} - -static PyMethodDef Py_pvoc_methods[] = { - {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS, - "synthesis of spectral grain"}, - {NULL} -}; - -AUBIO_TYPEOBJECT(pvoc, "aubio.pvoc") diff --git a/interfaces/python/run_all_tests b/interfaces/python/run_all_tests deleted file mode 100755 index ad18a92c..00000000 --- a/interfaces/python/run_all_tests +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env python - -if __name__ == '__main__': - import os, sys, unittest - def load_test(): - # get relevant files - curdir = os.path.dirname(sys.argv[0]) - if curdir == '': curdir = '.' - files = os.listdir(curdir) - modfiles = filter (lambda y: y.endswith('.py'), files) - modfiles = filter (lambda f: f.startswith('test_'), modfiles) - # get module names - modnames = map (lambda x: os.path.splitext(x)[0], modfiles) - # import them - modules = map (__import__, modnames) - # create a test suites from the imported module - load_from_module = unittest.defaultTestLoader.loadTestsFromModule - tests = map(load_from_module, modules) - return unittest.TestSuite(tests) - unittest.main(defaultTest = 'load_test') diff --git a/interfaces/python/setup.py b/interfaces/python/setup.py deleted file mode 100755 index ef05441d..00000000 --- a/interfaces/python/setup.py +++ /dev/null @@ -1,41 +0,0 @@ -#! /usr/bin/python - -from distutils.core import setup, Extension -from generator import generate_object_files -import os.path -import numpy - -library_dirs = ['../../build/src', '../../src/.libs'] -include_dirs = ['../../build/src', '../../src', '.' ] -library_dirs = filter (lambda x: os.path.isdir(x), library_dirs) -include_dirs = filter (lambda x: os.path.isdir(x), include_dirs) - -aubio_extension = Extension("_aubio", - ["aubiomodule.c", - "aubioproxy.c", - "py-cvec.c", - # example without macro - "py-filter.c", - # macroised - "py-filterbank.c", - "py-fft.c", - "py-phasevoc.c", - # generated files - ] + generate_object_files(), - include_dirs = include_dirs + [ numpy.get_include() ], - library_dirs = library_dirs, - libraries=['aubio']) - -setup(name='aubio', - version = '0.4.0alpha', - packages = ['aubio'], - description = 'interface to the aubio library', - long_description = 'interface to the aubio library', - license = 'GNU/GPL version 3', - author = 'Paul Brossier', - author_email = 'piem@aubio.org', - maintainer = 'Paul Brossier', - maintainer_email = 'piem@aubio.org', - url = 'http://aubio.org/', - ext_modules = [aubio_extension]) - diff --git a/interfaces/python/test_aubio.py b/interfaces/python/test_aubio.py deleted file mode 100755 index 951ade98..00000000 --- a/interfaces/python/test_aubio.py +++ /dev/null @@ -1,14 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite - -class aubiomodule_test_case(TestCase): - - def test_import(self): - """ try importing aubio """ - import aubio - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_cvec.py b/interfaces/python/test_cvec.py deleted file mode 100755 index 86916464..00000000 --- a/interfaces/python/test_cvec.py +++ /dev/null @@ -1,50 +0,0 @@ -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -from aubio import cvec -from numpy import array, shape, pi - -class aubio_cvec_test_case(TestCase): - - def test_vector_created_with_zeroes(self): - a = cvec(10) - a - shape(a.norm) - shape(a.phas) - a.norm[0] - assert_equal(a.norm, 0.) - assert_equal(a.phas, 0.) - - def test_vector_assign_element(self): - a = cvec() - a.norm[0] = 1 - assert_equal(a.norm[0], 1) - a.phas[0] = 1 - assert_equal(a.phas[0], 1) - - def test_vector_assign_element_end(self): - a = cvec() - a.norm[-1] = 1 - assert_equal(a.norm[-1], 1) - assert_equal(a.norm[len(a.norm)-1], 1) - a.phas[-1] = 1 - assert_equal(a.phas[-1], 1) - assert_equal(a.phas[len(a.phas)-1], 1) - - def test_assign_cvec_norm_slice(self): - spec = cvec(1024) - spec.norm[40:100] = 100 - assert_equal (spec.norm[0:40], 0) - assert_equal (spec.norm[40:100], 100) - assert_equal (spec.norm[100:-1], 0) - assert_equal (spec.phas, 0) - - def test_assign_cvec_phas_slice(self): - spec = cvec(1024) - spec.phas[39:-1] = -pi - assert_equal (spec.phas[0:39], 0) - assert_equal (spec.phas[39:-1], -pi) - assert_equal (spec.norm, 0) - -if __name__ == '__main__': - from unittest import main - main() diff --git a/interfaces/python/test_fft.py b/interfaces/python/test_fft.py deleted file mode 100755 index ccb6e4cf..00000000 --- a/interfaces/python/test_fft.py +++ /dev/null @@ -1,113 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -# WARNING: numpy also has an fft object -from aubio import fvec, fft, cvec -from numpy import array, shape -from math import pi - -class aubio_fft_test_case(TestCase): - - def test_members(self): - f = fft() - assert_equal (f.win_s, 1024) - - def test_output_dimensions(self): - """ check the dimensions of output """ - win_s = 1024 - timegrain = fvec(win_s) - f = fft(win_s) - fftgrain = f (timegrain) - assert_equal (fftgrain.norm, 0) - assert_equal (shape(fftgrain.norm), (win_s/2+1,)) - assert_equal (fftgrain.phas, 0) - assert_equal (shape(fftgrain.phas), (win_s/2+1,)) - - def test_zeros(self): - """ check the transform of zeros """ - win_s = 512 - timegrain = fvec(win_s) - f = fft(win_s) - fftgrain = f(timegrain) - assert_equal ( fftgrain.norm == 0, True ) - assert_equal ( fftgrain.phas == 0, True ) - - def test_impulse(self): - """ check the transform of one impulse at a random place """ - from random import random - from math import floor - win_s = 256 - i = floor(random()*win_s) - impulse = pi * random() - f = fft(win_s) - timegrain = fvec(win_s) - timegrain[i] = impulse - fftgrain = f ( timegrain ) - #self.plot_this ( fftgrain.phas ) - assert_almost_equal ( fftgrain.norm, impulse, decimal = 6 ) - assert_equal ( fftgrain.phas <= pi, True) - assert_equal ( fftgrain.phas >= -pi, True) - - def test_impulse_negative(self): - """ check the transform of one impulse at a random place """ - from random import random - from math import floor - win_s = 256 - i = 0 - impulse = -10. - f = fft(win_s) - timegrain = fvec(win_s) - timegrain[i] = impulse - fftgrain = f ( timegrain ) - #self.plot_this ( fftgrain.phas ) - assert_almost_equal ( fftgrain.norm, abs(impulse), decimal = 6 ) - if impulse < 0: - # phase can be pi or -pi, as it is not unwrapped - assert_almost_equal ( abs(fftgrain.phas[1:-1]) , pi, decimal = 6 ) - assert_almost_equal ( fftgrain.phas[0], pi, decimal = 6) - assert_almost_equal ( fftgrain.phas[-1], pi, decimal = 6) - else: - assert_equal ( fftgrain.phas[1:-1] == 0, True) - assert_equal ( fftgrain.phas[0] == 0, True) - assert_equal ( fftgrain.phas[-1] == 0, True) - # now check the resynthesis - synthgrain = f.rdo ( fftgrain ) - #self.plot_this ( fftgrain.phas.T ) - assert_equal ( fftgrain.phas <= pi, True) - assert_equal ( fftgrain.phas >= -pi, True) - #self.plot_this ( synthgrain - timegrain ) - assert_almost_equal ( synthgrain, timegrain, decimal = 6 ) - - def test_impulse_at_zero(self): - """ check the transform of one impulse at a index 0 """ - win_s = 1024 - impulse = pi - f = fft(win_s) - timegrain = fvec(win_s) - timegrain[0] = impulse - fftgrain = f ( timegrain ) - #self.plot_this ( fftgrain.phas ) - assert_equal ( fftgrain.phas[0], 0) - # could be 0 or -0 depending on fft implementation (0 for fftw3, -0 for ooura) - assert_almost_equal ( fftgrain.phas[1], 0) - assert_almost_equal ( fftgrain.norm[0], impulse, decimal = 6 ) - - def test_rdo_before_do(self): - """ check running fft.rdo before fft.do works """ - win_s = 1024 - impulse = pi - f = fft(win_s) - fftgrain = cvec(win_s) - t = f.rdo( fftgrain ) - assert_equal ( t, 0 ) - - def plot_this(self, this): - from pylab import plot, show - plot ( this ) - show () - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_filter.py b/interfaces/python/test_filter.py deleted file mode 100755 index 14a880d0..00000000 --- a/interfaces/python/test_filter.py +++ /dev/null @@ -1,68 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, assert_equal, assert_almost_equal -from aubio import fvec, digital_filter -from numpy import array - -def array_from_text_file(filename, dtype = 'float'): - return array([line.split() for line in open(filename).readlines()], - dtype = dtype) - -class aubio_filter_test_case(TestCase): - - def test_members(self): - f = digital_filter() - assert_equal (f.order, 7) - f = digital_filter(5) - assert_equal (f.order, 5) - f(fvec()) - - def test_cweighting_error(self): - f = digital_filter (2) - self.assertRaises ( ValueError, f.set_c_weighting, 44100 ) - f = digital_filter (8) - self.assertRaises ( ValueError, f.set_c_weighting, 44100 ) - f = digital_filter (5) - self.assertRaises ( ValueError, f.set_c_weighting, 4000 ) - f = digital_filter (5) - self.assertRaises ( ValueError, f.set_c_weighting, 193000 ) - f = digital_filter (7) - self.assertRaises ( ValueError, f.set_a_weighting, 193000 ) - f = digital_filter (5) - self.assertRaises ( ValueError, f.set_a_weighting, 192000 ) - - def test_c_weighting(self): - expected = array_from_text_file('c_weighting_test_simple.expected') - f = digital_filter(5) - f.set_c_weighting(44100) - v = fvec(32) - v[12] = .5 - u = f(v) - assert_almost_equal (expected[1], u) - - def test_a_weighting(self): - expected = array_from_text_file('a_weighting_test_simple.expected') - f = digital_filter(7) - f.set_a_weighting(44100) - v = fvec(32) - v[12] = .5 - u = f(v) - assert_almost_equal (expected[1], u) - - def test_a_weighting_parted(self): - expected = array_from_text_file('a_weighting_test_simple.expected') - f = digital_filter(7) - f.set_a_weighting(44100) - v = fvec(16) - v[12] = .5 - u = f(v) - assert_almost_equal (expected[1][:16], u) - # one more time - v = fvec(16) - u = f(v) - assert_almost_equal (expected[1][16:], u) - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_filterbank.py b/interfaces/python/test_filterbank.py deleted file mode 100755 index c00a5685..00000000 --- a/interfaces/python/test_filterbank.py +++ /dev/null @@ -1,23 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -from numpy import random -from aubio import cvec, filterbank - -class aubio_filterbank_test_case(TestCase): - - def test_members(self): - f = filterbank(40, 512) - assert_equal ([f.n_filters, f.win_s], [40, 512]) - - def test_set_coeffs(self): - f = filterbank(40, 512) - r = random.random([40, 512 / 2 + 1]).astype('float32') - f.set_coeffs(r) - assert_equal (r, f.get_coeffs()) - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_filterbank_mel.py b/interfaces/python/test_filterbank_mel.py deleted file mode 100755 index 532ca0b3..00000000 --- a/interfaces/python/test_filterbank_mel.py +++ /dev/null @@ -1,51 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -from numpy import array, shape -from aubio import cvec, filterbank - -class aubio_filterbank_mel_test_case(TestCase): - - def test_slaney(self): - f = filterbank(40, 512) - f.set_mel_coeffs_slaney(16000) - a = f.get_coeffs() - assert_equal(shape (a), (40, 512/2 + 1) ) - - def test_other_slaney(self): - f = filterbank(40, 512*2) - f.set_mel_coeffs_slaney(44100) - a = f.get_coeffs() - #print "sum is", sum(sum(a)) - for win_s in [256, 512, 1024, 2048, 4096]: - f = filterbank(40, win_s) - f.set_mel_coeffs_slaney(320000) - a = f.get_coeffs() - #print "sum is", sum(sum(a)) - - def test_triangle_freqs_zeros(self): - f = filterbank(9, 1024) - freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] - freqs = array(freq_list, dtype = 'float32') - f.set_triangle_bands(freqs, 48000) - f.get_coeffs().T - assert_equal ( f(cvec(1024)), 0) - - def test_triangle_freqs_ones(self): - f = filterbank(9, 1024) - freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] - freqs = array(freq_list, dtype = 'float32') - f.set_triangle_bands(freqs, 48000) - f.get_coeffs().T - spec = cvec(1024) - spec.norm[:] = 1 - assert_almost_equal ( f(spec), - [ 0.02070313, 0.02138672, 0.02127604, 0.02135417, - 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345]) - -if __name__ == '__main__': - from unittest import main - main() - - diff --git a/interfaces/python/test_fvec.py b/interfaces/python/test_fvec.py deleted file mode 100755 index 643c6f93..00000000 --- a/interfaces/python/test_fvec.py +++ /dev/null @@ -1,135 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -from aubio import fvec, zero_crossing_rate, alpha_norm, min_removal -from numpy import array, shape - -class aubio_fvec_test_case(TestCase): - - def test_vector_created_with_zeroes(self): - a = fvec(10) - a - shape(a) - a[0] - #del a - assert_equal(array(a), 0.) - - def test_vector_create_with_list(self): - a = fvec([0,1,2,3]) - assert_equal (range(4), a) - - def test_vector_assign_element(self): - a = fvec() - a[0] = 1 - assert_equal(a[0], 1) - - def test_vector_assign_element_end(self): - a = fvec() - a[-1] = 1 - assert_equal(a[-1], 1) - assert_equal(a[len(a)-1], 1) - - def test_vector(self): - a = fvec() - a, len(a) #a.length - a[0] - array(a) - a = fvec(10) - a = fvec(1) - a.T - array(a).T - a = range(len(a)) - - def test_wrong_values(self): - self.assertRaises (ValueError, fvec, -10) - - a = fvec(2) - self.assertRaises (IndexError, a.__getitem__, 3) - self.assertRaises (IndexError, a.__getitem__, 2) - - def test_alpha_norm_of_fvec(self): - a = fvec(2) - self.assertEquals (alpha_norm(a, 1), 0) - a[0] = 1 - self.assertEquals (alpha_norm(a, 1), 0.5) - a[1] = 1 - self.assertEquals (alpha_norm(a, 1), 1) - a = array([0, 1], dtype='float32') - from math import sqrt - assert_almost_equal (alpha_norm(a, 2), sqrt(2)/2.) - - def test_alpha_norm_of_none(self): - self.assertRaises (ValueError, alpha_norm, None, 1) - - def test_alpha_norm_of_array_of_float32(self): - # check scalar fails - a = array(1, dtype = 'float32') - self.assertRaises (ValueError, alpha_norm, a, 1) - # check 2d array fails - a = array([[2],[4]], dtype = 'float32') - self.assertRaises (ValueError, alpha_norm, a, 1) - # check 1d array - a = array(range(10), dtype = 'float32') - self.assertEquals (alpha_norm(a, 1), 4.5) - - def test_alpha_norm_of_array_of_int(self): - a = array(1, dtype = 'int') - self.assertRaises (ValueError, alpha_norm, a, 1) - a = array([[[1,2],[3,4]]], dtype = 'int') - self.assertRaises (ValueError, alpha_norm, a, 1) - a = array(range(10), dtype = 'int') - self.assertRaises (ValueError, alpha_norm, a, 1) - - def test_alpha_norm_of_array_of_string (self): - a = "hello" - self.assertRaises (ValueError, alpha_norm, a, 1) - - def test_zero_crossing_rate(self): - a = array([0,1,-1], dtype='float32') - assert_almost_equal (zero_crossing_rate(a), 1./3. ) - a = array([0.]*100, dtype='float32') - self.assertEquals (zero_crossing_rate(a), 0 ) - a = array([-1.]*100, dtype='float32') - self.assertEquals (zero_crossing_rate(a), 0 ) - a = array([1.]*100, dtype='float32') - self.assertEquals (zero_crossing_rate(a), 0 ) - - def test_alpha_norm_of_array_of_float64(self): - # check scalar fail - a = array(1, dtype = 'float64') - self.assertRaises (ValueError, alpha_norm, a, 1) - # check 3d array fail - a = array([[[1,2],[3,4]]], dtype = 'float64') - self.assertRaises (ValueError, alpha_norm, a, 1) - # check float64 1d array fail - a = array(range(10), dtype = 'float64') - self.assertRaises (ValueError, alpha_norm, a, 1) - # check float64 2d array fail - a = array([range(10), range(10)], dtype = 'float64') - self.assertRaises (ValueError, alpha_norm, a, 1) - - def test_fvec_min_removal_of_array(self): - a = array([20,1,19], dtype='float32') - b = min_removal(a) - assert_equal (array(b), [19, 0, 18]) - assert_equal (b, [19, 0, 18]) - assert_equal (a, b) - a[0] = 0 - assert_equal (a, b) - - def test_fvec_min_removal_of_array_float64(self): - a = array([20,1,19], dtype='float64') - self.assertRaises (ValueError, min_removal, a) - - def test_fvec_min_removal_of_fvec(self): - a = fvec(3) - a = array([20, 1, 19], dtype = 'float32') - b = min_removal(a) - assert_equal (array(b), [19, 0, 18]) - assert_equal (b, [19, 0, 18]) - assert_equal (a, b) - -if __name__ == '__main__': - from unittest import main - main() diff --git a/interfaces/python/test_onset.py b/interfaces/python/test_onset.py deleted file mode 100755 index c6642d51..00000000 --- a/interfaces/python/test_onset.py +++ /dev/null @@ -1,20 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -# WARNING: numpy also has an fft object -from aubio import onset, cvec -from numpy import array, shape, arange, zeros, log -from math import pi - -class aubio_onset(TestCase): - - def test_members(self): - o = onset() - assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate], - [1024,512,'default',44100]) - - -if __name__ == '__main__': - from unittest import main - main() diff --git a/interfaces/python/test_peakpicker.py b/interfaces/python/test_peakpicker.py deleted file mode 100755 index 08313d12..00000000 --- a/interfaces/python/test_peakpicker.py +++ /dev/null @@ -1,115 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, assert_equal, assert_almost_equal -from aubio import peakpicker, fvec - -class aubio_peakpicker(TestCase): - - def test_members(self): - o = peakpicker() - - def test_peakpicker_zeroes(self): - o = peakpicker() - assert_equal(o.get_thresholded_input(), 0.) - - def test_peakpick_set_threshold(self): - o = peakpicker() - new_threshold = threshold - o.set_threshold(new_threshold) - assert_almost_equal(new_threshold, o.get_threshold()) - - def test_peakpicker_get_threshold(self): - o = peakpicker() - new_threshold = o.get_threshold() - o.set_threshold(new_threshold) - assert_equal(new_threshold, o.get_threshold()) - -buf_size = 1024 -slice_size = 5 -delay = 1 -threshold = .9 - -class aubio_peakpicker_peaks(TestCase): - - def setUp(self): - self.o = peakpicker() - self.o.set_threshold (threshold) - self.vec = fvec(buf_size) - - def test_peakpicker_impulse(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. - self.peaks = [a] - - def test_peakpicker_ramp_up(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. / 4. * 1. - vec[a+1] = 1000. / 4. * 2. - vec[a+2] = 1000. / 4. * 3. - vec[a+3] = 1000. - self.peaks = [a+1] - - def test_peakpicker_ramp_down(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. - vec[a+1] = 1000. / 4. * 3. - vec[a+2] = 1000. / 4. * 2. - vec[a+3] = 1000. / 4. * 1. - self.peaks = [a] - - def test_peakpicker_plateau(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. / 2 - vec[a+1] = 1000. - vec[a+2] = 1000. - vec[a+3] = 1000. - vec[a+4] = 1000. / 2 - self.peaks = [a+1] - - def test_peakpicker_consecutive_peaks(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. / 2 - vec[a+1] = 1000. - vec[a+3] = 1000. - vec[a+4] = 1000. / 2 - self.peaks = [a] - - def test_peakpicker_distant_peaks(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. - vec[a+7] = 1000. - self.peaks = [a, a+7] - - def test_peakpicker_very_distant_peaks(self): - vec = self.vec; o = self.o - a = 345 - vec[a] = 1000. - vec[a+67] = 1000. - self.peaks = [a, a+67] - - def tearDown(self): - fpeaks = [] - for index in range(0,buf_size-slice_size): - sliced = self.vec[index:index+slice_size] - findex = self.o(sliced) - if findex: - # we found a peak - fpeak = index - findex - delay - #print self.peaks, index, '-', findex, '-', delay, '=', fpeak - if not round(index - findex - delay) in self.peaks: - self.fail('missing peak ' + str(fpeak)) - fpeaks.append(fpeak) - if len(fpeaks) != len(self.peaks): - self.fail('some peaks of ' + str(self.peaks) + 'were not found, got only ' + str(fpeaks)) - #print - #print fpeaks, self.peaks - -if __name__ == '__main__': - from unittest import main - main() diff --git a/interfaces/python/test_phasevoc.py b/interfaces/python/test_phasevoc.py deleted file mode 100755 index 5dd97866..00000000 --- a/interfaces/python/test_phasevoc.py +++ /dev/null @@ -1,65 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, run_module_suite -from numpy.testing import assert_equal, assert_almost_equal -from aubio import fvec, cvec, pvoc -from numpy import array, shape - -class aubio_pvoc_test_case(TestCase): - - def test_members(self): - f = pvoc() - assert_equal ([f.win_s, f.hop_s], [1024, 512]) - f = pvoc(2048, 128) - assert_equal ([f.win_s, f.hop_s], [2048, 128]) - - def test_zeros(self): - win_s, hop_s = 1024, 256 - f = pvoc (win_s, hop_s) - t = fvec (hop_s) - for time in range( 4 * win_s / hop_s ): - s = f(t) - r = f.rdo(s) - assert_equal ( array(t), 0) - assert_equal ( s.norm, 0) - assert_equal ( s.phas, 0) - assert_equal ( r, 0) - - def test_steps_two_channels(self): - """ check the resynthesis of steps is correct """ - f = pvoc(1024, 512) - t1 = fvec(512) - t2 = fvec(512) - # positive step in first channel - t1[100:200] = .1 - # positive step in second channel - t1[20:50] = -.1 - s1 = f(t1) - r1 = f.rdo(s1) - s2 = f(t2) - r2 = f.rdo(s2) - #self.plot_this ( s1.norm.T ) - assert_almost_equal ( t1, r2, decimal = 6 ) - - def test_steps_three_random_channels(self): - from random import random - f = pvoc(64, 16) - t0 = fvec(16) - t1 = fvec(16) - for i in xrange(16): - t1[i] = random() * 2. - 1. - t2 = f.rdo(f(t1)) - t2 = f.rdo(f(t0)) - t2 = f.rdo(f(t0)) - t2 = f.rdo(f(t0)) - assert_almost_equal( t1, t2, decimal = 6 ) - - def plot_this( self, this ): - from pylab import semilogy, show - semilogy ( this ) - show () - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_pitch.py b/interfaces/python/test_pitch.py deleted file mode 100755 index a0dd3a59..00000000 --- a/interfaces/python/test_pitch.py +++ /dev/null @@ -1,101 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase -from numpy.testing import assert_equal, assert_almost_equal -from numpy import random, sin, arange, mean, median -from math import pi -from aubio import fvec, pitch - -class aubio_mathutils_test_case(TestCase): - - def test_members(self): - p = pitch() - assert_equal ( [p.method, p.buf_size, p.hop_size, p.samplerate], - ['default', 1024, 512, 44100]) - - def test_members_not_default(self): - p = pitch('mcomb', 2048, 512, 32000) - assert_equal ( [p.method, p.buf_size, p.hop_size, p.samplerate], - ['mcomb', 2048, 512, 32000]) - - def test_run_on_zeros(self): - p = pitch('mcomb', 2048, 512, 32000) - f = fvec (512) - assert_equal ( p(f), 0. ) - - def test_run_on_ones(self): - p = pitch('mcomb', 2048, 512, 32000) - f = fvec (512) - f[:] = 1 - assert( p(f) != 0. ) - - def test_run_default_on_sinusoid(self): - method = 'default' - buf_size = 2048 - hop_size = 512 - samplerate = 32000 - freq = 450. - self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) - - def test_run_schmitt_on_sinusoid(self): - method = 'schmitt' - buf_size = 4096 - hop_size = 512 - samplerate = 44100 - freq = 800. - self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) - - def test_run_mcomb_on_sinusoid(self): - method = 'mcomb' - buf_size = 2048 - hop_size = 512 - samplerate = 44100 - freq = 10000. - self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) - - def test_run_fcomb_on_sinusoid(self): - method = 'fcomb' - buf_size = 2048 - hop_size = 512 - samplerate = 32000 - freq = 440. - self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) - - def test_run_yin_on_sinusoid(self): - method = 'yin' - buf_size = 4096 - hop_size = 512 - samplerate = 32000 - freq = 880. - self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) - - def test_run_yinfft_on_sinusoid(self): - method = 'yinfft' - buf_size = 2048 - hop_size = 512 - samplerate = 32000 - freq = 640. - self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) - - def run_pitch_on_sinusoid(self, method, buf_size, hop_size, samplerate, freq): - p = pitch(method, buf_size, hop_size, samplerate) - sinvec = self.build_sinusoid(hop_size * 100, freq, samplerate) - self.run_pitch(p, sinvec, freq) - - def build_sinusoid(self, length, freq, samplerate): - return sin( 2. * pi * arange(length).astype('float32') * freq / samplerate) - - def run_pitch(self, p, input_vec, freq): - count = 0 - pitches, errors = [], [] - for vec_slice in input_vec.reshape((-1, p.hop_size)): - pitch = p(vec_slice) - pitches.append(pitch) - errors.append(1. - pitch / freq) - # check that the mean of all relative errors is less than 10% - assert_almost_equal (mean(errors), 0., decimal = 2) - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_source.py b/interfaces/python/test_source.py deleted file mode 100755 index ae3b79bb..00000000 --- a/interfaces/python/test_source.py +++ /dev/null @@ -1,27 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, assert_equal, assert_almost_equal -from aubio import fvec, source -from numpy import array - -path = "/Users/piem/archives/sounds/loops/drum_Chocolate_Milk_-_Ation_Speaks_Louder_Than_Words.wav" - -class aubio_filter_test_case(TestCase): - - def test_members(self): - f = source(path) - print dir(f) - - def test_read(self): - f = source(path) - total_frames = 0 - while True: - vec, read = f() - total_frames += read - if read < f.hop_size: break - print "read", total_frames / float(f.samplerate), " seconds from", path - -if __name__ == '__main__': - from unittest import main - main() - diff --git a/interfaces/python/test_specdesc.py b/interfaces/python/test_specdesc.py deleted file mode 100755 index 675858d2..00000000 --- a/interfaces/python/test_specdesc.py +++ /dev/null @@ -1,238 +0,0 @@ -#! /usr/bin/env python - -from numpy.testing import TestCase, assert_equal, assert_almost_equal -from numpy import random, arange, log, zeros -from aubio import specdesc, cvec -from math import pi - -methods = ["default", - "energy", - "hfc", - "complex", - "phase", - "specdiff", - "kl", - "mkl", - "specflux", - "centroid", - "spread", - "skewness", - "kurtosis", - "slope", - "decrease", - "rolloff"] -buf_size = 2048 - -class aubio_specdesc(TestCase): - - def test_members(self): - o = specdesc() - - for method in methods: - o = specdesc(method, buf_size) - assert_equal ([o.buf_size, o.method], [buf_size, method]) - - spec = cvec(buf_size) - spec.norm[0] = 1 - spec.norm[1] = 1./2. - #print "%20s" % method, str(o(spec)) - o(spec) - spec.norm = random.random_sample((len(spec.norm),)).astype('float32') - spec.phas = random.random_sample((len(spec.phas),)).astype('float32') - #print "%20s" % method, str(o(spec)) - assert (o(spec) != 0.) - - def test_hfc(self): - o = specdesc("hfc", buf_size) - spec = cvec(buf_size) - # hfc of zeros is zero - assert_equal (o(spec), 0.) - # hfc of ones is sum of all bin numbers - spec.norm[:] = 1 - expected = sum(range(buf_size/2 + 2)) - assert_equal (o(spec), expected) - # changing phase doesn't change anything - spec.phas[:] = 1 - assert_equal (o(spec), sum(range(buf_size/2 + 2))) - - def test_phase(self): - o = specdesc("phase", buf_size) - spec = cvec(buf_size) - # phase of zeros is zero - assert_equal (o(spec), 0.) - spec.phas = random.random_sample((len(spec.phas),)).astype('float32') - # phase of random is not zero - spec.norm[:] = 1 - assert (o(spec) != 0.) - - def test_specdiff(self): - o = specdesc("phase", buf_size) - spec = cvec(buf_size) - # specdiff of zeros is zero - assert_equal (o(spec), 0.) - spec.phas = random.random_sample((len(spec.phas),)).astype('float32') - # phase of random is not zero - spec.norm[:] = 1 - assert (o(spec) != 0.) - - def test_hfc(self): - o = specdesc("hfc") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - assert_equal (a, c.norm) - assert_equal ( sum(a*(a+1)), o(c)) - - def test_complex(self): - o = specdesc("complex") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - assert_equal (a, c.norm) - # the previous run was on zeros, so previous frames are still 0 - # so we have sqrt ( abs ( r2 ^ 2) ) == r2 - assert_equal ( sum(a), o(c)) - # second time. c.norm = a, so, r1 = r2, and the euclidian distance is 0 - assert_equal ( 0, o(c)) - - def test_kl(self): - o = specdesc("kl") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - assert_almost_equal( sum(a * log(1.+ a/1.e-10 ) ) / o(c), 1., decimal=6) - - def test_mkl(self): - o = specdesc("mkl") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - assert_almost_equal( sum(log(1.+ a/1.e-10 ) ) / o(c), 1, decimal=6) - - def test_specflux(self): - o = specdesc("specflux") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - assert_equal( sum(a), o(c)) - assert_equal( 0, o(c)) - c.norm = zeros(c.length, dtype='float32') - assert_equal( 0, o(c)) - - def test_centroid(self): - o = specdesc("centroid") - c = cvec() - # make sure centroid of zeros is zero - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - centroid = sum(a*a) / sum(a) - assert_almost_equal (centroid, o(c), decimal = 2) - - c.norm = a * .5 - assert_almost_equal (centroid, o(c), decimal = 2) - - def test_spread(self): - o = specdesc("spread") - c = cvec(2048) - ramp = arange(c.length, dtype='float32') - assert_equal( 0., o(c)) - - a = ramp - c.norm = a - centroid = sum(a*a) / sum(a) - spread = sum( a * pow(ramp - centroid, 2.) ) / sum(a) - assert_almost_equal (o(c), spread, decimal = 1) - - def test_skewness(self): - o = specdesc("skewness") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - centroid = sum(a*a) / sum(a) - spread = sum( (a - centroid)**2 *a) / sum(a) - skewness = sum( (a - centroid)**3 *a) / sum(a) / spread **1.5 - assert_almost_equal (skewness, o(c), decimal = 2) - - c.norm = a * 3 - assert_almost_equal (skewness, o(c), decimal = 2) - - def test_kurtosis(self): - o = specdesc("kurtosis") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length, dtype='float32') - c.norm = a - centroid = sum(a*a) / sum(a) - spread = sum( (a - centroid)**2 *a) / sum(a) - kurtosis = sum( (a - centroid)**4 *a) / sum(a) / spread **2 - assert_almost_equal (kurtosis, o(c), decimal = 2) - - def test_slope(self): - o = specdesc("slope") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length * 2, 0, -2, dtype='float32') - k = arange(c.length, dtype='float32') - c.norm = a - num = len(a) * sum(k*a) - sum(k)*sum(a) - den = (len(a) * sum(k**2) - sum(k)**2) - slope = num/den/sum(a) - assert_almost_equal (slope, o(c), decimal = 5) - - a = arange(0, c.length * 2, +2, dtype='float32') - c.norm = a - num = len(a) * sum(k*a) - sum(k)*sum(a) - den = (len(a) * sum(k**2) - sum(k)**2) - slope = num/den/sum(a) - assert_almost_equal (slope, o(c), decimal = 5) - - a = arange(0, c.length * 2, +2, dtype='float32') - c.norm = a * 2 - assert_almost_equal (slope, o(c), decimal = 5) - - def test_decrease(self): - o = specdesc("decrease") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length * 2, 0, -2, dtype='float32') - k = arange(c.length, dtype='float32') - c.norm = a - decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) - assert_almost_equal (decrease, o(c), decimal = 5) - - a = arange(0, c.length * 2, +2, dtype='float32') - c.norm = a - decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) - assert_almost_equal (decrease, o(c), decimal = 5) - - a = arange(0, c.length * 2, +2, dtype='float32') - c.norm = a * 2 - decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) - assert_almost_equal (decrease, o(c), decimal = 5) - - def test_rolloff(self): - o = specdesc("rolloff") - c = cvec() - assert_equal( 0., o(c)) - a = arange(c.length * 2, 0, -2, dtype='float32') - k = arange(c.length, dtype='float32') - c.norm = a - cumsum = .95*sum(a*a) - i = 0; rollsum = 0 - while rollsum < cumsum: - rollsum += a[i]*a[i] - i+=1 - rolloff = i - assert_equal (rolloff, o(c)) - - -if __name__ == '__main__': - from unittest import main - main() diff --git a/python/README.md b/python/README.md new file mode 100644 index 00000000..f0054369 --- /dev/null +++ b/python/README.md @@ -0,0 +1,24 @@ +Python aubio module +=================== + +This module wraps the aubio library for python using the numpy module. + +See the [Python/C API Reference +Manual] (http://docs.python.org/c-api/index.html) and the [Numpy/C API +Reference](http://docs.scipy.org/doc/numpy/reference/c-api.html) + +Compiling python aubio on Mac OS X +---------------------------------- + +You should now be able to build the aubio python module out of the box on a +recent version of OS X (10.8.x). Make sure the variables are correct in the +file `build_osx` before running it: + + $ ./build_osx + +Additionally, you can fetch tools such [matplotlib](http://matplotlib.org/) to +use the demo scripts. One easy way to do it is to fetch the fully fledged +[Scipy superpack](http://fonnesbeck.github.com/ScipySuperpack/) + + $ curl -O https://raw.github.com/fonnesbeck/ScipySuperpack/master/install_superpack.sh + $ sh install_superpack.sh diff --git a/python/a_weighting_test_simple.expected b/python/a_weighting_test_simple.expected new file mode 100644 index 00000000..6cd3ff3d --- /dev/null +++ b/python/a_weighting_test_simple.expected @@ -0,0 +1,2 @@ + 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 5.00000000e-01 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 + 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.27870563e-01 2.58244342e-01 1.18719361e-01 -4.02623805e-02 -5.61812129e-02 -5.24739734e-02 -4.72329276e-02 -4.23394349e-02 -3.79219586e-02 -3.39473148e-02 -3.03724479e-02 -2.71574847e-02 -2.42664433e-02 -2.16669285e-02 -1.93297810e-02 -1.72287543e-02 -1.53402241e-02 -1.36429261e-02 -1.21177207e-02 -1.07473802e-02 diff --git a/python/aubio-types.h b/python/aubio-types.h new file mode 100644 index 00000000..d63bbcd4 --- /dev/null +++ b/python/aubio-types.h @@ -0,0 +1,49 @@ +#include +#include +#define NO_IMPORT_ARRAY +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include +#define AUBIO_UNSTABLE 1 +#include + +#define Py_default_vector_length 1024 +#define Py_default_vector_height 1 + +#define Py_aubio_default_samplerate 44100 + +#if HAVE_AUBIO_DOUBLE +#error "Ouch! Python interface for aubio has not been much tested yet." +#define AUBIO_NPY_SMPL NPY_DOUBLE +#else +#define AUBIO_NPY_SMPL NPY_FLOAT +#endif + +// special python type for cvec +typedef struct +{ + PyObject_HEAD + cvec_t * o; + uint_t length; + uint_t channels; +} Py_cvec; +extern PyTypeObject Py_cvecType; + +// defined in aubio-proxy.c +extern PyObject *PyAubio_CFvecToArray (fvec_t * self); +extern fvec_t *PyAubio_ArrayToCFvec (PyObject * self); + +extern Py_cvec *PyAubio_CCvecToPyCvec (cvec_t * self); +extern cvec_t *PyAubio_ArrayToCCvec (PyObject *input); + +extern PyObject *PyAubio_CFmatToArray (fmat_t * self); +extern fmat_t *PyAubio_ArrayToCFmat (PyObject *input); + +// hand written wrappers +extern PyTypeObject Py_filterType; + +extern PyTypeObject Py_filterbankType; + +extern PyTypeObject Py_fftType; + +extern PyTypeObject Py_pvocType; + diff --git a/python/aubio/__init__.py b/python/aubio/__init__.py new file mode 100644 index 00000000..136848b1 --- /dev/null +++ b/python/aubio/__init__.py @@ -0,0 +1,9 @@ +import numpy +from _aubio import * + +class fvec(numpy.ndarray): + + def __new__(self, length = 1024, **kwargs): + if type(length) == type([]): + return numpy.array(length, dtype='float32', **kwargs) + return numpy.zeros(length, dtype='float32', **kwargs) diff --git a/python/aubioinput.py b/python/aubioinput.py new file mode 100644 index 00000000..80bc9e4b --- /dev/null +++ b/python/aubioinput.py @@ -0,0 +1,141 @@ +#! /usr/bin/python + +import pygst +pygst.require('0.10') +import gst +import gobject +gobject.threads_init () + +def gst_buffer_to_numpy_array(buffer, chan): + import numpy + samples = numpy.frombuffer(buffer.data, dtype=numpy.float32) + if chan == 1: + return samples.T + else: + samples.resize([len(samples)/chan, chan]) + return samples.T + +class AubioSink(gst.BaseSink): + _caps = gst.caps_from_string('audio/x-raw-float, \ + rate=[ 1, 2147483647 ], \ + channels=[ 1, 2147483647 ], \ + endianness={ 1234, 4321 }, \ + width=32') + + __gsttemplates__ = ( + gst.PadTemplate ("sink", + gst.PAD_SINK, + gst.PAD_ALWAYS, + _caps), + ) + + def __init__(self, name, process): + self.__gobject_init__() + self.set_name(name) + self.process = process + self.adapter = gst.Adapter() + self.set_property('sync', False) + self.pos = 0 + + def set_property(self, name, value): + if name == 'hopsize': + # blocksize is in byte, convert from hopsize + from struct import calcsize + self.set_property('blocksize', value * calcsize('f')) + else: + super(gst.BaseSink, self).set_property(name, value) + + def do_render(self, buffer): + blocksize = self.get_property('blocksize') + caps = buffer.get_caps() + chan = caps[0]['channels'] + self.adapter.push(buffer) + while self.adapter.available() >= blocksize: + block = self.adapter.take_buffer(blocksize) + v = gst_buffer_to_numpy_array(block, chan) + if self.process: + self.process(v, self.pos) + self.pos += 1 + remaining = self.adapter.available() + if remaining < blocksize and remaining > 0: + block = self.adapter.take_buffer(remaining) + v = gst_buffer_to_numpy_array(block, chan) + if self.process: + self.process(v, self.pos) + self.pos += 1 + return gst.FLOW_OK + +gobject.type_register(AubioSink) + +class aubioinput(gst.Bin): + + ret = 0 + + def __init__(self, uri, process = None, hopsize = 512, + caps = None): + if uri.startswith('/'): + from urllib import quote + uri = 'file://'+quote(uri) + src = gst.element_factory_make('uridecodebin') + src.set_property('uri', uri) + src.connect('pad-added', self.source_pad_added_cb) + conv = gst.element_factory_make('audioconvert') + self.conv = conv + rsmpl = gst.element_factory_make('audioresample') + capsfilter = gst.element_factory_make('capsfilter') + if caps: + capsfilter.set_property('caps', gst.caps_from_string(caps)) + sink = AubioSink("AubioSink", process = process) + sink.set_property('hopsize', hopsize) # * calcsize('f')) + + self.pipeline = gst.Pipeline() + + self.bus = self.pipeline.get_bus() + self.bus.add_signal_watch() + self.bus.connect('message', self.on_eos) + + self.apad = conv.get_pad('sink') + + self.pipeline.add(src, conv, rsmpl, capsfilter, sink) + + gst.element_link_many(conv, rsmpl, capsfilter, sink) + + self.mainloop = gobject.MainLoop() + self.pipeline.set_state(gst.STATE_PLAYING) + + def run(self): + self.mainloop.run() + return self.ret + + def source_pad_added_cb(self, src, pad): + name = pad.get_caps()[0].get_name() + if name == 'audio/x-raw-float' or name == 'audio/x-raw-int': + pad.link(self.conv.get_pad("sink")) + + def source_pad_removed_cb(self, src, pad): + pad.unlink(self.conv.get_pad("sink")) + + def on_eos(self, bus, msg): + if msg.type == gst.MESSAGE_EOS: + self.bus.remove_signal_watch() + self.pipeline.set_state(gst.STATE_PAUSED) + self.mainloop.quit() + elif msg.type == gst.MESSAGE_ERROR: + print "ERROR", msg.parse_error() + self.bus.remove_signal_watch() + self.pipeline.set_state(gst.STATE_PAUSED) + self.mainloop.quit() + self.ret = 1 # set return value to 1 in case of error + +if __name__ == '__main__': + import sys + if len(sys.argv) < 2: + print "Usage: %s " % sys.argv[0] + sys.exit(1) + for filename in sys.argv[1:]: + peak = [0.] # use a mutable + def process(buf, hop): + peak[0] = max( peak[0], abs(buf.max()) ) + a = aubioinput(filename, process = process, hopsize = 512) + if a.run() == 0: # only display the results if no + print "Finished reading %s, peak value is %f" % (filename, max(peak)) diff --git a/python/aubiomodule.c b/python/aubiomodule.c new file mode 100644 index 00000000..df5787e1 --- /dev/null +++ b/python/aubiomodule.c @@ -0,0 +1,161 @@ +#include +#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include + +#include "aubio-types.h" +#include "generated/aubio-generated.h" + +static char Py_alpha_norm_doc[] = "compute alpha normalisation factor"; + +static PyObject * +Py_alpha_norm (PyObject * self, PyObject * args) +{ + PyObject *input; + fvec_t *vec; + smpl_t alpha; + PyObject *result; + + if (!PyArg_ParseTuple (args, "Of:alpha_norm", &input, &alpha)) { + return NULL; + } + + if (input == NULL) { + return NULL; + } + + vec = PyAubio_ArrayToCFvec (input); + + if (vec == NULL) { + return NULL; + } + + // compute the function + result = Py_BuildValue ("f", fvec_alpha_norm (vec, alpha)); + if (result == NULL) { + return NULL; + } + + return result; +} + +static char Py_zero_crossing_rate_doc[] = "compute zero crossing rate"; + +static PyObject * +Py_zero_crossing_rate (PyObject * self, PyObject * args) +{ + PyObject *input; + fvec_t *vec; + PyObject *result; + + if (!PyArg_ParseTuple (args, "O:zero_crossing_rate", &input)) { + return NULL; + } + + if (input == NULL) { + return NULL; + } + + vec = PyAubio_ArrayToCFvec (input); + + if (vec == NULL) { + return NULL; + } + + // compute the function + result = Py_BuildValue ("f", aubio_zero_crossing_rate (vec)); + if (result == NULL) { + return NULL; + } + + return result; +} + +static char Py_min_removal_doc[] = "compute zero crossing rate"; + +static PyObject * +Py_min_removal(PyObject * self, PyObject * args) +{ + PyObject *input; + fvec_t *vec; + + if (!PyArg_ParseTuple (args, "O:min_removal", &input)) { + return NULL; + } + + if (input == NULL) { + return NULL; + } + + vec = PyAubio_ArrayToCFvec (input); + + if (vec == NULL) { + return NULL; + } + + // compute the function + fvec_min_removal (vec); + + // since this function does not return, we could return None + //return Py_None; + // however it is convenient to return the modified vector + return (PyObject *) PyAubio_CFvecToArray(vec); + // or even without converting it back to an array + //Py_INCREF(vec); + //return (PyObject *)vec; +} + +static PyMethodDef aubio_methods[] = { + {"alpha_norm", Py_alpha_norm, METH_VARARGS, Py_alpha_norm_doc}, + {"zero_crossing_rate", Py_zero_crossing_rate, METH_VARARGS, + Py_zero_crossing_rate_doc}, + {"min_removal", Py_min_removal, METH_VARARGS, Py_min_removal_doc}, + {NULL, NULL} /* Sentinel */ +}; + +static char aubio_module_doc[] = "Python module for the aubio library"; + +PyMODINIT_FUNC +init_aubio (void) +{ + PyObject *m; + int err; + + if ( (PyType_Ready (&Py_cvecType) < 0) + || (PyType_Ready (&Py_filterType) < 0) + || (PyType_Ready (&Py_filterbankType) < 0) + || (PyType_Ready (&Py_fftType) < 0) + || (PyType_Ready (&Py_pvocType) < 0) + // generated objects + || (generated_types_ready() < 0 ) + ) { + return; + } + + m = Py_InitModule3 ("_aubio", aubio_methods, aubio_module_doc); + + if (m == NULL) { + return; + } + + err = _import_array (); + + if (err != 0) { + fprintf (stderr, + "Unable to import Numpy C API from aubio module (error %d)\n", err); + } + + Py_INCREF (&Py_cvecType); + PyModule_AddObject (m, "cvec", (PyObject *) & Py_cvecType); + Py_INCREF (&Py_filterType); + PyModule_AddObject (m, "digital_filter", (PyObject *) & Py_filterType); + Py_INCREF (&Py_filterbankType); + PyModule_AddObject (m, "filterbank", (PyObject *) & Py_filterbankType); + Py_INCREF (&Py_fftType); + PyModule_AddObject (m, "fft", (PyObject *) & Py_fftType); + Py_INCREF (&Py_pvocType); + PyModule_AddObject (m, "pvoc", (PyObject *) & Py_pvocType); + + // generated objects + add_generated_objects(m); +} diff --git a/python/aubioproxy.c b/python/aubioproxy.c new file mode 100644 index 00000000..9b7f9179 --- /dev/null +++ b/python/aubioproxy.c @@ -0,0 +1,153 @@ +#include "aubio-types.h" + +fvec_t * +PyAubio_ArrayToCFvec (PyObject *input) { + PyObject *array; + fvec_t *vec; + if (input == NULL) { + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); + goto fail; + } + // parsing input object into a Py_fvec + if (PyArray_Check(input)) { + + // we got an array, convert it to an fvec + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); + goto fail; + } else if (PyArray_NDIM ((PyArrayObject *)input) > 1) { + PyErr_SetString (PyExc_ValueError, + "input array has more than one dimensions"); + goto fail; + } + + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { + PyErr_SetString (PyExc_ValueError, "input array should be float"); + goto fail; + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { + PyErr_SetString (PyExc_ValueError, "input array should be float32"); + goto fail; + } else { + // input data type is float32, nothing else to do + array = input; + } + + // vec = new_fvec (vec->length); + // no need to really allocate fvec, just its struct member + vec = (fvec_t *)malloc(sizeof(fvec_t)); + vec->length = PyArray_SIZE ((PyArrayObject *)array); + vec->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)array, 0); + + } else if (PyObject_TypeCheck (input, &PyList_Type)) { + PyErr_SetString (PyExc_ValueError, "does not convert from list yet"); + return NULL; + } else { + PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input"); + return NULL; + } + + return vec; + +fail: + return NULL; +} + +PyObject * +PyAubio_CFvecToArray (fvec_t * self) +{ + npy_intp dims[] = { self->length, 1 }; + return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data); +} + +Py_cvec * +PyAubio_CCvecToPyCvec (cvec_t * input) { + Py_cvec *vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); + vec->length = input->length; + vec->o = input; + Py_INCREF(vec); + return vec; +} + +cvec_t * +PyAubio_ArrayToCCvec (PyObject *input) { + if (PyObject_TypeCheck (input, &Py_cvecType)) { + return ((Py_cvec*)input)->o; + } else { + PyErr_SetString (PyExc_ValueError, "input array should be float32"); + return NULL; + } +} + +PyObject * +PyAubio_CFmatToArray (fmat_t * input) +{ + PyObject *array = NULL; + uint_t i; + npy_intp dims[] = { input->length, 1 }; + PyObject *concat = PyList_New (0), *tmp = NULL; + for (i = 0; i < input->height; i++) { + tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->data[i]); + PyList_Append (concat, tmp); + Py_DECREF (tmp); + } + array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2); + Py_DECREF (concat); + return array; +} + +fmat_t * +PyAubio_ArrayToCFmat (PyObject *input) { + PyObject *array; + fmat_t *mat; + uint_t i; + if (input == NULL) { + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); + goto fail; + } + // parsing input object into a Py_fvec + if (PyArray_Check(input)) { + + // we got an array, convert it to an fvec + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); + goto fail; + } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { + PyErr_SetString (PyExc_ValueError, + "input array has more than two dimensions"); + goto fail; + } + + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { + PyErr_SetString (PyExc_ValueError, "input array should be float"); + goto fail; + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { + PyErr_SetString (PyExc_ValueError, "input array should be float32"); + goto fail; + } else { + // input data type is float32, nothing else to do + array = input; + } + + // no need to really allocate fvec, just its struct member + mat = (fmat_t *)malloc(sizeof(fmat_t)); + mat->length = PyArray_DIM ((PyArrayObject *)array, 1); + mat->height = PyArray_DIM ((PyArrayObject *)array, 0); + mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height); + for (i=0; i< mat->height; i++) { + mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)array, i); + } + + } else if (PyObject_TypeCheck (input, &PyList_Type)) { + PyErr_SetString (PyExc_ValueError, "can not convert list to fmat"); + return NULL; + } else { + PyErr_SetString (PyExc_ValueError, "can only accept matrix of float as input"); + return NULL; + } + + return mat; + +fail: + return NULL; +} + diff --git a/python/aubiowraphell.h b/python/aubiowraphell.h new file mode 100644 index 00000000..d60cc30a --- /dev/null +++ b/python/aubiowraphell.h @@ -0,0 +1,90 @@ +#include "aubio-types.h" + +#define AUBIO_DECLARE(NAME, PARAMS...) \ +typedef struct { \ + PyObject_HEAD \ + aubio_ ## NAME ## _t * o; \ + PARAMS; \ +} Py_## NAME; + +#define AUBIO_INIT(NAME, PARAMS... ) \ +static int \ +Py_ ## NAME ## _init (Py_ ## NAME * self, PyObject * args, PyObject * kwds) \ +{ \ + self->o = new_aubio_## NAME ( PARAMS ); \ + if (self->o == NULL) { \ + PyErr_SetString (PyExc_StandardError, "error creating object"); \ + return -1; \ + } \ +\ + return 0; \ +} + +#define AUBIO_DEL(NAME) \ +static void \ +Py_ ## NAME ## _del ( Py_ ## NAME * self) \ +{ \ + del_aubio_ ## NAME (self->o); \ + self->ob_type->tp_free ((PyObject *) self); \ +} + +#define AUBIO_MEMBERS_START(NAME) \ +static PyMemberDef Py_ ## NAME ## _members[] = { + +#define AUBIO_MEMBERS_STOP(NAME) \ + {NULL} \ +}; + +#define AUBIO_METHODS(NAME) \ +static PyMethodDef Py_ ## NAME ## _methods[] = { \ + {NULL} \ +}; + + +#define AUBIO_TYPEOBJECT(NAME, PYNAME) \ +PyTypeObject Py_ ## NAME ## Type = { \ + PyObject_HEAD_INIT (NULL) \ + 0, \ + PYNAME, \ + sizeof (Py_ ## NAME), \ + 0, \ + (destructor) Py_ ## NAME ## _del, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + (ternaryfunc)Py_ ## NAME ## _do, \ + 0, \ + 0, \ + 0, \ + 0, \ + Py_TPFLAGS_DEFAULT, \ + Py_ ## NAME ## _doc, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + Py_ ## NAME ## _methods, \ + Py_ ## NAME ## _members, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + (initproc) Py_ ## NAME ## _init, \ + 0, \ + Py_ ## NAME ## _new, \ +}; + +// some more helpers +#define AUBIO_NEW_VEC(name, type, lengthval) \ + name = (type *) PyObject_New (type, & type ## Type); \ + name->length = lengthval; diff --git a/python/build_linux b/python/build_linux new file mode 100755 index 00000000..05c97ecb --- /dev/null +++ b/python/build_linux @@ -0,0 +1,9 @@ +#! /bin/sh + +set -e +set -x + +python setup.py clean build +export PYTHONPATH=./build/lib.linux-x86_64-2.7/ +export LD_LIBRARY_PATH=../../build/src/ +./run_all_tests --verbose diff --git a/python/build_osx b/python/build_osx new file mode 100755 index 00000000..7f5cc3b6 --- /dev/null +++ b/python/build_osx @@ -0,0 +1,9 @@ +#! /bin/sh + +set -e +set -x + +python setup.py clean build +export PYTHONPATH=./build/lib.macosx-10.6-intel-2.7:$PYTHONPATH +export DYLD_LIBRARY_PATH=../../build/src +./run_all_tests --verbose diff --git a/python/c_weighting_test_simple.expected b/python/c_weighting_test_simple.expected new file mode 100644 index 00000000..70e2b159 --- /dev/null +++ b/python/c_weighting_test_simple.expected @@ -0,0 +1,2 @@ + 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 5.00000000e-01 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 + 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.08504281e-01 2.31621372e-01 1.38614617e-01 1.58040475e-02 -9.84900252e-04 -2.72686896e-03 -2.87772967e-03 -2.87932142e-03 -2.86783482e-03 -2.85529016e-03 -2.84270413e-03 -2.83016008e-03 -2.81766458e-03 -2.80521796e-03 -2.79282009e-03 -2.78047079e-03 -2.76816989e-03 -2.75591721e-03 -2.74371257e-03 -2.73155579e-03 diff --git a/python/demo_beats_and_tempo.py b/python/demo_beats_and_tempo.py new file mode 100755 index 00000000..2b33bb19 --- /dev/null +++ b/python/demo_beats_and_tempo.py @@ -0,0 +1,39 @@ +#! /usr/bin/env python + +import sys +from aubio import tempo, source + +win_s = 512 # fft size +hop_s = win_s / 2 # hop size +samplerate = 44100 + +if len(sys.argv) < 2: + print "Usage: %s " % sys.argv[0] + sys.exit(1) + +filename = sys.argv[1] +beats = [] + +s = source(filename, samplerate, hop_s) +t = tempo("default", win_s, hop_s) + +block_read = 0 +while True: + samples, read = s() + isbeat = t(samples) + if isbeat: + thisbeat = (block_read * hop_s + isbeat[0]) / samplerate + print "%.4f" % thisbeat + beats.append (thisbeat) + block_read += 1 + if read < hop_s: break + +periods = [60./(b - a) for a,b in zip(beats[:-1],beats[1:])] + +from numpy import mean, median +print 'mean period:', mean(periods), 'bpm' +print 'median period:', median(periods), 'bpm' + +from pylab import plot, show +plot(beats[1:], periods) +show() diff --git a/python/demo_filterbank_slaney.py b/python/demo_filterbank_slaney.py new file mode 100755 index 00000000..636dc809 --- /dev/null +++ b/python/demo_filterbank_slaney.py @@ -0,0 +1,21 @@ +#! /usr/bin/env python + +from aubio import filterbank +from numpy import array, arange, vstack + +win_s = 8192 +samplerate = 16000 + +f = filterbank(40, win_s) +f.set_mel_coeffs_slaney(samplerate) + +from pylab import loglog, title, show, xlim, ylim, xlabel, ylabel +xlim([0,samplerate / 2]) +times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * 40) +loglog(times.T, f.get_coeffs().T, '.-') +title('Mel frequency bands coefficients') +xlim([100, 7500]) +ylim([1.0e-3, 2.0e-2]) +xlabel('Frequency (Hz)') +ylabel('Amplitude') +show() diff --git a/python/demo_filterbank_triangle_bands.py b/python/demo_filterbank_triangle_bands.py new file mode 100755 index 00000000..7b02e7d9 --- /dev/null +++ b/python/demo_filterbank_triangle_bands.py @@ -0,0 +1,47 @@ +#! /usr/bin/env python + +from aubio import filterbank, fvec +from pylab import loglog, show, subplot, xlim, ylim, xlabel, ylabel, title +from numpy import vstack, arange + +win_s = 2048 +samplerate = 48000 + +freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000] +n_filters = len(freq_list) - 2 + +f = filterbank(n_filters, win_s) +freqs = fvec(freq_list) +f.set_triangle_bands(freqs, samplerate) + +subplot(211) +title('Examples of filterbank built with set_triangle_bands and set_coeffs') +times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters) +loglog(times.T, f.get_coeffs().T, '.-') +xlim([50, samplerate/2]) +ylim([1.0e-6, 2.0e-2]) +ylabel('Amplitude') + +## build a new filterbank + +freq_list = [60, 80, 200, 400, 800, 1200, 1600, 3200, 6400, 10000, 15000, 24000] +n_filters = len(freq_list) - 2 + +f = filterbank(n_filters, win_s) +freqs = fvec(freq_list) +f.set_triangle_bands(freqs, samplerate) + +coeffs = f.get_coeffs() +coeffs[4] *= 5. + +f.set_coeffs(coeffs) + +subplot(212) +times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters) +loglog(times.T, f.get_coeffs().T, '.-') +xlim([50, samplerate/2]) +ylim([1.0e-6, 2.0e-2]) +xlabel('Frequency (Hz)') +ylabel('Amplitude') + +show() diff --git a/python/demo_onset_sinusoid.py b/python/demo_onset_sinusoid.py new file mode 100755 index 00000000..97f9231d --- /dev/null +++ b/python/demo_onset_sinusoid.py @@ -0,0 +1,84 @@ +#! /usr/bin/env python + +from numpy import random, sin, arange, ones, zeros +from math import pi +from aubio import fvec, onset + +def build_sinusoid(length, freqs, samplerate): + return sin( 2. * pi * arange(length) * freqs / samplerate) + +def run_onset(p, input_vec): + f = fvec (p.hop_size) + cands = [] + count = 0 + for vec_slice in input_vec.reshape((-1, p.hop_size)): + f[:] = vec_slice + cands.append(o(f)) + return cands + +methods = ['default', + 'energy', + 'complex', + 'phase', + 'specdiff', + 'kl', + 'mkl', + 'specflux', + 'centroid', + 'spread', + 'skewness', + 'kurtosis', + 'slope', + 'decrease', + 'rolloff', + ] + +cands = {} +buf_size = 2048 +hop_size = 512 +samplerate = 44100 +sin_length = (samplerate * 10) % 512 * 512 +freqs = zeros(sin_length) + +partition = sin_length / 8 +pointer = 0 + +pointer += partition +freqs[pointer: pointer + partition] = 440 + +pointer += partition +pointer += partition +freqs[ pointer : pointer + partition ] = 740 + +pointer += partition +freqs[ pointer : pointer + partition ] = 1480 + +pointer += partition +pointer += partition +freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8) + +a = build_sinusoid(sin_length, freqs, samplerate) + +for method in methods: + o = onset(method, buf_size, hop_size, samplerate) + cands[method] = run_onset(o, a) + +print "done computing" + +if 1: + from pylab import plot, show, xlabel, ylabel, legend, ylim, subplot + subplot (211) + legend(methods+['ground truth'], 'upper right') + xlabel('time (s)') + ylabel('amplitude') + ramp = arange(0, sin_length).astype('float') / samplerate + plot(ramp, a, ':') + subplot (212) + ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate + for method in methods: + plot(ramp, cands[method],'.-') + legend(methods, 'upper right') + xlabel('time (s)') + ylabel('spectral descriptor value') + show() + diff --git a/python/demo_pitch_sinusoid.py b/python/demo_pitch_sinusoid.py new file mode 100755 index 00000000..6407e586 --- /dev/null +++ b/python/demo_pitch_sinusoid.py @@ -0,0 +1,68 @@ +#! /usr/bin/env python + +from numpy import random, sin, arange, ones, zeros +from math import pi +from aubio import fvec, pitch + +def build_sinusoid(length, freqs, samplerate): + return sin( 2. * pi * arange(length) * freqs / samplerate) + +def run_pitch(p, input_vec): + f = fvec (p.hop_size) + cands = [] + count = 0 + for vec_slice in input_vec.reshape((-1, p.hop_size)): + f[:] = vec_slice + cands.append(p(f)) + return cands + +methods = ['default', 'schmitt', 'fcomb', 'mcomb', 'yin', 'yinfft'] + +cands = {} +buf_size = 2048 +hop_size = 512 +samplerate = 44100 +sin_length = (samplerate * 10) % 512 * 512 +freqs = zeros(sin_length) + +partition = sin_length / 8 +pointer = 0 + +pointer += partition +freqs[pointer: pointer + partition] = 440 + +pointer += partition +pointer += partition +freqs[ pointer : pointer + partition ] = 740 + +pointer += partition +freqs[ pointer : pointer + partition ] = 1480 + +pointer += partition +pointer += partition +freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8) + +a = build_sinusoid(sin_length, freqs, samplerate) + +for method in methods: + p = pitch(method, buf_size, hop_size, samplerate) + cands[method] = run_pitch(p, a) + +print "done computing" + +if 1: + from pylab import plot, show, xlabel, ylabel, legend, ylim + ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate + for method in methods: + plot(ramp, cands[method],'.-') + + # plot ground truth + ramp = arange(0, sin_length).astype('float') / samplerate + plot(ramp, freqs, ':') + + legend(methods+['ground truth'], 'upper right') + xlabel('time (s)') + ylabel('frequency (Hz)') + ylim([0,2000]) + show() + diff --git a/python/demo_simple_robot_voice.py b/python/demo_simple_robot_voice.py new file mode 100755 index 00000000..84c9c6ec --- /dev/null +++ b/python/demo_simple_robot_voice.py @@ -0,0 +1,29 @@ +#! /usr/bin/env python + +import sys +from aubio import source, sink, pvoc + +if __name__ == '__main__': + if len(sys.argv) < 2: + print 'usage: %s ' % sys.argv[0] + sys.exit(1) + samplerate = 44100 + f = source(sys.argv[1], samplerate, 256) + g = sink(sys.argv[2], samplerate) + total_frames, read = 0, 256 + + win_s = 512 # fft size + hop_s = win_s / 2 # hop size + pv = pvoc(win_s, hop_s) # phase vocoder + + while read: + samples, read = f() + spectrum = pv(samples) # compute spectrum + spectrum.phas[:] = 0. # zero phase + new_samples = pv.rdo(spectrum) # compute modified samples + g(new_samples, read) # write to output + total_frames += read + + print "wrote", total_frames, "from", f.uri, "to", g.uri + + diff --git a/python/demo_sink.py b/python/demo_sink.py new file mode 100755 index 00000000..702838c5 --- /dev/null +++ b/python/demo_sink.py @@ -0,0 +1,17 @@ +#! /usr/bin/env python + +import sys +from aubio import source, sink + +if __name__ == '__main__': + if len(sys.argv) < 3: + print 'usage: %s ' % sys.argv[0] + sys.exit(1) + f = source(sys.argv[1], 8000, 256) + g = sink(sys.argv[2], 8000) + total_frames, read = 0, 256 + while read: + vec, read = f() + g(vec, read) + total_frames += read + print "read", total_frames / float(f.samplerate), "seconds from", f.uri diff --git a/python/demo_source.py b/python/demo_source.py new file mode 100755 index 00000000..65925fc0 --- /dev/null +++ b/python/demo_source.py @@ -0,0 +1,15 @@ +#! /usr/bin/env python + +import sys +from aubio import source + +if __name__ == '__main__': + if len(sys.argv) < 2: + print 'usage: %s ' % sys.argv[0] + sys.exit(1) + f = source(sys.argv[1], 8000, 256) + total_frames, read = 0, 256 + while read: + vec, read = f() + total_frames += read + print "read", total_frames / float(f.samplerate), "seconds from", f.uri diff --git a/python/demo_spectrogram.py b/python/demo_spectrogram.py new file mode 100755 index 00000000..16bd69ef --- /dev/null +++ b/python/demo_spectrogram.py @@ -0,0 +1,63 @@ +#! /usr/bin/env python + +import sys +from aubio import pvoc, source +from numpy import array, arange, zeros, shape, log10, vstack +from pylab import imshow, show, cm, axis, ylabel, xlabel, xticks, yticks + +def get_spectrogram(filename): + samplerate = 44100 + win_s = 512 # fft window size + hop_s = win_s / 2 # hop size + fft_s = win_s / 2 + 1 # spectrum bins + + a = source(filename, samplerate, hop_s) # source file + pv = pvoc(win_s, hop_s) # phase vocoder + specgram = zeros([0, fft_s], dtype='float32') # numpy array to store spectrogram + + # analysis + while True: + samples, read = a() # read file + specgram = vstack((specgram,pv(samples).norm)) # store new norm vector + if read < a.hop_size: break + + # plotting + imshow(log10(specgram.T + .001), origin = 'bottom', aspect = 'auto', cmap=cm.gray_r) + axis([0, len(specgram), 0, len(specgram[0])]) + # show axes in Hz and seconds + time_step = hop_s / float(samplerate) + total_time = len(specgram) * time_step + print "total time: %0.2fs" % total_time, + print ", samplerate: %.2fkHz" % (samplerate / 1000.) + n_xticks = 10 + n_yticks = 10 + + def get_rounded_ticks( top_pos, step, n_ticks ): + top_label = top_pos * step + # get the first label + ticks_first_label = top_pos * step / n_ticks + # round to the closest .1 + ticks_first_label = round ( ticks_first_label * 10. ) / 10. + # compute all labels from the first rounded one + ticks_labels = [ ticks_first_label * n for n in range(n_ticks) ] + [ top_label ] + # get the corresponding positions + ticks_positions = [ ticks_labels[n] / step for n in range(n_ticks) ] + [ top_pos ] + # convert to string + ticks_labels = [ "%.1f" % x for x in ticks_labels ] + # return position, label tuple to use with x/yticks + return ticks_positions, ticks_labels + + # apply to the axis + xticks( *get_rounded_ticks ( len(specgram), time_step, n_xticks ) ) + yticks( *get_rounded_ticks ( len(specgram[0]), (samplerate / 2. / 1000.) / len(specgram[0]), n_yticks ) ) + ylabel('Frequency (kHz)') + xlabel('Time (s)') + +if __name__ == '__main__': + if len(sys.argv) < 2: + print "Usage: %s " % sys.argv[0] + else: + for soundfile in sys.argv[1:]: + get_spectrogram(soundfile) + # display graph + show() diff --git a/python/demo_tss.py b/python/demo_tss.py new file mode 100755 index 00000000..0d670ce1 --- /dev/null +++ b/python/demo_tss.py @@ -0,0 +1,47 @@ +#! /usr/bin/env python + +import sys +from aubio import source, sink, pvoc, tss + +if __name__ == '__main__': + if len(sys.argv) < 2: + print 'usage: %s ' % sys.argv[0] + sys.exit(1) + + samplerate = 44100 + win_s = 512 # fft size + hop_s = win_s / 2 # block size + threshold = 0.26 + + f = source(sys.argv[1], samplerate, hop_s) + g = sink(sys.argv[2], samplerate) + h = sink(sys.argv[3], samplerate) + + pv = pvoc(win_s, hop_s) # phase vocoder + pw = pvoc(win_s, hop_s) # another phase vocoder + t = tss(win_s, hop_s) # transient steady state separation + + t.set_threshold(threshold) + + read = hop_s + + while read: + samples, read = f() # read file + spec = pv(samples) # compute spectrum + trans_spec, stead_spec = t(spec) # transient steady-state separation + transients = pv.rdo(trans_spec) # overlap-add synthesis of transients + steadstate = pw.rdo(stead_spec) # overlap-add synthesis of steady states + g(transients, read) # write transients to output + h(steadstate, read) # write steady states to output + + del f, g, h # finish writing the files now + + from demo_spectrogram import get_spectrogram + from pylab import subplot, show + subplot(311) + get_spectrogram(sys.argv[1]) + subplot(312) + get_spectrogram(sys.argv[2]) + subplot(313) + get_spectrogram(sys.argv[3]) + show() diff --git a/python/gen_pyobject.py b/python/gen_pyobject.py new file mode 100644 index 00000000..20f4534a --- /dev/null +++ b/python/gen_pyobject.py @@ -0,0 +1,526 @@ +#! /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], +} + +# TODO +# do function: for now, only the following pattern is supported: +# void aubio__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 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'], +} + +# default value for variables +aubioinitvalue = { + 'uint_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', + '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)PyInt_AsLong', +} + +# aubio to python +aubiovectopyobj = { + 'fvec_t*': 'PyAubio_CFvecToArray', + 'cvec_t*': 'PyAubio_CCvecToPyCvec', + 'smpl_t': 'PyFloat_FromDouble', + 'uint_t*': 'PyInt_FromLong', + 'uint_t': 'PyInt_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(map(lambda p: aubio2pytypes[p['type']], 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 (%(pname)s > 0) { + self->%(pname)s = %(pname)s; + } else if (%(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(map(lambda p: p['type'] + ' ' + p['name'] + ";", 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 = " return Py_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__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: + 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__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; + } + return Py_None; +} +""" % {'funcname': method_name, 'objname': name, + 'out_type': out_type, 'setter_args': setter_args, 'parse_args': parse_args } + shortname = method_name.split(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__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(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 diff --git a/python/generator.py b/python/generator.py new file mode 100755 index 00000000..6e904a1e --- /dev/null +++ b/python/generator.py @@ -0,0 +1,187 @@ +#! /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) + + 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_object_files(): + if os.path.isdir('generated'): shutil.rmtree('generated') + os.mkdir('generated') + + generated_objects = [] + cpp_output, cpp_objects = get_cpp_objects() + skip_objects = ['fft', + 'pvoc', + 'filter', + 'filterbank', + 'resampler', + 'sndfile', + 'sink_apple_audio', + 'sink_sndfile', + 'source_apple_audio', + 'source_sndfile'] + + 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) + #for method in object_methods: + # write_msg(method) + new_methods = 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 = 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 = 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) + + 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 = 'generated/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 + +""" + + for each in generated_objects: + s += "extern PyTypeObject Py_%sType;\n" % \ + each.replace('aubio_','').replace('_t','') + + types_ready = [] + for each in generated_objects: + types_ready.append(" PyType_Ready (&Py_%sType) < 0" % \ + each.replace('aubio_','').replace('_t','') ) + + 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('generated/aubio-generated.h', 'w') + fd.write(s) + + from os import listdir + generated_files = listdir('generated') + generated_files = filter(lambda x: x.endswith('.c'), generated_files) + generated_files = ['generated/'+f for f in generated_files] + return generated_files + +if __name__ == '__main__': + generate_object_files() diff --git a/python/py-cvec.c b/python/py-cvec.c new file mode 100644 index 00000000..940508fb --- /dev/null +++ b/python/py-cvec.c @@ -0,0 +1,302 @@ +#include "aubio-types.h" + +/* cvec type definition + +class cvec(): + def __init__(self, length = 1024): + self.length = length + self.norm = array(length) + self.phas = array(length) + +*/ + +static char Py_cvec_doc[] = "cvec object"; + +static PyObject * +Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int length= 0; + Py_cvec *self; + static char *kwlist[] = { "length", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, + &length)) { + return NULL; + } + + + self = (Py_cvec *) type->tp_alloc (type, 0); + + self->length = Py_default_vector_length / 2 + 1; + + if (self == NULL) { + return NULL; + } + + if (length > 0) { + self->length = length / 2 + 1; + } else if (length < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative number of elements"); + return NULL; + } + + return (PyObject *) self; +} + +static int +Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds) +{ + self->o = new_cvec ((self->length - 1) * 2); + if (self->o == NULL) { + return -1; + } + + return 0; +} + +static void +Py_cvec_del (Py_cvec * self) +{ + del_cvec (self->o); + self->ob_type->tp_free ((PyObject *) self); +} + +static PyObject * +Py_cvec_repr (Py_cvec * self, PyObject * unused) +{ + PyObject *format = NULL; + PyObject *args = NULL; + PyObject *result = NULL; + + format = PyString_FromString ("aubio cvec of %d elements"); + if (format == NULL) { + goto fail; + } + + args = Py_BuildValue ("I", self->length); + if (args == NULL) { + goto fail; + } + cvec_print ( self->o ); + + result = PyString_Format (format, args); + +fail: + Py_XDECREF (format); + Py_XDECREF (args); + + return result; +} + +PyObject * +PyAubio_CvecNormToArray (Py_cvec * self) +{ + npy_intp dims[] = { self->o->length, 1 }; + return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm); +} + + +PyObject * +PyAubio_CvecPhasToArray (Py_cvec * self) +{ + npy_intp dims[] = { self->o->length, 1 }; + return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas); +} + +PyObject * +PyAubio_ArrayToCvecPhas (PyObject * self) +{ + return NULL; +} + +PyObject * +Py_cvec_get_norm (Py_cvec * self, void *closure) +{ + return PyAubio_CvecNormToArray(self); +} + +PyObject * +Py_cvec_get_phas (Py_cvec * self, void *closure) +{ + return PyAubio_CvecPhasToArray(self); +} + +static int +Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure) +{ + PyArrayObject * array; + if (input == NULL) { + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); + goto fail; + } + if (PyArray_Check(input)) { + + // we got an array, convert it to a cvec.norm + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); + goto fail; + } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { + PyErr_SetString (PyExc_ValueError, + "input array has more than two dimensions"); + goto fail; + } + + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { + PyErr_SetString (PyExc_ValueError, "input array should be float"); + goto fail; + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { + PyErr_SetString (PyExc_ValueError, "input array should be float32"); + goto fail; + } + array = (PyArrayObject *)input; + + // check input array dimensions + if (PyArray_NDIM (array) != 1) { + PyErr_Format (PyExc_ValueError, + "input array has %d dimensions, not 1", + PyArray_NDIM (array)); + goto fail; + } else { + if (vec->o->length != PyArray_SIZE (array)) { + PyErr_Format (PyExc_ValueError, + "input array has length %d, but cvec has length %d", + (int)PyArray_SIZE (array), vec->o->length); + goto fail; + } + } + + vec->o->norm = (smpl_t *) PyArray_GETPTR1 (array, 0); + + } else { + PyErr_SetString (PyExc_ValueError, "can only accept array as input"); + return 1; + } + + Py_INCREF(array); + return 0; + +fail: + return 1; +} + +static int +Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) +{ + PyArrayObject * array; + if (input == NULL) { + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); + goto fail; + } + if (PyArray_Check(input)) { + + // we got an array, convert it to a cvec.phas + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); + goto fail; + } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { + PyErr_SetString (PyExc_ValueError, + "input array has more than two dimensions"); + goto fail; + } + + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { + PyErr_SetString (PyExc_ValueError, "input array should be float"); + goto fail; + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { + PyErr_SetString (PyExc_ValueError, "input array should be float32"); + goto fail; + } + array = (PyArrayObject *)input; + + // check input array dimensions + if (PyArray_NDIM (array) != 1) { + PyErr_Format (PyExc_ValueError, + "input array has %d dimensions, not 1", + PyArray_NDIM (array)); + goto fail; + } else { + if (vec->o->length != PyArray_SIZE (array)) { + PyErr_Format (PyExc_ValueError, + "input array has length %d, but cvec has length %d", + (int)PyArray_SIZE (array), vec->o->length); + goto fail; + } + } + + vec->o->phas = (smpl_t *) PyArray_GETPTR1 (array, 0); + + } else { + PyErr_SetString (PyExc_ValueError, "can only accept array as input"); + return 1; + } + + Py_INCREF(array); + return 0; + +fail: + return 1; +} + +static PyMemberDef Py_cvec_members[] = { + // TODO remove READONLY flag and define getter/setter + {"length", T_INT, offsetof (Py_cvec, length), READONLY, + "length attribute"}, + {NULL} /* Sentinel */ +}; + +static PyMethodDef Py_cvec_methods[] = { + {NULL} +}; + +static PyGetSetDef Py_cvec_getseters[] = { + {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, + "Numpy vector of shape (length,) containing the magnitude", + NULL}, + {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, + "Numpy vector of shape (length,) containing the phase", + NULL}, + {NULL} /* sentinel */ +}; + +PyTypeObject Py_cvecType = { + PyObject_HEAD_INIT (NULL) + 0, /* ob_size */ + "aubio.cvec", /* tp_name */ + sizeof (Py_cvec), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) Py_cvec_del, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc) Py_cvec_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_cvec_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Py_cvec_methods, /* tp_methods */ + Py_cvec_members, /* tp_members */ + Py_cvec_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc) Py_cvec_init, /* tp_init */ + 0, /* tp_alloc */ + Py_cvec_new, /* tp_new */ +}; diff --git a/python/py-fft.c b/python/py-fft.c new file mode 100644 index 00000000..19d7b49b --- /dev/null +++ b/python/py-fft.c @@ -0,0 +1,107 @@ +#include "aubiowraphell.h" + +static char Py_fft_doc[] = "fft object"; + +AUBIO_DECLARE(fft, uint_t win_s) + +//AUBIO_NEW(fft) +static PyObject * +Py_fft_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int win_s = 0; + Py_fft *self; + static char *kwlist[] = { "win_s", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, + &win_s)) { + return NULL; + } + + self = (Py_fft *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->win_s = Py_default_vector_length; + + if (self == NULL) { + return NULL; + } + + if (win_s > 0) { + self->win_s = win_s; + } else if (win_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative window size"); + return NULL; + } + + return (PyObject *) self; +} + + +AUBIO_INIT(fft, self->win_s) + +AUBIO_DEL(fft) + +static PyObject * +Py_fft_do(PyObject * self, PyObject * args) +{ + PyObject *input; + fvec_t *vec; + cvec_t *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCFvec (input); + + if (vec == NULL) { + return NULL; + } + + output = new_cvec(((Py_fft *) self)->win_s); + + // compute the function + aubio_fft_do (((Py_fft *)self)->o, vec, output); + return (PyObject *)PyAubio_CCvecToPyCvec(output); +} + +AUBIO_MEMBERS_START(fft) + {"win_s", T_INT, offsetof (Py_fft, win_s), READONLY, + "size of the window"}, +AUBIO_MEMBERS_STOP(fft) + +static PyObject * +Py_fft_rdo(Py_fft * self, PyObject * args) +{ + PyObject *input; + cvec_t *vec; + fvec_t *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCCvec (input); + + if (vec == NULL) { + return NULL; + } + + output = new_fvec(self->win_s); + + // compute the function + aubio_fft_rdo (((Py_fft *)self)->o, vec, output); + return (PyObject *)PyAubio_CFvecToArray(output); +} + +static PyMethodDef Py_fft_methods[] = { + {"rdo", (PyCFunction) Py_fft_rdo, METH_VARARGS, + "synthesis of spectral grain"}, + {NULL} +}; + +AUBIO_TYPEOBJECT(fft, "aubio.fft") diff --git a/python/py-filter.c b/python/py-filter.c new file mode 100644 index 00000000..5b9fee64 --- /dev/null +++ b/python/py-filter.c @@ -0,0 +1,198 @@ +#include "aubio-types.h" + +typedef struct +{ + PyObject_HEAD + aubio_filter_t * o; + uint_t order; +} Py_filter; + +static char Py_filter_doc[] = "filter object"; + +static PyObject * +Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int order= 0; + Py_filter *self; + static char *kwlist[] = { "order", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, + &order)) { + return NULL; + } + + self = (Py_filter *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->order = 7; + + if (order > 0) { + self->order = order; + } else if (order < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative order"); + return NULL; + } + + return (PyObject *) self; +} + +static int +Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds) +{ + self->o = new_aubio_filter (self->order); + if (self->o == NULL) { + return -1; + } + + return 0; +} + +static void +Py_filter_del (Py_filter * self) +{ + del_aubio_filter (self->o); + self->ob_type->tp_free ((PyObject *) self); +} + +static PyObject * +Py_filter_do(Py_filter * self, PyObject * args) +{ + PyObject *input; + fvec_t *vec; + + if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) { + return NULL; + } + + if (input == NULL) { + return NULL; + } + + vec = PyAubio_ArrayToCFvec (input); + + if (vec == NULL) { + return NULL; + } + + // compute the function + fvec_t * out = new_fvec(vec->length); + aubio_filter_do_outplace (self->o, vec, out); + return PyAubio_CFvecToArray(out); +} + +static PyObject * +Py_filter_set_c_weighting (Py_filter * self, PyObject *args) +{ + uint_t err = 0; + uint_t samplerate; + if (!PyArg_ParseTuple (args, "I", &samplerate)) { + return NULL; + } + + err = aubio_filter_set_c_weighting (self->o, samplerate); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter to C-weighting"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filter_set_a_weighting (Py_filter * self, PyObject *args) +{ + uint_t err = 0; + uint_t samplerate; + if (!PyArg_ParseTuple (args, "I", &samplerate)) { + return NULL; + } + + err = aubio_filter_set_a_weighting (self->o, samplerate); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter to A-weighting"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filter_set_biquad(Py_filter * self, PyObject *args) +{ + uint_t err = 0; + lsmp_t b0, b1, b2, a1, a2; + if (!PyArg_ParseTuple (args, "ddddd", &b0, &b1, &b2, &a1, &a2)) { + return NULL; + } + + err = aubio_filter_set_biquad (self->o, b0, b1, b2, a1, a2); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter with biquad coefficients"); + return NULL; + } + return Py_None; +} + +static PyMemberDef Py_filter_members[] = { + // TODO remove READONLY flag and define getter/setter + {"order", T_INT, offsetof (Py_filter, order), READONLY, + "order of the filter"}, + {NULL} /* Sentinel */ +}; + +static PyMethodDef Py_filter_methods[] = { + {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_VARARGS, + "set filter coefficients to C-weighting"}, + {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_VARARGS, + "set filter coefficients to A-weighting"}, + {"set_biquad", (PyCFunction) Py_filter_set_biquad, METH_VARARGS, + "set b0, b1, b2, a1, a2 biquad coefficients"}, + {NULL} +}; + +PyTypeObject Py_filterType = { + PyObject_HEAD_INIT (NULL) + 0, /* ob_size */ + "aubio.digital_filter", /* tp_name */ + sizeof (Py_filter), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) Py_filter_del, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, //(reprfunc) Py_filter_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)Py_filter_do, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_filter_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Py_filter_methods, /* tp_methods */ + Py_filter_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc) Py_filter_init, /* tp_init */ + 0, /* tp_alloc */ + Py_filter_new, /* tp_new */ +}; diff --git a/python/py-filterbank.c b/python/py-filterbank.c new file mode 100644 index 00000000..cc0da481 --- /dev/null +++ b/python/py-filterbank.c @@ -0,0 +1,183 @@ +#include "aubiowraphell.h" + +static char Py_filterbank_doc[] = "filterbank object"; + +AUBIO_DECLARE(filterbank, uint_t n_filters; uint_t win_s) + +//AUBIO_NEW(filterbank) +static PyObject * +Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int win_s = 0, n_filters = 0; + Py_filterbank *self; + static char *kwlist[] = { "n_filters", "win_s", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, + &n_filters, &win_s)) { + return NULL; + } + + self = (Py_filterbank *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->win_s = Py_default_vector_length; + if (win_s > 0) { + self->win_s = win_s; + } else if (win_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative window size"); + return NULL; + } + + self->n_filters = 40; + if (n_filters > 0) { + self->n_filters = n_filters; + } else if (n_filters < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative number of filters"); + return NULL; + } + + return (PyObject *) self; +} + + +AUBIO_INIT(filterbank, self->n_filters, self->win_s) + +AUBIO_DEL(filterbank) + +static PyObject * +Py_filterbank_do(Py_filterbank * self, PyObject * args) +{ + PyObject *input; + cvec_t *vec; + fvec_t *out; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCCvec (input); + + if (vec == NULL) { + return NULL; + } + + out = new_fvec (self->n_filters); + + // compute the function + aubio_filterbank_do (self->o, vec, out); + return (PyObject *)PyAubio_CFvecToArray(out); +} + +AUBIO_MEMBERS_START(filterbank) + {"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY, + "size of the window"}, + {"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY, + "number of filters"}, +AUBIO_MEMBERS_STOP(filterbank) + +static PyObject * +Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) +{ + uint_t err = 0; + + PyObject *input; + uint_t samplerate; + fvec_t *freqs; + if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) { + return NULL; + } + + if (input == NULL) { + return NULL; + } + + freqs = PyAubio_ArrayToCFvec (input); + + if (freqs == NULL) { + return NULL; + } + + err = aubio_filterbank_set_triangle_bands (self->o, + freqs, samplerate); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter to A-weighting"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) +{ + uint_t err = 0; + + uint_t samplerate; + if (!PyArg_ParseTuple (args, "I", &samplerate)) { + return NULL; + } + + err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate); + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter to A-weighting"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filterbank_set_coeffs (Py_filterbank * self, PyObject *args) +{ + uint_t err = 0; + + PyObject *input; + fmat_t *coeffs; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + coeffs = PyAubio_ArrayToCFmat (input); + + if (coeffs == NULL) { + PyErr_SetString (PyExc_ValueError, + "unable to parse input array"); + return NULL; + } + + err = aubio_filterbank_set_coeffs (self->o, coeffs); + + if (err > 0) { + PyErr_SetString (PyExc_ValueError, + "error when setting filter coefficients"); + return NULL; + } + return Py_None; +} + +static PyObject * +Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused) +{ + return (PyObject *)PyAubio_CFmatToArray( + aubio_filterbank_get_coeffs (self->o) ); +} + +static PyMethodDef Py_filterbank_methods[] = { + {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands, + METH_VARARGS, "set coefficients of filterbanks"}, + {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney, + METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"}, + {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs, + METH_NOARGS, "get coefficients of filterbank"}, + {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs, + METH_VARARGS, "set coefficients of filterbank"}, + {NULL} +}; + +AUBIO_TYPEOBJECT(filterbank, "aubio.filterbank") diff --git a/python/py-phasevoc.c b/python/py-phasevoc.c new file mode 100644 index 00000000..6767e921 --- /dev/null +++ b/python/py-phasevoc.c @@ -0,0 +1,118 @@ +#include "aubiowraphell.h" + +static char Py_pvoc_doc[] = "pvoc object"; + +AUBIO_DECLARE(pvoc, uint_t win_s; uint_t hop_s) + +//AUBIO_NEW(pvoc) +static PyObject * +Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) +{ + int win_s = 0, hop_s = 0; + Py_pvoc *self; + static char *kwlist[] = { "win_s", "hop_s", NULL }; + + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, + &win_s, &hop_s)) { + return NULL; + } + + self = (Py_pvoc *) type->tp_alloc (type, 0); + + if (self == NULL) { + return NULL; + } + + self->win_s = Py_default_vector_length; + self->hop_s = Py_default_vector_length/2; + + if (self == NULL) { + return NULL; + } + + if (win_s > 0) { + self->win_s = win_s; + } else if (win_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative window size"); + return NULL; + } + + if (hop_s > 0) { + self->hop_s = hop_s; + } else if (hop_s < 0) { + PyErr_SetString (PyExc_ValueError, + "can not use negative hop size"); + return NULL; + } + + return (PyObject *) self; +} + + +AUBIO_INIT(pvoc, self->win_s, self->hop_s) + +AUBIO_DEL(pvoc) + +static PyObject * +Py_pvoc_do(Py_pvoc * self, PyObject * args) +{ + PyObject *input; + fvec_t *vec; + cvec_t *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCFvec (input); + + if (vec == NULL) { + return NULL; + } + + output = new_cvec(self->win_s); + + // compute the function + aubio_pvoc_do (self->o, vec, output); + return (PyObject *)PyAubio_CCvecToPyCvec(output); +} + +AUBIO_MEMBERS_START(pvoc) + {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY, + "size of the window"}, + {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY, + "size of the hop"}, +AUBIO_MEMBERS_STOP(pvoc) + +static PyObject * +Py_pvoc_rdo(Py_pvoc * self, PyObject * args) +{ + PyObject *input; + cvec_t *vec; + fvec_t *output; + + if (!PyArg_ParseTuple (args, "O", &input)) { + return NULL; + } + + vec = PyAubio_ArrayToCCvec (input); + + if (vec == NULL) { + return NULL; + } + + output = new_fvec(self->hop_s); + + // compute the function + aubio_pvoc_rdo (self->o, vec, output); + return (PyObject *)PyAubio_CFvecToArray(output); +} + +static PyMethodDef Py_pvoc_methods[] = { + {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS, + "synthesis of spectral grain"}, + {NULL} +}; + +AUBIO_TYPEOBJECT(pvoc, "aubio.pvoc") diff --git a/python/run_all_tests b/python/run_all_tests new file mode 100755 index 00000000..ad18a92c --- /dev/null +++ b/python/run_all_tests @@ -0,0 +1,20 @@ +#! /usr/bin/env python + +if __name__ == '__main__': + import os, sys, unittest + def load_test(): + # get relevant files + curdir = os.path.dirname(sys.argv[0]) + if curdir == '': curdir = '.' + files = os.listdir(curdir) + modfiles = filter (lambda y: y.endswith('.py'), files) + modfiles = filter (lambda f: f.startswith('test_'), modfiles) + # get module names + modnames = map (lambda x: os.path.splitext(x)[0], modfiles) + # import them + modules = map (__import__, modnames) + # create a test suites from the imported module + load_from_module = unittest.defaultTestLoader.loadTestsFromModule + tests = map(load_from_module, modules) + return unittest.TestSuite(tests) + unittest.main(defaultTest = 'load_test') diff --git a/python/setup.py b/python/setup.py new file mode 100755 index 00000000..f6f88a1e --- /dev/null +++ b/python/setup.py @@ -0,0 +1,41 @@ +#! /usr/bin/python + +from distutils.core import setup, Extension +from generator import generate_object_files +import os.path +import numpy + +library_dirs = ['../build/src', '../src/.libs'] +include_dirs = ['../build/src', '../src', '.' ] +library_dirs = filter (lambda x: os.path.isdir(x), library_dirs) +include_dirs = filter (lambda x: os.path.isdir(x), include_dirs) + +aubio_extension = Extension("_aubio", + ["aubiomodule.c", + "aubioproxy.c", + "py-cvec.c", + # example without macro + "py-filter.c", + # macroised + "py-filterbank.c", + "py-fft.c", + "py-phasevoc.c", + # generated files + ] + generate_object_files(), + include_dirs = include_dirs + [ numpy.get_include() ], + library_dirs = library_dirs, + libraries=['aubio']) + +setup(name='aubio', + version = '0.4.0alpha', + packages = ['aubio'], + description = 'interface to the aubio library', + long_description = 'interface to the aubio library', + license = 'GNU/GPL version 3', + author = 'Paul Brossier', + author_email = 'piem@aubio.org', + maintainer = 'Paul Brossier', + maintainer_email = 'piem@aubio.org', + url = 'http://aubio.org/', + ext_modules = [aubio_extension]) + diff --git a/python/test_aubio.py b/python/test_aubio.py new file mode 100755 index 00000000..951ade98 --- /dev/null +++ b/python/test_aubio.py @@ -0,0 +1,14 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite + +class aubiomodule_test_case(TestCase): + + def test_import(self): + """ try importing aubio """ + import aubio + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_cvec.py b/python/test_cvec.py new file mode 100755 index 00000000..86916464 --- /dev/null +++ b/python/test_cvec.py @@ -0,0 +1,50 @@ +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +from aubio import cvec +from numpy import array, shape, pi + +class aubio_cvec_test_case(TestCase): + + def test_vector_created_with_zeroes(self): + a = cvec(10) + a + shape(a.norm) + shape(a.phas) + a.norm[0] + assert_equal(a.norm, 0.) + assert_equal(a.phas, 0.) + + def test_vector_assign_element(self): + a = cvec() + a.norm[0] = 1 + assert_equal(a.norm[0], 1) + a.phas[0] = 1 + assert_equal(a.phas[0], 1) + + def test_vector_assign_element_end(self): + a = cvec() + a.norm[-1] = 1 + assert_equal(a.norm[-1], 1) + assert_equal(a.norm[len(a.norm)-1], 1) + a.phas[-1] = 1 + assert_equal(a.phas[-1], 1) + assert_equal(a.phas[len(a.phas)-1], 1) + + def test_assign_cvec_norm_slice(self): + spec = cvec(1024) + spec.norm[40:100] = 100 + assert_equal (spec.norm[0:40], 0) + assert_equal (spec.norm[40:100], 100) + assert_equal (spec.norm[100:-1], 0) + assert_equal (spec.phas, 0) + + def test_assign_cvec_phas_slice(self): + spec = cvec(1024) + spec.phas[39:-1] = -pi + assert_equal (spec.phas[0:39], 0) + assert_equal (spec.phas[39:-1], -pi) + assert_equal (spec.norm, 0) + +if __name__ == '__main__': + from unittest import main + main() diff --git a/python/test_fft.py b/python/test_fft.py new file mode 100755 index 00000000..ccb6e4cf --- /dev/null +++ b/python/test_fft.py @@ -0,0 +1,113 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +# WARNING: numpy also has an fft object +from aubio import fvec, fft, cvec +from numpy import array, shape +from math import pi + +class aubio_fft_test_case(TestCase): + + def test_members(self): + f = fft() + assert_equal (f.win_s, 1024) + + def test_output_dimensions(self): + """ check the dimensions of output """ + win_s = 1024 + timegrain = fvec(win_s) + f = fft(win_s) + fftgrain = f (timegrain) + assert_equal (fftgrain.norm, 0) + assert_equal (shape(fftgrain.norm), (win_s/2+1,)) + assert_equal (fftgrain.phas, 0) + assert_equal (shape(fftgrain.phas), (win_s/2+1,)) + + def test_zeros(self): + """ check the transform of zeros """ + win_s = 512 + timegrain = fvec(win_s) + f = fft(win_s) + fftgrain = f(timegrain) + assert_equal ( fftgrain.norm == 0, True ) + assert_equal ( fftgrain.phas == 0, True ) + + def test_impulse(self): + """ check the transform of one impulse at a random place """ + from random import random + from math import floor + win_s = 256 + i = floor(random()*win_s) + impulse = pi * random() + f = fft(win_s) + timegrain = fvec(win_s) + timegrain[i] = impulse + fftgrain = f ( timegrain ) + #self.plot_this ( fftgrain.phas ) + assert_almost_equal ( fftgrain.norm, impulse, decimal = 6 ) + assert_equal ( fftgrain.phas <= pi, True) + assert_equal ( fftgrain.phas >= -pi, True) + + def test_impulse_negative(self): + """ check the transform of one impulse at a random place """ + from random import random + from math import floor + win_s = 256 + i = 0 + impulse = -10. + f = fft(win_s) + timegrain = fvec(win_s) + timegrain[i] = impulse + fftgrain = f ( timegrain ) + #self.plot_this ( fftgrain.phas ) + assert_almost_equal ( fftgrain.norm, abs(impulse), decimal = 6 ) + if impulse < 0: + # phase can be pi or -pi, as it is not unwrapped + assert_almost_equal ( abs(fftgrain.phas[1:-1]) , pi, decimal = 6 ) + assert_almost_equal ( fftgrain.phas[0], pi, decimal = 6) + assert_almost_equal ( fftgrain.phas[-1], pi, decimal = 6) + else: + assert_equal ( fftgrain.phas[1:-1] == 0, True) + assert_equal ( fftgrain.phas[0] == 0, True) + assert_equal ( fftgrain.phas[-1] == 0, True) + # now check the resynthesis + synthgrain = f.rdo ( fftgrain ) + #self.plot_this ( fftgrain.phas.T ) + assert_equal ( fftgrain.phas <= pi, True) + assert_equal ( fftgrain.phas >= -pi, True) + #self.plot_this ( synthgrain - timegrain ) + assert_almost_equal ( synthgrain, timegrain, decimal = 6 ) + + def test_impulse_at_zero(self): + """ check the transform of one impulse at a index 0 """ + win_s = 1024 + impulse = pi + f = fft(win_s) + timegrain = fvec(win_s) + timegrain[0] = impulse + fftgrain = f ( timegrain ) + #self.plot_this ( fftgrain.phas ) + assert_equal ( fftgrain.phas[0], 0) + # could be 0 or -0 depending on fft implementation (0 for fftw3, -0 for ooura) + assert_almost_equal ( fftgrain.phas[1], 0) + assert_almost_equal ( fftgrain.norm[0], impulse, decimal = 6 ) + + def test_rdo_before_do(self): + """ check running fft.rdo before fft.do works """ + win_s = 1024 + impulse = pi + f = fft(win_s) + fftgrain = cvec(win_s) + t = f.rdo( fftgrain ) + assert_equal ( t, 0 ) + + def plot_this(self, this): + from pylab import plot, show + plot ( this ) + show () + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_filter.py b/python/test_filter.py new file mode 100755 index 00000000..14a880d0 --- /dev/null +++ b/python/test_filter.py @@ -0,0 +1,68 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, assert_equal, assert_almost_equal +from aubio import fvec, digital_filter +from numpy import array + +def array_from_text_file(filename, dtype = 'float'): + return array([line.split() for line in open(filename).readlines()], + dtype = dtype) + +class aubio_filter_test_case(TestCase): + + def test_members(self): + f = digital_filter() + assert_equal (f.order, 7) + f = digital_filter(5) + assert_equal (f.order, 5) + f(fvec()) + + def test_cweighting_error(self): + f = digital_filter (2) + self.assertRaises ( ValueError, f.set_c_weighting, 44100 ) + f = digital_filter (8) + self.assertRaises ( ValueError, f.set_c_weighting, 44100 ) + f = digital_filter (5) + self.assertRaises ( ValueError, f.set_c_weighting, 4000 ) + f = digital_filter (5) + self.assertRaises ( ValueError, f.set_c_weighting, 193000 ) + f = digital_filter (7) + self.assertRaises ( ValueError, f.set_a_weighting, 193000 ) + f = digital_filter (5) + self.assertRaises ( ValueError, f.set_a_weighting, 192000 ) + + def test_c_weighting(self): + expected = array_from_text_file('c_weighting_test_simple.expected') + f = digital_filter(5) + f.set_c_weighting(44100) + v = fvec(32) + v[12] = .5 + u = f(v) + assert_almost_equal (expected[1], u) + + def test_a_weighting(self): + expected = array_from_text_file('a_weighting_test_simple.expected') + f = digital_filter(7) + f.set_a_weighting(44100) + v = fvec(32) + v[12] = .5 + u = f(v) + assert_almost_equal (expected[1], u) + + def test_a_weighting_parted(self): + expected = array_from_text_file('a_weighting_test_simple.expected') + f = digital_filter(7) + f.set_a_weighting(44100) + v = fvec(16) + v[12] = .5 + u = f(v) + assert_almost_equal (expected[1][:16], u) + # one more time + v = fvec(16) + u = f(v) + assert_almost_equal (expected[1][16:], u) + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_filterbank.py b/python/test_filterbank.py new file mode 100755 index 00000000..c00a5685 --- /dev/null +++ b/python/test_filterbank.py @@ -0,0 +1,23 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +from numpy import random +from aubio import cvec, filterbank + +class aubio_filterbank_test_case(TestCase): + + def test_members(self): + f = filterbank(40, 512) + assert_equal ([f.n_filters, f.win_s], [40, 512]) + + def test_set_coeffs(self): + f = filterbank(40, 512) + r = random.random([40, 512 / 2 + 1]).astype('float32') + f.set_coeffs(r) + assert_equal (r, f.get_coeffs()) + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_filterbank_mel.py b/python/test_filterbank_mel.py new file mode 100755 index 00000000..532ca0b3 --- /dev/null +++ b/python/test_filterbank_mel.py @@ -0,0 +1,51 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +from numpy import array, shape +from aubio import cvec, filterbank + +class aubio_filterbank_mel_test_case(TestCase): + + def test_slaney(self): + f = filterbank(40, 512) + f.set_mel_coeffs_slaney(16000) + a = f.get_coeffs() + assert_equal(shape (a), (40, 512/2 + 1) ) + + def test_other_slaney(self): + f = filterbank(40, 512*2) + f.set_mel_coeffs_slaney(44100) + a = f.get_coeffs() + #print "sum is", sum(sum(a)) + for win_s in [256, 512, 1024, 2048, 4096]: + f = filterbank(40, win_s) + f.set_mel_coeffs_slaney(320000) + a = f.get_coeffs() + #print "sum is", sum(sum(a)) + + def test_triangle_freqs_zeros(self): + f = filterbank(9, 1024) + freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] + freqs = array(freq_list, dtype = 'float32') + f.set_triangle_bands(freqs, 48000) + f.get_coeffs().T + assert_equal ( f(cvec(1024)), 0) + + def test_triangle_freqs_ones(self): + f = filterbank(9, 1024) + freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] + freqs = array(freq_list, dtype = 'float32') + f.set_triangle_bands(freqs, 48000) + f.get_coeffs().T + spec = cvec(1024) + spec.norm[:] = 1 + assert_almost_equal ( f(spec), + [ 0.02070313, 0.02138672, 0.02127604, 0.02135417, + 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345]) + +if __name__ == '__main__': + from unittest import main + main() + + diff --git a/python/test_fvec.py b/python/test_fvec.py new file mode 100755 index 00000000..643c6f93 --- /dev/null +++ b/python/test_fvec.py @@ -0,0 +1,135 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +from aubio import fvec, zero_crossing_rate, alpha_norm, min_removal +from numpy import array, shape + +class aubio_fvec_test_case(TestCase): + + def test_vector_created_with_zeroes(self): + a = fvec(10) + a + shape(a) + a[0] + #del a + assert_equal(array(a), 0.) + + def test_vector_create_with_list(self): + a = fvec([0,1,2,3]) + assert_equal (range(4), a) + + def test_vector_assign_element(self): + a = fvec() + a[0] = 1 + assert_equal(a[0], 1) + + def test_vector_assign_element_end(self): + a = fvec() + a[-1] = 1 + assert_equal(a[-1], 1) + assert_equal(a[len(a)-1], 1) + + def test_vector(self): + a = fvec() + a, len(a) #a.length + a[0] + array(a) + a = fvec(10) + a = fvec(1) + a.T + array(a).T + a = range(len(a)) + + def test_wrong_values(self): + self.assertRaises (ValueError, fvec, -10) + + a = fvec(2) + self.assertRaises (IndexError, a.__getitem__, 3) + self.assertRaises (IndexError, a.__getitem__, 2) + + def test_alpha_norm_of_fvec(self): + a = fvec(2) + self.assertEquals (alpha_norm(a, 1), 0) + a[0] = 1 + self.assertEquals (alpha_norm(a, 1), 0.5) + a[1] = 1 + self.assertEquals (alpha_norm(a, 1), 1) + a = array([0, 1], dtype='float32') + from math import sqrt + assert_almost_equal (alpha_norm(a, 2), sqrt(2)/2.) + + def test_alpha_norm_of_none(self): + self.assertRaises (ValueError, alpha_norm, None, 1) + + def test_alpha_norm_of_array_of_float32(self): + # check scalar fails + a = array(1, dtype = 'float32') + self.assertRaises (ValueError, alpha_norm, a, 1) + # check 2d array fails + a = array([[2],[4]], dtype = 'float32') + self.assertRaises (ValueError, alpha_norm, a, 1) + # check 1d array + a = array(range(10), dtype = 'float32') + self.assertEquals (alpha_norm(a, 1), 4.5) + + def test_alpha_norm_of_array_of_int(self): + a = array(1, dtype = 'int') + self.assertRaises (ValueError, alpha_norm, a, 1) + a = array([[[1,2],[3,4]]], dtype = 'int') + self.assertRaises (ValueError, alpha_norm, a, 1) + a = array(range(10), dtype = 'int') + self.assertRaises (ValueError, alpha_norm, a, 1) + + def test_alpha_norm_of_array_of_string (self): + a = "hello" + self.assertRaises (ValueError, alpha_norm, a, 1) + + def test_zero_crossing_rate(self): + a = array([0,1,-1], dtype='float32') + assert_almost_equal (zero_crossing_rate(a), 1./3. ) + a = array([0.]*100, dtype='float32') + self.assertEquals (zero_crossing_rate(a), 0 ) + a = array([-1.]*100, dtype='float32') + self.assertEquals (zero_crossing_rate(a), 0 ) + a = array([1.]*100, dtype='float32') + self.assertEquals (zero_crossing_rate(a), 0 ) + + def test_alpha_norm_of_array_of_float64(self): + # check scalar fail + a = array(1, dtype = 'float64') + self.assertRaises (ValueError, alpha_norm, a, 1) + # check 3d array fail + a = array([[[1,2],[3,4]]], dtype = 'float64') + self.assertRaises (ValueError, alpha_norm, a, 1) + # check float64 1d array fail + a = array(range(10), dtype = 'float64') + self.assertRaises (ValueError, alpha_norm, a, 1) + # check float64 2d array fail + a = array([range(10), range(10)], dtype = 'float64') + self.assertRaises (ValueError, alpha_norm, a, 1) + + def test_fvec_min_removal_of_array(self): + a = array([20,1,19], dtype='float32') + b = min_removal(a) + assert_equal (array(b), [19, 0, 18]) + assert_equal (b, [19, 0, 18]) + assert_equal (a, b) + a[0] = 0 + assert_equal (a, b) + + def test_fvec_min_removal_of_array_float64(self): + a = array([20,1,19], dtype='float64') + self.assertRaises (ValueError, min_removal, a) + + def test_fvec_min_removal_of_fvec(self): + a = fvec(3) + a = array([20, 1, 19], dtype = 'float32') + b = min_removal(a) + assert_equal (array(b), [19, 0, 18]) + assert_equal (b, [19, 0, 18]) + assert_equal (a, b) + +if __name__ == '__main__': + from unittest import main + main() diff --git a/python/test_onset.py b/python/test_onset.py new file mode 100755 index 00000000..c6642d51 --- /dev/null +++ b/python/test_onset.py @@ -0,0 +1,20 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +# WARNING: numpy also has an fft object +from aubio import onset, cvec +from numpy import array, shape, arange, zeros, log +from math import pi + +class aubio_onset(TestCase): + + def test_members(self): + o = onset() + assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate], + [1024,512,'default',44100]) + + +if __name__ == '__main__': + from unittest import main + main() diff --git a/python/test_peakpicker.py b/python/test_peakpicker.py new file mode 100755 index 00000000..08313d12 --- /dev/null +++ b/python/test_peakpicker.py @@ -0,0 +1,115 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, assert_equal, assert_almost_equal +from aubio import peakpicker, fvec + +class aubio_peakpicker(TestCase): + + def test_members(self): + o = peakpicker() + + def test_peakpicker_zeroes(self): + o = peakpicker() + assert_equal(o.get_thresholded_input(), 0.) + + def test_peakpick_set_threshold(self): + o = peakpicker() + new_threshold = threshold + o.set_threshold(new_threshold) + assert_almost_equal(new_threshold, o.get_threshold()) + + def test_peakpicker_get_threshold(self): + o = peakpicker() + new_threshold = o.get_threshold() + o.set_threshold(new_threshold) + assert_equal(new_threshold, o.get_threshold()) + +buf_size = 1024 +slice_size = 5 +delay = 1 +threshold = .9 + +class aubio_peakpicker_peaks(TestCase): + + def setUp(self): + self.o = peakpicker() + self.o.set_threshold (threshold) + self.vec = fvec(buf_size) + + def test_peakpicker_impulse(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. + self.peaks = [a] + + def test_peakpicker_ramp_up(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. / 4. * 1. + vec[a+1] = 1000. / 4. * 2. + vec[a+2] = 1000. / 4. * 3. + vec[a+3] = 1000. + self.peaks = [a+1] + + def test_peakpicker_ramp_down(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. + vec[a+1] = 1000. / 4. * 3. + vec[a+2] = 1000. / 4. * 2. + vec[a+3] = 1000. / 4. * 1. + self.peaks = [a] + + def test_peakpicker_plateau(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. / 2 + vec[a+1] = 1000. + vec[a+2] = 1000. + vec[a+3] = 1000. + vec[a+4] = 1000. / 2 + self.peaks = [a+1] + + def test_peakpicker_consecutive_peaks(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. / 2 + vec[a+1] = 1000. + vec[a+3] = 1000. + vec[a+4] = 1000. / 2 + self.peaks = [a] + + def test_peakpicker_distant_peaks(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. + vec[a+7] = 1000. + self.peaks = [a, a+7] + + def test_peakpicker_very_distant_peaks(self): + vec = self.vec; o = self.o + a = 345 + vec[a] = 1000. + vec[a+67] = 1000. + self.peaks = [a, a+67] + + def tearDown(self): + fpeaks = [] + for index in range(0,buf_size-slice_size): + sliced = self.vec[index:index+slice_size] + findex = self.o(sliced) + if findex: + # we found a peak + fpeak = index - findex - delay + #print self.peaks, index, '-', findex, '-', delay, '=', fpeak + if not round(index - findex - delay) in self.peaks: + self.fail('missing peak ' + str(fpeak)) + fpeaks.append(fpeak) + if len(fpeaks) != len(self.peaks): + self.fail('some peaks of ' + str(self.peaks) + 'were not found, got only ' + str(fpeaks)) + #print + #print fpeaks, self.peaks + +if __name__ == '__main__': + from unittest import main + main() diff --git a/python/test_phasevoc.py b/python/test_phasevoc.py new file mode 100755 index 00000000..5dd97866 --- /dev/null +++ b/python/test_phasevoc.py @@ -0,0 +1,65 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, run_module_suite +from numpy.testing import assert_equal, assert_almost_equal +from aubio import fvec, cvec, pvoc +from numpy import array, shape + +class aubio_pvoc_test_case(TestCase): + + def test_members(self): + f = pvoc() + assert_equal ([f.win_s, f.hop_s], [1024, 512]) + f = pvoc(2048, 128) + assert_equal ([f.win_s, f.hop_s], [2048, 128]) + + def test_zeros(self): + win_s, hop_s = 1024, 256 + f = pvoc (win_s, hop_s) + t = fvec (hop_s) + for time in range( 4 * win_s / hop_s ): + s = f(t) + r = f.rdo(s) + assert_equal ( array(t), 0) + assert_equal ( s.norm, 0) + assert_equal ( s.phas, 0) + assert_equal ( r, 0) + + def test_steps_two_channels(self): + """ check the resynthesis of steps is correct """ + f = pvoc(1024, 512) + t1 = fvec(512) + t2 = fvec(512) + # positive step in first channel + t1[100:200] = .1 + # positive step in second channel + t1[20:50] = -.1 + s1 = f(t1) + r1 = f.rdo(s1) + s2 = f(t2) + r2 = f.rdo(s2) + #self.plot_this ( s1.norm.T ) + assert_almost_equal ( t1, r2, decimal = 6 ) + + def test_steps_three_random_channels(self): + from random import random + f = pvoc(64, 16) + t0 = fvec(16) + t1 = fvec(16) + for i in xrange(16): + t1[i] = random() * 2. - 1. + t2 = f.rdo(f(t1)) + t2 = f.rdo(f(t0)) + t2 = f.rdo(f(t0)) + t2 = f.rdo(f(t0)) + assert_almost_equal( t1, t2, decimal = 6 ) + + def plot_this( self, this ): + from pylab import semilogy, show + semilogy ( this ) + show () + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_pitch.py b/python/test_pitch.py new file mode 100755 index 00000000..a0dd3a59 --- /dev/null +++ b/python/test_pitch.py @@ -0,0 +1,101 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase +from numpy.testing import assert_equal, assert_almost_equal +from numpy import random, sin, arange, mean, median +from math import pi +from aubio import fvec, pitch + +class aubio_mathutils_test_case(TestCase): + + def test_members(self): + p = pitch() + assert_equal ( [p.method, p.buf_size, p.hop_size, p.samplerate], + ['default', 1024, 512, 44100]) + + def test_members_not_default(self): + p = pitch('mcomb', 2048, 512, 32000) + assert_equal ( [p.method, p.buf_size, p.hop_size, p.samplerate], + ['mcomb', 2048, 512, 32000]) + + def test_run_on_zeros(self): + p = pitch('mcomb', 2048, 512, 32000) + f = fvec (512) + assert_equal ( p(f), 0. ) + + def test_run_on_ones(self): + p = pitch('mcomb', 2048, 512, 32000) + f = fvec (512) + f[:] = 1 + assert( p(f) != 0. ) + + def test_run_default_on_sinusoid(self): + method = 'default' + buf_size = 2048 + hop_size = 512 + samplerate = 32000 + freq = 450. + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) + + def test_run_schmitt_on_sinusoid(self): + method = 'schmitt' + buf_size = 4096 + hop_size = 512 + samplerate = 44100 + freq = 800. + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) + + def test_run_mcomb_on_sinusoid(self): + method = 'mcomb' + buf_size = 2048 + hop_size = 512 + samplerate = 44100 + freq = 10000. + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) + + def test_run_fcomb_on_sinusoid(self): + method = 'fcomb' + buf_size = 2048 + hop_size = 512 + samplerate = 32000 + freq = 440. + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) + + def test_run_yin_on_sinusoid(self): + method = 'yin' + buf_size = 4096 + hop_size = 512 + samplerate = 32000 + freq = 880. + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) + + def test_run_yinfft_on_sinusoid(self): + method = 'yinfft' + buf_size = 2048 + hop_size = 512 + samplerate = 32000 + freq = 640. + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) + + def run_pitch_on_sinusoid(self, method, buf_size, hop_size, samplerate, freq): + p = pitch(method, buf_size, hop_size, samplerate) + sinvec = self.build_sinusoid(hop_size * 100, freq, samplerate) + self.run_pitch(p, sinvec, freq) + + def build_sinusoid(self, length, freq, samplerate): + return sin( 2. * pi * arange(length).astype('float32') * freq / samplerate) + + def run_pitch(self, p, input_vec, freq): + count = 0 + pitches, errors = [], [] + for vec_slice in input_vec.reshape((-1, p.hop_size)): + pitch = p(vec_slice) + pitches.append(pitch) + errors.append(1. - pitch / freq) + # check that the mean of all relative errors is less than 10% + assert_almost_equal (mean(errors), 0., decimal = 2) + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_source.py b/python/test_source.py new file mode 100755 index 00000000..ae3b79bb --- /dev/null +++ b/python/test_source.py @@ -0,0 +1,27 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, assert_equal, assert_almost_equal +from aubio import fvec, source +from numpy import array + +path = "/Users/piem/archives/sounds/loops/drum_Chocolate_Milk_-_Ation_Speaks_Louder_Than_Words.wav" + +class aubio_filter_test_case(TestCase): + + def test_members(self): + f = source(path) + print dir(f) + + def test_read(self): + f = source(path) + total_frames = 0 + while True: + vec, read = f() + total_frames += read + if read < f.hop_size: break + print "read", total_frames / float(f.samplerate), " seconds from", path + +if __name__ == '__main__': + from unittest import main + main() + diff --git a/python/test_specdesc.py b/python/test_specdesc.py new file mode 100755 index 00000000..675858d2 --- /dev/null +++ b/python/test_specdesc.py @@ -0,0 +1,238 @@ +#! /usr/bin/env python + +from numpy.testing import TestCase, assert_equal, assert_almost_equal +from numpy import random, arange, log, zeros +from aubio import specdesc, cvec +from math import pi + +methods = ["default", + "energy", + "hfc", + "complex", + "phase", + "specdiff", + "kl", + "mkl", + "specflux", + "centroid", + "spread", + "skewness", + "kurtosis", + "slope", + "decrease", + "rolloff"] +buf_size = 2048 + +class aubio_specdesc(TestCase): + + def test_members(self): + o = specdesc() + + for method in methods: + o = specdesc(method, buf_size) + assert_equal ([o.buf_size, o.method], [buf_size, method]) + + spec = cvec(buf_size) + spec.norm[0] = 1 + spec.norm[1] = 1./2. + #print "%20s" % method, str(o(spec)) + o(spec) + spec.norm = random.random_sample((len(spec.norm),)).astype('float32') + spec.phas = random.random_sample((len(spec.phas),)).astype('float32') + #print "%20s" % method, str(o(spec)) + assert (o(spec) != 0.) + + def test_hfc(self): + o = specdesc("hfc", buf_size) + spec = cvec(buf_size) + # hfc of zeros is zero + assert_equal (o(spec), 0.) + # hfc of ones is sum of all bin numbers + spec.norm[:] = 1 + expected = sum(range(buf_size/2 + 2)) + assert_equal (o(spec), expected) + # changing phase doesn't change anything + spec.phas[:] = 1 + assert_equal (o(spec), sum(range(buf_size/2 + 2))) + + def test_phase(self): + o = specdesc("phase", buf_size) + spec = cvec(buf_size) + # phase of zeros is zero + assert_equal (o(spec), 0.) + spec.phas = random.random_sample((len(spec.phas),)).astype('float32') + # phase of random is not zero + spec.norm[:] = 1 + assert (o(spec) != 0.) + + def test_specdiff(self): + o = specdesc("phase", buf_size) + spec = cvec(buf_size) + # specdiff of zeros is zero + assert_equal (o(spec), 0.) + spec.phas = random.random_sample((len(spec.phas),)).astype('float32') + # phase of random is not zero + spec.norm[:] = 1 + assert (o(spec) != 0.) + + def test_hfc(self): + o = specdesc("hfc") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + assert_equal (a, c.norm) + assert_equal ( sum(a*(a+1)), o(c)) + + def test_complex(self): + o = specdesc("complex") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + assert_equal (a, c.norm) + # the previous run was on zeros, so previous frames are still 0 + # so we have sqrt ( abs ( r2 ^ 2) ) == r2 + assert_equal ( sum(a), o(c)) + # second time. c.norm = a, so, r1 = r2, and the euclidian distance is 0 + assert_equal ( 0, o(c)) + + def test_kl(self): + o = specdesc("kl") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + assert_almost_equal( sum(a * log(1.+ a/1.e-10 ) ) / o(c), 1., decimal=6) + + def test_mkl(self): + o = specdesc("mkl") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + assert_almost_equal( sum(log(1.+ a/1.e-10 ) ) / o(c), 1, decimal=6) + + def test_specflux(self): + o = specdesc("specflux") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + assert_equal( sum(a), o(c)) + assert_equal( 0, o(c)) + c.norm = zeros(c.length, dtype='float32') + assert_equal( 0, o(c)) + + def test_centroid(self): + o = specdesc("centroid") + c = cvec() + # make sure centroid of zeros is zero + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + centroid = sum(a*a) / sum(a) + assert_almost_equal (centroid, o(c), decimal = 2) + + c.norm = a * .5 + assert_almost_equal (centroid, o(c), decimal = 2) + + def test_spread(self): + o = specdesc("spread") + c = cvec(2048) + ramp = arange(c.length, dtype='float32') + assert_equal( 0., o(c)) + + a = ramp + c.norm = a + centroid = sum(a*a) / sum(a) + spread = sum( a * pow(ramp - centroid, 2.) ) / sum(a) + assert_almost_equal (o(c), spread, decimal = 1) + + def test_skewness(self): + o = specdesc("skewness") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + centroid = sum(a*a) / sum(a) + spread = sum( (a - centroid)**2 *a) / sum(a) + skewness = sum( (a - centroid)**3 *a) / sum(a) / spread **1.5 + assert_almost_equal (skewness, o(c), decimal = 2) + + c.norm = a * 3 + assert_almost_equal (skewness, o(c), decimal = 2) + + def test_kurtosis(self): + o = specdesc("kurtosis") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length, dtype='float32') + c.norm = a + centroid = sum(a*a) / sum(a) + spread = sum( (a - centroid)**2 *a) / sum(a) + kurtosis = sum( (a - centroid)**4 *a) / sum(a) / spread **2 + assert_almost_equal (kurtosis, o(c), decimal = 2) + + def test_slope(self): + o = specdesc("slope") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length * 2, 0, -2, dtype='float32') + k = arange(c.length, dtype='float32') + c.norm = a + num = len(a) * sum(k*a) - sum(k)*sum(a) + den = (len(a) * sum(k**2) - sum(k)**2) + slope = num/den/sum(a) + assert_almost_equal (slope, o(c), decimal = 5) + + a = arange(0, c.length * 2, +2, dtype='float32') + c.norm = a + num = len(a) * sum(k*a) - sum(k)*sum(a) + den = (len(a) * sum(k**2) - sum(k)**2) + slope = num/den/sum(a) + assert_almost_equal (slope, o(c), decimal = 5) + + a = arange(0, c.length * 2, +2, dtype='float32') + c.norm = a * 2 + assert_almost_equal (slope, o(c), decimal = 5) + + def test_decrease(self): + o = specdesc("decrease") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length * 2, 0, -2, dtype='float32') + k = arange(c.length, dtype='float32') + c.norm = a + decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) + assert_almost_equal (decrease, o(c), decimal = 5) + + a = arange(0, c.length * 2, +2, dtype='float32') + c.norm = a + decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) + assert_almost_equal (decrease, o(c), decimal = 5) + + a = arange(0, c.length * 2, +2, dtype='float32') + c.norm = a * 2 + decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) + assert_almost_equal (decrease, o(c), decimal = 5) + + def test_rolloff(self): + o = specdesc("rolloff") + c = cvec() + assert_equal( 0., o(c)) + a = arange(c.length * 2, 0, -2, dtype='float32') + k = arange(c.length, dtype='float32') + c.norm = a + cumsum = .95*sum(a*a) + i = 0; rollsum = 0 + while rollsum < cumsum: + rollsum += a[i]*a[i] + i+=1 + rolloff = i + assert_equal (rolloff, o(c)) + + +if __name__ == '__main__': + from unittest import main + main()