Showing the changes to python (87 of 129 files). Show all
Unified · Split
| @@ -1,5 +0,0 @@ | ||
| 1 | −EXTRA_DIST = README | |
| 2 | −SUBDIRS = aubio | |
| 3 | −dist_bin_SCRIPTS = aubiocut aubiopitch | |
| 4 | −dist_noinst_SCRIPTS = aubiocompare-onset aubioplot-notes \ | |
| 5 | − aubiofilter-notes aubionotes aubiocompare-onset aubioweb.py | |
| @@ -1,30 +0,0 @@ | ||
| 1 | −# Here you will find some examples of python scripts and some evaluation | |
| 2 | −# routines. The python interface for libaubio is generated using Swig. | |
| 3 | − | |
| 4 | −# To have it working before installation, you will need to set LD_LIBRARY_PATH. | |
| 5 | −# for instance, to run the python script from within aubio/python/, you can use | |
| 6 | −# '. README' | |
| 7 | − | |
| 8 | −export LD_LIBRARY_PATH=../src/.libs:../ext/.libs | |
| 9 | −export PYTHONPATH=aubio/.libs | |
| 10 | − | |
| 11 | −echo """ | |
| 12 | − | |
| 13 | −the aubio/ directory should be organised as follow: | |
| 14 | − | |
| 15 | − aubiowrapper.py,_aubiowrapper.so, aubio_wrap.c, aubio_wrap.o | |
| 16 | − swig generated aubio interface | |
| 17 | − aubioclass.py | |
| 18 | − human usable interface | |
| 19 | − plot/ | |
| 20 | − everything required to plot | |
| 21 | − web/ | |
| 22 | − tools to use aubioweb.py | |
| 23 | − bench/ | |
| 24 | − tools to explore a database of sound file and run benchmarks on it | |
| 25 | − eval/ | |
| 26 | − tools to evaluate the performance of aubio extractors | |
| 27 | − aubioweb.py | |
| 28 | − a hack to pipe aubio in mod_python | |
| 29 | − | |
| 30 | −""" | |
| @@ -0,0 +1,24 @@ | ||
| 1 | +Python aubio module | |
| 2 | +=================== | |
| 3 | + | |
| 4 | +This module wraps the aubio library for python using the numpy module. | |
| 5 | + | |
| 6 | +See the [Python/C API Reference | |
| 7 | +Manual] (http://docs.python.org/c-api/index.html) and the [Numpy/C API | |
| 8 | +Reference](http://docs.scipy.org/doc/numpy/reference/c-api.html) | |
| 9 | + | |
| 10 | +Compiling python aubio on Mac OS X | |
| 11 | +---------------------------------- | |
| 12 | + | |
| 13 | +You should now be able to build the aubio python module out of the box on a | |
| 14 | +recent version of OS X (10.8.x). Make sure the variables are correct in the | |
| 15 | +file `build_osx` before running it: | |
| 16 | + | |
| 17 | + $ ./build_osx | |
| 18 | + | |
| 19 | +Additionally, you can fetch tools such [matplotlib](http://matplotlib.org/) to | |
| 20 | +use the demo scripts. One easy way to do it is to fetch the fully fledged | |
| 21 | +[Scipy superpack](http://fonnesbeck.github.com/ScipySuperpack/) | |
| 22 | + | |
| 23 | + $ curl -O https://raw.github.com/fonnesbeck/ScipySuperpack/master/install_superpack.sh | |
| 24 | + $ sh install_superpack.sh | |
| @@ -0,0 +1,2 @@ | ||
| 1 | + 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 | |
| 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 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 | |
| @@ -0,0 +1,49 @@ | ||
| 1 | +#include <Python.h> | |
| 2 | +#include <structmember.h> | |
| 3 | +#define NO_IMPORT_ARRAY | |
| 4 | +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION | |
| 5 | +#include <numpy/arrayobject.h> | |
| 6 | +#define AUBIO_UNSTABLE 1 | |
| 7 | +#include <aubio.h> | |
| 8 | + | |
| 9 | +#define Py_default_vector_length 1024 | |
| 10 | +#define Py_default_vector_height 1 | |
| 11 | + | |
| 12 | +#define Py_aubio_default_samplerate 44100 | |
| 13 | + | |
| 14 | +#if HAVE_AUBIO_DOUBLE | |
| 15 | +#error "Ouch! Python interface for aubio has not been much tested yet." | |
| 16 | +#define AUBIO_NPY_SMPL NPY_DOUBLE | |
| 17 | +#else | |
| 18 | +#define AUBIO_NPY_SMPL NPY_FLOAT | |
| 19 | +#endif | |
| 20 | + | |
| 21 | +// special python type for cvec | |
| 22 | +typedef struct | |
| 23 | +{ | |
| 24 | + PyObject_HEAD | |
| 25 | + cvec_t * o; | |
| 26 | + uint_t length; | |
| 27 | + uint_t channels; | |
| 28 | +} Py_cvec; | |
| 29 | +extern PyTypeObject Py_cvecType; | |
| 30 | + | |
| 31 | +// defined in aubio-proxy.c | |
| 32 | +extern PyObject *PyAubio_CFvecToArray (fvec_t * self); | |
| 33 | +extern fvec_t *PyAubio_ArrayToCFvec (PyObject * self); | |
| 34 | + | |
| 35 | +extern Py_cvec *PyAubio_CCvecToPyCvec (cvec_t * self); | |
| 36 | +extern cvec_t *PyAubio_ArrayToCCvec (PyObject *input); | |
| 37 | + | |
| 38 | +extern PyObject *PyAubio_CFmatToArray (fmat_t * self); | |
| 39 | +extern fmat_t *PyAubio_ArrayToCFmat (PyObject *input); | |
| 40 | + | |
| 41 | +// hand written wrappers | |
| 42 | +extern PyTypeObject Py_filterType; | |
| 43 | + | |
| 44 | +extern PyTypeObject Py_filterbankType; | |
| 45 | + | |
| 46 | +extern PyTypeObject Py_fftType; | |
| 47 | + | |
| 48 | +extern PyTypeObject Py_pvocType; | |
| 49 | + | |
| @@ -1,66 +0,0 @@ | ||
| 1 | −nobase_pkgpython_PYTHON = \ | |
| 2 | − __init__.py \ | |
| 3 | − onsetcompare.py \ | |
| 4 | − gnuplot.py \ | |
| 5 | − median.py \ | |
| 6 | − txtfile.py \ | |
| 7 | − aubioclass.py \ | |
| 8 | − task/__init__.py \ | |
| 9 | − task/params.py \ | |
| 10 | − task/onset.py \ | |
| 11 | − task/silence.py \ | |
| 12 | − task/cut.py \ | |
| 13 | − task/beat.py \ | |
| 14 | − task/task.py \ | |
| 15 | − task/pitch.py \ | |
| 16 | − task/notes.py \ | |
| 17 | − bench/__init__.py \ | |
| 18 | − bench/broadcast.py \ | |
| 19 | − bench/config.py \ | |
| 20 | − bench/node.py \ | |
| 21 | − bench/onset.py \ | |
| 22 | − plot/__init__.py \ | |
| 23 | − plot/keyboard.py \ | |
| 24 | − web/__init__.py \ | |
| 25 | − web/browser.py \ | |
| 26 | − web/html.py | |
| 27 | − | |
| 28 | −nodist_pkgpython_PYTHON = aubiowrapper.py _aubiowrapper.so | |
| 29 | − | |
| 30 | −_aubiowrapper.so: _aubiowrapper.la | |
| 31 | − | |
| 32 | −if MINGW | |
| 33 | −SWLDFLAGS = -L${prefix}/bin -lpython${PYTHON_VERSION} | |
| 34 | −else | |
| 35 | −if DARWIN | |
| 36 | −SWLDFLAGS = -bundle -framework Python | |
| 37 | −else | |
| 38 | −SWLDFLAGS = -shared | |
| 39 | −endif | |
| 40 | −endif | |
| 41 | − | |
| 42 | −CLEANFILES = *.pyc *.so *.o aubio_wrap.c aubiowrapper.py | |
| 43 | − | |
| 44 | −NOWARN_CFLAGS = -Wno-missing-prototypes -Wno-missing-declarations \ | |
| 45 | − -Wno-strict-aliasing | |
| 46 | − | |
| 47 | −AM_CFLAGS = @AUBIO_CFLAGS@ @SNDFILE_CFLAGS@ \ | |
| 48 | − $(NOWARN_CFLAGS) $(SWCFLAGS) \ | |
| 49 | − -I$(top_builddir)/src -I$(top_srcdir)/src \ | |
| 50 | − -I$(top_srcdir)/examples \ | |
| 51 | − -I/usr/include/python${PYTHON_VERSION} \ | |
| 52 | − -I${prefix}/include/python${PYTHON_VERSION} \ | |
| 53 | − -I/usr/include \ | |
| 54 | − -I${prefix}/include | |
| 55 | − | |
| 56 | −AUBIO_LDFLAGS = $(SWLDFLAGS) \ | |
| 57 | − @SNDFILE_LIBS@ \ | |
| 58 | − -L$(top_builddir)/src -laubio | |
| 59 | − | |
| 60 | −pkgpyexec_LTLIBRARIES = _aubiowrapper.la | |
| 61 | − | |
| 62 | −_aubiowrapper_la_LDFLAGS = -module -avoid-version $(AUBIO_LDFLAGS) | |
| 63 | −_aubiowrapper_la_SOURCES = aubio_wrap.c $(top_srcdir)/examples/sndfileio.c | |
| 64 | − | |
| 65 | −aubio_wrap.c aubiowrapper.py: | |
| 66 | − $(SWIG) -outdir . -o aubio_wrap.c -python $(top_srcdir)/swig/aubio.i | |
| @@ -1,28 +1,9 @@ | ||
| 1 | −"""Copyright (C) 2004 Paul Brossier <piem@altern.org> | |
| 2 | −print aubio.__LICENSE__ for the terms of use | |
| 3 | −""" | |
| 1 | +import numpy | |
| 2 | +from _aubio import * | |
| 4 | 3 | |
| 5 | −__LICENSE__ = """\ | |
| 6 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 4 | +class fvec(numpy.ndarray): | |
| 7 | 5 | |
| 8 | − This file is part of aubio. | |
| 9 | − | |
| 10 | − aubio is free software: you can redistribute it and/or modify | |
| 11 | − it under the terms of the GNU General Public License as published by | |
| 12 | − the Free Software Foundation, either version 3 of the License, or | |
| 13 | − (at your option) any later version. | |
| 14 | − | |
| 15 | − aubio is distributed in the hope that it will be useful, | |
| 16 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − GNU General Public License for more details. | |
| 19 | − | |
| 20 | − You should have received a copy of the GNU General Public License | |
| 21 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 22 | −""" | |
| 23 | − | |
| 24 | −#from aubioclass import * | |
| 25 | −#from onsetcompare import * | |
| 26 | −#from median import * | |
| 27 | −#from noteroc import * | |
| 28 | −#from txtfile import * | |
| 6 | + def __new__(self, length = 1024, **kwargs): | |
| 7 | + if type(length) == type([]): | |
| 8 | + return numpy.array(length, dtype='float32', **kwargs) | |
| 9 | + return numpy.zeros(length, dtype='float32', **kwargs) | |
| @@ -1,160 +0,0 @@ | ||
| 1 | −from aubiowrapper import * | |
| 2 | − | |
| 3 | −class fvec: | |
| 4 | − def __init__(self,size): | |
| 5 | − self.vec = new_fvec(size) | |
| 6 | − def __call__(self): | |
| 7 | − return self.vec | |
| 8 | − def __del__(self): | |
| 9 | − del_fvec(self()) | |
| 10 | − def get(self,pos): | |
| 11 | − return fvec_read_sample(self(),pos) | |
| 12 | − def set(self,value,pos): | |
| 13 | − return fvec_write_sample(self(),value,pos) | |
| 14 | − def data(self): | |
| 15 | − return fvec_get_data(self()) | |
| 16 | − | |
| 17 | −class cvec: | |
| 18 | − def __init__(self,size): | |
| 19 | − self.vec = new_cvec(size) | |
| 20 | − def __call__(self): | |
| 21 | − return self.vec | |
| 22 | − def __del__(self): | |
| 23 | − del_cvec(self()) | |
| 24 | − def get(self,pos): | |
| 25 | − return self.get_norm(pos) | |
| 26 | − def set(self,val,pos): | |
| 27 | − self.set_norm(val,pos) | |
| 28 | − def get_norm(self,pos): | |
| 29 | − return cvec_read_norm(self(),pos) | |
| 30 | − def set_norm(self,val,pos): | |
| 31 | − cvec_write_norm(self(),val,pos) | |
| 32 | − def get_phas(self,pos): | |
| 33 | − return cvec_read_phas(self(),pos) | |
| 34 | − def set_phas(self,val,pos): | |
| 35 | − cvec_write_phas(self(),val,pos) | |
| 36 | − | |
| 37 | −class sndfile: | |
| 38 | − def __init__(self,filename,model=None): | |
| 39 | − if (model!=None): | |
| 40 | − self.file = new_aubio_sndfile_wo(model.file,filename) | |
| 41 | − else: | |
| 42 | − self.file = new_aubio_sndfile_ro(filename) | |
| 43 | − if self.file == None: | |
| 44 | − raise IOError, "failed opening file %s" % filename | |
| 45 | − def __del__(self): | |
| 46 | − if self.file != None: del_aubio_sndfile(self.file) | |
| 47 | − def info(self): | |
| 48 | − aubio_sndfile_info(self.file) | |
| 49 | − def samplerate(self): | |
| 50 | − return aubio_sndfile_samplerate(self.file) | |
| 51 | − def channels(self): | |
| 52 | − return aubio_sndfile_channels(self.file) | |
| 53 | − def read(self,nfram,vecread): | |
| 54 | − return aubio_sndfile_read_mono(self.file,nfram,vecread()) | |
| 55 | − def write(self,nfram,vecwrite): | |
| 56 | − return aubio_sndfile_write(self.file,nfram,vecwrite()) | |
| 57 | − | |
| 58 | −class pvoc: | |
| 59 | − def __init__(self,buf,hop): | |
| 60 | − self.pv = new_aubio_pvoc(buf,hop) | |
| 61 | − def __del__(self): | |
| 62 | − del_aubio_pvoc(self.pv) | |
| 63 | − def do(self,tf,tc): | |
| 64 | − aubio_pvoc_do(self.pv,tf(),tc()) | |
| 65 | − def rdo(self,tc,tf): | |
| 66 | − aubio_pvoc_rdo(self.pv,tc(),tf()) | |
| 67 | − | |
| 68 | −class onsetdetection: | |
| 69 | − """ class for aubio_specdesc """ | |
| 70 | − def __init__(self,mode,buf): | |
| 71 | − self.od = new_aubio_specdesc(mode,buf) | |
| 72 | − def do(self,tc,tf): | |
| 73 | − aubio_specdesc_do(self.od,tc(),tf()) | |
| 74 | − def __del__(self): | |
| 75 | − del_aubio_specdesc(self.od) | |
| 76 | − | |
| 77 | −class peakpick: | |
| 78 | − """ class for aubio_peakpicker """ | |
| 79 | − def __init__(self,threshold=0.1): | |
| 80 | − self.pp = new_aubio_peakpicker() | |
| 81 | − self.out = new_fvec(1) | |
| 82 | − aubio_peakpicker_set_threshold (self.pp, threshold) | |
| 83 | − def do(self,fv): | |
| 84 | − aubio_peakpicker_do(self.pp, fv(), self.out) | |
| 85 | − return fvec_read_sample(self.out, 0) | |
| 86 | − def getval(self): | |
| 87 | − return aubio_peakpicker_get_adaptive_threshold(self.pp) | |
| 88 | − def __del__(self): | |
| 89 | − del_aubio_peakpicker(self.pp) | |
| 90 | − | |
| 91 | −class onsetpick: | |
| 92 | − """ superclass for aubio_pvoc + aubio_specdesc + aubio_peakpicker """ | |
| 93 | − def __init__(self,bufsize,hopsize,myvec,threshold,mode='dual',derivate=False,dcthreshold=0): | |
| 94 | − self.myfft = cvec(bufsize) | |
| 95 | − self.pv = pvoc(bufsize,hopsize) | |
| 96 | − if mode in ['dual'] : | |
| 97 | − self.myod = onsetdetection("hfc",bufsize) | |
| 98 | − self.myod2 = onsetdetection("mkl",bufsize) | |
| 99 | − self.myonset = fvec(1) | |
| 100 | − self.myonset2 = fvec(1) | |
| 101 | − else: | |
| 102 | − self.myod = onsetdetection(mode,bufsize) | |
| 103 | − self.myonset = fvec(1) | |
| 104 | − self.mode = mode | |
| 105 | − self.pp = peakpick(float(threshold)) | |
| 106 | − self.derivate = derivate | |
| 107 | − self.dcthreshold = dcthreshold | |
| 108 | − self.oldval = 0. | |
| 109 | − | |
| 110 | − def do(self,myvec): | |
| 111 | − self.pv.do(myvec,self.myfft) | |
| 112 | − self.myod.do(self.myfft,self.myonset) | |
| 113 | − if self.mode == 'dual': | |
| 114 | − self.myod2.do(self.myfft,self.myonset2) | |
| 115 | − self.myonset.set(self.myonset.get(0)*self.myonset2.get(0),0) | |
| 116 | − if self.derivate: | |
| 117 | − val = self.myonset.get(0) | |
| 118 | − dval = val - self.oldval | |
| 119 | − self.oldval = val | |
| 120 | − if dval > 0: self.myonset.set(dval,0) | |
| 121 | − else: self.myonset.set(0.,0,0) | |
| 122 | − isonset, dval = self.pp.do(self.myonset),self.myonset.get(0) | |
| 123 | − if self.dcthreshold: | |
| 124 | − if dval < self.dcthreshold: isonset = 0 | |
| 125 | − return isonset, dval | |
| 126 | − | |
| 127 | −class pitch: | |
| 128 | − def __init__(self,mode="mcomb",bufsize=2048,hopsize=1024, | |
| 129 | − samplerate=44100.,omode="freq",tolerance=0.1): | |
| 130 | − self.pitchp = new_aubio_pitch(mode,bufsize,hopsize, | |
| 131 | − samplerate) | |
| 132 | − self.mypitch = fvec(1) | |
| 133 | − aubio_pitch_set_unit(self.pitchp,omode) | |
| 134 | − aubio_pitch_set_tolerance(self.pitchp,tolerance) | |
| 135 | − #self.filt = filter(srate,"adsgn") | |
| 136 | − def __del__(self): | |
| 137 | − del_aubio_pitch(self.pitchp) | |
| 138 | − def __call__(self,myvec): | |
| 139 | − aubio_pitch_do(self.pitchp,myvec(), self.mypitch()) | |
| 140 | − return self.mypitch.get(0) | |
| 141 | − | |
| 142 | −class filter: | |
| 143 | − def __init__(self,srate,type=None): | |
| 144 | − if (type=="adsgn"): | |
| 145 | − self.filter = new_aubio_adsgn_filter(srate) | |
| 146 | − def __del__(self): | |
| 147 | − #del_aubio_filter(self.filter) | |
| 148 | − pass | |
| 149 | − def __call__(self,myvec): | |
| 150 | − aubio_filter_do(self.filter,myvec()) | |
| 151 | − | |
| 152 | −class beattracking: | |
| 153 | − """ class for aubio_beattracking """ | |
| 154 | − def __init__(self,winlen,channels): | |
| 155 | − self.p = new_aubio_beattracking(winlen,channels) | |
| 156 | − def do(self,dfframe,out): | |
| 157 | − return aubio_beattracking_do(self.p,dfframe(),out()) | |
| 158 | − def __del__(self): | |
| 159 | − del_aubio_beattracking(self.p) | |
| 160 | − | |
Empty file deleted.
| @@ -1,25 +0,0 @@ | ||
| 1 | −from config import * | |
| 2 | − | |
| 3 | −class run_broadcast: | |
| 4 | − def __init__(self,command,*args): | |
| 5 | − for host in REMOTEHOSTS: | |
| 6 | − command(host,args[0],args[1:]) | |
| 7 | − | |
| 8 | −def remote_sync(host,path='',options=''): | |
| 9 | − optstring = '' | |
| 10 | − for i in options: | |
| 11 | − optstring = "%s %s" % (optstring,i) | |
| 12 | − print RSYNC_CMD,optstring,RSYNC_OPT,' --delete', | |
| 13 | − print '%s%s%s%s%s' % (path,'/ ',host,':',path) | |
| 14 | − | |
| 15 | − | |
| 16 | −def fetch_results(host,path='',options=''): | |
| 17 | − optstring = '' | |
| 18 | − for i in options: | |
| 19 | − optstring = "%s %s" % (optstring,i) | |
| 20 | − print RSYNC_CMD,optstring,RSYNC_OPT,' --update', | |
| 21 | − print '%s%s%s%s%s' % (host,':',path,'/ ',path) | |
| 22 | − | |
| 23 | −def remote_queue(host,command,options=''): | |
| 24 | − print 'oarsub -p "hostname = \'',host,'\'',command | |
| 25 | − | |
| @@ -1,22 +0,0 @@ | ||
| 1 | − | |
| 2 | −filefound = 0 | |
| 3 | −try: | |
| 4 | − filename = "/etc/aubio-bench.conf" | |
| 5 | − execfile(filename) | |
| 6 | − filefound = 1 | |
| 7 | −except IOError: | |
| 8 | − print "no system wide configuration file found in", filename | |
| 9 | − | |
| 10 | −try: | |
| 11 | − import os | |
| 12 | − filename = "%s%s%s" % (os.getenv('HOME'),os.sep,".aubio-bench.conf") | |
| 13 | − execfile(filename) | |
| 14 | − filefound = 1 | |
| 15 | −except IOError: | |
| 16 | − #print "no user configuration file found in", filename | |
| 17 | − pass | |
| 18 | − | |
| 19 | −if filefound == 0: | |
| 20 | − import sys | |
| 21 | − print "error: no configuration file found at all" | |
| 22 | − sys.exit(1) | |
| @@ -1,224 +0,0 @@ | ||
| 1 | −from config import * | |
| 2 | −import commands,sys | |
| 3 | −import re | |
| 4 | − | |
| 5 | −def runcommand(cmd,debug=0): | |
| 6 | − if VERBOSE >= VERBOSE_CMD or debug: print cmd | |
| 7 | − if debug: return | |
| 8 | − status, output = commands.getstatusoutput(cmd) | |
| 9 | − if status == 0 or VERBOSE >= VERBOSE_OUT: | |
| 10 | − output = output.split('\n') | |
| 11 | − if VERBOSE >= VERBOSE_OUT: | |
| 12 | − for i in output: | |
| 13 | − if i: print i | |
| 14 | − if not status == 0: | |
| 15 | − print 'error:',status,output | |
| 16 | − print 'command returning error was',cmd | |
| 17 | − #sys.exit(1) | |
| 18 | − if output == '' or output == ['']: return | |
| 19 | − return output | |
| 20 | − | |
| 21 | −def list_files(datapath,filter='f', maxdepth = -1): | |
| 22 | − if not os.path.exists(datapath): | |
| 23 | ||
| 24 | − print "ERR: no directory %s were found" % datapath | |
| 25 | − sys.exit(1) | |
| 26 | − if maxdepth >= 0: maxstring = " -maxdepth %d " % maxdepth | |
| 27 | − else: maxstring = "" | |
| 28 | − cmd = '%s' * 6 % ('find ',datapath,maxstring,' -type ',filter, "| sort -n") | |
| 29 | − return runcommand(cmd) | |
| 30 | − | |
| 31 | −def list_wav_files(datapath,maxdepth = -1): | |
| 32 | − return list_files(datapath, filter="f -name '*.wav'",maxdepth = maxdepth) | |
| 33 | − | |
| 34 | −sndfile_filter = "f -name '*.wav' -o -name '*.aif' -o -name '*.aiff'" | |
| 35 | − | |
| 36 | −def list_snd_files(datapath,maxdepth = -1): | |
| 37 | − return list_files(datapath, filter=sndfile_filter, | |
| 38 | − maxdepth = maxdepth) | |
| 39 | − | |
| 40 | −def list_res_files(datapath,maxdepth = -1): | |
| 41 | − return list_files(datapath, filter="f -name '*.txt'", maxdepth = maxdepth) | |
| 42 | − | |
| 43 | −def list_dirs(datapath): | |
| 44 | − return list_files(datapath, filter="d") | |
| 45 | − | |
| 46 | −def mkdir(path): | |
| 47 | − cmd = '%s%s' % ('mkdir -p ',path) | |
| 48 | − return runcommand(cmd) | |
| 49 | − | |
| 50 | −def act_on_data (action,datapath,respath=None,suffix='.txt',filter='f',sub='\.wav$',**keywords): | |
| 51 | − """ execute action(datafile,resfile) on all files in datapath """ | |
| 52 | − dirlist = list_files(datapath,filter=filter) | |
| 53 | − if dirlist == ['']: dirlist = [] | |
| 54 | − if respath: | |
| 55 | − respath_in_datapath = re.split(datapath, respath,maxsplit=1)[1:] | |
| 56 | − if(respath_in_datapath and suffix == ''): | |
| 57 | − print 'error: respath in datapath and no suffix used' | |
| 58 | − for i in dirlist: | |
| 59 | − j = re.split(datapath, i,maxsplit=1)[1] | |
| 60 | − j = re.sub(sub,'',j) | |
| 61 | − #j = "%s%s%s"%(respath,j,suffix) | |
| 62 | − if respath: | |
| 63 | − j = "%s%s"%(respath,j) | |
| 64 | − if sub != '': | |
| 65 | − j = re.sub(sub,suffix,j) | |
| 66 | − else: | |
| 67 | − j = "%s%s" % (j,suffix) | |
| 68 | − action(i,j,**keywords) | |
| 69 | − | |
| 70 | −def act_on_results (action,datapath,respath,filter='d'): | |
| 71 | − """ execute action(respath) an all subdirectories in respath """ | |
| 72 | − dirlist = list_files(datapath,filter='d') | |
| 73 | − respath_in_datapath = re.split(datapath, respath,maxsplit=1)[1:] | |
| 74 | − if(respath_in_datapath and not filter == 'd' and suffix == ''): | |
| 75 | − print 'warning: respath is in datapath' | |
| 76 | − for i in dirlist: | |
| 77 | − s = re.split(datapath, i ,maxsplit=1)[1] | |
| 78 | − action("%s%s%s"%(respath,'/',s)) | |
| 79 | − | |
| 80 | −def act_on_files (action,listfiles,listres=None,suffix='.txt',filter='f',sub='\.wav$',**keywords): | |
| 81 | − """ execute action(respath) an all subdirectories in respath """ | |
| 82 | − if listres and len(listfiles) <= len(listres): | |
| 83 | − for i in range(len(listfiles)): | |
| 84 | − action(listfiles[i],listres[i],**keywords) | |
| 85 | − else: | |
| 86 | − for i in listfiles: | |
| 87 | − action(i,None,**keywords) | |
| 88 | − | |
| 89 | −class bench: | |
| 90 | − """ class to run benchmarks on directories """ | |
| 91 | − def __init__(self,datadir,resdir=None,checkres=False,checkanno=False,params=[]): | |
| 92 | − from aubio.task.params import taskparams | |
| 93 | − self.datadir = datadir | |
| 94 | − # path to write results path to | |
| 95 | − self.resdir = resdir | |
| 96 | − # list of annotation files | |
| 97 | − self.reslist = [] | |
| 98 | − # list used to gather results | |
| 99 | − self.results = [] | |
| 100 | − if not params: self.params = taskparams() | |
| 101 | − else: self.params = params | |
| 102 | − print "Checking data directory", self.datadir | |
| 103 | − self.checkdata() | |
| 104 | − if checkanno: self.checkanno() | |
| 105 | − if checkres: self.checkres() | |
| 106 | − | |
| 107 | − def checkdata(self): | |
| 108 | − if os.path.isfile(self.datadir): | |
| 109 | − self.dirlist = os.path.dirname(self.datadir) | |
| 110 | − elif os.path.isdir(self.datadir): | |
| 111 | − self.dirlist = list_dirs(self.datadir) | |
| 112 | − # allow dir* matching through find commands? | |
| 113 | − else: | |
| 114 | − print "ERR: path not understood" | |
| 115 | − sys.exit(1) | |
| 116 | − print "Listing directories in data directory", | |
| 117 | − if self.dirlist: | |
| 118 | − print " (%d elements)" % len(self.dirlist) | |
| 119 | − else: | |
| 120 | − print " (0 elements)" | |
| 121 | − print "ERR: no directory %s were found" % self.datadir | |
| 122 | − sys.exit(1) | |
| 123 | − print "Listing sound files in data directory", | |
| 124 | − self.sndlist = list_snd_files(self.datadir) | |
| 125 | − if self.sndlist: | |
| 126 | − print " (%d elements)" % len(self.sndlist) | |
| 127 | − else: | |
| 128 | − print " (0 elements)" | |
| 129 | − print "ERR: no sound files were found in", self.datadir | |
| 130 | − sys.exit(1) | |
| 131 | − | |
| 132 | − def checkanno(self): | |
| 133 | − print "Listing annotations in data directory", | |
| 134 | − self.reslist = list_res_files(self.datadir) | |
| 135 | − print " (%d elements)" % len(self.reslist) | |
| 136 | − #for each in self.reslist: print each | |
| 137 | − if not self.reslist or len(self.reslist) < len (self.sndlist): | |
| 138 | − print "ERR: not enough annotations" | |
| 139 | − return -1 | |
| 140 | − else: | |
| 141 | − print "Found enough annotations" | |
| 142 | − | |
| 143 | − def checkres(self): | |
| 144 | − print "Creating results directory" | |
| 145 | − act_on_results(mkdir,self.datadir,self.resdir,filter='d') | |
| 146 | − | |
| 147 | − def pretty_print(self,sep='|'): | |
| 148 | − for i in self.printnames: | |
| 149 | − print self.formats[i] % self.v[i], sep, | |
| 150 | ||
| 151 | − | |
| 152 | − def pretty_titles(self,sep='|'): | |
| 153 | − for i in self.printnames: | |
| 154 | − print self.formats[i] % i, sep, | |
| 155 | ||
| 156 | − | |
| 157 | − def dir_exec(self): | |
| 158 | − """ run file_exec on every input file """ | |
| 159 | − self.l , self.labs = [], [] | |
| 160 | − self.v = {} | |
| 161 | − for i in self.valuenames: | |
| 162 | − self.v[i] = [] | |
| 163 | − for i in self.valuelists: | |
| 164 | − self.v[i] = [] | |
| 165 | − act_on_files(self.file_exec,self.sndlist,self.reslist, \ | |
| 166 | − suffix='',filter=sndfile_filter) | |
| 167 | − | |
| 168 | − def dir_eval(self): | |
| 169 | − pass | |
| 170 | − | |
| 171 | − def file_gettruth(self,input): | |
| 172 | − """ get ground truth filenames """ | |
| 173 | − from os.path import isfile | |
| 174 | − ftrulist = [] | |
| 175 | − # search for match as filetask.input,".txt" | |
| 176 | − ftru = '.'.join(input.split('.')[:-1]) | |
| 177 | − ftru = '.'.join((ftru,'txt')) | |
| 178 | − if isfile(ftru): | |
| 179 | − ftrulist.append(ftru) | |
| 180 | − else: | |
| 181 | − # search for matches for filetask.input in the list of results | |
| 182 | − for i in range(len(self.reslist)): | |
| 183 | − check = '.'.join(self.reslist[i].split('.')[:-1]) | |
| 184 | − check = '_'.join(check.split('_')[:-1]) | |
| 185 | − if check == '.'.join(input.split('.')[:-1]): | |
| 186 | − ftrulist.append(self.reslist[i]) | |
| 187 | − return ftrulist | |
| 188 | − | |
| 189 | − def file_exec(self,input,output): | |
| 190 | − """ create filetask, extract data, evaluate """ | |
| 191 | − filetask = self.task(input,params=self.params) | |
| 192 | − computed_data = filetask.compute_all() | |
| 193 | − ftrulist = self.file_gettruth(filetask.input) | |
| 194 | − for i in ftrulist: | |
| 195 | − filetask.eval(computed_data,i,mode='rocloc',vmode='') | |
| 196 | − """ append filetask.v to self.v """ | |
| 197 | − for i in self.valuenames: | |
| 198 | − self.v[i].append(filetask.v[i]) | |
| 199 | − for j in self.valuelists: | |
| 200 | − if filetask.v[j]: | |
| 201 | − for i in range(len(filetask.v[j])): | |
| 202 | − self.v[j].append(filetask.v[j][i]) | |
| 203 | − | |
| 204 | − def file_eval(self): | |
| 205 | − pass | |
| 206 | − | |
| 207 | − def file_plot(self): | |
| 208 | − pass | |
| 209 | − | |
| 210 | − def dir_plot(self): | |
| 211 | − pass | |
| 212 | − | |
| 213 | − def run_bench(self): | |
| 214 | − for mode in self.modes: | |
| 215 | − self.params.mode = mode | |
| 216 | − self.dir_exec() | |
| 217 | − self.dir_eval() | |
| 218 | − self.dir_plot() | |
| 219 | − | |
| 220 | − def dir_eval_print(self): | |
| 221 | − self.dir_exec() | |
| 222 | − self.dir_eval() | |
| 223 | − self.pretty_print() | |
| 224 | − | |
| @@ -1,303 +0,0 @@ | ||
| 1 | − | |
| 2 | −from aubio.bench.node import * | |
| 3 | −from os.path import dirname,basename | |
| 4 | − | |
| 5 | −def mmean(l): | |
| 6 | − return sum(l)/max(float(len(l)),1) | |
| 7 | − | |
| 8 | −def stdev(l): | |
| 9 | − smean = 0 | |
| 10 | − if not len(l): return smean | |
| 11 | − lmean = mmean(l) | |
| 12 | − for i in l: | |
| 13 | − smean += (i-lmean)**2 | |
| 14 | − smean *= 1. / len(l) | |
| 15 | − return smean**.5 | |
| 16 | − | |
| 17 | −class benchonset(bench): | |
| 18 | − | |
| 19 | − """ list of values to store per file """ | |
| 20 | − valuenames = ['orig','missed','Tm','expc','bad','Td'] | |
| 21 | − """ list of lists to store per file """ | |
| 22 | − valuelists = ['l','labs'] | |
| 23 | − """ list of values to print per dir """ | |
| 24 | − printnames = [ 'mode', 'thres', 'dist', 'prec', 'recl', | |
| 25 | − 'GD', 'FP', | |
| 26 | − 'Torig', 'Ttrue', 'Tfp', 'Tfn', 'TTm', 'TTd', | |
| 27 | − 'aTtrue', 'aTfp', 'aTfn', 'aTm', 'aTd', | |
| 28 | − 'mean', 'smean', 'amean', 'samean'] | |
| 29 | − | |
| 30 | − """ per dir """ | |
| 31 | − formats = {'mode': "%12s" , 'thres': "%5.4s", | |
| 32 | − 'dist': "%5.4s", 'prec': "%5.4s", 'recl': "%5.4s", | |
| 33 | − 'Torig': "%5.4s", 'Ttrue': "%5.4s", 'Tfp': "%5.4s", 'Tfn': "%5.4s", | |
| 34 | − 'TTm': "%5.4s", 'TTd': "%5.4s", | |
| 35 | − 'aTtrue':"%5.4s", 'aTfp': "%5.4s", 'aTfn': "%5.4s", | |
| 36 | − 'aTm': "%5.4s", 'aTd': "%5.4s", | |
| 37 | − 'mean': "%5.6s", 'smean': "%5.6s", | |
| 38 | − 'amean': "%5.6s", 'samean': "%5.6s", | |
| 39 | − "GD": "%5.4s", "FP": "%5.4s", | |
| 40 | − "GDm": "%5.4s", "FPd": "%5.4s", | |
| 41 | − "bufsize": "%5.4s", "hopsize": "%5.4s", | |
| 42 | − "time": "%5.4s"} | |
| 43 | − | |
| 44 | − def dir_eval(self): | |
| 45 | − """ evaluate statistical data over the directory """ | |
| 46 | − v = self.v | |
| 47 | − | |
| 48 | − v['mode'] = self.params.onsetmode | |
| 49 | − v['thres'] = self.params.threshold | |
| 50 | − v['bufsize'] = self.params.bufsize | |
| 51 | − v['hopsize'] = self.params.hopsize | |
| 52 | − v['silence'] = self.params.silence | |
| 53 | − v['mintol'] = self.params.mintol | |
| 54 | − | |
| 55 | − v['Torig'] = sum(v['orig']) | |
| 56 | − v['TTm'] = sum(v['Tm']) | |
| 57 | − v['TTd'] = sum(v['Td']) | |
| 58 | − v['Texpc'] = sum(v['expc']) | |
| 59 | − v['Tbad'] = sum(v['bad']) | |
| 60 | − v['Tmissed'] = sum(v['missed']) | |
| 61 | − v['aTm'] = mmean(v['Tm']) | |
| 62 | − v['aTd'] = mmean(v['Td']) | |
| 63 | − | |
| 64 | − v['mean'] = mmean(v['l']) | |
| 65 | − v['smean'] = stdev(v['l']) | |
| 66 | − | |
| 67 | − v['amean'] = mmean(v['labs']) | |
| 68 | − v['samean'] = stdev(v['labs']) | |
| 69 | − | |
| 70 | − # old type calculations | |
| 71 | − # good detection rate | |
| 72 | − v['GD'] = 100.*(v['Torig']-v['Tmissed']-v['TTm'])/v['Torig'] | |
| 73 | − # false positive rate | |
| 74 | − v['FP'] = 100.*(v['Tbad']+v['TTd'])/v['Torig'] | |
| 75 | − # good detection counting merged detections as good | |
| 76 | − v['GDm'] = 100.*(v['Torig']-v['Tmissed'])/v['Torig'] | |
| 77 | − # false positives counting doubled as good | |
| 78 | − v['FPd'] = 100.*v['Tbad']/v['Torig'] | |
| 79 | − | |
| 80 | − # mirex type annotations | |
| 81 | − totaltrue = v['Texpc']-v['Tbad']-v['TTd'] | |
| 82 | − totalfp = v['Tbad']+v['TTd'] | |
| 83 | − totalfn = v['Tmissed']+v['TTm'] | |
| 84 | − self.v['Ttrue'] = totaltrue | |
| 85 | − self.v['Tfp'] = totalfp | |
| 86 | − self.v['Tfn'] = totalfn | |
| 87 | − # average over the number of annotation files | |
| 88 | − N = float(len(self.reslist)) | |
| 89 | − self.v['aTtrue'] = totaltrue/N | |
| 90 | − self.v['aTfp'] = totalfp/N | |
| 91 | − self.v['aTfn'] = totalfn/N | |
| 92 | − | |
| 93 | − # F-measure | |
| 94 | − self.P = 100.*float(totaltrue)/max(totaltrue + totalfp,1) | |
| 95 | − self.R = 100.*float(totaltrue)/max(totaltrue + totalfn,1) | |
| 96 | − #if self.R < 0: self.R = 0 | |
| 97 | − self.F = 2.* self.P*self.R / max(float(self.P+self.R),1) | |
| 98 | − self.v['dist'] = self.F | |
| 99 | − self.v['prec'] = self.P | |
| 100 | − self.v['recl'] = self.R | |
| 101 | − | |
| 102 | − | |
| 103 | − """ | |
| 104 | − Plot functions | |
| 105 | − """ | |
| 106 | − | |
| 107 | − def plotroc(self,d,plottitle=""): | |
| 108 | − import Gnuplot, Gnuplot.funcutils | |
| 109 | − gd = [] | |
| 110 | − fp = [] | |
| 111 | − for i in self.vlist: | |
| 112 | − gd.append(i['GD']) | |
| 113 | − fp.append(i['FP']) | |
| 114 | − d.append(Gnuplot.Data(fp, gd, with_='linespoints', | |
| 115 | − title="%s %s" % (plottitle,i['mode']) )) | |
| 116 | − | |
| 117 | − def plotplotroc(self,d,outplot=0,extension='ps'): | |
| 118 | − import Gnuplot, Gnuplot.funcutils | |
| 119 | − from sys import exit | |
| 120 | − g = Gnuplot.Gnuplot(debug=0, persist=1) | |
| 121 | − if outplot: | |
| 122 | − if extension == 'ps': ext, extension = '.ps' , 'postscript' | |
| 123 | − elif extension == 'png': ext, extension = '.png', 'png' | |
| 124 | − elif extension == 'svg': ext, extension = '.svg', 'svg' | |
| 125 | − else: exit("ERR: unknown plot extension") | |
| 126 | − g('set terminal %s' % extension) | |
| 127 | − g('set output \'roc-%s%s\'' % (outplot,ext)) | |
| 128 | − xmax = 30 #max(fp) | |
| 129 | − ymin = 50 | |
| 130 | − g('set xrange [0:%f]' % xmax) | |
| 131 | − g('set yrange [%f:100]' % ymin) | |
| 132 | − # grid set | |
| 133 | − g('set grid') | |
| 134 | − g('set xtics 0,5,%f' % xmax) | |
| 135 | − g('set ytics %f,5,100' % ymin) | |
| 136 | − g('set key 27,65') | |
| 137 | − #g('set format \"%g\"') | |
| 138 | − g.title(basename(self.datadir)) | |
| 139 | − g.xlabel('false positives (%)') | |
| 140 | − g.ylabel('correct detections (%)') | |
| 141 | − g.plot(*d) | |
| 142 | − | |
| 143 | − def plotpr(self,d,plottitle=""): | |
| 144 | − import Gnuplot, Gnuplot.funcutils | |
| 145 | − x = [] | |
| 146 | − y = [] | |
| 147 | − for i in self.vlist: | |
| 148 | − x.append(i['prec']) | |
| 149 | − y.append(i['recl']) | |
| 150 | − d.append(Gnuplot.Data(x, y, with_='linespoints', | |
| 151 | − title="%s %s" % (plottitle,i['mode']) )) | |
| 152 | − | |
| 153 | − def plotplotpr(self,d,outplot=0,extension='ps'): | |
| 154 | − import Gnuplot, Gnuplot.funcutils | |
| 155 | − from sys import exit | |
| 156 | − g = Gnuplot.Gnuplot(debug=0, persist=1) | |
| 157 | − if outplot: | |
| 158 | − if extension == 'ps': ext, extension = '.ps' , 'postscript' | |
| 159 | − elif extension == 'png': ext, extension = '.png', 'png' | |
| 160 | − elif extension == 'svg': ext, extension = '.svg', 'svg' | |
| 161 | − else: exit("ERR: unknown plot extension") | |
| 162 | − g('set terminal %s' % extension) | |
| 163 | − g('set output \'pr-%s%s\'' % (outplot,ext)) | |
| 164 | − g.title(basename(self.datadir)) | |
| 165 | − g.xlabel('Recall (%)') | |
| 166 | − g.ylabel('Precision (%)') | |
| 167 | − g.plot(*d) | |
| 168 | − | |
| 169 | − def plotfmeas(self,d,plottitle=""): | |
| 170 | − import Gnuplot, Gnuplot.funcutils | |
| 171 | − x,y = [],[] | |
| 172 | − for i in self.vlist: | |
| 173 | − x.append(i['thres']) | |
| 174 | − y.append(i['dist']) | |
| 175 | − d.append(Gnuplot.Data(x, y, with_='linespoints', | |
| 176 | − title="%s %s" % (plottitle,i['mode']) )) | |
| 177 | − | |
| 178 | − def plotplotfmeas(self,d,outplot="",extension='ps', title="F-measure"): | |
| 179 | − import Gnuplot, Gnuplot.funcutils | |
| 180 | − from sys import exit | |
| 181 | − g = Gnuplot.Gnuplot(debug=0, persist=1) | |
| 182 | − if outplot: | |
| 183 | − if extension == 'ps': terminal = 'postscript' | |
| 184 | − elif extension == 'png': terminal = 'png' | |
| 185 | − elif extension == 'svg': terminal = 'svg' | |
| 186 | − else: exit("ERR: unknown plot extension") | |
| 187 | − g('set terminal %s' % terminal) | |
| 188 | − g('set output \'fmeas-%s.%s\'' % (outplot,extension)) | |
| 189 | − g.xlabel('threshold \\delta') | |
| 190 | − g.ylabel('F-measure (%)') | |
| 191 | − g('set xrange [0:1.2]') | |
| 192 | − g('set yrange [0:100]') | |
| 193 | − g.title(basename(self.datadir)) | |
| 194 | − # grid set | |
| 195 | − #g('set grid') | |
| 196 | − #g('set xtics 0,5,%f' % xmax) | |
| 197 | − #g('set ytics %f,5,100' % ymin) | |
| 198 | − #g('set key 27,65') | |
| 199 | − #g('set format \"%g\"') | |
| 200 | − g.plot(*d) | |
| 201 | − | |
| 202 | − def plotfmeasvar(self,d,var,plottitle=""): | |
| 203 | − import Gnuplot, Gnuplot.funcutils | |
| 204 | − x,y = [],[] | |
| 205 | − for i in self.vlist: | |
| 206 | − x.append(i[var]) | |
| 207 | − y.append(i['dist']) | |
| 208 | − d.append(Gnuplot.Data(x, y, with_='linespoints', | |
| 209 | − title="%s %s" % (plottitle,i['mode']) )) | |
| 210 | − | |
| 211 | − def plotplotfmeasvar(self,d,var,outplot="",extension='ps', title="F-measure"): | |
| 212 | − import Gnuplot, Gnuplot.funcutils | |
| 213 | − from sys import exit | |
| 214 | − g = Gnuplot.Gnuplot(debug=0, persist=1) | |
| 215 | − if outplot: | |
| 216 | − if extension == 'ps': terminal = 'postscript' | |
| 217 | − elif extension == 'png': terminal = 'png' | |
| 218 | − elif extension == 'svg': terminal = 'svg' | |
| 219 | − else: exit("ERR: unknown plot extension") | |
| 220 | − g('set terminal %s' % terminal) | |
| 221 | − g('set output \'fmeas-%s.%s\'' % (outplot,extension)) | |
| 222 | − g.xlabel(var) | |
| 223 | − g.ylabel('F-measure (%)') | |
| 224 | − #g('set xrange [0:1.2]') | |
| 225 | − g('set yrange [0:100]') | |
| 226 | − g.title(basename(self.datadir)) | |
| 227 | − g.plot(*d) | |
| 228 | − | |
| 229 | − def plotdiffs(self,d,plottitle=""): | |
| 230 | − import Gnuplot, Gnuplot.funcutils | |
| 231 | − v = self.v | |
| 232 | − l = v['l'] | |
| 233 | − mean = v['mean'] | |
| 234 | − smean = v['smean'] | |
| 235 | − amean = v['amean'] | |
| 236 | − samean = v['samean'] | |
| 237 | − val = [] | |
| 238 | − per = [0] * 100 | |
| 239 | − for i in range(0,100): | |
| 240 | − val.append(i*.001-.05) | |
| 241 | − for j in l: | |
| 242 | − if abs(j-val[i]) <= 0.001: | |
| 243 | − per[i] += 1 | |
| 244 | − total = v['Torig'] | |
| 245 | − for i in range(len(per)): per[i] /= total/100. | |
| 246 | − | |
| 247 | − d.append(Gnuplot.Data(val, per, with_='fsteps', | |
| 248 | − title="%s %s" % (plottitle,v['mode']) )) | |
| 249 | − #d.append('mean=%f,sigma=%f,eps(x) title \"\"'% (mean,smean)) | |
| 250 | − #d.append('mean=%f,sigma=%f,eps(x) title \"\"'% (amean,samean)) | |
| 251 | − | |
| 252 | − | |
| 253 | − def plotplotdiffs(self,d,outplot=0,extension='ps'): | |
| 254 | − import Gnuplot, Gnuplot.funcutils | |
| 255 | − from sys import exit | |
| 256 | − g = Gnuplot.Gnuplot(debug=0, persist=1) | |
| 257 | − if outplot: | |
| 258 | − if extension == 'ps': ext, extension = '.ps' , 'postscript' | |
| 259 | − elif extension == 'png': ext, extension = '.png', 'png' | |
| 260 | − elif extension == 'svg': ext, extension = '.svg', 'svg' | |
| 261 | − else: exit("ERR: unknown plot extension") | |
| 262 | − g('set terminal %s' % extension) | |
| 263 | − g('set output \'diffhist-%s%s\'' % (outplot,ext)) | |
| 264 | − g('eps(x) = 1./(sigma*(2.*3.14159)**.5) * exp ( - ( x - mean ) ** 2. / ( 2. * sigma ** 2. ))') | |
| 265 | − g.title(basename(self.datadir)) | |
| 266 | − g.xlabel('delay to hand-labelled onset (s)') | |
| 267 | − g.ylabel('% number of correct detections / ms ') | |
| 268 | − g('set xrange [-0.05:0.05]') | |
| 269 | − g('set yrange [0:20]') | |
| 270 | − g.plot(*d) | |
| 271 | − | |
| 272 | − | |
| 273 | − def plothistcat(self,d,plottitle=""): | |
| 274 | − import Gnuplot, Gnuplot.funcutils | |
| 275 | − total = v['Torig'] | |
| 276 | − for i in range(len(per)): per[i] /= total/100. | |
| 277 | − | |
| 278 | − d.append(Gnuplot.Data(val, per, with_='fsteps', | |
| 279 | − title="%s %s" % (plottitle,v['mode']) )) | |
| 280 | − #d.append('mean=%f,sigma=%f,eps(x) title \"\"'% (mean,smean)) | |
| 281 | − #d.append('mean=%f,sigma=%f,eps(x) title \"\"'% (amean,samean)) | |
| 282 | − | |
| 283 | − | |
| 284 | − def plotplothistcat(self,d,outplot=0,extension='ps'): | |
| 285 | − import Gnuplot, Gnuplot.funcutils | |
| 286 | − from sys import exit | |
| 287 | − g = Gnuplot.Gnuplot(debug=0, persist=1) | |
| 288 | − if outplot: | |
| 289 | − if extension == 'ps': ext, extension = '.ps' , 'postscript' | |
| 290 | − elif extension == 'png': ext, extension = '.png', 'png' | |
| 291 | − elif extension == 'svg': ext, extension = '.svg', 'svg' | |
| 292 | − else: exit("ERR: unknown plot extension") | |
| 293 | − g('set terminal %s' % extension) | |
| 294 | − g('set output \'diffhist-%s%s\'' % (outplot,ext)) | |
| 295 | − g('eps(x) = 1./(sigma*(2.*3.14159)**.5) * exp ( - ( x - mean ) ** 2. / ( 2. * sigma ** 2. ))') | |
| 296 | − g.title(basename(self.datadir)) | |
| 297 | − g.xlabel('delay to hand-labelled onset (s)') | |
| 298 | − g.ylabel('% number of correct detections / ms ') | |
| 299 | − g('set xrange [-0.05:0.05]') | |
| 300 | − g('set yrange [0:20]') | |
| 301 | − g.plot(*d) | |
| 302 | − | |
| 303 | − | |
| @@ -1,222 +0,0 @@ | ||
| 1 | −"""Copyright (C) 2004 Paul Brossier <piem@altern.org> | |
| 2 | −print aubio.__LICENSE__ for the terms of use | |
| 3 | −""" | |
| 4 | − | |
| 5 | −__LICENSE__ = """\ | |
| 6 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 7 | − | |
| 8 | − This file is part of aubio. | |
| 9 | − | |
| 10 | − aubio is free software: you can redistribute it and/or modify | |
| 11 | − it under the terms of the GNU General Public License as published by | |
| 12 | − the Free Software Foundation, either version 3 of the License, or | |
| 13 | − (at your option) any later version. | |
| 14 | − | |
| 15 | − aubio is distributed in the hope that it will be useful, | |
| 16 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − GNU General Public License for more details. | |
| 19 | − | |
| 20 | − You should have received a copy of the GNU General Public License | |
| 21 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 22 | −""" | |
| 23 | − | |
| 24 | − | |
| 25 | −def audio_to_array(filename): | |
| 26 | − import aubio.aubioclass | |
| 27 | − from numpy import arange | |
| 28 | − hopsize = 2048 | |
| 29 | − filei = aubio.aubioclass.sndfile(filename) | |
| 30 | − framestep = 1/(filei.samplerate()+0.) | |
| 31 | − channels = filei.channels() | |
| 32 | − myvec = aubio.aubioclass.fvec(hopsize,channels) | |
| 33 | − data = [] | |
| 34 | − readsize = hopsize | |
| 35 | − while (readsize==hopsize): | |
| 36 | − readsize = filei.read(hopsize,myvec) | |
| 37 | − #for i in range(channels): | |
| 38 | − i = 0 | |
| 39 | − curpos = 0 | |
| 40 | − while (curpos < readsize): | |
| 41 | − data.append(myvec.get(curpos,i)) | |
| 42 | − curpos+=1 | |
| 43 | − time = arange(len(data))*framestep | |
| 44 | − return time,data | |
| 45 | − | |
| 46 | −def plot_audio(filenames, g, options): | |
| 47 | − todraw = len(filenames) | |
| 48 | − xorig = 0. | |
| 49 | − xratio = 1./todraw | |
| 50 | − g('set multiplot;') | |
| 51 | − while (len(filenames)): | |
| 52 | − time,data = audio_to_array(filenames.pop(0)) | |
| 53 | − if todraw==1: | |
| 54 | − if max(time) < 1.: | |
| 55 | − time = [t*1000. for t in time] | |
| 56 | − g.xlabel('Time (ms)') | |
| 57 | − else: | |
| 58 | − g.xlabel('Time (s)') | |
| 59 | − g.ylabel('Amplitude') | |
| 60 | − curplot = make_audio_plot(time,data) | |
| 61 | − g('set size %f,%f;' % (options.xsize*xratio,options.ysize) ) | |
| 62 | − g('set origin %f,0.;' % (xorig) ) | |
| 63 | − g('set style data lines; \ | |
| 64 | − set yrange [-1.:1.]; \ | |
| 65 | − set xrange [0:%f]' % time[-1]) | |
| 66 | − g.plot(curplot) | |
| 67 | − xorig += options.xsize*xratio | |
| 68 | − g('unset multiplot;') | |
| 69 | − | |
| 70 | −def audio_to_spec(filename,minf = 0, maxf = 0, lowthres = -20., | |
| 71 | − bufsize= 8192, hopsize = 1024): | |
| 72 | − from aubioclass import fvec,cvec,pvoc,sndfile | |
| 73 | − from math import log10 | |
| 74 | − filei = sndfile(filename) | |
| 75 | − srate = float(filei.samplerate()) | |
| 76 | − framestep = hopsize/srate | |
| 77 | − freqstep = srate/bufsize | |
| 78 | − channels = filei.channels() | |
| 79 | − myvec = fvec(hopsize,channels) | |
| 80 | − myfft = cvec(bufsize,channels) | |
| 81 | − pv = pvoc(bufsize,hopsize,channels) | |
| 82 | − data,time,freq = [],[],[] | |
| 83 | − | |
| 84 | − if maxf == 0.: maxf = bufsize/2 | |
| 85 | − else: maxf = int(maxf/freqstep) | |
| 86 | − if minf: minf = int(minf/freqstep) | |
| 87 | − else: minf = 0 | |
| 88 | − | |
| 89 | − for f in range(minf,maxf): | |
| 90 | − freq.append(f*freqstep) | |
| 91 | − readsize = hopsize | |
| 92 | − frameread = 0 | |
| 93 | − while (readsize==hopsize): | |
| 94 | − readsize = filei.read(hopsize,myvec) | |
| 95 | − pv.do(myvec,myfft) | |
| 96 | − frame = [] | |
| 97 | − i = 0 #for i in range(channels): | |
| 98 | − curpos = minf | |
| 99 | − while (curpos < maxf): | |
| 100 | − frame.append(max(lowthres,20.*log10(myfft.get(curpos,i)**2+0.00001))) | |
| 101 | − curpos+=1 | |
| 102 | − time.append(frameread*framestep) | |
| 103 | − data.append(frame) | |
| 104 | − frameread += 1 | |
| 105 | − # crop data if unfinished frames | |
| 106 | − if len(data[-1]) != len(data[0]): | |
| 107 | − data = data[0:-2] | |
| 108 | − time = time[0:-2] | |
| 109 | − # verify size consistency | |
| 110 | − assert len(data) == len(time) | |
| 111 | − assert len(data[0]) == len(freq) | |
| 112 | − return data,time,freq | |
| 113 | − | |
| 114 | −def plot_spec(filename, g, options): | |
| 115 | − import Gnuplot | |
| 116 | − data,time,freq = audio_to_spec(filename, | |
| 117 | − minf=options.minf,maxf=options.maxf, | |
| 118 | − bufsize=options.bufsize,hopsize=options.hopsize) | |
| 119 | − xorig = 0. | |
| 120 | − if max(time) < 1.: | |
| 121 | − time = [t*1000. for t in time] | |
| 122 | − g.xlabel('Time (ms)') | |
| 123 | − else: | |
| 124 | − g.xlabel('Time (s)') | |
| 125 | − if options.xsize < 0.5 and not options.log and max(time) > 1.: | |
| 126 | − freq = [f/1000. for f in freq] | |
| 127 | − options.minf /= 1000. | |
| 128 | − options.maxf /= 1000. | |
| 129 | − g.ylabel('Frequency (kHz)') | |
| 130 | − else: | |
| 131 | − g.ylabel('Frequency (Hz)') | |
| 132 | − g('set pm3d map') | |
| 133 | − g('set palette rgbformulae -25,-24,-32') | |
| 134 | − g('set cbtics 20') | |
| 135 | − #g('set colorbox horizontal') | |
| 136 | − g('set xrange [0.:%f]' % time[-1]) | |
| 137 | − if options.log: | |
| 138 | − g('set log y') | |
| 139 | − g('set yrange [%f:%f]' % (max(10,options.minf),options.maxf)) | |
| 140 | − else: | |
| 141 | − g('set yrange [%f:%f]' % (options.minf,options.maxf)) | |
| 142 | − g.splot(Gnuplot.GridData(data,time,freq, binary=1)) | |
| 143 | − #xorig += 1./todraw | |
| 144 | − | |
| 145 | −def downsample_audio(time,data,maxpoints=10000): | |
| 146 | − """ resample audio data to last only maxpoints """ | |
| 147 | − from numpy import array, resize | |
| 148 | − length = len(time) | |
| 149 | − downsample = length/maxpoints | |
| 150 | − if downsample == 0: downsample = 1 | |
| 151 | − x = resize(array(time),length)[0:-1:downsample] | |
| 152 | − y = resize(array(data),length)[0:-1:downsample] | |
| 153 | − return x,y | |
| 154 | − | |
| 155 | −def make_audio_plot(time,data,maxpoints=10000): | |
| 156 | − """ create gnuplot plot from an audio file """ | |
| 157 | − import Gnuplot, Gnuplot.funcutils | |
| 158 | − x,y = downsample_audio(time,data,maxpoints=maxpoints) | |
| 159 | − return Gnuplot.Data(x,y,with_='lines') | |
| 160 | − | |
| 161 | −def make_audio_envelope(time,data,maxpoints=10000): | |
| 162 | − """ create gnuplot plot from an audio file """ | |
| 163 | − from numpy import array | |
| 164 | − import Gnuplot, Gnuplot.funcutils | |
| 165 | − bufsize = 500 | |
| 166 | − x = [i.mean() for i in resize(array(time), (len(time)/bufsize,bufsize))] | |
| 167 | − y = [i.mean() for i in resize(array(data), (len(time)/bufsize,bufsize))] | |
| 168 | − x,y = downsample_audio(x,y,maxpoints=maxpoints) | |
| 169 | − return Gnuplot.Data(x,y,with_='lines') | |
| 170 | − | |
| 171 | −def gnuplot_addargs(parser): | |
| 172 | − """ add common gnuplot argument to OptParser object """ | |
| 173 | − parser.add_option("-x","--xsize", | |
| 174 | − action="store", dest="xsize", default=1., | |
| 175 | − type='float',help="define xsize for plot") | |
| 176 | − parser.add_option("-y","--ysize", | |
| 177 | − action="store", dest="ysize", default=1., | |
| 178 | − type='float',help="define ysize for plot") | |
| 179 | − parser.add_option("--debug", | |
| 180 | − action="store_true", dest="debug", default=False, | |
| 181 | − help="use gnuplot debug mode") | |
| 182 | − parser.add_option("--persist", | |
| 183 | − action="store_false", dest="persist", default=True, | |
| 184 | − help="do not use gnuplot persistant mode") | |
| 185 | − parser.add_option("--lmargin", | |
| 186 | − action="store", dest="lmargin", default=None, | |
| 187 | − type='int',help="define left margin for plot") | |
| 188 | − parser.add_option("--rmargin", | |
| 189 | − action="store", dest="rmargin", default=None, | |
| 190 | − type='int',help="define right margin for plot") | |
| 191 | − parser.add_option("--bmargin", | |
| 192 | − action="store", dest="bmargin", default=None, | |
| 193 | − type='int',help="define bottom margin for plot") | |
| 194 | − parser.add_option("--tmargin", | |
| 195 | − action="store", dest="tmargin", default=None, | |
| 196 | − type='int',help="define top margin for plot") | |
| 197 | − parser.add_option("-O","--outplot", | |
| 198 | − action="store", dest="outplot", default=None, | |
| 199 | − help="save plot to output.{ps,png}") | |
| 200 | − | |
| 201 | −def gnuplot_create(outplot='',extension='', options=None): | |
| 202 | − import Gnuplot | |
| 203 | − if options: | |
| 204 | − g = Gnuplot.Gnuplot(debug=options.debug, persist=options.persist) | |
| 205 | − else: | |
| 206 | − g = Gnuplot.Gnuplot(persist=1) | |
| 207 | − if not extension or not outplot: return g | |
| 208 | − if extension == 'ps': ext, extension = '.ps' , 'postscript' | |
| 209 | − elif extension == 'eps': ext, extension = '.eps' , 'postscript enhanced' | |
| 210 | − elif extension == 'epsc': ext, extension = '.eps' , 'postscript enhanced color' | |
| 211 | − elif extension == 'png': ext, extension = '.png', 'png' | |
| 212 | − elif extension == 'svg': ext, extension = '.svg', 'svg' | |
| 213 | − else: exit("ERR: unknown plot extension") | |
| 214 | − g('set terminal %s' % extension) | |
| 215 | − if options and options.lmargin: g('set lmargin %i' % options.lmargin) | |
| 216 | − if options and options.rmargin: g('set rmargin %i' % options.rmargin) | |
| 217 | − if options and options.bmargin: g('set bmargin %i' % options.bmargin) | |
| 218 | − if options and options.tmargin: g('set tmargin %i' % options.tmargin) | |
| 219 | − if outplot != "stdout": | |
| 220 | − g('set output \'%s%s\'' % (outplot,ext)) | |
| 221 | − if options: g('set size %f,%f' % (options.xsize, options.ysize)) | |
| 222 | − return g | |
| @@ -1,69 +0,0 @@ | ||
| 1 | −"""Copyright (C) 2004 Paul Brossier <piem@altern.org> | |
| 2 | −print aubio.__LICENSE__ for the terms of use | |
| 3 | −""" | |
| 4 | − | |
| 5 | −__LICENSE__ = """\ | |
| 6 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 7 | − | |
| 8 | − This file is part of aubio. | |
| 9 | − | |
| 10 | − aubio is free software: you can redistribute it and/or modify | |
| 11 | − it under the terms of the GNU General Public License as published by | |
| 12 | − the Free Software Foundation, either version 3 of the License, or | |
| 13 | − (at your option) any later version. | |
| 14 | − | |
| 15 | − aubio is distributed in the hope that it will be useful, | |
| 16 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − GNU General Public License for more details. | |
| 19 | − | |
| 20 | − You should have received a copy of the GNU General Public License | |
| 21 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 22 | −""" | |
| 23 | − | |
| 24 | −""" | |
| 25 | −original author Tim Peters | |
| 26 | −modified by Paul Brossier <piem@altern.org> | |
| 27 | −inspired from http://www.ics.uci.edu/~eppstein/161/python/peters-selection.py | |
| 28 | −""" | |
| 29 | − | |
| 30 | −def short_find(a, rank): | |
| 31 | − """ find the rank-th value in sorted a """ | |
| 32 | − # copy to b before sorting | |
| 33 | − b = a[:] | |
| 34 | − b.sort() | |
| 35 | − return b[rank - 1] | |
| 36 | − | |
| 37 | −def percental(a, rank): | |
| 38 | − """ Find the rank'th-smallest value in a, in worst-case linear time. """ | |
| 39 | − n = len(a) | |
| 40 | − assert 1 <= rank <= n | |
| 41 | − if n <= 7: | |
| 42 | − return short_find(a, rank) | |
| 43 | − | |
| 44 | − ## Find median of median-of-7's. | |
| 45 | − ##medians = [short_find(a[i : i+7], 4) for i in xrange(0, n-6, 7)] | |
| 46 | − #median = find(medians, (len(medians) + 1) // 2) | |
| 47 | − | |
| 48 | − # modified to Find median | |
| 49 | − median = short_find([a[0], a[-1], a[n//2]], 2) | |
| 50 | − | |
| 51 | − # Partition around the median. | |
| 52 | − # a[:i] <= median | |
| 53 | − # a[j+1:] >= median | |
| 54 | − i, j = 0, n-1 | |
| 55 | − while i <= j: | |
| 56 | − while a[i] < median: | |
| 57 | − i += 1 | |
| 58 | − while a[j] > median: | |
| 59 | − j -= 1 | |
| 60 | − if i <= j: | |
| 61 | − a[i], a[j] = a[j], a[i] | |
| 62 | − i += 1 | |
| 63 | − j -= 1 | |
| 64 | − | |
| 65 | − if rank <= i: | |
| 66 | − return percental(a[:i], rank) | |
| 67 | − else: | |
| 68 | − return percental(a[i:], rank - i) | |
| 69 | − | |
| @@ -1,143 +0,0 @@ | ||
| 1 | −"""Copyright (C) 2004 Paul Brossier <piem@altern.org> | |
| 2 | −print aubio.__LICENSE__ for the terms of use | |
| 3 | −""" | |
| 4 | − | |
| 5 | −__LICENSE__ = """\ | |
| 6 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 7 | − | |
| 8 | − This file is part of aubio. | |
| 9 | − | |
| 10 | − aubio is free software: you can redistribute it and/or modify | |
| 11 | − it under the terms of the GNU General Public License as published by | |
| 12 | − the Free Software Foundation, either version 3 of the License, or | |
| 13 | − (at your option) any later version. | |
| 14 | − | |
| 15 | − aubio is distributed in the hope that it will be useful, | |
| 16 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − GNU General Public License for more details. | |
| 19 | − | |
| 20 | − You should have received a copy of the GNU General Public License | |
| 21 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 22 | −""" | |
| 23 | − | |
| 24 | −""" this file contains routines to compare two lists of onsets or notes. | |
| 25 | −it somewhat implements the Receiver Operating Statistic (ROC). | |
| 26 | −see http://en.wikipedia.org/wiki/Receiver_operating_characteristic | |
| 27 | −""" | |
| 28 | − | |
| 29 | −def onset_roc(ltru, lexp, eps): | |
| 30 | − """ compute differences between two lists | |
| 31 | − orig = hits + missed + merged | |
| 32 | − expc = hits + bad + doubled | |
| 33 | − returns orig, missed, merged, expc, bad, doubled | |
| 34 | − """ | |
| 35 | − orig, expc = len(ltru), len(lexp) | |
| 36 | − # if lexp is empty | |
| 37 | − if expc == 0 : return orig,orig,0,0,0,0 | |
| 38 | − missed, bad, doubled, merged = 0, 0, 0, 0 | |
| 39 | − # find missed and doubled ones first | |
| 40 | − for x in ltru: | |
| 41 | − correspond = 0 | |
| 42 | − for y in lexp: | |
| 43 | − if abs(x-y) <= eps: correspond += 1 | |
| 44 | − if correspond == 0: missed += 1 | |
| 45 | − elif correspond > 1: doubled += correspond - 1 | |
| 46 | − # then look for bad and merged ones | |
| 47 | − for y in lexp: | |
| 48 | − correspond = 0 | |
| 49 | − for x in ltru: | |
| 50 | − if abs(x-y) <= eps: correspond += 1 | |
| 51 | − if correspond == 0: bad += 1 | |
| 52 | − elif correspond > 1: merged += correspond - 1 | |
| 53 | − # check consistancy of the results | |
| 54 | − assert ( orig - missed - merged == expc - bad - doubled) | |
| 55 | − return orig, missed, merged, expc, bad, doubled | |
| 56 | − | |
| 57 | −def onset_diffs(ltru, lexp, eps): | |
| 58 | − """ compute differences between two lists | |
| 59 | − orig = hits + missed + merged | |
| 60 | − expc = hits + bad + doubled | |
| 61 | − returns orig, missed, merged, expc, bad, doubled | |
| 62 | − """ | |
| 63 | − orig, expc = len(ltru), len(lexp) | |
| 64 | − # if lexp is empty | |
| 65 | − l = [] | |
| 66 | − if expc == 0 : return l | |
| 67 | − # find missed and doubled ones first | |
| 68 | − for x in ltru: | |
| 69 | − correspond = 0 | |
| 70 | − for y in lexp: | |
| 71 | − if abs(x-y) <= eps: l.append(y-x) | |
| 72 | − # return list of diffs | |
| 73 | − return l | |
| 74 | − | |
| 75 | −def onset_rocloc(ltru, lexp, eps): | |
| 76 | − """ compute differences between two lists | |
| 77 | − orig = hits + missed + merged | |
| 78 | − expc = hits + bad + doubled | |
| 79 | − returns orig, missed, merged, expc, bad, doubled | |
| 80 | − """ | |
| 81 | − orig, expc = len(ltru), len(lexp) | |
| 82 | − l = [] | |
| 83 | − labs = [] | |
| 84 | − mean = 0 | |
| 85 | − # if lexp is empty | |
| 86 | − if expc == 0 : return orig,orig,0,0,0,0,l,mean | |
| 87 | − missed, bad, doubled, merged = 0, 0, 0, 0 | |
| 88 | − # find missed and doubled ones first | |
| 89 | − for x in ltru: | |
| 90 | − correspond = 0 | |
| 91 | − for y in lexp: | |
| 92 | − if abs(x-y) <= eps: correspond += 1 | |
| 93 | − if correspond == 0: missed += 1 | |
| 94 | − elif correspond > 1: doubled += correspond - 1 | |
| 95 | − # then look for bad and merged ones | |
| 96 | − for y in lexp: | |
| 97 | − correspond = 0 | |
| 98 | − for x in ltru: | |
| 99 | − if abs(x-y) <= eps: | |
| 100 | − correspond += 1 | |
| 101 | − l.append(y-x) | |
| 102 | − labs.append(abs(y-x)) | |
| 103 | − if correspond == 0: bad += 1 | |
| 104 | − elif correspond > 1: merged += correspond - 1 | |
| 105 | − # check consistancy of the results | |
| 106 | − assert ( orig - missed - merged == expc - bad - doubled) | |
| 107 | − return orig, missed, merged, expc, bad, doubled, l, labs | |
| 108 | − | |
| 109 | −def notes_roc (la, lb, eps): | |
| 110 | − from numpy import transpose, add, resize | |
| 111 | − """ creates a matrix of size len(la)*len(lb) then look for hit and miss | |
| 112 | − in it within eps tolerance windows """ | |
| 113 | − gdn,fpw,fpg,fpa,fdo,fdp = 0,0,0,0,0,0 | |
| 114 | − m = len(la) | |
| 115 | − n = len(lb) | |
| 116 | − x = resize(la[:][0],(n,m)) | |
| 117 | − y = transpose(resize(lb[:][0],(m,n))) | |
| 118 | − teps = (abs(x-y) <= eps[0]) | |
| 119 | − x = resize(la[:][1],(n,m)) | |
| 120 | − y = transpose(resize(lb[:][1],(m,n))) | |
| 121 | − tpitc = (abs(x-y) <= eps[1]) | |
| 122 | − res = teps * tpitc | |
| 123 | − res = add.reduce(res,axis=0) | |
| 124 | − for i in range(len(res)) : | |
| 125 | − if res[i] > 1: | |
| 126 | − gdn+=1 | |
| 127 | − fdo+=res[i]-1 | |
| 128 | − elif res [i] == 1: | |
| 129 | − gdn+=1 | |
| 130 | − fpa = n - gdn - fpa | |
| 131 | − return gdn,fpw,fpg,fpa,fdo,fdp | |
| 132 | − | |
| 133 | −def load_onsets(filename) : | |
| 134 | − """ load onsets targets / candidates files in arrays """ | |
| 135 | − l = []; | |
| 136 | − | |
| 137 | − f = open(filename,'ro') | |
| 138 | − while 1: | |
| 139 | − line = f.readline().split() | |
| 140 | − if not line : break | |
| 141 | − l.append(float(line[0])) | |
| 142 | − | |
| 143 | − return l | |
Empty file deleted.
| @@ -1,46 +0,0 @@ | ||
| 1 | − | |
| 2 | −def draw_keyboard(firstnote = 21, lastnote = 108, y0 = 0, y1 = 1): | |
| 3 | − import Gnuplot | |
| 4 | − octaves = 10 | |
| 5 | − | |
| 6 | − # build template of white notes | |
| 7 | − scalew = 12/7. | |
| 8 | − xw_temp = [i*scalew for i in range(0,7)] | |
| 9 | − # build template of black notes | |
| 10 | − scaleb = 6/7. | |
| 11 | − xb_temp = [i*scaleb for i in [1,3,7,9,11]] | |
| 12 | − | |
| 13 | − xb,xw = [],[] | |
| 14 | − for octave in range(octaves-1): | |
| 15 | − for i in xb_temp: | |
| 16 | − curnote = i+12*octave | |
| 17 | − if curnote > firstnote-1 and curnote < lastnote+1: | |
| 18 | − xb = xb + [curnote] | |
| 19 | − for octave in range(octaves-1): | |
| 20 | − for i in xw_temp: | |
| 21 | − curnote = i+12*octave | |
| 22 | − if curnote > firstnote-1 and curnote < lastnote+1: | |
| 23 | − xw = xw + [curnote] | |
| 24 | − | |
| 25 | − xwdelta = [1/2. * scalew for i in range(len(xw))] | |
| 26 | − yw = [y0+(y1-y0)*1/2. for i in range(len(xw))] | |
| 27 | − ywdelta = [(y1-y0)*1/2. for i in range(len(xw))] | |
| 28 | − | |
| 29 | − xbdelta = [2/3. * scaleb for i in range(len(xb))] | |
| 30 | − yb = [y0+(y1-y0)*2/3. for i in range(len(xb))] | |
| 31 | − ybdelta = [(y1-y0)*1/3. for i in range(len(xb))] | |
| 32 | − | |
| 33 | − whites = Gnuplot.Data(xw,yw,xwdelta,ywdelta,with_ = 'boxxyerrorbars') | |
| 34 | − blacks = Gnuplot.Data(xb,yb,xbdelta,ybdelta,with_ = 'boxxyerrorbars fill solid') | |
| 35 | − | |
| 36 | − return blacks,whites | |
| 37 | − | |
| 38 | −if __name__ == '__main__': | |
| 39 | − from aubio.gnuplot import gnuplot_create | |
| 40 | − blacks,whites = draw_keyboard(firstnote = 21, lastnote = 108) | |
| 41 | − g = gnuplot_create('','') | |
| 42 | − #g('set style fill solid .5') | |
| 43 | − #g('set xrange [60-.5:72+.5]') | |
| 44 | − #g('set yrange [-0.1:1.1]') | |
| 45 | − | |
| 46 | − g.plot(whites,blacks) | |
| @@ -1,90 +0,0 @@ | ||
| 1 | −__LICENSE__ = """\ | |
| 2 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 3 | − | |
| 4 | − This file is part of aubio. | |
| 5 | − | |
| 6 | − aubio is free software: you can redistribute it and/or modify | |
| 7 | − it under the terms of the GNU General Public License as published by | |
| 8 | − the Free Software Foundation, either version 3 of the License, or | |
| 9 | − (at your option) any later version. | |
| 10 | − | |
| 11 | − aubio is distributed in the hope that it will be useful, | |
| 12 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | − GNU General Public License for more details. | |
| 15 | − | |
| 16 | − You should have received a copy of the GNU General Public License | |
| 17 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | −""" | |
| 19 | − | |
| 20 | −def plotnote(la,title=None) : | |
| 21 | − if la[0,:].size() == 3: | |
| 22 | − d = plotnote_withends(la, plot_title=title) | |
| 23 | − else: | |
| 24 | − # scale data if in freq (for REF.txt files) | |
| 25 | − if max(la[:,1] > 128 ): | |
| 26 | − print "scaling frequency data to midi range" | |
| 27 | − la[:,1] /= 6.875 | |
| 28 | − la[:,1] = log(la[:,1])/0.6931 | |
| 29 | − la[:,1] *= 12 | |
| 30 | − la[:,1] -= 3 | |
| 31 | − d = plotnote_withoutends(la, plot_title=title) | |
| 32 | − return d | |
| 33 | − | |
| 34 | −def plotnote_multi(lalist,title=None,fileout=None) : | |
| 35 | − d=list() | |
| 36 | − for i in range(len(lalist)): | |
| 37 | − d.append(plotnote(lalist[i], title=title)) | |
| 38 | − return d | |
| 39 | − | |
| 40 | − | |
| 41 | −def plotnote_withends(la,plot_title=None) : | |
| 42 | − from numpy import array | |
| 43 | − import Gnuplot, Gnuplot.funcutils | |
| 44 | − d=[] | |
| 45 | − x_widths = array(la[:,1]-la[:,0])/2. | |
| 46 | − d.append(Gnuplot.Data( | |
| 47 | − la[:,0]+x_widths, # x centers | |
| 48 | − la[:,2], # y centers | |
| 49 | − x_widths, # x errors | |
| 50 | − __notesheight*ones(len(la)), # y errors | |
| 51 | − title=plot_title,with_=('boxxyerrorbars fs 3'))) | |
| 52 | − return d | |
| 53 | − | |
| 54 | − | |
| 55 | −def plotnote_withoutends(la,plot_title=None) : | |
| 56 | − """ bug: fails drawing last note """ | |
| 57 | − from numpy import array | |
| 58 | − import Gnuplot, Gnuplot.funcutils | |
| 59 | − d=[] | |
| 60 | − x_widths = array(la[1:,0]-la[:-1,0])/2; | |
| 61 | − d.append(Gnuplot.Data( | |
| 62 | − la[:-1,0]+x_widths, # x centers | |
| 63 | − la[:-1,1], # y centers | |
| 64 | − x_widths, # x errors | |
| 65 | − __notesheight*ones(len(la)-1), # y errors | |
| 66 | − title=plot_title,with_=('boxxyerrorbars fs 3'))) | |
| 67 | − return d | |
| 68 | − | |
| 69 | −def plotnote_do(d,fileout=None): | |
| 70 | − import Gnuplot, Gnuplot.funcutils | |
| 71 | − g = Gnuplot.Gnuplot(debug=1, persist=1) | |
| 72 | − g.gnuplot('set style fill solid border 1; \ | |
| 73 | − set size ratio 1/6; \ | |
| 74 | − set boxwidth 0.9 relative; \ | |
| 75 | − set mxtics 2.5; \ | |
| 76 | − set mytics 2.5; \ | |
| 77 | − set xtics 5; \ | |
| 78 | − set ytics 1; \ | |
| 79 | − set grid xtics ytics mxtics mytics') | |
| 80 | − | |
| 81 | − g.xlabel('Time (s)') | |
| 82 | − g.ylabel('Midi pitch') | |
| 83 | − # do the plot | |
| 84 | − #g.gnuplot('set multiplot') | |
| 85 | − #for i in d: | |
| 86 | − g.plot(d[0]) | |
| 87 | − #g.gnuplot('set nomultiplot') | |
| 88 | − if fileout != None: | |
| 89 | − g.hardcopy(fileout, enhanced=1, color=0) | |
| 90 | − | |
| @@ -1,9 +0,0 @@ | ||
| 1 | −from aubio.aubioclass import * | |
| 2 | −from aubio.task.task import task | |
| 3 | −from aubio.task.params import taskparams | |
| 4 | −from aubio.task.silence import tasksilence | |
| 5 | −from aubio.task.onset import taskonset | |
| 6 | −from aubio.task.beat import taskbeat | |
| 7 | −from aubio.task.cut import taskcut | |
| 8 | −from aubio.task.pitch import taskpitch | |
| 9 | −from aubio.task.notes import tasknotes | |
| @@ -1,262 +0,0 @@ | ||
| 1 | −from aubio.aubioclass import * | |
| 2 | −from onset import taskonset | |
| 3 | − | |
| 4 | −class taskbeat(taskonset): | |
| 5 | − def __init__(self,input,params=None,output=None): | |
| 6 | − """ open the input file and initialize arguments | |
| 7 | − parameters should be set *before* calling this method. | |
| 8 | − """ | |
| 9 | − taskonset.__init__(self,input,output=None,params=params) | |
| 10 | − self.btwinlen = 512**2/self.params.hopsize | |
| 11 | − self.btstep = self.btwinlen/4 | |
| 12 | − self.btoutput = fvec(self.btstep,self.channels) | |
| 13 | − self.dfframe = fvec(self.btwinlen,self.channels) | |
| 14 | − self.bt = beattracking(self.btwinlen,self.channels) | |
| 15 | − self.pos2 = 0 | |
| 16 | − self.old = -1000 | |
| 17 | − | |
| 18 | − def __call__(self): | |
| 19 | − taskonset.__call__(self) | |
| 20 | − #results = taskonset.__call__(self) | |
| 21 | − # write to current file | |
| 22 | − if self.pos2 == self.btstep - 1 : | |
| 23 | − self.bt.do(self.dfframe,self.btoutput) | |
| 24 | − for i in range (self.btwinlen - self.btstep): | |
| 25 | − self.dfframe.set(self.dfframe.get(i+self.btstep,0),i,0) | |
| 26 | − for i in range(self.btwinlen - self.btstep, self.btwinlen): | |
| 27 | − self.dfframe.set(0,i,0) | |
| 28 | − self.pos2 = -1; | |
| 29 | − self.pos2 += 1 | |
| 30 | − val = self.opick.pp.getval() | |
| 31 | − #if not results: val = 0 | |
| 32 | − #else: val = results[1] | |
| 33 | − self.dfframe.set(val,self.btwinlen - self.btstep + self.pos2,0) | |
| 34 | − i=0 | |
| 35 | − for i in range(1,int( self.btoutput.get(0,0) ) ): | |
| 36 | − if self.pos2 == self.btoutput.get(i,0) and \ | |
| 37 | − aubio_silence_detection(self.myvec(), | |
| 38 | − self.params.silence)!=1: | |
| 39 | − now = self.frameread-0 | |
| 40 | − period = (60 * self.params.samplerate) / ((now - self.old) * self.params.hopsize) | |
| 41 | − self.old = now | |
| 42 | − return now,period | |
| 43 | − | |
| 44 | − def eval(self,results,tol=0.20,tolcontext=0.25): | |
| 45 | − obeats = self.gettruth() | |
| 46 | − etime = [result[0] for result in results] | |
| 47 | − otime = [obeat[0] for obeat in obeats] | |
| 48 | − CML_tot, CML_max, CML_start, CML_end = 0,0,0,0 | |
| 49 | − AML_tot, AML_max, AML_start, AML_end = 0,0,0,0 | |
| 50 | − AMLd_tot, AMLd_max, AMLd_start, AMLd_end = 0,0,0,0 | |
| 51 | − AMLh_tot, AMLh_max, AMLh_start, AMLh_end = 0,0,0,0 | |
| 52 | − AMLo_tot, AMLo_max, AMLo_start, AMLo_end = 0,0,0,0 | |
| 53 | − # results iteration | |
| 54 | − j = 1 | |
| 55 | − # for each annotation | |
| 56 | − for i in range(2,len(otime)-2): | |
| 57 | − if j+1 >= len(etime): break | |
| 58 | − count = 0 | |
| 59 | − # look for next matching beat | |
| 60 | − while otime[i] > etime[j] - (otime[i] - otime[i+1])*tol: | |
| 61 | − if count > 0: | |
| 62 | − #print "spurious etime" | |
| 63 | − if CML_end - CML_start > CML_max: | |
| 64 | − CML_max = CML_end - CML_start | |
| 65 | − CML_start, CML_end = j, j | |
| 66 | − if AMLh_end - AMLh_start > AMLh_max: | |
| 67 | − AMLh_max = AMLh_end - AMLh_start | |
| 68 | − AMLh_start, AMLh_end = j, j | |
| 69 | − if AMLd_end - AMLd_start > AMLd_max: | |
| 70 | − AMLd_max = AMLd_end - AMLd_start | |
| 71 | − AMLd_start, AMLd_end = j, j | |
| 72 | − if AMLo_end - AMLo_start > AMLo_max: | |
| 73 | − AMLo_max = AMLo_end - AMLo_start | |
| 74 | − AMLo_start, AMLo_end = j, j | |
| 75 | − j += 1 | |
| 76 | − count += 1 | |
| 77 | − if j+1 >= len(etime): break | |
| 78 | − #print otime[i-1],etime[j-1]," ",otime[i],etime[j]," ",otime[i+1],etime[j+1] | |
| 79 | − prevtempo = (otime[i] - otime[i-1]) | |
| 80 | − nexttempo = (otime[i+1] - otime[i]) | |
| 81 | − | |
| 82 | − current0 = (etime[j] > otime[i] - prevtempo*tol) | |
| 83 | − current1 = (etime[j] < otime[i] + prevtempo*tol) | |
| 84 | − | |
| 85 | − # check correct tempo | |
| 86 | − prev0 = (etime[j-1] > otime[i-1] - prevtempo*tolcontext) | |
| 87 | − prev1 = (etime[j-1] < otime[i-1] + prevtempo*tolcontext) | |
| 88 | − next0 = (etime[j+1] > otime[i+1] - nexttempo*tolcontext) | |
| 89 | − next1 = (etime[j+1] < otime[i+1] + nexttempo*tolcontext) | |
| 90 | − | |
| 91 | − # check for off beat | |
| 92 | − prevoffb0 = (etime[j-1] > otime[i-1] - prevtempo/2 - prevtempo*tolcontext) | |
| 93 | − prevoffb1 = (etime[j-1] < otime[i-1] - prevtempo/2 + prevtempo*tolcontext) | |
| 94 | − nextoffb0 = (etime[j+1] > otime[i+1] - nexttempo/2 - nexttempo*tolcontext) | |
| 95 | − nextoffb1 = (etime[j+1] < otime[i+1] - nexttempo/2 + nexttempo*tolcontext) | |
| 96 | − | |
| 97 | − # check half tempo | |
| 98 | − prevhalf0 = (etime[j-1] > otime[i-1] + prevtempo - prevtempo/2*tolcontext) | |
| 99 | − prevhalf1 = (etime[j-1] < otime[i-1] + prevtempo + prevtempo/2*tolcontext) | |
| 100 | − nexthalf0 = (etime[j+1] > otime[i+1] - nexttempo - nexttempo/2*tolcontext) | |
| 101 | − nexthalf1 = (etime[j+1] < otime[i+1] - nexttempo + nexttempo/2*tolcontext) | |
| 102 | − | |
| 103 | − # check double tempo | |
| 104 | − prevdoub0 = (etime[j-1] > otime[i-1] - prevtempo - prevtempo*2*tolcontext) | |
| 105 | − prevdoub1 = (etime[j-1] < otime[i-1] - prevtempo + prevtempo*2*tolcontext) | |
| 106 | − nextdoub0 = (etime[j+1] > otime[i+1] + nexttempo - nexttempo*2*tolcontext) | |
| 107 | − nextdoub1 = (etime[j+1] < otime[i+1] + nexttempo + nexttempo*2*tolcontext) | |
| 108 | − | |
| 109 | − if current0 and current1 and prev0 and prev1 and next0 and next1: | |
| 110 | − #print "YES!" | |
| 111 | − CML_end = j | |
| 112 | − CML_tot += 1 | |
| 113 | − else: | |
| 114 | − if CML_end - CML_start > CML_max: | |
| 115 | − CML_max = CML_end - CML_start | |
| 116 | − CML_start, CML_end = j, j | |
| 117 | − if current0 and current1 and prevhalf0 and prevhalf1 and nexthalf0 and nexthalf1: | |
| 118 | − AMLh_end = j | |
| 119 | − AMLh_tot += 1 | |
| 120 | − else: | |
| 121 | − if AMLh_end - AMLh_start > AMLh_max: | |
| 122 | − AMLh_max = AMLh_end - AMLh_start | |
| 123 | − AMLh_start, AMLh_end = j, j | |
| 124 | − if current0 and current1 and prevdoub0 and prevdoub1 and nextdoub0 and nextdoub1: | |
| 125 | − AMLd_end = j | |
| 126 | − AMLd_tot += 1 | |
| 127 | − else: | |
| 128 | − if AMLd_end - AMLd_start > AMLd_max: | |
| 129 | − AMLd_max = AMLd_end - AMLd_start | |
| 130 | − AMLd_start, AMLd_end = j, j | |
| 131 | − if current0 and current1 and prevoffb0 and prevoffb1 and nextoffb0 and nextoffb1: | |
| 132 | − AMLo_end = j | |
| 133 | − AMLo_tot += 1 | |
| 134 | − else: | |
| 135 | − if AMLo_end - AMLo_start > AMLo_max: | |
| 136 | − AMLo_max = AMLo_end - AMLo_start | |
| 137 | − AMLo_start, AMLo_end = j, j | |
| 138 | − # look for next matching beat | |
| 139 | − count = 0 | |
| 140 | − while otime[i] > etime[j] - (otime[i] - otime[i+1])*tolcontext: | |
| 141 | − j += 1 | |
| 142 | − if count > 0: | |
| 143 | − #print "spurious etime" | |
| 144 | − start = j | |
| 145 | − count += 1 | |
| 146 | − total = float(len(otime)) | |
| 147 | − CML_tot /= total | |
| 148 | − AMLh_tot /= total | |
| 149 | − AMLd_tot /= total | |
| 150 | − AMLo_tot /= total | |
| 151 | − CML_cont = CML_max/total | |
| 152 | − AMLh_cont = AMLh_max/total | |
| 153 | − AMLd_cont = AMLd_max/total | |
| 154 | − AMLo_cont = AMLo_max/total | |
| 155 | − return CML_cont, CML_tot, AMLh_cont, AMLh_tot, AMLd_cont, AMLd_tot, AMLo_cont, AMLo_tot | |
| 156 | − | |
| 157 | −# for i in allfreq: | |
| 158 | −# freq.append(float(i) / 2. / N * samplerate ) | |
| 159 | −# while freq[i]>freqs[j]: | |
| 160 | −# j += 1 | |
| 161 | −# a0 = weight[j-1] | |
| 162 | −# a1 = weight[j] | |
| 163 | −# f0 = freqs[j-1] | |
| 164 | −# f1 = freqs[j] | |
| 165 | −# if f0!=0: | |
| 166 | −# iweight.append((a1-a0)/(f1-f0)*freq[i] + (a0 - (a1 - a0)/(f1/f0 -1.))) | |
| 167 | −# else: | |
| 168 | −# iweight.append((a1-a0)/(f1-f0)*freq[i] + a0) | |
| 169 | −# while freq[i]>freqs[j]: | |
| 170 | −# j += 1 | |
| 171 | − | |
| 172 | − def eval2(self,results,tol=0.2): | |
| 173 | − truth = self.gettruth() | |
| 174 | − obeats = [i[0] for i in truth] | |
| 175 | − ebeats = [i[0]*self.params.step for i in results] | |
| 176 | − NP = max(len(obeats), len(ebeats)) | |
| 177 | − N = int(round(max(max(obeats), max(ebeats))*100.)+100) | |
| 178 | − W = int(round(tol*100.*60./median([i[1] for i in truth], len(truth)/2))) | |
| 179 | − ofunc = [0 for i in range(N+W)] | |
| 180 | − efunc = [0 for i in range(N+W)] | |
| 181 | − for i in obeats: ofunc[int(round(i*100.)+W)] = 1 | |
| 182 | − for i in ebeats: efunc[int(round(i*100.)+W)] = 1 | |
| 183 | − assert len(obeats) == sum(ofunc) | |
| 184 | − autocor = 0; m =0 | |
| 185 | − for m in range (-W, W): | |
| 186 | − for i in range(W,N): | |
| 187 | − autocor += ofunc[i] * efunc[i-m] | |
| 188 | − autocor /= float(NP) | |
| 189 | − return autocor | |
| 190 | − | |
| 191 | − def evaluation(self,results,tol=0.2,start=5.): | |
| 192 | − | |
| 193 | − """ beat tracking evaluation function | |
| 194 | − | |
| 195 | − computes P-score of experimental results (ebeats) | |
| 196 | − against ground truth annotations (obeats) """ | |
| 197 | − | |
| 198 | − from aubio.median import short_find as median | |
| 199 | − truth = self.gettruth() | |
| 200 | − ebeats = [i[0]*self.params.step for i in results] | |
| 201 | − obeats = [i[0] for i in truth] | |
| 202 | − | |
| 203 | − # trim anything found before start | |
| 204 | − while obeats[0] < start: obeats.pop(0) | |
| 205 | − while ebeats[0] < start: ebeats.pop(0) | |
| 206 | − # maximum number of beats found | |
| 207 | − NP = max(len(obeats), len(ebeats)) | |
| 208 | − # length of ofunc and efunc vector | |
| 209 | − N = int(round(max(max(obeats), max(ebeats))*100.)+100) | |
| 210 | − # compute W median of ground truth tempi | |
| 211 | − tempi = [] | |
| 212 | − for i in range(1,len(obeats)): tempi.append(obeats[i]-obeats[i-1]) | |
| 213 | − W = int(round(tol*100.*median(tempi,len(tempi)/2))) | |
| 214 | − # build ofunc and efunc functions, starting with W zeros | |
| 215 | − ofunc = [0 for i in range(N+W)] | |
| 216 | − efunc = [0 for i in range(N+W)] | |
| 217 | − for i in obeats: ofunc[int(round(i*100.)+W)] = 1 | |
| 218 | − for i in ebeats: efunc[int(round(i*100.)+W)] = 1 | |
| 219 | − # optional: make sure we didn't miss any beats | |
| 220 | − assert len(obeats) == sum(ofunc) | |
| 221 | − assert len(ebeats) == sum(efunc) | |
| 222 | − # compute auto correlation | |
| 223 | − autocor = 0; m =0 | |
| 224 | − for m in range (-W, W): | |
| 225 | − for i in range(W,N): | |
| 226 | − autocor += ofunc[i] * efunc[i-m] | |
| 227 | − autocor /= float(NP) | |
| 228 | − return autocor | |
| 229 | − | |
| 230 | − def gettruth(self): | |
| 231 | − import os.path | |
| 232 | − from aubio.txtfile import read_datafile | |
| 233 | − datafile = self.input.replace('.wav','.txt') | |
| 234 | − if not os.path.isfile(datafile): | |
| 235 | − print "no ground truth " | |
| 236 | − return False,False | |
| 237 | − else: | |
| 238 | − values = read_datafile(datafile,depth=0) | |
| 239 | − old = -1000 | |
| 240 | − for i in range(len(values)): | |
| 241 | − now = values[i] | |
| 242 | − period = 60 / (now - old) | |
| 243 | − old = now | |
| 244 | − values[i] = [now,period] | |
| 245 | − return values | |
| 246 | − | |
| 247 | − | |
| 248 | − def plot(self,oplots,results): | |
| 249 | − import Gnuplot | |
| 250 | − oplots.append(Gnuplot.Data(results,with_='linespoints',title="auto")) | |
| 251 | − | |
| 252 | − def plotplot(self,wplot,oplots,outplot=None,extension=None,xsize=1.,ysize=1.,spectro=False): | |
| 253 | − import Gnuplot | |
| 254 | − from aubio.gnuplot import gnuplot_create, audio_to_array, make_audio_plot | |
| 255 | − import re | |
| 256 | − # audio data | |
| 257 | − #time,data = audio_to_array(self.input) | |
| 258 | − #f = make_audio_plot(time,data) | |
| 259 | − | |
| 260 | − g = gnuplot_create(outplot=outplot, extension=extension) | |
| 261 | − oplots = [Gnuplot.Data(self.gettruth(),with_='linespoints',title="orig")] + oplots | |
| 262 | − g.plot(*oplots) | |
| @@ -1,42 +0,0 @@ | ||
| 1 | −from task import task | |
| 2 | −from aubio.aubioclass import * | |
| 3 | − | |
| 4 | −class taskcut(task): | |
| 5 | − def __init__(self,input,slicetimes,params=None,output=None): | |
| 6 | − """ open the input file and initialize arguments | |
| 7 | − parameters should be set *before* calling this method. | |
| 8 | − """ | |
| 9 | − from os.path import basename,splitext | |
| 10 | − task.__init__(self,input,output=None,params=params) | |
| 11 | − self.soundoutbase, self.soundoutext = splitext(basename(self.input)) | |
| 12 | − self.newname = "%s%s%09.5f%s%s" % (self.soundoutbase,".", | |
| 13 | − self.frameread*self.params.step,".",self.soundoutext) | |
| 14 | − self.fileo = sndfile(self.newname,model=self.filei) | |
| 15 | − self.myvec = fvec(self.params.hopsize,self.channels) | |
| 16 | − self.mycopy = fvec(self.params.hopsize,self.channels) | |
| 17 | − self.slicetimes = slicetimes | |
| 18 | − | |
| 19 | − def __call__(self): | |
| 20 | − task.__call__(self) | |
| 21 | − # write to current file | |
| 22 | − if len(self.slicetimes) and self.frameread >= self.slicetimes[0][0]: | |
| 23 | − self.slicetimes.pop(0) | |
| 24 | − # write up to 1st zero crossing | |
| 25 | − zerocross = 0 | |
| 26 | − while ( abs( self.myvec.get(zerocross,0) ) > self.params.zerothres ): | |
| 27 | − zerocross += 1 | |
| 28 | − writesize = self.fileo.write(zerocross,self.myvec) | |
| 29 | − fromcross = 0 | |
| 30 | − while (zerocross < self.readsize): | |
| 31 | − for i in range(self.channels): | |
| 32 | − self.mycopy.set(self.myvec.get(zerocross,i),fromcross,i) | |
| 33 | − fromcross += 1 | |
| 34 | − zerocross += 1 | |
| 35 | − del self.fileo | |
| 36 | − self.fileo = sndfile("%s%s%09.5f%s%s" % (self.soundoutbase,".", | |
| 37 | − self.frameread*self.params.step,".",self.soundoutext),model=self.filei) | |
| 38 | − writesize = self.fileo.write(fromcross,self.mycopy) | |
| 39 | − else: | |
| 40 | − writesize = self.fileo.write(self.readsize,self.myvec) | |
| 41 | − | |
| 42 | − | |
| @@ -1,159 +0,0 @@ | ||
| 1 | − | |
| 2 | −from aubio.task import task | |
| 3 | −from aubio.aubioclass import * | |
| 4 | − | |
| 5 | −class tasknotes(task): | |
| 6 | − def __init__(self,input,output=None,params=None): | |
| 7 | − task.__init__(self,input,params=params) | |
| 8 | − self.opick = onsetpick(self.params.bufsize, | |
| 9 | − self.params.hopsize, | |
| 10 | − self.channels, | |
| 11 | − self.myvec, | |
| 12 | − self.params.threshold, | |
| 13 | − mode=self.params.onsetmode, | |
| 14 | − dcthreshold=self.params.dcthreshold, | |
| 15 | − derivate=self.params.derivate) | |
| 16 | − self.pitchdet = pitch(mode=self.params.pitchmode, | |
| 17 | − bufsize=self.params.pbufsize, | |
| 18 | − hopsize=self.params.phopsize, | |
| 19 | − channels=self.channels, | |
| 20 | − samplerate=self.srate, | |
| 21 | − omode=self.params.omode) | |
| 22 | − self.olist = [] | |
| 23 | − self.ofunc = [] | |
| 24 | − self.maxofunc = 0 | |
| 25 | − self.last = -1000 | |
| 26 | − self.oldifreq = 0 | |
| 27 | − if self.params.localmin: | |
| 28 | − self.ovalist = [0., 0., 0., 0., 0.] | |
| 29 | − | |
| 30 | − def __call__(self): | |
| 31 | − from aubio.median import short_find | |
| 32 | − task.__call__(self) | |
| 33 | − isonset,val = self.opick.do(self.myvec) | |
| 34 | − if (aubio_silence_detection(self.myvec(),self.params.silence)): | |
| 35 | − isonset=0 | |
| 36 | − freq = -1. | |
| 37 | − else: | |
| 38 | − freq = self.pitchdet(self.myvec) | |
| 39 | − minpitch = self.params.pitchmin | |
| 40 | − maxpitch = self.params.pitchmax | |
| 41 | − if maxpitch and freq > maxpitch : | |
| 42 | − freq = -1. | |
| 43 | − elif minpitch and freq < minpitch : | |
| 44 | − freq = -1. | |
| 45 | − freq = aubio_freqtomidi(freq) | |
| 46 | − if self.params.pitchsmooth: | |
| 47 | − self.shortlist.append(freq) | |
| 48 | − self.shortlist.pop(0) | |
| 49 | − smoothfreq = short_find(self.shortlist, | |
| 50 | − len(self.shortlist)/2) | |
| 51 | − freq = smoothfreq | |
| 52 | − now = self.frameread | |
| 53 | − ifreq = int(round(freq)) | |
| 54 | − if self.oldifreq == ifreq: | |
| 55 | − self.oldifreq = ifreq | |
| 56 | − else: | |
| 57 | − self.oldifreq = ifreq | |
| 58 | − ifreq = 0 | |
| 59 | − # take back delay | |
| 60 | − if self.params.delay != 0.: now -= self.params.delay | |
| 61 | − if now < 0 : | |
| 62 | − now = 0 | |
| 63 | − if (isonset == 1): | |
| 64 | − if self.params.mintol: | |
| 65 | − # prune doubled | |
| 66 | − if (now - self.last) > self.params.mintol: | |
| 67 | − self.last = now | |
| 68 | − return now, 1, freq, ifreq | |
| 69 | − else: | |
| 70 | − return now, 0, freq, ifreq | |
| 71 | − else: | |
| 72 | − return now, 1, freq, ifreq | |
| 73 | − else: | |
| 74 | − return now, 0, freq, ifreq | |
| 75 | − | |
| 76 | − | |
| 77 | − def fprint(self,foo): | |
| 78 | − print self.params.step*foo[0], foo[1], foo[2], foo[3] | |
| 79 | − | |
| 80 | − def compute_all(self): | |
| 81 | − """ Compute data """ | |
| 82 | − now, onset, freq, ifreq = [], [], [], [] | |
| 83 | − while(self.readsize==self.params.hopsize): | |
| 84 | − n, o, f, i = self() | |
| 85 | − now.append(n*self.params.step) | |
| 86 | − onset.append(o) | |
| 87 | − freq.append(f) | |
| 88 | − ifreq.append(i) | |
| 89 | − if self.params.verbose: | |
| 90 | − self.fprint((n,o,f,i)) | |
| 91 | − return now, onset, freq, ifreq | |
| 92 | − | |
| 93 | − def plot(self,now,onset,freq,ifreq,oplots): | |
| 94 | − import Gnuplot | |
| 95 | − | |
| 96 | − oplots.append(Gnuplot.Data(now,freq,with_='lines', | |
| 97 | − title=self.params.pitchmode)) | |
| 98 | − oplots.append(Gnuplot.Data(now,ifreq,with_='lines', | |
| 99 | − title=self.params.pitchmode)) | |
| 100 | − | |
| 101 | − temponsets = [] | |
| 102 | − for i in onset: | |
| 103 | − temponsets.append(i*1000) | |
| 104 | − oplots.append(Gnuplot.Data(now,temponsets,with_='impulses', | |
| 105 | − title=self.params.pitchmode)) | |
| 106 | − | |
| 107 | − def plotplot(self,wplot,oplots,outplot=None,multiplot = 0): | |
| 108 | − from aubio.gnuplot import gnuplot_init, audio_to_array, make_audio_plot | |
| 109 | − import re | |
| 110 | − import Gnuplot | |
| 111 | − # audio data | |
| 112 | − time,data = audio_to_array(self.input) | |
| 113 | − f = make_audio_plot(time,data) | |
| 114 | − | |
| 115 | − # check if ground truth exists | |
| 116 | − #timet,pitcht = self.gettruth() | |
| 117 | − #if timet and pitcht: | |
| 118 | − # oplots = [Gnuplot.Data(timet,pitcht,with_='lines', | |
| 119 | − # title='ground truth')] + oplots | |
| 120 | − | |
| 121 | − t = Gnuplot.Data(0,0,with_='impulses') | |
| 122 | − | |
| 123 | − g = gnuplot_init(outplot) | |
| 124 | − g('set title \'%s\'' % (re.sub('.*/','',self.input))) | |
| 125 | − g('set multiplot') | |
| 126 | − # hack to align left axis | |
| 127 | − g('set lmargin 15') | |
| 128 | − # plot waveform and onsets | |
| 129 | − g('set size 1,0.3') | |
| 130 | − g('set origin 0,0.7') | |
| 131 | − g('set xrange [0:%f]' % max(time)) | |
| 132 | − g('set yrange [-1:1]') | |
| 133 | − g.ylabel('amplitude') | |
| 134 | − g.plot(f) | |
| 135 | − g('unset title') | |
| 136 | − # plot onset detection function | |
| 137 | − | |
| 138 | − | |
| 139 | − g('set size 1,0.7') | |
| 140 | − g('set origin 0,0') | |
| 141 | − g('set xrange [0:%f]' % max(time)) | |
| 142 | − g('set yrange [20:100]') | |
| 143 | − g('set key right top') | |
| 144 | − g('set noclip one') | |
| 145 | − #g('set format x ""') | |
| 146 | − #g('set log y') | |
| 147 | − #g.xlabel('time (s)') | |
| 148 | − g.ylabel('f0 (Hz)') | |
| 149 | − if multiplot: | |
| 150 | − for i in range(len(oplots)): | |
| 151 | − # plot onset detection functions | |
| 152 | − g('set size 1,%f' % (0.7/(len(oplots)))) | |
| 153 | − g('set origin 0,%f' % (float(i)*0.7/(len(oplots)))) | |
| 154 | − g('set xrange [0:%f]' % max(time)) | |
| 155 | − g.plot(oplots[i]) | |
| 156 | − else: | |
| 157 | − g.plot(*oplots) | |
| 158 | − #g('unset multiplot') | |
| 159 | − | |
| @@ -1,220 +0,0 @@ | ||
| 1 | −from aubio.task.task import task | |
| 2 | −from aubio.aubioclass import * | |
| 3 | − | |
| 4 | −class taskonset(task): | |
| 5 | − def __init__(self,input,output=None,params=None): | |
| 6 | − """ open the input file and initialize arguments | |
| 7 | − parameters should be set *before* calling this method. | |
| 8 | − """ | |
| 9 | − task.__init__(self,input,params=params) | |
| 10 | − self.opick = onsetpick(self.params.bufsize, | |
| 11 | − self.params.hopsize, | |
| 12 | − self.myvec, | |
| 13 | − self.params.threshold, | |
| 14 | − mode=self.params.onsetmode, | |
| 15 | − dcthreshold=self.params.dcthreshold, | |
| 16 | − derivate=self.params.derivate) | |
| 17 | − self.olist = [] | |
| 18 | − self.ofunc = [] | |
| 19 | − self.maxofunc = 0 | |
| 20 | − self.last = 0 | |
| 21 | − if self.params.localmin: | |
| 22 | − self.ovalist = [0., 0., 0., 0., 0.] | |
| 23 | − | |
| 24 | − def __call__(self): | |
| 25 | − task.__call__(self) | |
| 26 | − isonset,val = self.opick.do(self.myvec) | |
| 27 | − if (aubio_silence_detection(self.myvec(),self.params.silence)): | |
| 28 | − isonset=0 | |
| 29 | − if self.params.storefunc: | |
| 30 | − self.ofunc.append(val) | |
| 31 | − if self.params.localmin: | |
| 32 | − if val > 0: self.ovalist.append(val) | |
| 33 | − else: self.ovalist.append(0) | |
| 34 | − self.ovalist.pop(0) | |
| 35 | − if (isonset > 0.): | |
| 36 | − if self.params.localmin: | |
| 37 | − # find local minima before peak | |
| 38 | − i=len(self.ovalist)-1 | |
| 39 | − while self.ovalist[i-1] < self.ovalist[i] and i > 0: | |
| 40 | − i -= 1 | |
| 41 | − now = (self.frameread+1-i) | |
| 42 | − else: | |
| 43 | − now = self.frameread | |
| 44 | − # take back delay | |
| 45 | − if self.params.delay != 0.: now -= self.params.delay | |
| 46 | − if now < 0 : | |
| 47 | − now = 0 | |
| 48 | − if self.params.mintol: | |
| 49 | − # prune doubled | |
| 50 | − if (now - self.last) > self.params.mintol: | |
| 51 | − self.last = now | |
| 52 | − return now, val | |
| 53 | − else: | |
| 54 | − return now, val | |
| 55 | − | |
| 56 | − | |
| 57 | − def fprint(self,foo): | |
| 58 | − print self.params.step*foo[0] | |
| 59 | − | |
| 60 | − def eval(self,inputdata,ftru,mode='roc',vmode=''): | |
| 61 | − from aubio.txtfile import read_datafile | |
| 62 | − from aubio.onsetcompare import onset_roc, onset_diffs, onset_rocloc | |
| 63 | − ltru = read_datafile(ftru,depth=0) | |
| 64 | − lres = [] | |
| 65 | − for i in range(len(inputdata)): lres.append(inputdata[i][0]*self.params.step) | |
| 66 | − if vmode=='verbose': | |
| 67 | − print "Running with mode %s" % self.params.onsetmode, | |
| 68 | − print " and threshold %f" % self.params.threshold, | |
| 69 | − print " on file", self.input | |
| 70 | − #print ltru; print lres | |
| 71 | − if mode == 'local': | |
| 72 | − l = onset_diffs(ltru,lres,self.params.tol) | |
| 73 | − mean = 0 | |
| 74 | − for i in l: mean += i | |
| 75 | − if len(l): mean = "%.3f" % (mean/len(l)) | |
| 76 | − else: mean = "?0" | |
| 77 | − return l, mean | |
| 78 | − elif mode == 'roc': | |
| 79 | − self.orig, self.missed, self.merged, \ | |
| 80 | − self.expc, self.bad, self.doubled = \ | |
| 81 | − onset_roc(ltru,lres,self.params.tol) | |
| 82 | − elif mode == 'rocloc': | |
| 83 | − self.v = {} | |
| 84 | − self.v['orig'], self.v['missed'], self.v['Tm'], \ | |
| 85 | − self.v['expc'], self.v['bad'], self.v['Td'], \ | |
| 86 | − self.v['l'], self.v['labs'] = \ | |
| 87 | − onset_rocloc(ltru,lres,self.params.tol) | |
| 88 | − | |
| 89 | − def plot(self,onsets,ofunc,wplot,oplots,nplot=False): | |
| 90 | − import Gnuplot, Gnuplot.funcutils | |
| 91 | − import aubio.txtfile | |
| 92 | − import os.path | |
| 93 | − from numpy import arange, array, ones | |
| 94 | − from aubio.onsetcompare import onset_roc | |
| 95 | − | |
| 96 | − x1,y1,y1p = [],[],[] | |
| 97 | − oplot = [] | |
| 98 | − if self.params.onsetmode in ('mkl','kl'): ofunc[0:10] = [0] * 10 | |
| 99 | − | |
| 100 | − self.lenofunc = len(ofunc) | |
| 101 | − self.maxofunc = max(ofunc) | |
| 102 | − # onset detection function | |
| 103 | − downtime = arange(len(ofunc))*self.params.step | |
| 104 | − oplot.append(Gnuplot.Data(downtime,ofunc,with_='lines',title=self.params.onsetmode)) | |
| 105 | − | |
| 106 | − # detected onsets | |
| 107 | − if not nplot: | |
| 108 | − for i in onsets: | |
| 109 | − x1.append(i[0]*self.params.step) | |
| 110 | − y1.append(self.maxofunc) | |
| 111 | − y1p.append(-self.maxofunc) | |
| 112 | − #x1 = array(onsets)*self.params.step | |
| 113 | − #y1 = self.maxofunc*ones(len(onsets)) | |
| 114 | − if x1: | |
| 115 | − oplot.append(Gnuplot.Data(x1,y1,with_='impulses')) | |
| 116 | − wplot.append(Gnuplot.Data(x1,y1p,with_='impulses')) | |
| 117 | − | |
| 118 | − oplots.append((oplot,self.params.onsetmode,self.maxofunc)) | |
| 119 | − | |
| 120 | − # check if ground truth datafile exists | |
| 121 | − datafile = self.input.replace('.wav','.txt') | |
| 122 | − if datafile == self.input: datafile = "" | |
| 123 | − if not os.path.isfile(datafile): | |
| 124 | − self.title = "" #"(no ground truth)" | |
| 125 | − else: | |
| 126 | − t_onsets = aubio.txtfile.read_datafile(datafile) | |
| 127 | − x2 = array(t_onsets).resize(len(t_onsets)) | |
| 128 | − y2 = self.maxofunc*ones(len(t_onsets)) | |
| 129 | − wplot.append(Gnuplot.Data(x2,y2,with_='impulses')) | |
| 130 | − | |
| 131 | − tol = 0.050 | |
| 132 | − | |
| 133 | − orig, missed, merged, expc, bad, doubled = \ | |
| 134 | − onset_roc(x2,x1,tol) | |
| 135 | − self.title = "GD %2.3f%% FP %2.3f%%" % \ | |
| 136 | − ((100*float(orig-missed-merged)/(orig)), | |
| 137 | − (100*float(bad+doubled)/(orig))) | |
| 138 | − | |
| 139 | − | |
| 140 | − def plotplot(self,wplot,oplots,outplot=None,extension=None,xsize=1.,ysize=1.,spectro=False): | |
| 141 | − from aubio.gnuplot import gnuplot_create, audio_to_array, make_audio_plot, audio_to_spec | |
| 142 | − import re | |
| 143 | − # prepare the plot | |
| 144 | − g = gnuplot_create(outplot=outplot, extension=extension) | |
| 145 | − g('set title \'%s\'' % (re.sub('.*/','',self.input))) | |
| 146 | − if spectro: | |
| 147 | − g('set size %f,%f' % (xsize,1.3*ysize) ) | |
| 148 | − else: | |
| 149 | − g('set size %f,%f' % (xsize,ysize) ) | |
| 150 | − g('set multiplot') | |
| 151 | − | |
| 152 | − # hack to align left axis | |
| 153 | − g('set lmargin 3') | |
| 154 | − g('set rmargin 6') | |
| 155 | − | |
| 156 | − if spectro: | |
| 157 | − import Gnuplot | |
| 158 | − minf = 50 | |
| 159 | − maxf = 500 | |
| 160 | − data,time,freq = audio_to_spec(self.input,minf=minf,maxf=maxf) | |
| 161 | − g('set size %f,%f' % (1.24*xsize , 0.34*ysize) ) | |
| 162 | − g('set origin %f,%f' % (-0.12,0.65*ysize)) | |
| 163 | − g('set xrange [0.:%f]' % time[-1]) | |
| 164 | − g('set yrange [%f:%f]' % (minf,maxf)) | |
| 165 | − g('set pm3d map') | |
| 166 | − g('unset colorbox') | |
| 167 | − g('set lmargin 0') | |
| 168 | − g('set rmargin 0') | |
| 169 | − g('set tmargin 0') | |
| 170 | − g('set palette rgbformulae -25,-24,-32') | |
| 171 | − g.xlabel('time (s)',offset=(0,1.)) | |
| 172 | − g.ylabel('freq (Hz)') | |
| 173 | − g('set origin 0,%f' % (1.0*ysize) ) | |
| 174 | − g('set format x "%1.1f"') | |
| 175 | − #if log: | |
| 176 | − # g('set yrange [%f:%f]' % (max(10,minf),maxf)) | |
| 177 | − # g('set log y') | |
| 178 | − g.splot(Gnuplot.GridData(data,time,freq, binary=1, title='')) | |
| 179 | − else: | |
| 180 | − # plot waveform and onsets | |
| 181 | − time,data = audio_to_array(self.input) | |
| 182 | − wplot = [make_audio_plot(time,data)] + wplot | |
| 183 | − g('set origin 0,%f' % (0.7*ysize) ) | |
| 184 | − g('set size %f,%f' % (xsize,0.3*ysize)) | |
| 185 | − g('set format y "%1f"') | |
| 186 | − g('set xrange [0:%f]' % max(time)) | |
| 187 | − g('set yrange [-1:1]') | |
| 188 | − g('set noytics') | |
| 189 | − g('set y2tics -1,1') | |
| 190 | − g.xlabel('time (s)',offset=(0,0.7)) | |
| 191 | − g.ylabel('amplitude') | |
| 192 | − g.plot(*wplot) | |
| 193 | − | |
| 194 | − # default settings for next plots | |
| 195 | − g('unset title') | |
| 196 | − g('set format x ""') | |
| 197 | − g('set format y "%3e"') | |
| 198 | − g('set tmargin 0') | |
| 199 | − g.xlabel('') | |
| 200 | − | |
| 201 | − N = len(oplots) | |
| 202 | − y = 0.7*ysize # the vertical proportion of the plot taken by onset functions | |
| 203 | − delta = 0.035 # the constant part of y taken by last plot label and data | |
| 204 | − for i in range(N): | |
| 205 | − # plot onset detection functions | |
| 206 | − g('set size %f,%f' % ( xsize, (y-delta)/N)) | |
| 207 | − g('set origin 0,%f' % ((N-i-1)*(y-delta)/N + delta )) | |
| 208 | − g('set nokey') | |
| 209 | − g('set xrange [0:%f]' % (self.lenofunc*self.params.step)) | |
| 210 | − g('set yrange [0:%f]' % (1.1*oplots[i][2])) | |
| 211 | − g('set y2tics ("0" 0, "%d" %d)' % (round(oplots[i][2]),round(oplots[i][2]))) | |
| 212 | − g.ylabel(oplots[i][1]) | |
| 213 | − if i == N-1: | |
| 214 | − g('set size %f,%f' % ( xsize, (y-delta)/N + delta ) ) | |
| 215 | − g('set origin 0,0') | |
| 216 | − g.xlabel('time (s)', offset=(0,0.7)) | |
| 217 | − g('set format x') | |
| 218 | − g.plot(*oplots[i][0]) | |
| 219 | − | |
| 220 | − g('unset multiplot') | |
| @@ -1,33 +0,0 @@ | ||
| 1 | − | |
| 2 | −class taskparams(object): | |
| 3 | − """ default parameters for task classes """ | |
| 4 | − def __init__(self,input=None,output=None): | |
| 5 | − self.silence = -90 | |
| 6 | − self.derivate = False | |
| 7 | − self.localmin = False | |
| 8 | − self.delay = 4. | |
| 9 | − self.storefunc = False | |
| 10 | − self.bufsize = 512 | |
| 11 | − self.hopsize = 256 | |
| 12 | − self.pbufsize = 2048 | |
| 13 | − self.phopsize = 512 | |
| 14 | − self.samplerate = 44100 | |
| 15 | − self.tol = 0.05 | |
| 16 | − self.mintol = 0.0 | |
| 17 | − self.step = float(self.hopsize)/float(self.samplerate) | |
| 18 | − self.threshold = 0.1 | |
| 19 | − self.onsetmode = 'dual' | |
| 20 | − self.pitchmode = 'yin' | |
| 21 | − # best threshold for yin monophonic Mirex04 (depth of f0) | |
| 22 | − self.yinthresh = 0.15 | |
| 23 | − # best thresh for yinfft monophonic Mirex04 (tradeoff sil/gd) | |
| 24 | − # also best param for yinfft polyphonic Mirex04 | |
| 25 | − self.yinfftthresh = 0.85 | |
| 26 | − self.pitchsmooth = 0 | |
| 27 | − self.pitchmin=20. | |
| 28 | − self.pitchmax=20000. | |
| 29 | − self.pitchdelay = -0.5 | |
| 30 | − self.dcthreshold = -1. | |
| 31 | − self.omode = "freq" | |
| 32 | − self.verbose = False | |
| 33 | − | |
| @@ -1,234 +0,0 @@ | ||
| 1 | −from aubio.task.task import task | |
| 2 | −from aubio.task.silence import tasksilence | |
| 3 | −from aubio.aubioclass import * | |
| 4 | − | |
| 5 | −class taskpitch(task): | |
| 6 | − def __init__(self,input,params=None): | |
| 7 | − task.__init__(self,input,params=params) | |
| 8 | − self.shortlist = [0. for i in range(self.params.pitchsmooth)] | |
| 9 | − if self.params.pitchmode == 'yin': | |
| 10 | − tolerance = self.params.yinthresh | |
| 11 | − elif self.params.pitchmode == 'yinfft': | |
| 12 | − tolerance = self.params.yinfftthresh | |
| 13 | − else: | |
| 14 | − tolerance = 0. | |
| 15 | − self.pitchdet = pitch(mode=self.params.pitchmode, | |
| 16 | − bufsize=self.params.bufsize, | |
| 17 | − hopsize=self.params.hopsize, | |
| 18 | − samplerate=self.srate, | |
| 19 | − omode=self.params.omode, | |
| 20 | − tolerance = tolerance) | |
| 21 | − | |
| 22 | − def __call__(self): | |
| 23 | − from aubio.median import short_find | |
| 24 | − task.__call__(self) | |
| 25 | − if (aubio_silence_detection(self.myvec(),self.params.silence)==1): | |
| 26 | − freq = -1. | |
| 27 | − else: | |
| 28 | − freq = self.pitchdet(self.myvec) | |
| 29 | − minpitch = self.params.pitchmin | |
| 30 | − maxpitch = self.params.pitchmax | |
| 31 | − if maxpitch and freq > maxpitch : | |
| 32 | − freq = -1. | |
| 33 | − elif minpitch and freq < minpitch : | |
| 34 | − freq = -1. | |
| 35 | − if self.params.pitchsmooth: | |
| 36 | − self.shortlist.append(freq) | |
| 37 | − self.shortlist.pop(0) | |
| 38 | − smoothfreq = short_find(self.shortlist, | |
| 39 | − len(self.shortlist)/2) | |
| 40 | − return smoothfreq | |
| 41 | − else: | |
| 42 | − return freq | |
| 43 | − | |
| 44 | − def compute_all(self): | |
| 45 | − """ Compute data """ | |
| 46 | − mylist = [] | |
| 47 | − while(self.readsize==self.params.hopsize): | |
| 48 | − freq = self() | |
| 49 | − mylist.append(freq) | |
| 50 | − if self.params.verbose: | |
| 51 | − self.fprint("%s\t%s" % (self.frameread*self.params.step,freq)) | |
| 52 | − return mylist | |
| 53 | − | |
| 54 | − def gettruth(self): | |
| 55 | − """ extract ground truth array in frequency """ | |
| 56 | − import os.path | |
| 57 | − """ from wavfile.txt """ | |
| 58 | − datafile = self.input.replace('.wav','.txt') | |
| 59 | − if datafile == self.input: datafile = "" | |
| 60 | − """ from file.<midinote>.wav """ | |
| 61 | − # FIXME very weak check | |
| 62 | − floatpit = self.input.split('.')[-2] | |
| 63 | − if not os.path.isfile(datafile) and len(self.input.split('.')) < 3: | |
| 64 | − print "no ground truth " | |
| 65 | − return False,False | |
| 66 | − elif floatpit: | |
| 67 | − try: | |
| 68 | − self.truth = float(floatpit) | |
| 69 | − #print "ground truth found in filename:", self.truth | |
| 70 | − tasksil = tasksilence(self.input,params=self.params) | |
| 71 | − time,pitch =[],[] | |
| 72 | − while(tasksil.readsize==tasksil.params.hopsize): | |
| 73 | − tasksil() | |
| 74 | − time.append(tasksil.params.step*(tasksil.frameread)) | |
| 75 | − if not tasksil.issilence: | |
| 76 | − pitch.append(self.truth) | |
| 77 | − else: | |
| 78 | − pitch.append(-1.) | |
| 79 | − return time,pitch | |
| 80 | − except ValueError: | |
| 81 | − # FIXME very weak check | |
| 82 | − if not os.path.isfile(datafile): | |
| 83 | − print "no ground truth found" | |
| 84 | − return 0,0 | |
| 85 | − else: | |
| 86 | − from aubio.txtfile import read_datafile | |
| 87 | − values = read_datafile(datafile) | |
| 88 | − time, pitch = [], [] | |
| 89 | − for i in range(len(values)): | |
| 90 | − time.append(values[i][0]) | |
| 91 | − if values[i][1] == 0.0: | |
| 92 | − pitch.append(-1.) | |
| 93 | − else: | |
| 94 | − pitch.append(aubio_freqtomidi(values[i][1])) | |
| 95 | − return time,pitch | |
| 96 | − | |
| 97 | − def oldeval(self,results): | |
| 98 | − def mmean(l): | |
| 99 | − return sum(l)/max(float(len(l)),1) | |
| 100 | − | |
| 101 | − from aubio.median import percental | |
| 102 | − timet,pitcht = self.gettruth() | |
| 103 | − res = [] | |
| 104 | − for i in results: | |
| 105 | − #print i,self.truth | |
| 106 | − if i <= 0: pass | |
| 107 | − else: res.append(self.truth-i) | |
| 108 | − if not res or len(res) < 3: | |
| 109 | − avg = self.truth; med = self.truth | |
| 110 | − else: | |
| 111 | − avg = mmean(res) | |
| 112 | − med = percental(res,len(res)/2) | |
| 113 | − return self.truth, self.truth-med, self.truth-avg | |
| 114 | − | |
| 115 | − def eval(self,pitch,tol=0.5): | |
| 116 | − timet,pitcht = self.gettruth() | |
| 117 | − pitch = [aubio_freqtomidi(i) for i in pitch] | |
| 118 | − for i in range(len(pitch)): | |
| 119 | − if pitch[i] == "nan" or pitch[i] == -1: | |
| 120 | − pitch[i] = -1 | |
| 121 | − time = [ (i+self.params.pitchdelay)*self.params.step for i in range(len(pitch)) ] | |
| 122 | − #print len(timet),len(pitcht) | |
| 123 | − #print len(time),len(pitch) | |
| 124 | − if len(timet) != len(time): | |
| 125 | − time = time[1:len(timet)+1] | |
| 126 | − pitch = pitch[1:len(pitcht)+1] | |
| 127 | − #pitcht = [aubio_freqtomidi(i) for i in pitcht] | |
| 128 | − for i in range(len(pitcht)): | |
| 129 | − if pitcht[i] == "nan" or pitcht[i] == "-inf" or pitcht[i] == -1: | |
| 130 | − pitcht[i] = -1 | |
| 131 | − assert len(timet) == len(time) | |
| 132 | − assert len(pitcht) == len(pitch) | |
| 133 | − osil, esil, opit, epit, echr = 0, 0, 0, 0, 0 | |
| 134 | − for i in range(len(pitcht)): | |
| 135 | − if pitcht[i] == -1: # currently silent | |
| 136 | − osil += 1 # count a silence | |
| 137 | − if pitch[i] <= 0. or pitch[i] == "nan": | |
| 138 | − esil += 1 # found a silence | |
| 139 | − else: | |
| 140 | − opit +=1 | |
| 141 | − if abs(pitcht[i] - pitch[i]) < tol: | |
| 142 | − epit += 1 | |
| 143 | − echr += 1 | |
| 144 | − elif abs(pitcht[i] - pitch[i]) % 12. < tol: | |
| 145 | − echr += 1 | |
| 146 | − #else: | |
| 147 | − # print timet[i], pitcht[i], time[i], pitch[i] | |
| 148 | − #print "origsilence", "foundsilence", "origpitch", "foundpitch", "orig pitchroma", "found pitchchroma" | |
| 149 | − #print 100.*esil/float(osil), 100.*epit/float(opit), 100.*echr/float(opit) | |
| 150 | − return osil, esil, opit, epit, echr | |
| 151 | − | |
| 152 | − def plot(self,pitch,wplot,oplots,titles,outplot=None): | |
| 153 | − import Gnuplot | |
| 154 | − | |
| 155 | − time = [ (i+self.params.pitchdelay)*self.params.step for i in range(len(pitch)) ] | |
| 156 | − pitch = [aubio_freqtomidi(i) for i in pitch] | |
| 157 | − oplots.append(Gnuplot.Data(time,pitch,with_='lines', | |
| 158 | − title=self.params.pitchmode)) | |
| 159 | − titles.append(self.params.pitchmode) | |
| 160 | − | |
| 161 | − | |
| 162 | − def plotplot(self,wplot,oplots,titles,outplot=None,extension=None,xsize=1.,ysize=1.,multiplot = 1, midi = 1, truth = 1): | |
| 163 | − from aubio.gnuplot import gnuplot_create , audio_to_array, make_audio_plot | |
| 164 | − import re | |
| 165 | − import Gnuplot | |
| 166 | − | |
| 167 | − # check if ground truth exists | |
| 168 | − if truth: | |
| 169 | − timet,pitcht = self.gettruth() | |
| 170 | − if timet and pitcht: | |
| 171 | − oplots = [Gnuplot.Data(timet,pitcht,with_='lines', | |
| 172 | − title='ground truth')] + oplots | |
| 173 | − | |
| 174 | − g = gnuplot_create(outplot=outplot, extension=extension) | |
| 175 | − g('set title \'%s\'' % (re.sub('.*/','',self.input))) | |
| 176 | − g('set size %f,%f' % (xsize,ysize) ) | |
| 177 | − g('set multiplot') | |
| 178 | − # hack to align left axis | |
| 179 | − g('set lmargin 4') | |
| 180 | − g('set rmargin 4') | |
| 181 | − # plot waveform | |
| 182 | − time,data = audio_to_array(self.input) | |
| 183 | − wplot = [make_audio_plot(time,data)] | |
| 184 | − g('set origin 0,%f' % (0.7*ysize) ) | |
| 185 | − g('set size %f,%f' % (xsize,0.3*ysize)) | |
| 186 | − #g('set format y "%1f"') | |
| 187 | − g('set xrange [0:%f]' % max(time)) | |
| 188 | − g('set yrange [-1:1]') | |
| 189 | − g('set noytics') | |
| 190 | − g('set y2tics -1,1') | |
| 191 | − g.xlabel('time (s)',offset=(0,0.7)) | |
| 192 | − g.ylabel('amplitude') | |
| 193 | − g.plot(*wplot) | |
| 194 | − | |
| 195 | − # default settings for next plots | |
| 196 | − g('unset title') | |
| 197 | − g('set format x ""') | |
| 198 | − g('set format y "%3e"') | |
| 199 | − g('set tmargin 0') | |
| 200 | − g.xlabel('') | |
| 201 | − g('set noclip one') | |
| 202 | − | |
| 203 | − if not midi: | |
| 204 | − g('set log y') | |
| 205 | − #g.xlabel('time (s)') | |
| 206 | − g.ylabel('f0 (Hz)') | |
| 207 | − g('set yrange [100:%f]' % self.params.pitchmax) | |
| 208 | − else: | |
| 209 | − g.ylabel('midi') | |
| 210 | − g('set yrange [%f:%f]' % (aubio_freqtomidi(self.params.pitchmin), aubio_freqtomidi(self.params.pitchmax))) | |
| 211 | − g('set y2tics %f,%f' % (round(aubio_freqtomidi(self.params.pitchmin)+.5),12)) | |
| 212 | − | |
| 213 | − if multiplot: | |
| 214 | − N = len(oplots) | |
| 215 | − y = 0.7*ysize # the vertical proportion of the plot taken by onset functions | |
| 216 | − delta = 0.035 # the constant part of y taken by last plot label and data | |
| 217 | − for i in range(N): | |
| 218 | − # plot pitch detection functions | |
| 219 | − g('set size %f,%f' % ( xsize, (y-delta)/N)) | |
| 220 | − g('set origin 0,%f' % ((N-i-1)*(y-delta)/N + delta )) | |
| 221 | − g('set nokey') | |
| 222 | − g('set xrange [0:%f]' % max(time)) | |
| 223 | − g.ylabel(titles[i]) | |
| 224 | − if i == N-1: | |
| 225 | − g('set size %f,%f' % (xsize, (y-delta)/N + delta ) ) | |
| 226 | − g('set origin 0,0') | |
| 227 | − g.xlabel('time (s)', offset=(0,0.7)) | |
| 228 | − g('set format x') | |
| 229 | − g.plot(oplots[i]) | |
| 230 | − else: | |
| 231 | − g('set key right top') | |
| 232 | − g.plot(*oplots) | |
| 233 | − g('unset multiplot') | |
| 234 | − | |
| @@ -1,28 +0,0 @@ | ||
| 1 | −from aubio.task.task import task | |
| 2 | −from aubio.aubioclass import * | |
| 3 | − | |
| 4 | −class tasksilence(task): | |
| 5 | − wassilence = 1 | |
| 6 | − issilence = 1 | |
| 7 | − def __call__(self): | |
| 8 | − task.__call__(self) | |
| 9 | − if (aubio_silence_detection(self.myvec(),self.params.silence)==1): | |
| 10 | − if self.wassilence == 1: self.issilence = 1 | |
| 11 | − else: self.issilence = 2 | |
| 12 | − self.wassilence = 1 | |
| 13 | − else: | |
| 14 | − if self.wassilence <= 0: self.issilence = 0 | |
| 15 | − else: self.issilence = -1 | |
| 16 | − self.wassilence = 0 | |
| 17 | − if self.issilence == -1: | |
| 18 | − return max(self.frameread-self.params.delay,0.), -1 | |
| 19 | − elif self.issilence == 2: | |
| 20 | − return max(self.frameread+self.params.delay,0.), 2 | |
| 21 | − | |
| 22 | − def fprint(self,foo): | |
| 23 | − print self.params.step*foo[0], | |
| 24 | − if foo[1] == 2: print "OFF" | |
| 25 | − else: print "ON" | |
| 26 | − | |
| 27 | − | |
| 28 | − | |
| @@ -1,53 +0,0 @@ | ||
| 1 | −from aubio.aubioclass import * | |
| 2 | −from params import taskparams | |
| 3 | − | |
| 4 | −class task(taskparams): | |
| 5 | − """ default template class to apply tasks on a stream """ | |
| 6 | − def __init__(self,input,output=None,params=None): | |
| 7 | − """ open the input file and initialize default argument | |
| 8 | − parameters should be set *before* calling this method. | |
| 9 | − """ | |
| 10 | − import time | |
| 11 | − self.tic = time.time() | |
| 12 | − if params == None: self.params = taskparams() | |
| 13 | − else: self.params = params | |
| 14 | − self.frameread = 0 | |
| 15 | − self.readsize = self.params.hopsize | |
| 16 | − self.input = input | |
| 17 | − self.filei = sndfile(self.input) | |
| 18 | − self.srate = self.filei.samplerate() | |
| 19 | − self.params.step = float(self.params.hopsize)/float(self.srate) | |
| 20 | − self.myvec = fvec(self.params.hopsize) | |
| 21 | − self.output = output | |
| 22 | − | |
| 23 | − def __call__(self): | |
| 24 | − self.readsize = self.filei.read(self.params.hopsize,self.myvec) | |
| 25 | − self.frameread += 1 | |
| 26 | − | |
| 27 | − def compute_all(self): | |
| 28 | − """ Compute data """ | |
| 29 | − mylist = [] | |
| 30 | − while(self.readsize==self.params.hopsize): | |
| 31 | − tmp = self() | |
| 32 | − if tmp: | |
| 33 | − mylist.append(tmp) | |
| 34 | − if self.params.verbose: | |
| 35 | − self.fprint(tmp) | |
| 36 | − return mylist | |
| 37 | − | |
| 38 | − def fprint(self,foo): | |
| 39 | − print foo | |
| 40 | − | |
| 41 | − def eval(self,results): | |
| 42 | − """ Eval data """ | |
| 43 | − pass | |
| 44 | − | |
| 45 | − def plot(self): | |
| 46 | − """ Plot data """ | |
| 47 | − pass | |
| 48 | − | |
| 49 | − def time(self): | |
| 50 | − import time | |
| 51 | − #print "CPU time is now %f seconds," % time.clock(), | |
| 52 | − #print "task execution took %f seconds" % (time.time() - self.tic) | |
| 53 | − return time.time() - self.tic | |
| @@ -1,47 +0,0 @@ | ||
| 1 | −"""Copyright (C) 2004 Paul Brossier <piem@altern.org> | |
| 2 | −print aubio.__LICENSE__ for the terms of use | |
| 3 | −""" | |
| 4 | − | |
| 5 | −__LICENSE__ = """\ | |
| 6 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 7 | − | |
| 8 | − This file is part of aubio. | |
| 9 | − | |
| 10 | − aubio is free software: you can redistribute it and/or modify | |
| 11 | − it under the terms of the GNU General Public License as published by | |
| 12 | − the Free Software Foundation, either version 3 of the License, or | |
| 13 | − (at your option) any later version. | |
| 14 | − | |
| 15 | − aubio is distributed in the hope that it will be useful, | |
| 16 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − GNU General Public License for more details. | |
| 19 | − | |
| 20 | − You should have received a copy of the GNU General Public License | |
| 21 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 22 | −""" | |
| 23 | − | |
| 24 | −def read_datafile(filename,depth=-1): | |
| 25 | − """read list data from a text file (columns of float)""" | |
| 26 | − if filename == '--' or filename == '-': | |
| 27 | − import sys | |
| 28 | − fres = sys.stdin | |
| 29 | − else: | |
| 30 | − fres = open(filename,'ro') | |
| 31 | − l = [] | |
| 32 | − while 1: | |
| 33 | − tmp = fres.readline() | |
| 34 | − if not tmp : break | |
| 35 | − else: tmp = tmp.split() | |
| 36 | − if depth > 0: | |
| 37 | − for i in range(min(depth,len(tmp))): | |
| 38 | − tmp[i] = float(tmp[i]) | |
| 39 | − l.append(tmp) | |
| 40 | − elif depth == 0: | |
| 41 | − l.append(float(tmp[0])) | |
| 42 | − else: | |
| 43 | − for i in range(len(tmp)): | |
| 44 | − tmp[i] = float(tmp[i]) | |
| 45 | − l.append(tmp) | |
| 46 | − return l | |
| 47 | − | |
Empty file deleted.
| @@ -1,167 +0,0 @@ | ||
| 1 | − # | |
| 2 | − # Copyright 2004 Apache Software Foundation | |
| 3 | − # | |
| 4 | − # Licensed under the Apache License, Version 2.0 (the "License"); you | |
| 5 | − # may not use this file except in compliance with the License. You | |
| 6 | − # may obtain a copy of the License at | |
| 7 | − # | |
| 8 | − # http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | − # | |
| 10 | − # Unless required by applicable law or agreed to in writing, software | |
| 11 | − # distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | − # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
| 13 | − # implied. See the License for the specific language governing | |
| 14 | − # permissions and limitations under the License. | |
| 15 | − # | |
| 16 | − # Originally developed by Gregory Trubetskoy. | |
| 17 | − # | |
| 18 | − # $Id: publisher.py,v 1.36 2004/02/16 19:47:27 grisha Exp $ | |
| 19 | − | |
| 20 | −""" | |
| 21 | − This handler is conceputally similar to Zope's ZPublisher, except | |
| 22 | − that it: | |
| 23 | − | |
| 24 | − 1. Is written specifically for mod_python and is therefore much faster | |
| 25 | − 2. Does not require objects to have a documentation string | |
| 26 | − 3. Passes all arguments as simply string | |
| 27 | − 4. Does not try to match Python errors to HTTP errors | |
| 28 | − 5. Does not give special meaning to '.' and '..'. | |
| 29 | − | |
| 30 | − This is a modified version of mod_python.publisher.handler Only the first | |
| 31 | − directory argument is matched, the rest is left for path_info. A default | |
| 32 | − one must be provided. | |
| 33 | − | |
| 34 | −""" | |
| 35 | − | |
| 36 | −from mod_python import apache | |
| 37 | −from mod_python import util | |
| 38 | −from mod_python.publisher import resolve_object,process_auth,imp_suffixes | |
| 39 | − | |
| 40 | −import sys | |
| 41 | −import os | |
| 42 | −import re | |
| 43 | − | |
| 44 | −from types import * | |
| 45 | − | |
| 46 | −def configure_handler(req,default): | |
| 47 | − | |
| 48 | − req.allow_methods(["GET", "POST"]) | |
| 49 | − if req.method not in ["GET", "POST"]: | |
| 50 | − raise apache.SERVER_RETURN, apache.HTTP_METHOD_NOT_ALLOWED | |
| 51 | − | |
| 52 | − func_path = "" | |
| 53 | − if req.path_info: | |
| 54 | − func_path = req.path_info[1:] # skip first / | |
| 55 | − #func_path = func_path.replace("/", ".") | |
| 56 | − #if func_path[-1:] == ".": | |
| 57 | − # func_path = func_path[:-1] | |
| 58 | − # changed: only keep the first directory | |
| 59 | − func_path = re.sub('/.*','',func_path) | |
| 60 | − | |
| 61 | − # default to 'index' if no path_info was given | |
| 62 | − if not func_path: | |
| 63 | − func_path = "index" | |
| 64 | − | |
| 65 | − # if any part of the path begins with "_", abort | |
| 66 | − if func_path[0] == '_' or func_path.count("._"): | |
| 67 | − raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND | |
| 68 | − | |
| 69 | − ## import the script | |
| 70 | − path, module_name = os.path.split(req.filename) | |
| 71 | − if not module_name: | |
| 72 | − module_name = "index" | |
| 73 | − | |
| 74 | − # get rid of the suffix | |
| 75 | − # explanation: Suffixes that will get stripped off | |
| 76 | − # are those that were specified as an argument to the | |
| 77 | − # AddHandler directive. Everything else will be considered | |
| 78 | − # a package.module rather than module.suffix | |
| 79 | − exts = req.get_addhandler_exts() | |
| 80 | − if not exts: | |
| 81 | − # this is SetHandler, make an exception for Python suffixes | |
| 82 | − exts = imp_suffixes | |
| 83 | − if req.extension: # this exists if we're running in a | .ext handler | |
| 84 | − exts += req.extension[1:] | |
| 85 | − if exts: | |
| 86 | − suffixes = exts.strip().split() | |
| 87 | − exp = "\\." + "$|\\.".join(suffixes) | |
| 88 | − suff_matcher = re.compile(exp) # python caches these, so its fast | |
| 89 | − module_name = suff_matcher.sub("", module_name) | |
| 90 | − | |
| 91 | − # import module (or reload if needed) | |
| 92 | − # the [path] argument tells import_module not to allow modules whose | |
| 93 | − # full path is not in [path] or below. | |
| 94 | − config = req.get_config() | |
| 95 | − autoreload=int(config.get("PythonAutoReload", 1)) | |
| 96 | − log=int(config.get("PythonDebug", 0)) | |
| 97 | − try: | |
| 98 | − module = apache.import_module(module_name, | |
| 99 | − autoreload=autoreload, | |
| 100 | − log=log, | |
| 101 | − path=[path]) | |
| 102 | − except ImportError: | |
| 103 | − et, ev, etb = sys.exc_info() | |
| 104 | − # try again, using default module, perhaps this is a | |
| 105 | − # /directory/function (as opposed to /directory/module/function) | |
| 106 | − func_path = module_name | |
| 107 | − module_name = "index" | |
| 108 | − try: | |
| 109 | − module = apache.import_module(module_name, | |
| 110 | − autoreload=autoreload, | |
| 111 | − log=log, | |
| 112 | − path=[path]) | |
| 113 | − except ImportError: | |
| 114 | − # raise the original exception | |
| 115 | − raise et, ev, etb | |
| 116 | − | |
| 117 | − # does it have an __auth__? | |
| 118 | − realm, user, passwd = process_auth(req, module) | |
| 119 | − | |
| 120 | − # resolve the object ('traverse') | |
| 121 | − try: | |
| 122 | − object = resolve_object(req, module, func_path, realm, user, passwd) | |
| 123 | − except AttributeError: | |
| 124 | − # changed, return the default path instead | |
| 125 | − #raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND | |
| 126 | − object = default | |
| 127 | − # not callable, a class or an unbound method | |
| 128 | − if (not callable(object) or | |
| 129 | − type(object) is ClassType or | |
| 130 | − (hasattr(object, 'im_self') and not object.im_self)): | |
| 131 | − | |
| 132 | − result = str(object) | |
| 133 | − | |
| 134 | − else: | |
| 135 | − # callable, (but not a class or unbound method) | |
| 136 | − | |
| 137 | − # process input, if any | |
| 138 | − req.form = util.FieldStorage(req, keep_blank_values=1) | |
| 139 | − | |
| 140 | − result = util.apply_fs_data(object, req.form, req=req) | |
| 141 | − | |
| 142 | − if result or req.bytes_sent > 0 or req.next: | |
| 143 | − | |
| 144 | − if result is None: | |
| 145 | − result = "" | |
| 146 | − else: | |
| 147 | − result = str(result) | |
| 148 | − | |
| 149 | − # unless content_type was manually set, we will attempt | |
| 150 | − # to guess it | |
| 151 | − if not req._content_type_set: | |
| 152 | − # make an attempt to guess content-type | |
| 153 | − if result[:100].strip()[:6].lower() == '<html>' \ | |
| 154 | − or result.find('</') > 0: | |
| 155 | − req.content_type = 'text/html' | |
| 156 | − else: | |
| 157 | − req.content_type = 'text/plain' | |
| 158 | − | |
| 159 | − if req.method != "HEAD": | |
| 160 | − req.write(result) | |
| 161 | − else: | |
| 162 | − req.write("") | |
| 163 | − return apache.OK | |
| 164 | − else: | |
| 165 | − req.log_error("mod_python.publisher: %s returned nothing." % `object`) | |
| 166 | − return apache.HTTP_INTERNAL_SERVER_ERROR | |
| 167 | − | |
| @@ -1,286 +0,0 @@ | ||
| 1 | −from aubio.bench.node import * | |
| 2 | − | |
| 3 | −def parse_args(req): | |
| 4 | − req.basehref = BASEHREF | |
| 5 | − req.datadir = DATADIR | |
| 6 | − if req.path_info: path_info = req.path_info | |
| 7 | − else: path_info = '/' | |
| 8 | − location = re.sub('^/show_[a-z0-9]*/','',path_info) | |
| 9 | − location = re.sub('^/play_[a-z0-9]*/','',location) | |
| 10 | − location = re.sub('^/index/','',location) | |
| 11 | − location = re.sub('^/','',location) | |
| 12 | − location = re.sub('/$','',location) | |
| 13 | − datapath = "%s/%s" % (DATADIR,location) | |
| 14 | − respath = "%s/%s" % (DATADIR,location) | |
| 15 | − last = re.sub('/$','',location) | |
| 16 | − last = last.split('/')[-1] | |
| 17 | − first = path_info.split('/')[1] | |
| 18 | − # store some of this in the mp_request | |
| 19 | − req.location, req.datapath, req.respath = location, datapath, respath | |
| 20 | − req.first, req.last = first, last | |
| 21 | − | |
| 22 | − if location: | |
| 23 | − if not (os.path.isfile(datapath) or | |
| 24 | − os.path.isdir(datapath) or | |
| 25 | − location in ['feedback','email']): | |
| 26 | − # the path was not understood | |
| 27 | − from mod_python import apache | |
| 28 | − req.write("<html> path not found %s</html>" % (datapath)) | |
| 29 | − raise apache.SERVER_RETURN, apache.OK | |
| 30 | − #from mod_python import apache | |
| 31 | − #raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND | |
| 32 | − | |
| 33 | −def navigation(req): | |
| 34 | − """ main html navigation header """ | |
| 35 | − from mod_python import psp | |
| 36 | − req.content_type = "text/html" | |
| 37 | − parse_args(req) | |
| 38 | − datapath = req.datapath | |
| 39 | − location = req.location | |
| 40 | − | |
| 41 | − # deal with session | |
| 42 | − if req.sess.is_new(): | |
| 43 | − msg = "<b>Welcome %s</b><br>" % req.sess['login'] | |
| 44 | − else: | |
| 45 | − msg = "<b>Welcome back %s</b><br>" % req.sess['login'] | |
| 46 | − | |
| 47 | − # start writing | |
| 48 | − tmpl = psp.PSP(req, filename='header.tmpl') | |
| 49 | − tmpl.run(vars = { 'title': "aubioweb / %s / %s" % (req.first,location), | |
| 50 | − 'basehref': '/~piem/', | |
| 51 | − 'message': msg, | |
| 52 | − 'action': req.first}) | |
| 53 | − | |
| 54 | − req.write("<h2>Content of ") | |
| 55 | − print_link(req,"","/") | |
| 56 | − y = location.split('/') | |
| 57 | − for i in range(len(y)-1): | |
| 58 | − print_link(req,"/".join(y[:i+1]),y[i]) | |
| 59 | − req.write(" / ") | |
| 60 | − req.write("%s</h2>\n" % y[-1]) | |
| 61 | − | |
| 62 | − a = {'show_info' : 'info', | |
| 63 | − 'show_sound': 'waveform', | |
| 64 | − 'show_onset': 'onset', | |
| 65 | − 'index' : 'index', | |
| 66 | − 'show_pitch': 'pitch', | |
| 67 | − 'play_m3u': 'stream (m3u/ogg)', | |
| 68 | − 'play_ogg': 'save (ogg)', | |
| 69 | − 'play_wav': 'save (wav)', | |
| 70 | − } | |
| 71 | − | |
| 72 | − # print task lists (only remaining tasks) | |
| 73 | − print_link(req,re.sub('%s.*'%req.last,'',location),"go up") | |
| 74 | − akeys = a.keys(); akeys.sort(); | |
| 75 | − curkey = req.first | |
| 76 | − for akey in akeys: | |
| 77 | − if akey != curkey: | |
| 78 | − req.write(":: ") | |
| 79 | − print_link(req,"/".join((akey,location)),a[akey]) | |
| 80 | − else: | |
| 81 | − req.write(":: ") | |
| 82 | − req.write("<b>%s</b>" % a[akey]) | |
| 83 | − req.write("<br>") | |
| 84 | − | |
| 85 | − # list the content of the directories | |
| 86 | − listdir,listfiles = [],[] | |
| 87 | − if os.path.isdir(datapath): | |
| 88 | − listfiles = list_snd_files(datapath) | |
| 89 | − listdir = list_dirs(datapath) | |
| 90 | − listdir.pop(0) # kick the current dir | |
| 91 | − elif os.path.isfile(datapath): | |
| 92 | − listfiles = [datapath] | |
| 93 | − listdir = [re.sub(req.last,'',location)] | |
| 94 | − | |
| 95 | − link_list(req,listdir,title="Subdirectories") | |
| 96 | − link_list(req,listfiles,title="Files") | |
| 97 | − | |
| 98 | −def footer(req): | |
| 99 | − """ html navigation footer """ | |
| 100 | − from mod_python import psp | |
| 101 | − tmpl = psp.PSP(req, filename='footer.tmpl') | |
| 102 | − tmpl.run(vars = { 'time': -req.mtime+req.request_time }) | |
| 103 | − | |
| 104 | −def apply_on_data(req, func,**keywords): | |
| 105 | − # bug: hardcoded snd file filter | |
| 106 | − act_on_data(func,req.datapath,req.respath, | |
| 107 | − filter="f -maxdepth 1 -name '*.wav' -o -name '*.aif'",**keywords) | |
| 108 | − | |
| 109 | −def print_link(req,target,name,basehref=BASEHREF): | |
| 110 | − req.write("<a href='%s/%s'>%s</a>\n" % (basehref,target,name)) | |
| 111 | − | |
| 112 | −def print_img(req,target,name='',basehref=BASEHREF): | |
| 113 | − if name == '': name = target | |
| 114 | − req.write("<img src='%s/%s' alt='%s' title='%s'>\n" % (basehref,target,name,name)) | |
| 115 | − | |
| 116 | −def link_list(req,targetlist,basehref=BASEHREF,title=None): | |
| 117 | − if len(targetlist) > 1: | |
| 118 | − if title: req.write("<h3>%s</h3>"%title) | |
| 119 | − req.write('<ul>') | |
| 120 | − for i in targetlist: | |
| 121 | − s = re.split('%s/'%DATADIR,i,maxsplit=1)[1] | |
| 122 | − if s: | |
| 123 | − req.write('<li>') | |
| 124 | − print_link(req,s,s) | |
| 125 | − req.write('</li>') | |
| 126 | − req.write('</ul>') | |
| 127 | − | |
| 128 | −def print_list(req,list): | |
| 129 | − req.write("<pre>\n") | |
| 130 | − for i in list: req.write("%s\n" % i) | |
| 131 | − req.write("</pre>\n") | |
| 132 | − | |
| 133 | −def print_command(req,command): | |
| 134 | − req.write("<h4>%s</h4>\n" % re.sub('%%','%',command)) | |
| 135 | − def print_runcommand(input,output): | |
| 136 | − cmd = re.sub('(%)?%i','%s' % input, command) | |
| 137 | − cmd = re.sub('(%)?%o','%s' % output, cmd) | |
| 138 | − print_list(req,runcommand(cmd)) | |
| 139 | − apply_on_data(req,print_runcommand) | |
| 140 | − | |
| 141 | −def datapath_to_location(input): | |
| 142 | − location = re.sub(DATADIR,'',input) | |
| 143 | − return re.sub('^/*','',location) | |
| 144 | − | |
| 145 | −## drawing hacks | |
| 146 | −def draw_func(req,func): | |
| 147 | − import re | |
| 148 | − req.content_type = "image/png" | |
| 149 | − # build location (strip the func_path, add DATADIR) | |
| 150 | − location = re.sub('^/draw_[a-z]*/','%s/'%DATADIR,req.path_info) | |
| 151 | − location = re.sub('.png$','',location) | |
| 152 | − if not os.path.isfile(location): | |
| 153 | − from mod_python import apache | |
| 154 | − raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND | |
| 155 | − # replace location in func | |
| 156 | − cmd = re.sub('(%)?%i','%s' % location, func) | |
| 157 | − # add PYTHONPATH at the beginning, | |
| 158 | − cmd = "%s%s 2> /dev/null" % (PYTHONPATH,cmd) | |
| 159 | − for each in runcommand(cmd): | |
| 160 | − req.write("%s\n"%each) | |
| 161 | − | |
| 162 | −def show_task(req,task): | |
| 163 | − def show_task_file(input,output,task): | |
| 164 | − location = datapath_to_location(input) | |
| 165 | − print_img(req,"draw_%s/%s" % (task,location)) | |
| 166 | − navigation(req) | |
| 167 | − req.write("<h3>%s</h3>\n" % task) | |
| 168 | − apply_on_data(req,show_task_file,task=task) | |
| 169 | − footer(req) | |
| 170 | − | |
| 171 | −## waveform_foo | |
| 172 | −def draw_sound(req): | |
| 173 | − draw_func(req,"aubioplot-audio %%i stdout 2> /dev/null") | |
| 174 | − | |
| 175 | −def show_sound(req): | |
| 176 | − show_task(req,"sound") | |
| 177 | − | |
| 178 | −## pitch foo | |
| 179 | −def draw_pitch(req,threshold='0.3'): | |
| 180 | − draw_func(req,"aubiopitch -i %%i -p -m schmitt,yin,fcomb,mcomb -t %s -O stdout" % threshold) | |
| 181 | − | |
| 182 | −def show_pitch(req): | |
| 183 | − show_task(req,"pitch") | |
| 184 | − | |
| 185 | −## onset foo | |
| 186 | −def draw_onset(req,threshold='0.3'): | |
| 187 | − draw_func(req,"aubiocut -i %%i -p -m complex -t %s -O stdout" % threshold) | |
| 188 | − | |
| 189 | −def show_onset(req,threshold='0.3',details=''): | |
| 190 | − def onset_file(input,output): | |
| 191 | − location = datapath_to_location(input) | |
| 192 | − print_img(req,"draw_onset/%s?threshold=%s"%(location,threshold)) | |
| 193 | − print_link(req,"?threshold=%s" % (float(threshold)-0.1),"-") | |
| 194 | − req.write("%s\n" % threshold) | |
| 195 | − print_link(req,"?threshold=%s" % (float(threshold)+0.1),"+") | |
| 196 | − # bug: hardcoded sndfile extension | |
| 197 | − anote = re.sub('\.wav$','.txt',input) | |
| 198 | − if anote == input: anote = "" | |
| 199 | − res = get_extract(input,threshold) | |
| 200 | − if os.path.isfile(anote): | |
| 201 | − tru = get_anote(anote) | |
| 202 | − print_list(req,get_results(tru,res,0.05)) | |
| 203 | − else: | |
| 204 | − req.write("no ground truth found<br>\n") | |
| 205 | − if details: | |
| 206 | − req.write("<h4>Extraction</h4>\n") | |
| 207 | − print_list(req,res) | |
| 208 | − else: | |
| 209 | − req.write("<a href='%s/show_onset/%s?details=yes&threshold=%s'>details</a><br>\n" % | |
| 210 | − (req.basehref,location,threshold)) | |
| 211 | − if details and os.path.isfile(anote): | |
| 212 | − req.write("<h4>Computed differences</h4>\n") | |
| 213 | − ldiffs = get_diffs(tru,res,0.05) | |
| 214 | − print_list(req,ldiffs) | |
| 215 | − req.write("<h4>Annotations</h4>\n") | |
| 216 | − print_list(req,tru) | |
| 217 | − navigation(req) | |
| 218 | − req.write("<h3>Onset</h3>\n") | |
| 219 | − apply_on_data(req,onset_file) | |
| 220 | − footer(req) | |
| 221 | − | |
| 222 | −def get_anote(anote): | |
| 223 | − import aubio.onsetcompare | |
| 224 | − # FIXME: should import with txtfile.read_datafile | |
| 225 | − return aubio.onsetcompare.load_onsets(anote) | |
| 226 | − | |
| 227 | −def get_diffs(anote,extract,tol): | |
| 228 | − import aubio.onsetcompare | |
| 229 | − return aubio.onsetcompare.onset_diffs(anote,extract,tol) | |
| 230 | − | |
| 231 | −def get_extract(datapath,threshold='0.3'): | |
| 232 | − cmd = "%saubiocut -v -m complex -t %s -i %s" % (PYTHONPATH,threshold,datapath) | |
| 233 | − lo = runcommand(cmd) | |
| 234 | − for i in range(len(lo)): lo[i] = float(lo[i]) | |
| 235 | − return lo | |
| 236 | − | |
| 237 | −def get_results(anote,extract,tol): | |
| 238 | − import aubio.onsetcompare | |
| 239 | − orig, missed, merged, expc, bad, doubled = aubio.onsetcompare.onset_roc(anote,extract,tol) | |
| 240 | − s =("GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)), | |
| 241 | − "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) , | |
| 242 | − "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) , | |
| 243 | − "FP-pruned %2.8f\t" % (100*float(bad)/(orig)) ) | |
| 244 | − return s | |
| 245 | − | |
| 246 | −# play m3u foo | |
| 247 | −def play_m3u(req): | |
| 248 | − def show_task_file(input,output,task): | |
| 249 | − location = datapath_to_location(input) | |
| 250 | − req.write("http://%s%s/play_ogg/%s\n" % (HOSTNAME,BASEHREF,re.sub("play_m3u",task,location))) | |
| 251 | − req.content_type = "audio/mpegurl" | |
| 252 | − parse_args(req) | |
| 253 | − apply_on_data(req,show_task_file,task="play_ogg") | |
| 254 | − | |
| 255 | −# play wav foo | |
| 256 | −def play_wav(req): | |
| 257 | − req.content_type = "audio/x-wav" | |
| 258 | − func = "cat %%i" | |
| 259 | − # build location (strip the func_path, add DATADIR) | |
| 260 | − location = re.sub('^/play_wav/','%s/'%DATADIR,req.path_info) | |
| 261 | − if not os.path.isfile(location): | |
| 262 | − from mod_python import apache | |
| 263 | − raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND | |
| 264 | − # replace location in func | |
| 265 | − cmd = re.sub('(%)?%i','%s' % location, func) | |
| 266 | − # add PYTHONPATH at the beginning, | |
| 267 | − cmd = "%s 2> /dev/null" % cmd | |
| 268 | − for each in runcommand(cmd): | |
| 269 | − req.write("%s\n"%each) | |
| 270 | − | |
| 271 | −# play ogg foo | |
| 272 | −def play_ogg(req): | |
| 273 | − req.content_type = "application/ogg" | |
| 274 | − func = "oggenc -o - %%i" | |
| 275 | − # build location (strip the func_path, add DATADIR) | |
| 276 | − location = re.sub('^/play_ogg/','%s/'%DATADIR,req.path_info) | |
| 277 | − location = re.sub('.ogg$','',location) | |
| 278 | − if not os.path.isfile(location): | |
| 279 | − from mod_python import apache | |
| 280 | − raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND | |
| 281 | − # replace location in func | |
| 282 | − cmd = re.sub('(%)?%i','%s' % location, func) | |
| 283 | − # add PYTHONPATH at the beginning, | |
| 284 | − cmd = "%s 2> /dev/null" % cmd | |
| 285 | − for each in runcommand(cmd): | |
| 286 | − req.write("%s\n"%each) | |
| @@ -1,17 +0,0 @@ | ||
| 1 | −# vim:set syntax=python: | |
| 2 | − | |
| 3 | −pyaubio = ctx.new_task_gen(name = 'python-aubio', | |
| 4 | − features = 'c cshlib pyext', | |
| 5 | − source = '../../swig/aubio.i', | |
| 6 | − add_objects = 'sndfileio', | |
| 7 | − target = '_aubiowrapper', | |
| 8 | − use = ['aubio'], | |
| 9 | − uselib = ['SNDFILE'], | |
| 10 | − swig_flags = '-python -Wall', | |
| 11 | − includes = '. ../../src ../../examples') | |
| 12 | −pyaubio.install_path = '${PYTHONDIR}/${PACKAGE}' | |
| 13 | − | |
| 14 | −# install python files | |
| 15 | −ctx.install_files('${PYTHONDIR}/${PACKAGE}/', ctx.path.ant_glob('**/*.py')) | |
| 16 | −# install swig generated python file | |
| 17 | −ctx.install_files('${PYTHONDIR}/${PACKAGE}/', '../../swig/aubiowrapper.py') | |
| @@ -1,114 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −"""Copyright (C) 2004 Paul Brossier <piem@altern.org> | |
| 4 | − | |
| 5 | −print aubio.__LICENSE__ for the terms of use | |
| 6 | − | |
| 7 | −or see LICENSE.txt in the aubio installation directory. | |
| 8 | −""" | |
| 9 | −__LICENSE__ = """\ | |
| 10 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 11 | − | |
| 12 | − This file is part of aubio. | |
| 13 | − | |
| 14 | − aubio is free software: you can redistribute it and/or modify | |
| 15 | − it under the terms of the GNU General Public License as published by | |
| 16 | − the Free Software Foundation, either version 3 of the License, or | |
| 17 | − (at your option) any later version. | |
| 18 | − | |
| 19 | − aubio is distributed in the hope that it will be useful, | |
| 20 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 21 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 22 | − GNU General Public License for more details. | |
| 23 | − | |
| 24 | − You should have received a copy of the GNU General Public License | |
| 25 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 26 | −""" | |
| 27 | − | |
| 28 | − | |
| 29 | −__HELP__ = """\ | |
| 30 | −# required arguments | |
| 31 | − -c targetfilename | |
| 32 | − -o detectfilename | |
| 33 | −(both must be text files with 1 time a line expressed in seconds) | |
| 34 | − | |
| 35 | −# optional arguments | |
| 36 | − -D <delay> delay in seconds | |
| 37 | − -v verbose mode | |
| 38 | − -d debug mode | |
| 39 | − | |
| 40 | −# output | |
| 41 | −results:number of correct detections | |
| 42 | − number of incorrect detections | |
| 43 | − number of doubled detections | |
| 44 | − number of total detections | |
| 45 | − number of total targets | |
| 46 | − | |
| 47 | −# example: | |
| 48 | −$ aubioonset-comp -c checked-onsets.txt -o handlab-onsets.txt -v | |
| 49 | −( gd fp dd ) tot / real | |
| 50 | −( 5 4 0 ) 9 / 9 | |
| 51 | −55.5555555556 %GD 44.4444444444 %FP 0.0 %OD | |
| 52 | − | |
| 53 | −# bugs | |
| 54 | −does not scale to very long lists | |
| 55 | −""" | |
| 56 | − | |
| 57 | −import sys | |
| 58 | −from aubio.onsetcompare import onset_roc, onset_diffs | |
| 59 | −from aubio.txtfile import read_datafile | |
| 60 | − | |
| 61 | −# default values | |
| 62 | −fileo=None;filec=None;vmode=None;dmode=None;delay=0. | |
| 63 | −# default tolerance is 50 ms | |
| 64 | −#tol = 0.050 | |
| 65 | −tol = 0.048 | |
| 66 | −# default mode is onset | |
| 67 | −mode = 'onset' | |
| 68 | − | |
| 69 | −while len(sys.argv) >=2: | |
| 70 | − option = sys.argv[1]; del sys.argv[1] | |
| 71 | − if option == '-h': print __HELP__; sys.exit() | |
| 72 | − if option == '-o': fileo = sys.argv[1]; del sys.argv[1] | |
| 73 | − if option == '-c': filec = sys.argv[1]; del sys.argv[1] | |
| 74 | − if option == '-v': vmode = 'verbose' | |
| 75 | − if option == '-d': dmode = 'debug' | |
| 76 | − if option == '-D': delay = float(sys.argv[1]); del sys.argv[1] | |
| 77 | − if option == '-tol': tol = float(sys.argv[1]); del sys.argv[1] | |
| 78 | − if option == '-l': mode = 'localisation' | |
| 79 | − | |
| 80 | −# arguments required | |
| 81 | −if (not fileo) or (not filec): | |
| 82 | − print 'wrong set of arguments. use \'-h\' for help' | |
| 83 | − sys.exit('error: needs at least \'-c targets.txt -o detected.txt\'') | |
| 84 | − | |
| 85 | −# load files | |
| 86 | −ltru, lres = read_datafile(fileo,depth=0),read_datafile(filec,depth=0) | |
| 87 | − | |
| 88 | −# delay onsets as required with -D | |
| 89 | −if delay: | |
| 90 | − for i in range(len(lres)): | |
| 91 | − lres[i] = lres[i] + delay | |
| 92 | −# compute errors types | |
| 93 | −if mode == 'localisation': | |
| 94 | − l = onset_diffs(ltru,lres,tol) | |
| 95 | − for i in l: print "%.3f" % i | |
| 96 | −else: | |
| 97 | − orig, missed, merged, expc, bad, doubled = onset_roc(ltru,lres,tol) | |
| 98 | − | |
| 99 | − # print results | |
| 100 | − #print "orig, missed, merged, expc, bad, doubled:" | |
| 101 | − if vmode=='verbose': | |
| 102 | − print "orig", orig | |
| 103 | − print "expc", expc | |
| 104 | − print "missed",missed | |
| 105 | − print "merged", merged | |
| 106 | − print "bad", bad | |
| 107 | − print "doubled", doubled | |
| 108 | − print "correct", orig-missed-merged | |
| 109 | − print "GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)), | |
| 110 | − print "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) , | |
| 111 | − print "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) , | |
| 112 | − print "FP-pruned %2.8f\t" % (100*float(bad)/(orig)) | |
| 113 | − else: | |
| 114 | − print orig, missed, merged, expc, bad, doubled | |
| @@ -1,156 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −""" this file was written by Paul Brossier | |
| 4 | − it is released under the GNU/GPL license. | |
| 5 | −""" | |
| 6 | − | |
| 7 | −import sys | |
| 8 | −from aubio.task import * | |
| 9 | − | |
| 10 | −usage = "usage: %s [options] -i soundfile" % sys.argv[0] | |
| 11 | − | |
| 12 | −def parse_args(): | |
| 13 | − from optparse import OptionParser | |
| 14 | − parser = OptionParser(usage=usage) | |
| 15 | − parser.add_option("-i","--input", | |
| 16 | − action="store", dest="filename", | |
| 17 | − help="input sound file") | |
| 18 | − parser.add_option("-m","--mode", | |
| 19 | − action="store", dest="mode", default='dual', | |
| 20 | − help="onset detection mode [default=dual] \ | |
| 21 | − complexdomain|hfc|phase|specdiff|energy|kl|mkl|dual") | |
| 22 | − parser.add_option("-B","--bufsize", | |
| 23 | − action="store", dest="bufsize", default=512, | |
| 24 | − help="buffer size [default=512]") | |
| 25 | − parser.add_option("-H","--hopsize", | |
| 26 | − action="store", dest="hopsize", default=256, | |
| 27 | − help="overlap size [default=256]") | |
| 28 | − parser.add_option("-t","--threshold", | |
| 29 | − action="store", dest="threshold", default=0.3, | |
| 30 | − help="onset peak picking threshold [default=0.3]") | |
| 31 | − parser.add_option("-C","--dcthreshold", | |
| 32 | − action="store", dest="dcthreshold", default=1., | |
| 33 | − help="onset peak picking DC component [default=1.]") | |
| 34 | − parser.add_option("-s","--silence", | |
| 35 | − action="store", dest="silence", default=-70, | |
| 36 | − help="silence threshold [default=-70]") | |
| 37 | − parser.add_option("-M","--mintol", | |
| 38 | − action="store", dest="mintol", default=0.048, | |
| 39 | − help="minimum inter onset interval [default=0.048]") | |
| 40 | − parser.add_option("-D","--delay", | |
| 41 | − action="store", dest="delay", | |
| 42 | − help="number of seconds to take back [default=system]\ | |
| 43 | − default system delay is 3*hopsize/samplerate") | |
| 44 | − parser.add_option("-L","--localmin", | |
| 45 | − action="store_true", dest="localmin", default=False, | |
| 46 | − help="use local minima after peak detection") | |
| 47 | − parser.add_option("-c","--cut", | |
| 48 | − action="store_true", dest="cut", default=False, | |
| 49 | − help="cut input sound file at detected labels \ | |
| 50 | − best used with option -L") | |
| 51 | − parser.add_option("-d","--derivate", | |
| 52 | − action="store_true", dest="derivate", default=False, | |
| 53 | − help="derivate onset detection function") | |
| 54 | − parser.add_option("-S","--silencecut", | |
| 55 | − action="store_true", dest="silencecut", default=False, | |
| 56 | − help="outputs silence locations") | |
| 57 | − parser.add_option("-z","--zerocross", | |
| 58 | − action="store", dest="zerothres", default=0.008, | |
| 59 | − help="zero-crossing threshold for slicing [default=0.00008]") | |
| 60 | − # plotting functions | |
| 61 | − parser.add_option("-p","--plot", | |
| 62 | − action="store_true", dest="plot", default=False, | |
| 63 | − help="draw plot") | |
| 64 | − parser.add_option("-x","--xsize", | |
| 65 | − action="store", dest="xsize", default=1., | |
| 66 | − type='float', help="define xsize for plot") | |
| 67 | − parser.add_option("-y","--ysize", | |
| 68 | − action="store", dest="ysize", default=1., | |
| 69 | − type='float', help="define ysize for plot") | |
| 70 | − parser.add_option("-f","--function", | |
| 71 | − action="store_true", dest="func", default=False, | |
| 72 | − help="print detection function") | |
| 73 | − parser.add_option("-n","--no-onsets", | |
| 74 | − action="store_true", dest="nplot", default=False, | |
| 75 | − help="do not plot detected onsets") | |
| 76 | − parser.add_option("-O","--outplot", | |
| 77 | − action="store", dest="outplot", default=None, | |
| 78 | − help="save plot to output.{ps,png}") | |
| 79 | − parser.add_option("-F","--spectrogram", | |
| 80 | − action="store_true", dest="spectro", default=False, | |
| 81 | − help="add spectrogram to the plot") | |
| 82 | − parser.add_option("-v","--verbose", | |
| 83 | − action="store_true", dest="verbose", default=True, | |
| 84 | − help="make lots of noise [default]") | |
| 85 | − parser.add_option("-q","--quiet", | |
| 86 | − action="store_false", dest="verbose", default=True, | |
| 87 | − help="be quiet") | |
| 88 | − # to be implemented | |
| 89 | − parser.add_option("-b","--beat", | |
| 90 | − action="store_true", dest="beat", default=False, | |
| 91 | − help="output beat locations") | |
| 92 | − (options, args) = parser.parse_args() | |
| 93 | − if not options.filename: | |
| 94 | − print "no file name given\n", usage | |
| 95 | − sys.exit(1) | |
| 96 | − return options, args | |
| 97 | − | |
| 98 | −options, args = parse_args() | |
| 99 | − | |
| 100 | −filename = options.filename | |
| 101 | −params = taskparams() | |
| 102 | −params.hopsize = int(options.hopsize) | |
| 103 | −params.bufsize = int(options.bufsize) | |
| 104 | −params.threshold = float(options.threshold) | |
| 105 | −params.dcthreshold = float(options.dcthreshold) | |
| 106 | −params.zerothres = float(options.zerothres) | |
| 107 | −params.silence = float(options.silence) | |
| 108 | −params.mintol = float(options.mintol) | |
| 109 | −params.verbose = options.verbose | |
| 110 | −# default take back system delay | |
| 111 | −if options.delay: params.delay = int(float(options.delay)/params.step) | |
| 112 | − | |
| 113 | −dotask = taskonset | |
| 114 | −if options.beat: | |
| 115 | − dotask = taskbeat | |
| 116 | −elif options.silencecut: | |
| 117 | − dotask = tasksilence | |
| 118 | −elif options.plot or options.func: | |
| 119 | − params.storefunc=True | |
| 120 | −else: | |
| 121 | − params.storefunc=False | |
| 122 | − | |
| 123 | −lonsets, lofunc = [], [] | |
| 124 | −wplot,oplots = [],[] | |
| 125 | −modes = options.mode.split(',') | |
| 126 | −for i in range(len(modes)): | |
| 127 | − params.onsetmode = modes[i] | |
| 128 | − filetask = dotask(filename,params=params) | |
| 129 | − onsets = filetask.compute_all() | |
| 130 | − | |
| 131 | − #lonsets.append(onsets) | |
| 132 | − if not options.silencecut: | |
| 133 | − ofunc = filetask.ofunc | |
| 134 | − lofunc.append(ofunc) | |
| 135 | − | |
| 136 | − if options.plot: | |
| 137 | − if options.beat: | |
| 138 | − filetask.plot(oplots, onsets) | |
| 139 | − else: | |
| 140 | − filetask.plot(onsets, ofunc, wplot, oplots, nplot=options.nplot) | |
| 141 | − | |
| 142 | − if options.func: | |
| 143 | − for i in ofunc: | |
| 144 | − print i | |
| 145 | − | |
| 146 | −if options.outplot: | |
| 147 | − extension = options.outplot.split('.')[-1] | |
| 148 | − outplot = '.'.join(options.outplot.split('.')[:-1]) | |
| 149 | −else: | |
| 150 | − extension,outplot = None,None | |
| 151 | −if options.plot: filetask.plotplot(wplot, oplots, outplot=outplot, extension=extension, | |
| 152 | − xsize=options.xsize,ysize=options.ysize,spectro=options.spectro) | |
| 153 | − | |
| 154 | −if options.cut: | |
| 155 | − a = taskcut(filename,onsets,params=params) | |
| 156 | − a.compute_all() | |
| @@ -1,86 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −__LICENSE__ = """\ | |
| 4 | − Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | |
| 5 | − | |
| 6 | − This file is part of aubio. | |
| 7 | − | |
| 8 | − aubio is free software: you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU General Public License as published by | |
| 10 | − the Free Software Foundation, either version 3 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − aubio is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 17 | − | |
| 18 | − You should have received a copy of the GNU General Public License | |
| 19 | − along with aubio. If not, see <http://www.gnu.org/licenses/>. | |
| 20 | −""" | |
| 21 | − | |
| 22 | −__HELP__ = """\ | |
| 23 | −# required arguments | |
| 24 | − -c targetfilename | |
| 25 | − -o detectfilename | |
| 26 | −(both must be text files with 1 time a line expressed in seconds) | |
| 27 | − | |
| 28 | −# optional arguments | |
| 29 | − -D <delay> delay in seconds | |
| 30 | − -v verbose mode | |
| 31 | − -d debug mode | |
| 32 | − | |
| 33 | −# output | |
| 34 | −results:number of correct detections | |
| 35 | − number of incorrect detections | |
| 36 | − number of doubled detections | |
| 37 | − number of total detections | |
| 38 | − number of total targets | |
| 39 | − | |
| 40 | −# example: | |
| 41 | −$ aubioonset-comp -c checked-onsets.txt -o handlab-onsets.txt -v | |
| 42 | −( gd fp dd ) tot / real | |
| 43 | −( 5 4 0 ) 9 / 9 | |
| 44 | −55.5555555556 %GD 44.4444444444 %FP 0.0 %OD | |
| 45 | − | |
| 46 | −# bugs | |
| 47 | −does not scale to very long lists | |
| 48 | −""" | |
| 49 | − | |
| 50 | −import sys | |
| 51 | −from aubio.onsetcompare import onset_diffs | |
| 52 | −from aubio.txtfile import read_datafile | |
| 53 | − | |
| 54 | −# default values | |
| 55 | −fileo=None;filec=None;vmode=None;dmode=None;delay=0. | |
| 56 | −# default tolerance is 50 ms | |
| 57 | −#tol = 0.050 | |
| 58 | −tol = 0.048 | |
| 59 | − | |
| 60 | −while len(sys.argv) >=2: | |
| 61 | − option = sys.argv[1]; del sys.argv[1] | |
| 62 | − if option == '-h': print __HELP__; sys.exit() | |
| 63 | − if option == '-o': fileo = sys.argv[1]; del sys.argv[1] | |
| 64 | − if option == '-c': filec = sys.argv[1]; del sys.argv[1] | |
| 65 | − if option == '-v': vmode = 'verbose' | |
| 66 | − if option == '-d': dmode = 'debug' | |
| 67 | − if option == '-D': delay = float(sys.argv[1]); del sys.argv[1] | |
| 68 | − if option == '-tol': tol = float(sys.argv[1]); del sys.argv[1] | |
| 69 | − | |
| 70 | −# arguments required | |
| 71 | −if (not fileo) or (not filec): | |
| 72 | − print 'wrong set of arguments. use \'-h\' for help' | |
| 73 | − sys.exit('error: needs at least \'-c targets.txt -o detected.txt\'') | |
| 74 | − | |
| 75 | −# load files | |
| 76 | −ltru, lres = read_datafile(fileo,depth=0),read_datafile(filec,depth=0) | |
| 77 | − | |
| 78 | −# delay onsets as required with -D | |
| 79 | −if delay: | |
| 80 | − for i in range(len(lres)): | |
| 81 | − lres[i] = lres[i] + delay | |
| 82 | −# compute errors types | |
| 83 | −l = onset_diffs(ltru,lres,tol) | |
| 84 | −# print with 1ms precision | |
| 85 | −for i in l: print "%.3f" % float(i) | |
| 86 | − | |
| @@ -1,94 +0,0 @@ | ||
| 1 | −#!/usr/bin/python | |
| 2 | − | |
| 3 | −""" this file is used to get filter the (old) output format of aubionotes """ | |
| 4 | − | |
| 5 | −# default parameters | |
| 6 | −__eps = [0.250,0.50] # minimum length, pitch tolerance (ms,midipitch) | |
| 7 | −__plot = 0 # -P (command line switch) | |
| 8 | −__delay = 0.0 # -D <value> (fixed delay for score alignement) | |
| 9 | −__winlength = 10 # -w <value> (window length for pitch estimation in frames) | |
| 10 | − | |
| 11 | −import getopt | |
| 12 | −import sys | |
| 13 | − | |
| 14 | −def parse_args (sysargs): | |
| 15 | − from getopt import gnu_getopt | |
| 16 | − shortopts ='i:o:t:p:w:D:P:' | |
| 17 | − longopts =('input=','output=','tolpitch=','toltime=','winlength=','delay','plot=') | |
| 18 | − args,tmp = gnu_getopt(sysargs,shortopts,longopts) | |
| 19 | − assert len(args) > 1 | |
| 20 | − plot = __plot | |
| 21 | − delay = __delay | |
| 22 | − eps = __eps | |
| 23 | − winlength = __winlength | |
| 24 | − plot = __plot | |
| 25 | − fileout = '/tmp/testprint.ps' | |
| 26 | − args.sort() | |
| 27 | − for i in range(len(args)): # a bad way | |
| 28 | − if args[i][0] == '-i' or args[i][0] == '--input': | |
| 29 | − fileorg = args[i][1] | |
| 30 | − if args[i][0] == '-o' or args[i][0] == '--output': | |
| 31 | − fileerr = args[i][1] | |
| 32 | − if args[i][0] == '-t' or args[i][0] == '--toltime': | |
| 33 | − eps[0] = float(args[i][1]) | |
| 34 | − if args[i][0] == '-p' or args[i][0] == '--tolpitch': | |
| 35 | − eps[1] = float(args[i][1]) | |
| 36 | − if args[i][0] == '-D' or args[i][0] == '--delay': | |
| 37 | − delay = float(args[i][1]) | |
| 38 | − if args[i][0] == '-w' or args[i][0] == '--winlength': | |
| 39 | − winlength = int(args[i][1]) | |
| 40 | − if args[i][0] == '-P' or args[i][0] == '--plot': | |
| 41 | − plot = 1 | |
| 42 | − fileout = args[i][1] | |
| 43 | − return fileorg,fileerr,eps,winlength,plot,delay,fileout | |
| 44 | − | |
| 45 | −def usage(): | |
| 46 | − print __file__, "with at least some arguments" | |
| 47 | − | |
| 48 | −def main(): | |
| 49 | − try: | |
| 50 | − opts,args = getopt.getopt(sys.argv[1:], | |
| 51 | − "hvo:i:p:P", | |
| 52 | − ["help", "output=", "verbose", "input=", "plot="]) | |
| 53 | − except getopt.GetoptError: | |
| 54 | − usage() | |
| 55 | − sys.exit(2) | |
| 56 | − | |
| 57 | − input = None | |
| 58 | − output = None | |
| 59 | − verbose = False | |
| 60 | − winlength = __winlength | |
| 61 | − plot = __plot | |
| 62 | − eps = __eps | |
| 63 | − | |
| 64 | − for o, a in opts: | |
| 65 | − if o in ("-v", "--verbose"): | |
| 66 | − verbose = True | |
| 67 | − if o in ("-h", "--help"): | |
| 68 | − usage() | |
| 69 | − sys.exit(2) | |
| 70 | − if o in ("--output"): | |
| 71 | − output = a | |
| 72 | − if o in ("-i", "--input"): | |
| 73 | − input = a | |
| 74 | − if o in ("-P", "--plot"): | |
| 75 | − plot = 1 | |
| 76 | − | |
| 77 | − assert input != None and input != "", "no input file" | |
| 78 | − | |
| 79 | − from aubio import notefilter,txtfile,gnuplot | |
| 80 | − """ load midi and raw data """ | |
| 81 | − from numpy import array | |
| 82 | − notelist = array(txtfile.read_datafile(input)) | |
| 83 | − """ filter it out """ | |
| 84 | − notelist_filtered = notefilter.segraw_onsets4(notelist,winlength,eps) | |
| 85 | − if verbose == 1 : | |
| 86 | − for a,b in notelist_filtered: | |
| 87 | − print a,b | |
| 88 | − """ plot results """ | |
| 89 | − if plot == 1 : | |
| 90 | − gnuplot.plotnote(notelist_filtered,title=input,fileout=output) | |
| 91 | − | |
| 92 | −if __name__ == "__main__": | |
| 93 | − main() | |
| 94 | − | |
| @@ -0,0 +1,141 @@ | ||
| 1 | +#! /usr/bin/python | |
| 2 | + | |
| 3 | +import pygst | |
| 4 | +pygst.require('0.10') | |
| 5 | +import gst | |
| 6 | +import gobject | |
| 7 | +gobject.threads_init () | |
| 8 | + | |
| 9 | +def gst_buffer_to_numpy_array(buffer, chan): | |
| 10 | + import numpy | |
| 11 | + samples = numpy.frombuffer(buffer.data, dtype=numpy.float32) | |
| 12 | + if chan == 1: | |
| 13 | + return samples.T | |
| 14 | + else: | |
| 15 | + samples.resize([len(samples)/chan, chan]) | |
| 16 | + return samples.T | |
| 17 | + | |
| 18 | +class AubioSink(gst.BaseSink): | |
| 19 | + _caps = gst.caps_from_string('audio/x-raw-float, \ | |
| 20 | + rate=[ 1, 2147483647 ], \ | |
| 21 | + channels=[ 1, 2147483647 ], \ | |
| 22 | + endianness={ 1234, 4321 }, \ | |
| 23 | + width=32') | |
| 24 | + | |
| 25 | + __gsttemplates__ = ( | |
| 26 | + gst.PadTemplate ("sink", | |
| 27 | + gst.PAD_SINK, | |
| 28 | + gst.PAD_ALWAYS, | |
| 29 | + _caps), | |
| 30 | + ) | |
| 31 | + | |
| 32 | + def __init__(self, name, process): | |
| 33 | + self.__gobject_init__() | |
| 34 | + self.set_name(name) | |
| 35 | + self.process = process | |
| 36 | + self.adapter = gst.Adapter() | |
| 37 | + self.set_property('sync', False) | |
| 38 | + self.pos = 0 | |
| 39 | + | |
| 40 | + def set_property(self, name, value): | |
| 41 | + if name == 'hopsize': | |
| 42 | + # blocksize is in byte, convert from hopsize | |
| 43 | + from struct import calcsize | |
| 44 | + self.set_property('blocksize', value * calcsize('f')) | |
| 45 | + else: | |
| 46 | + super(gst.BaseSink, self).set_property(name, value) | |
| 47 | + | |
| 48 | + def do_render(self, buffer): | |
| 49 | + blocksize = self.get_property('blocksize') | |
| 50 | + caps = buffer.get_caps() | |
| 51 | + chan = caps[0]['channels'] | |
| 52 | + self.adapter.push(buffer) | |
| 53 | + while self.adapter.available() >= blocksize: | |
| 54 | + block = self.adapter.take_buffer(blocksize) | |
| 55 | + v = gst_buffer_to_numpy_array(block, chan) | |
| 56 | + if self.process: | |
| 57 | + self.process(v, self.pos) | |
| 58 | + self.pos += 1 | |
| 59 | + remaining = self.adapter.available() | |
| 60 | + if remaining < blocksize and remaining > 0: | |
| 61 | + block = self.adapter.take_buffer(remaining) | |
| 62 | + v = gst_buffer_to_numpy_array(block, chan) | |
| 63 | + if self.process: | |
| 64 | + self.process(v, self.pos) | |
| 65 | + self.pos += 1 | |
| 66 | + return gst.FLOW_OK | |
| 67 | + | |
| 68 | +gobject.type_register(AubioSink) | |
| 69 | + | |
| 70 | +class aubioinput(gst.Bin): | |
| 71 | + | |
| 72 | + ret = 0 | |
| 73 | + | |
| 74 | + def __init__(self, uri, process = None, hopsize = 512, | |
| 75 | + caps = None): | |
| 76 | + if uri.startswith('/'): | |
| 77 | + from urllib import quote | |
| 78 | + uri = 'file://'+quote(uri) | |
| 79 | + src = gst.element_factory_make('uridecodebin') | |
| 80 | + src.set_property('uri', uri) | |
| 81 | + src.connect('pad-added', self.source_pad_added_cb) | |
| 82 | + conv = gst.element_factory_make('audioconvert') | |
| 83 | + self.conv = conv | |
| 84 | + rsmpl = gst.element_factory_make('audioresample') | |
| 85 | + capsfilter = gst.element_factory_make('capsfilter') | |
| 86 | + if caps: | |
| 87 | + capsfilter.set_property('caps', gst.caps_from_string(caps)) | |
| 88 | + sink = AubioSink("AubioSink", process = process) | |
| 89 | + sink.set_property('hopsize', hopsize) # * calcsize('f')) | |
| 90 | + | |
| 91 | + self.pipeline = gst.Pipeline() | |
| 92 | + | |
| 93 | + self.bus = self.pipeline.get_bus() | |
| 94 | + self.bus.add_signal_watch() | |
| 95 | + self.bus.connect('message', self.on_eos) | |
| 96 | + | |
| 97 | + self.apad = conv.get_pad('sink') | |
| 98 | + | |
| 99 | + self.pipeline.add(src, conv, rsmpl, capsfilter, sink) | |
| 100 | + | |
| 101 | + gst.element_link_many(conv, rsmpl, capsfilter, sink) | |
| 102 | + | |
| 103 | + self.mainloop = gobject.MainLoop() | |
| 104 | + self.pipeline.set_state(gst.STATE_PLAYING) | |
| 105 | + | |
| 106 | + def run(self): | |
| 107 | + self.mainloop.run() | |
| 108 | + return self.ret | |
| 109 | + | |
| 110 | + def source_pad_added_cb(self, src, pad): | |
| 111 | + name = pad.get_caps()[0].get_name() | |
| 112 | + if name == 'audio/x-raw-float' or name == 'audio/x-raw-int': | |
| 113 | + pad.link(self.conv.get_pad("sink")) | |
| 114 | + | |
| 115 | + def source_pad_removed_cb(self, src, pad): | |
| 116 | + pad.unlink(self.conv.get_pad("sink")) | |
| 117 | + | |
| 118 | + def on_eos(self, bus, msg): | |
| 119 | + if msg.type == gst.MESSAGE_EOS: | |
| 120 | + self.bus.remove_signal_watch() | |
| 121 | + self.pipeline.set_state(gst.STATE_PAUSED) | |
| 122 | + self.mainloop.quit() | |
| 123 | + elif msg.type == gst.MESSAGE_ERROR: | |
| 124 | + print "ERROR", msg.parse_error() | |
| 125 | + self.bus.remove_signal_watch() | |
| 126 | + self.pipeline.set_state(gst.STATE_PAUSED) | |
| 127 | + self.mainloop.quit() | |
| 128 | + self.ret = 1 # set return value to 1 in case of error | |
| 129 | + | |
| 130 | +if __name__ == '__main__': | |
| 131 | + import sys | |
| 132 | + if len(sys.argv) < 2: | |
| 133 | + print "Usage: %s <filename>" % sys.argv[0] | |
| 134 | + sys.exit(1) | |
| 135 | + for filename in sys.argv[1:]: | |
| 136 | + peak = [0.] # use a mutable | |
| 137 | + def process(buf, hop): | |
| 138 | + peak[0] = max( peak[0], abs(buf.max()) ) | |
| 139 | + a = aubioinput(filename, process = process, hopsize = 512) | |
| 140 | + if a.run() == 0: # only display the results if no | |
| 141 | + print "Finished reading %s, peak value is %f" % (filename, max(peak)) | |
| @@ -0,0 +1,161 @@ | ||
| 1 | +#include <Python.h> | |
| 2 | +#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API | |
| 3 | +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION | |
| 4 | +#include <numpy/arrayobject.h> | |
| 5 | + | |
| 6 | +#include "aubio-types.h" | |
| 7 | +#include "generated/aubio-generated.h" | |
| 8 | + | |
| 9 | +static char Py_alpha_norm_doc[] = "compute alpha normalisation factor"; | |
| 10 | + | |
| 11 | +static PyObject * | |
| 12 | +Py_alpha_norm (PyObject * self, PyObject * args) | |
| 13 | +{ | |
| 14 | + PyObject *input; | |
| 15 | + fvec_t *vec; | |
| 16 | + smpl_t alpha; | |
| 17 | + PyObject *result; | |
| 18 | + | |
| 19 | + if (!PyArg_ParseTuple (args, "Of:alpha_norm", &input, &alpha)) { | |
| 20 | + return NULL; | |
| 21 | + } | |
| 22 | + | |
| 23 | + if (input == NULL) { | |
| 24 | + return NULL; | |
| 25 | + } | |
| 26 | + | |
| 27 | + vec = PyAubio_ArrayToCFvec (input); | |
| 28 | + | |
| 29 | + if (vec == NULL) { | |
| 30 | + return NULL; | |
| 31 | + } | |
| 32 | + | |
| 33 | + // compute the function | |
| 34 | + result = Py_BuildValue ("f", fvec_alpha_norm (vec, alpha)); | |
| 35 | + if (result == NULL) { | |
| 36 | + return NULL; | |
| 37 | + } | |
| 38 | + | |
| 39 | + return result; | |
| 40 | +} | |
| 41 | + | |
| 42 | +static char Py_zero_crossing_rate_doc[] = "compute zero crossing rate"; | |
| 43 | + | |
| 44 | +static PyObject * | |
| 45 | +Py_zero_crossing_rate (PyObject * self, PyObject * args) | |
| 46 | +{ | |
| 47 | + PyObject *input; | |
| 48 | + fvec_t *vec; | |
| 49 | + PyObject *result; | |
| 50 | + | |
| 51 | + if (!PyArg_ParseTuple (args, "O:zero_crossing_rate", &input)) { | |
| 52 | + return NULL; | |
| 53 | + } | |
| 54 | + | |
| 55 | + if (input == NULL) { | |
| 56 | + return NULL; | |
| 57 | + } | |
| 58 | + | |
| 59 | + vec = PyAubio_ArrayToCFvec (input); | |
| 60 | + | |
| 61 | + if (vec == NULL) { | |
| 62 | + return NULL; | |
| 63 | + } | |
| 64 | + | |
| 65 | + // compute the function | |
| 66 | + result = Py_BuildValue ("f", aubio_zero_crossing_rate (vec)); | |
| 67 | + if (result == NULL) { | |
| 68 | + return NULL; | |
| 69 | + } | |
| 70 | + | |
| 71 | + return result; | |
| 72 | +} | |
| 73 | + | |
| 74 | +static char Py_min_removal_doc[] = "compute zero crossing rate"; | |
| 75 | + | |
| 76 | +static PyObject * | |
| 77 | +Py_min_removal(PyObject * self, PyObject * args) | |
| 78 | +{ | |
| 79 | + PyObject *input; | |
| 80 | + fvec_t *vec; | |
| 81 | + | |
| 82 | + if (!PyArg_ParseTuple (args, "O:min_removal", &input)) { | |
| 83 | + return NULL; | |
| 84 | + } | |
| 85 | + | |
| 86 | + if (input == NULL) { | |
| 87 | + return NULL; | |
| 88 | + } | |
| 89 | + | |
| 90 | + vec = PyAubio_ArrayToCFvec (input); | |
| 91 | + | |
| 92 | + if (vec == NULL) { | |
| 93 | + return NULL; | |
| 94 | + } | |
| 95 | + | |
| 96 | + // compute the function | |
| 97 | + fvec_min_removal (vec); | |
| 98 | + | |
| 99 | + // since this function does not return, we could return None | |
| 100 | + //return Py_None; | |
| 101 | + // however it is convenient to return the modified vector | |
| 102 | + return (PyObject *) PyAubio_CFvecToArray(vec); | |
| 103 | + // or even without converting it back to an array | |
| 104 | + //Py_INCREF(vec); | |
| 105 | + //return (PyObject *)vec; | |
| 106 | +} | |
| 107 | + | |
| 108 | +static PyMethodDef aubio_methods[] = { | |
| 109 | + {"alpha_norm", Py_alpha_norm, METH_VARARGS, Py_alpha_norm_doc}, | |
| 110 | + {"zero_crossing_rate", Py_zero_crossing_rate, METH_VARARGS, | |
| 111 | + Py_zero_crossing_rate_doc}, | |
| 112 | + {"min_removal", Py_min_removal, METH_VARARGS, Py_min_removal_doc}, | |
| 113 | + {NULL, NULL} /* Sentinel */ | |
| 114 | +}; | |
| 115 | + | |
| 116 | +static char aubio_module_doc[] = "Python module for the aubio library"; | |
| 117 | + | |
| 118 | +PyMODINIT_FUNC | |
| 119 | +init_aubio (void) | |
| 120 | +{ | |
| 121 | + PyObject *m; | |
| 122 | + int err; | |
| 123 | + | |
| 124 | + if ( (PyType_Ready (&Py_cvecType) < 0) | |
| 125 | + || (PyType_Ready (&Py_filterType) < 0) | |
| 126 | + || (PyType_Ready (&Py_filterbankType) < 0) | |
| 127 | + || (PyType_Ready (&Py_fftType) < 0) | |
| 128 | + || (PyType_Ready (&Py_pvocType) < 0) | |
| 129 | + // generated objects | |
| 130 | + || (generated_types_ready() < 0 ) | |
| 131 | + ) { | |
| 132 | + return; | |
| 133 | + } | |
| 134 | + | |
| 135 | + m = Py_InitModule3 ("_aubio", aubio_methods, aubio_module_doc); | |
| 136 | + | |
| 137 | + if (m == NULL) { | |
| 138 | + return; | |
| 139 | + } | |
| 140 | + | |
| 141 | + err = _import_array (); | |
| 142 | + | |
| 143 | + if (err != 0) { | |
| 144 | + fprintf (stderr, | |
| 145 | + "Unable to import Numpy C API from aubio module (error %d)\n", err); | |
| 146 | + } | |
| 147 | + | |
| 148 | + Py_INCREF (&Py_cvecType); | |
| 149 | + PyModule_AddObject (m, "cvec", (PyObject *) & Py_cvecType); | |
| 150 | + Py_INCREF (&Py_filterType); | |
| 151 | + PyModule_AddObject (m, "digital_filter", (PyObject *) & Py_filterType); | |
| 152 | + Py_INCREF (&Py_filterbankType); | |
| 153 | + PyModule_AddObject (m, "filterbank", (PyObject *) & Py_filterbankType); | |
| 154 | + Py_INCREF (&Py_fftType); | |
| 155 | + PyModule_AddObject (m, "fft", (PyObject *) & Py_fftType); | |
| 156 | + Py_INCREF (&Py_pvocType); | |
| 157 | + PyModule_AddObject (m, "pvoc", (PyObject *) & Py_pvocType); | |
| 158 | + | |
| 159 | + // generated objects | |
| 160 | + add_generated_objects(m); | |
| 161 | +} | |
| @@ -1,79 +0,0 @@ | ||
| 1 | −#!/usr/bin/python | |
| 2 | − | |
| 3 | −def do(filein,threshold): | |
| 4 | − | |
| 5 | − import aubio.aubioclass | |
| 6 | − import aubio.median | |
| 7 | − from math import floor | |
| 8 | − hopsize = 512 | |
| 9 | − bufsize = 4096 | |
| 10 | − channels = 1 | |
| 11 | − frameread = 0 | |
| 12 | − silthres = -80. | |
| 13 | − filei = aubio.aubioclass.sndfile(filein) | |
| 14 | − srate = filei.samplerate() | |
| 15 | − myvec = aubio.aubioclass.fvec(hopsize,channels) | |
| 16 | − readsize = filei.read(hopsize,myvec) | |
| 17 | − ppick = aubio.aubioclass.pitchpick(bufsize,hopsize,channels,myvec,srate) | |
| 18 | − opick = aubio.aubioclass.onsetpick(bufsize,hopsize,channels,myvec,threshold) | |
| 19 | − mylist = list() | |
| 20 | − | |
| 21 | − wassilence = 0 | |
| 22 | − lastpitch = 0 | |
| 23 | − starttime = 0 | |
| 24 | − while(readsize==hopsize): | |
| 25 | − readsize = filei.read(hopsize,myvec) | |
| 26 | − val = ppick.do(myvec) | |
| 27 | − midival = aubio.aubioclass.bintomidi(val,srate,bufsize) | |
| 28 | − isonset,onset = opick.do(myvec) | |
| 29 | − now = (frameread)*hopsize/(srate+0.) | |
| 30 | − issilence = aubio.aubioclass.aubio_silence_detection(myvec.vec,silthres) | |
| 31 | − | |
| 32 | − estmidival = 0 | |
| 33 | − if (issilence == 1): | |
| 34 | − if (wassilence == 0): | |
| 35 | − #outputnow | |
| 36 | − endtime = (frameread-3)*hopsize/(srate+0.) | |
| 37 | − if len(mylist) > 5 : | |
| 38 | − estmidival = aubio.median.percental(mylist,len(mylist)/2) | |
| 39 | − print "sil", starttime, endtime, estmidival | |
| 40 | − #resetnow | |
| 41 | − mylist = list() | |
| 42 | − else: | |
| 43 | − wassilence = 1 | |
| 44 | − else: | |
| 45 | − if isonset == 1: | |
| 46 | − if (wassilence == 0): | |
| 47 | − #outputnow | |
| 48 | − endtime = (frameread-3)*hopsize/(srate+0.) | |
| 49 | − #estmidival = aubio.median.percental(around(array(mylist)),len(mylist)//2) | |
| 50 | − if len(mylist) > 5 : | |
| 51 | − estmidival = aubio.median.percental(mylist,len(mylist)/2) | |
| 52 | − print starttime, endtime, estmidival | |
| 53 | − #resetnow | |
| 54 | − mylist = list() | |
| 55 | − #store start time | |
| 56 | − starttime = (frameread-3)*hopsize/(srate+0.) | |
| 57 | − else: | |
| 58 | − """ | |
| 59 | − if(listfull): | |
| 60 | − #outputnow | |
| 61 | − endtime = (frameread-3)*hopsize/(srate+0.) | |
| 62 | − print starttime, endtime, estimmidival | |
| 63 | − else: | |
| 64 | − """ | |
| 65 | − #bufferize | |
| 66 | − if midival > 50 and midival < 75: | |
| 67 | − mylist.append(floor(midival)) | |
| 68 | − wassilence = 0 | |
| 69 | − | |
| 70 | − | |
| 71 | − #elif( midival > 45 ): | |
| 72 | − # mylist.append(( now , midival+12 )) | |
| 73 | − #mylist.append(toappend) | |
| 74 | − frameread += 1 | |
| 75 | − | |
| 76 | − | |
| 77 | −if __name__ == "__main__": | |
| 78 | − import sys | |
| 79 | − do(sys.argv[1],sys.argv[2]) | |
| @@ -1,131 +0,0 @@ | ||
| 1 | −#!/usr/bin/python | |
| 2 | − | |
| 3 | −""" this file was written by Paul Brossier | |
| 4 | − it is released under the GNU/GPL license. | |
| 5 | −""" | |
| 6 | − | |
| 7 | −import sys | |
| 8 | −from aubio.task import * | |
| 9 | − | |
| 10 | −usage = "usage: %s [options] -i soundfile" % sys.argv[0] | |
| 11 | − | |
| 12 | − | |
| 13 | −def parse_args(): | |
| 14 | − from optparse import OptionParser | |
| 15 | − parser = OptionParser(usage=usage) | |
| 16 | − parser.add_option("-i","--input", | |
| 17 | − action="store", dest="filename", | |
| 18 | − help="input sound file") | |
| 19 | − parser.add_option("-m","--mode", | |
| 20 | − action="store", dest="mode", default='yinfft', | |
| 21 | − help="pitch detection mode [default=mcomb] \ | |
| 22 | − mcomb|yin|fcomb|schmitt") | |
| 23 | − parser.add_option("-u","--units", | |
| 24 | − action="store", dest="omode", default="freq", | |
| 25 | − help="output pitch in units [default=Hz] \ | |
| 26 | − freq|midi|cent|bin") | |
| 27 | − parser.add_option("-B","--bufsize", | |
| 28 | − action="store", dest="bufsize", default=None, | |
| 29 | − help="buffer size [default=2048]") | |
| 30 | − parser.add_option("-H","--hopsize", | |
| 31 | − action="store", dest="hopsize", default=None, | |
| 32 | − help="overlap size [default=512]") | |
| 33 | − parser.add_option("-t","--threshold", | |
| 34 | − action="store", dest="threshold", default=0.1, | |
| 35 | − help="pitch threshold (for yin) [default=0.1]") | |
| 36 | − parser.add_option("-s","--silence", | |
| 37 | − action="store", dest="silence", default=-70, | |
| 38 | − help="silence threshold [default=-70]") | |
| 39 | − parser.add_option("-D","--delay", | |
| 40 | − action="store", dest="delay", | |
| 41 | − help="number of seconds frames to take back [default=0]") | |
| 42 | − parser.add_option("-S","--smoothing", | |
| 43 | − action="store", dest="smoothing", default=False, | |
| 44 | − help="use a median filter of N frames [default=0]") | |
| 45 | − parser.add_option("-M","--maximum", | |
| 46 | − action="store", dest="pitchmax", default=False, | |
| 47 | − help="maximum pitch value to look for (Hz) [default=20000]") | |
| 48 | − parser.add_option("-l","--minimum", | |
| 49 | − action="store", dest="pitchmin", default=False, | |
| 50 | − help="minimum pitch value to look for (Hz) [default=20]") | |
| 51 | − # to be implemented | |
| 52 | − parser.add_option("-n","--note", | |
| 53 | − action="store_true", dest="note", default=False, | |
| 54 | − help="NOT IMPLEMENTED output notes") | |
| 55 | − # plotting functions | |
| 56 | − parser.add_option("-T","--plottruth", | |
| 57 | − action="store_true", dest="plottruth", default=False, | |
| 58 | − help="draw plot of the ground truth pitch track") | |
| 59 | − parser.add_option("-p","--plot", | |
| 60 | − action="store_true", dest="plot", default=False, | |
| 61 | − help="draw plot of the pitch track") | |
| 62 | − parser.add_option("-x","--xsize", | |
| 63 | − action="store", dest="xsize", default=1., | |
| 64 | − type='float', help="define xsize for plot") | |
| 65 | − parser.add_option("-y","--ysize", | |
| 66 | − action="store", dest="ysize", default=1., | |
| 67 | − type='float', help="define ysize for plot") | |
| 68 | − parser.add_option("-O","--outplot", | |
| 69 | − action="store", dest="outplot", default=None, | |
| 70 | − help="save the plot to output.{ps,png,svg} instead of displaying it") | |
| 71 | − parser.add_option("-v","--verbose", | |
| 72 | − action="store_true", dest="verbose", default=True, | |
| 73 | − help="make lots of noise") | |
| 74 | − parser.add_option("-q","--quiet", | |
| 75 | − action="store_false", dest="verbose", default=True, | |
| 76 | − help="be quiet") | |
| 77 | − (options, args) = parser.parse_args() | |
| 78 | − if not options.bufsize: | |
| 79 | − if options.mode == "yin": options.bufsize = 1024 | |
| 80 | − if options.mode == "schmitt": options.bufsize = 2048 | |
| 81 | − if options.mode == "mcomb": options.bufsize = 4096 | |
| 82 | − if options.mode == "fcomb": options.bufsize = 4096 | |
| 83 | − else: options.bufsize = 2048 | |
| 84 | − if not options.hopsize: | |
| 85 | − options.hopsize = float(options.bufsize) / 2 | |
| 86 | − if not options.filename: | |
| 87 | − print "no file name given\n", usage | |
| 88 | − sys.exit(1) | |
| 89 | − return options, args | |
| 90 | − | |
| 91 | −options, args = parse_args() | |
| 92 | − | |
| 93 | −#print options.bufsize, options.hopsize | |
| 94 | − | |
| 95 | −filename = options.filename | |
| 96 | −params = taskparams() | |
| 97 | −params.samplerate = float(sndfile(filename).samplerate()) | |
| 98 | −params.hopsize = int(options.hopsize) | |
| 99 | −params.bufsize = int(options.bufsize) | |
| 100 | −params.step = params.samplerate/float(params.hopsize) | |
| 101 | −params.yinthresh = float(options.threshold) | |
| 102 | −params.silence = float(options.silence) | |
| 103 | −params.verbose = options.verbose | |
| 104 | −if options.smoothing: params.pitchsmooth = int(options.smoothing) | |
| 105 | −if options.pitchmax: params.pitchmax = int(options.pitchmax) | |
| 106 | −if options.pitchmin: params.pitchmin = int(options.pitchmin) | |
| 107 | −#mintol = float(options.mintol)*step | |
| 108 | −# default take back system delay | |
| 109 | −if options.delay: params.pitchdelay = float(options.delay) | |
| 110 | − | |
| 111 | −if options.note: | |
| 112 | − exit("not implemented yet") | |
| 113 | − | |
| 114 | −wplot,oplots,titles = [],[],[] | |
| 115 | −modes = options.mode.split(',') | |
| 116 | −for i in range(len(modes)): | |
| 117 | − pitch = [] | |
| 118 | − params.pitchmode = modes[i] | |
| 119 | − filetask = taskpitch(filename,params=params) | |
| 120 | − pitch = filetask.compute_all() | |
| 121 | − #print filetask.eval(pitch[i]) | |
| 122 | − if options.plot: filetask.plot(pitch,wplot,oplots,titles) | |
| 123 | − | |
| 124 | −if options.outplot: | |
| 125 | − extension = options.outplot.split('.')[-1] | |
| 126 | − outplot = '.'.join(options.outplot.split('.')[:-1]) | |
| 127 | −else: | |
| 128 | − extension,outplot = None,None | |
| 129 | −if options.plot: | |
| 130 | − filetask.plotplot(wplot,oplots,titles,outplot=outplot,extension=extension, | |
| 131 | − xsize=options.xsize,ysize=options.ysize,truth=options.plottruth) | |
| @@ -1,31 +0,0 @@ | ||
| 1 | −#!/usr/bin/python | |
| 2 | − | |
| 3 | −import sys | |
| 4 | −from aubio.gnuplot import gnuplot_create,gnuplot_addargs,plot_audio | |
| 5 | − | |
| 6 | −usage = "usage: %s [options] -i soundfile" % sys.argv[0] | |
| 7 | − | |
| 8 | −def parse_args(): | |
| 9 | − from optparse import OptionParser | |
| 10 | − parser = OptionParser(usage=usage) | |
| 11 | − parser.add_option("-i","--input", | |
| 12 | − action="store", dest="filename", | |
| 13 | − help="input sound file") | |
| 14 | − gnuplot_addargs(parser) | |
| 15 | − (options, args) = parser.parse_args() | |
| 16 | − if not options.filename: | |
| 17 | − print "no file name given\n", usage | |
| 18 | − sys.exit(1) | |
| 19 | − return options, args | |
| 20 | − | |
| 21 | −options, args = parse_args() | |
| 22 | − | |
| 23 | −if options.outplot: | |
| 24 | − extension = options.outplot.split('.')[-1] | |
| 25 | − outplot = '.'.join(options.outplot.split('.')[:-1]) | |
| 26 | −else: | |
| 27 | − extension = '' | |
| 28 | − outplot = None | |
| 29 | − | |
| 30 | −g = gnuplot_create(outplot,extension,options) | |
| 31 | −plot_audio(options.filename.split(','), g, options) | |
| @@ -1,31 +0,0 @@ | ||
| 1 | −#!/usr/bin/python | |
| 2 | − | |
| 3 | −def parse_args (sysargs): | |
| 4 | − from getopt import gnu_getopt | |
| 5 | − shortopts ='i:o:' | |
| 6 | − longopts =('input=','output=') | |
| 7 | − args,tmp = gnu_getopt(sysargs,shortopts,longopts) | |
| 8 | − args.sort() | |
| 9 | − filein,fileout= None,None | |
| 10 | − for i in range(len(args)): # a bad way | |
| 11 | − if args[i][0] == '-i' or args[i][0] == '--input': | |
| 12 | − filein = args[i][1] | |
| 13 | − if args[i][0] == '-o' or args[i][0] == '--output': | |
| 14 | − fileout = args[i][1] | |
| 15 | − assert filein != None, 'precise filein' | |
| 16 | − return filein,fileout | |
| 17 | − | |
| 18 | −def main (sysargs) : | |
| 19 | − from aubio.txtfile import read_datafile | |
| 20 | − from aubio.gnuplot import plotnote,plotnote_do | |
| 21 | − from numpy import array | |
| 22 | − filein,fileout = parse_args(sysargs) | |
| 23 | − #print 'checking', fileerr, 'against', fileorg | |
| 24 | − """ load midi and raw data """ | |
| 25 | − d = plotnote(array(read_datafile(filein)),title=filein) | |
| 26 | − plotnote_do(d,fileout=fileout) | |
| 27 | − | |
| 28 | −if __name__ == "__main__": | |
| 29 | − import sys | |
| 30 | − main(sys.argv[1:]) | |
| 31 | − | |
| @@ -1,51 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −""" this file was written by Paul Brossier | |
| 4 | − it is released under the GNU/GPL license. | |
| 5 | −""" | |
| 6 | − | |
| 7 | −import sys | |
| 8 | −from aubio.gnuplot import gnuplot_create,gnuplot_addargs,plot_spec | |
| 9 | − | |
| 10 | −usage = "usage: %s [options] -i soundfile" % sys.argv[0] | |
| 11 | − | |
| 12 | −def parse_args(): | |
| 13 | − from optparse import OptionParser | |
| 14 | − parser = OptionParser(usage=usage) | |
| 15 | − parser.add_option("-i","--input", | |
| 16 | − action="store", dest="filename", | |
| 17 | − help="input sound file") | |
| 18 | − parser.add_option("-M","--maxf", | |
| 19 | − action="store", dest="maxf", default=10000., | |
| 20 | − type='float',help="higher frequency limit") | |
| 21 | − parser.add_option("-L","--minf", | |
| 22 | − action="store", dest="minf", default=0., | |
| 23 | − type='float',help="lower frequency limit") | |
| 24 | − parser.add_option("-l","--log", | |
| 25 | − action="store_true", dest="log", default=False, | |
| 26 | − help="plot on a logarithmic scale") | |
| 27 | − parser.add_option("-B","--bufsize", type='int', | |
| 28 | − action="store", dest="bufsize", default=8192, | |
| 29 | − help="buffer size [default=8192]") | |
| 30 | − parser.add_option("-H","--hopsize", type='int', | |
| 31 | − action="store", dest="hopsize", default=1024, | |
| 32 | − help="overlap size [default=1024]") | |
| 33 | − gnuplot_addargs(parser) | |
| 34 | − (options, args) = parser.parse_args() | |
| 35 | − if not options.filename: | |
| 36 | − print "no file name given\n", usage | |
| 37 | − sys.exit(1) | |
| 38 | − return options, args | |
| 39 | − | |
| 40 | −options, args = parse_args() | |
| 41 | −filename = options.filename | |
| 42 | − | |
| 43 | −if options.outplot: | |
| 44 | − extension = options.outplot.split('.')[-1] | |
| 45 | − outplot = '.'.join(options.outplot.split('.')[:-1]) | |
| 46 | −else: | |
| 47 | − extension = '' | |
| 48 | − outplot = None | |
| 49 | − | |
| 50 | −g = gnuplot_create(outplot,extension,options) | |
| 51 | −plot_spec(filename, g, options) | |
| @@ -1,135 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −""" this file was written by Paul Brossier | |
| 4 | − it is released under the GNU/GPL license. | |
| 5 | −""" | |
| 6 | − | |
| 7 | −import sys,time | |
| 8 | −from aubio.task import task,taskparams | |
| 9 | −from aubio.aubioclass import fvec | |
| 10 | −from aubio.gnuplot import gnuplot_create | |
| 11 | −from aubio.aubiowrapper import * | |
| 12 | − | |
| 13 | −usage = "usage: %s [options] -i soundfile" % sys.argv[0] | |
| 14 | − | |
| 15 | −def parse_args(): | |
| 16 | − from optparse import OptionParser | |
| 17 | − parser = OptionParser(usage=usage) | |
| 18 | − parser.add_option("-i","--input", | |
| 19 | − action="store", dest="filename", | |
| 20 | − help="input sound file") | |
| 21 | − parser.add_option("-n","--printframe", | |
| 22 | − action="store", dest="printframe", default=-1, | |
| 23 | − help="make a plot of the n_th frame") | |
| 24 | − parser.add_option("-x","--xsize", | |
| 25 | − action="store", dest="xsize", default=1., | |
| 26 | − help="define xsize for plot") | |
| 27 | − parser.add_option("-y","--ysize", | |
| 28 | − action="store", dest="ysize", default=1., | |
| 29 | − help="define ysize for plot") | |
| 30 | − parser.add_option("-O","--outplot", | |
| 31 | − action="store", dest="outplot", default=None, | |
| 32 | − help="save plot to output.{ps,png}") | |
| 33 | − (options, args) = parser.parse_args() | |
| 34 | − if not options.filename: | |
| 35 | − print "no file name given\n", usage | |
| 36 | − sys.exit(1) | |
| 37 | − return options, args | |
| 38 | − | |
| 39 | −def plotdata(x,y,plottitle="",**keyw): | |
| 40 | − import Gnuplot | |
| 41 | − return Gnuplot.Data(x, y, title="%s" % plottitle,**keyw) | |
| 42 | − | |
| 43 | −options, args = parse_args() | |
| 44 | −filename = options.filename | |
| 45 | −xsize = float(options.xsize) | |
| 46 | −ysize = float(options.ysize)*2 | |
| 47 | − | |
| 48 | −printframe = int(options.printframe) | |
| 49 | −if printframe == -1: | |
| 50 | − print "Will wait for ^D to skip to next plot" | |
| 51 | − print "Press enter before to print to file" | |
| 52 | − | |
| 53 | − | |
| 54 | −g = gnuplot_create() | |
| 55 | −params = taskparams() | |
| 56 | −params.hopsize = 2048 # 512 | |
| 57 | −params.bufsize = params.hopsize #2048 | |
| 58 | −taskfile = task(filename,params=params) | |
| 59 | − | |
| 60 | −yin = fvec(params.bufsize/2,1) | |
| 61 | − | |
| 62 | −t = [i for i in range(params.bufsize)] | |
| 63 | −a = [0 for i in range(params.bufsize)] | |
| 64 | − | |
| 65 | −while (taskfile.readsize == params.hopsize): | |
| 66 | − taskfile() | |
| 67 | − | |
| 68 | − n = [i for i in range(params.bufsize/2)] | |
| 69 | − a = [taskfile.myvec.get(i,0) for i in range(params.hopsize/2)] | |
| 70 | − aubio_pitchyin_diff(taskfile.myvec(),yin()) # compute d[t] | |
| 71 | − c = [yin.get(i,0) for i in range(params.bufsize/2)] | |
| 72 | − aubio_pitchyin_getcum(yin()) # compute d'[t] | |
| 73 | − y = [yin.get(i,0) for i in range(params.bufsize/2)] | |
| 74 | − thresh = [0.1 for i in range(params.bufsize/2)] | |
| 75 | − #t.append((i/float(params.hopsize)+taskfile.frameread)*params.step),t.pop(0) | |
| 76 | − d = [plotdata(n,a,plottitle="signal", with_='lines'), | |
| 77 | − plotdata(n,c,plottitle="d[t]",axes='x1y2', with_='lines lt 1'), | |
| 78 | − plotdata(n,y,plottitle="d'[t]",axes='x1y1', with_='lines lt 2'), | |
| 79 | − plotdata(n,thresh,plottitle="threshold",axes='x1y1', with_='lines lt 3')] | |
| 80 | − #g('set xrange [%f:%f]' % (t[0],t[-1])) | |
| 81 | − #time.sleep(.2) | |
| 82 | − g.reset() | |
| 83 | − g('set yrange [-1:3]') | |
| 84 | − g('set xrange [0:%d]' % (params.bufsize/2)) | |
| 85 | − g('set title \"%s\"' % "Example of period detection using YIN") | |
| 86 | − if printframe == -1: | |
| 87 | − g.replot(*d) | |
| 88 | − a = sys.stdin.read() | |
| 89 | − if a == "\n" or printframe == taskfile.frameread: | |
| 90 | − from os.path import basename | |
| 91 | − outplot = "_".join([basename(sys.argv[0]),'_'.join(basename(filename).split('.')),"%d" % taskfile.frameread]) | |
| 92 | − print outplot | |
| 93 | − f = gnuplot_create(outplot=outplot,extension='ps') | |
| 94 | − f('set size %f,%f;' % (xsize,ysize) ) | |
| 95 | − f('set lmargin %f' % (15*xsize)) | |
| 96 | − f('set rmargin %f' % (10*xsize)) | |
| 97 | − #f('set title \"%s\"' % "Example of period detection using YIN") | |
| 98 | − f('set multiplot') | |
| 99 | − f.ylabel('amplitude',offset=(+.5,0)) | |
| 100 | − f.xlabel('time (samples)') | |
| 101 | − f('set size %f,%f;' % (xsize,ysize*0.4) ) | |
| 102 | − f('set orig %f,%f;' % (0,ysize*0.6) ) | |
| 103 | − sigmax = max(abs(min(a)),abs(max(a))) | |
| 104 | − f('set yrange [%f:%f]' % (-1.3*sigmax,1.3*sigmax)) | |
| 105 | − f('set xrange [0:%d]' % (params.bufsize/2)) | |
| 106 | − f.plot(d[0]) | |
| 107 | − | |
| 108 | − f.ylabel('') | |
| 109 | − f.xlabel('lag (samples)') | |
| 110 | − f('set bmargin %f' % (4*ysize)) | |
| 111 | − f('set size %f,%f;' % (xsize,ysize*0.6) ) | |
| 112 | − f('set orig %f,%f;' % (0,0) ) | |
| 113 | − f('set autoscale') | |
| 114 | − f('set xrange [0:%d]' % (params.bufsize/2)) | |
| 115 | − f('set notitle') | |
| 116 | − f('set y2tics') | |
| 117 | − f('set ytics nomirror') | |
| 118 | − f('set noytics') | |
| 119 | − f('set key right') | |
| 120 | − f.plot(d[1]) | |
| 121 | − | |
| 122 | − f.ylabel('amplitude') | |
| 123 | − f.xlabel('') | |
| 124 | − f('set y2tics nomirror') | |
| 125 | − f('set ytics nomirror') | |
| 126 | − f('set noy2tics') | |
| 127 | − f('set noxtics') | |
| 128 | − f('set ytics') | |
| 129 | − f('set key left') | |
| 130 | − f.plot(d[2],d[3]) | |
| 131 | − #f('set yrange [-1:3]') | |
| 132 | − #f.plot(*d) | |
| 133 | − print "saved plot", outplot, 'ps' | |
| 134 | − elif printframe < taskfile.frameread: | |
| 135 | − break | |
| @@ -0,0 +1,153 @@ | ||
| 1 | +#include "aubio-types.h" | |
| 2 | + | |
| 3 | +fvec_t * | |
| 4 | +PyAubio_ArrayToCFvec (PyObject *input) { | |
| 5 | + PyObject *array; | |
| 6 | + fvec_t *vec; | |
| 7 | + if (input == NULL) { | |
| 8 | + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); | |
| 9 | + goto fail; | |
| 10 | + } | |
| 11 | + // parsing input object into a Py_fvec | |
| 12 | + if (PyArray_Check(input)) { | |
| 13 | + | |
| 14 | + // we got an array, convert it to an fvec | |
| 15 | + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { | |
| 16 | + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); | |
| 17 | + goto fail; | |
| 18 | + } else if (PyArray_NDIM ((PyArrayObject *)input) > 1) { | |
| 19 | + PyErr_SetString (PyExc_ValueError, | |
| 20 | + "input array has more than one dimensions"); | |
| 21 | + goto fail; | |
| 22 | + } | |
| 23 | + | |
| 24 | + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { | |
| 25 | + PyErr_SetString (PyExc_ValueError, "input array should be float"); | |
| 26 | + goto fail; | |
| 27 | + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { | |
| 28 | + PyErr_SetString (PyExc_ValueError, "input array should be float32"); | |
| 29 | + goto fail; | |
| 30 | + } else { | |
| 31 | + // input data type is float32, nothing else to do | |
| 32 | + array = input; | |
| 33 | + } | |
| 34 | + | |
| 35 | + // vec = new_fvec (vec->length); | |
| 36 | + // no need to really allocate fvec, just its struct member | |
| 37 | + vec = (fvec_t *)malloc(sizeof(fvec_t)); | |
| 38 | + vec->length = PyArray_SIZE ((PyArrayObject *)array); | |
| 39 | + vec->data = (smpl_t *) PyArray_GETPTR1 ((PyArrayObject *)array, 0); | |
| 40 | + | |
| 41 | + } else if (PyObject_TypeCheck (input, &PyList_Type)) { | |
| 42 | + PyErr_SetString (PyExc_ValueError, "does not convert from list yet"); | |
| 43 | + return NULL; | |
| 44 | + } else { | |
| 45 | + PyErr_SetString (PyExc_ValueError, "can only accept vector of float as input"); | |
| 46 | + return NULL; | |
| 47 | + } | |
| 48 | + | |
| 49 | + return vec; | |
| 50 | + | |
| 51 | +fail: | |
| 52 | + return NULL; | |
| 53 | +} | |
| 54 | + | |
| 55 | +PyObject * | |
| 56 | +PyAubio_CFvecToArray (fvec_t * self) | |
| 57 | +{ | |
| 58 | + npy_intp dims[] = { self->length, 1 }; | |
| 59 | + return PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, self->data); | |
| 60 | +} | |
| 61 | + | |
| 62 | +Py_cvec * | |
| 63 | +PyAubio_CCvecToPyCvec (cvec_t * input) { | |
| 64 | + Py_cvec *vec = (Py_cvec*) PyObject_New (Py_cvec, &Py_cvecType); | |
| 65 | + vec->length = input->length; | |
| 66 | + vec->o = input; | |
| 67 | + Py_INCREF(vec); | |
| 68 | + return vec; | |
| 69 | +} | |
| 70 | + | |
| 71 | +cvec_t * | |
| 72 | +PyAubio_ArrayToCCvec (PyObject *input) { | |
| 73 | + if (PyObject_TypeCheck (input, &Py_cvecType)) { | |
| 74 | + return ((Py_cvec*)input)->o; | |
| 75 | + } else { | |
| 76 | + PyErr_SetString (PyExc_ValueError, "input array should be float32"); | |
| 77 | + return NULL; | |
| 78 | + } | |
| 79 | +} | |
| 80 | + | |
| 81 | +PyObject * | |
| 82 | +PyAubio_CFmatToArray (fmat_t * input) | |
| 83 | +{ | |
| 84 | + PyObject *array = NULL; | |
| 85 | + uint_t i; | |
| 86 | + npy_intp dims[] = { input->length, 1 }; | |
| 87 | + PyObject *concat = PyList_New (0), *tmp = NULL; | |
| 88 | + for (i = 0; i < input->height; i++) { | |
| 89 | + tmp = PyArray_SimpleNewFromData (1, dims, AUBIO_NPY_SMPL, input->data[i]); | |
| 90 | + PyList_Append (concat, tmp); | |
| 91 | + Py_DECREF (tmp); | |
| 92 | + } | |
| 93 | + array = PyArray_FromObject (concat, AUBIO_NPY_SMPL, 2, 2); | |
| 94 | + Py_DECREF (concat); | |
| 95 | + return array; | |
| 96 | +} | |
| 97 | + | |
| 98 | +fmat_t * | |
| 99 | +PyAubio_ArrayToCFmat (PyObject *input) { | |
| 100 | + PyObject *array; | |
| 101 | + fmat_t *mat; | |
| 102 | + uint_t i; | |
| 103 | + if (input == NULL) { | |
| 104 | + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); | |
| 105 | + goto fail; | |
| 106 | + } | |
| 107 | + // parsing input object into a Py_fvec | |
| 108 | + if (PyArray_Check(input)) { | |
| 109 | + | |
| 110 | + // we got an array, convert it to an fvec | |
| 111 | + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { | |
| 112 | + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); | |
| 113 | + goto fail; | |
| 114 | + } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { | |
| 115 | + PyErr_SetString (PyExc_ValueError, | |
| 116 | + "input array has more than two dimensions"); | |
| 117 | + goto fail; | |
| 118 | + } | |
| 119 | + | |
| 120 | + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { | |
| 121 | + PyErr_SetString (PyExc_ValueError, "input array should be float"); | |
| 122 | + goto fail; | |
| 123 | + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { | |
| 124 | + PyErr_SetString (PyExc_ValueError, "input array should be float32"); | |
| 125 | + goto fail; | |
| 126 | + } else { | |
| 127 | + // input data type is float32, nothing else to do | |
| 128 | + array = input; | |
| 129 | + } | |
| 130 | + | |
| 131 | + // no need to really allocate fvec, just its struct member | |
| 132 | + mat = (fmat_t *)malloc(sizeof(fmat_t)); | |
| 133 | + mat->length = PyArray_DIM ((PyArrayObject *)array, 1); | |
| 134 | + mat->height = PyArray_DIM ((PyArrayObject *)array, 0); | |
| 135 | + mat->data = (smpl_t **)malloc(sizeof(smpl_t*) * mat->height); | |
| 136 | + for (i=0; i< mat->height; i++) { | |
| 137 | + mat->data[i] = (smpl_t*)PyArray_GETPTR1 ((PyArrayObject *)array, i); | |
| 138 | + } | |
| 139 | + | |
| 140 | + } else if (PyObject_TypeCheck (input, &PyList_Type)) { | |
| 141 | + PyErr_SetString (PyExc_ValueError, "can not convert list to fmat"); | |
| 142 | + return NULL; | |
| 143 | + } else { | |
| 144 | + PyErr_SetString (PyExc_ValueError, "can only accept matrix of float as input"); | |
| 145 | + return NULL; | |
| 146 | + } | |
| 147 | + | |
| 148 | + return mat; | |
| 149 | + | |
| 150 | +fail: | |
| 151 | + return NULL; | |
| 152 | +} | |
| 153 | + | |
| @@ -1,113 +0,0 @@ | ||
| 1 | −#!/usr/bin/python | |
| 2 | − | |
| 3 | −doc = """ | |
| 4 | −This script works with mod_python to browse a collection of annotated wav files | |
| 5 | −and results. | |
| 6 | − | |
| 7 | −you will need to have at least the following packages need to be installed (the | |
| 8 | −name of the command line tool is precised in parenthesis): | |
| 9 | − | |
| 10 | −libapache-mod-python (apache2 prefered) | |
| 11 | −sndfile-programs (sndfile-info) | |
| 12 | −vorbis-tools (oggenc) | |
| 13 | −python-gnuplot | |
| 14 | −python-numpy | |
| 15 | − | |
| 16 | −Try the command line tools in aubio/python to test your installation. | |
| 17 | − | |
| 18 | −NOTE: this script is probably horribly insecure. | |
| 19 | − | |
| 20 | −example configuration for apache to put in your preferred virtual host. | |
| 21 | − | |
| 22 | −<Directory /home/piem/public_html/aubioweb> | |
| 23 | − # Minimal config | |
| 24 | − AddHandler mod_python .py | |
| 25 | − # Disable these in production | |
| 26 | − PythonDebug On | |
| 27 | − PythonAutoReload on | |
| 28 | − # Default handler in url | |
| 29 | − PythonHandler aubioweb | |
| 30 | − ## Authentication stuff (optional) | |
| 31 | − #PythonAuthenHandler aubioweb | |
| 32 | − #AuthType Basic | |
| 33 | − #AuthName "Restricted Area" | |
| 34 | − #require valid-user | |
| 35 | − # make default listing | |
| 36 | − DirectoryIndex aubioweb/ | |
| 37 | −</Directory> | |
| 38 | − | |
| 39 | −""" | |
| 40 | − | |
| 41 | −from aubio.web.html import * | |
| 42 | − | |
| 43 | −def handler(req): | |
| 44 | − from aubio.web.browser import * | |
| 45 | − from mod_python import Session | |
| 46 | − req.sess = Session.Session(req) | |
| 47 | − req.sess['login']='new aubio user' | |
| 48 | − req.sess.save() | |
| 49 | − return configure_handler(req,index) | |
| 50 | − | |
| 51 | −def index(req,threshold='0.3'): | |
| 52 | − navigation(req) | |
| 53 | − print_command(req,"sfinfo %%i") | |
| 54 | − return footer(req) | |
| 55 | − | |
| 56 | −def show_info(req,verbose=''): | |
| 57 | − navigation(req) | |
| 58 | − print_command(req,"sndfile-info %%i") | |
| 59 | − return footer(req) | |
| 60 | − | |
| 61 | −def feedback(req): | |
| 62 | − navigation(req) | |
| 63 | − req.write(""" | |
| 64 | − Please provide feedback below: | |
| 65 | − <p> | |
| 66 | − <form action="/~piem/aubioweb/email" method="POST"> | |
| 67 | − Name: <input type="text" name="name"><br> | |
| 68 | − Email: <input type="text" name="email"><br> | |
| 69 | − Comment: <textarea name="comment" rows=4 cols=20></textarea><br> | |
| 70 | − <input type="submit"> | |
| 71 | − </form> | |
| 72 | − """) | |
| 73 | − | |
| 74 | −WEBMASTER='piem@calabaza' | |
| 75 | −SMTP_SERVER='localhost' | |
| 76 | − | |
| 77 | −def email(req,name,email,comment): | |
| 78 | − import smtplib | |
| 79 | − # make sure the user provided all the parameters | |
| 80 | − if not (name and email and comment): | |
| 81 | − return "A required parameter is missing, \ | |
| 82 | − please go back and correct the error" | |
| 83 | − # create the message text | |
| 84 | − msg = """\ | |
| 85 | −From: %s | |
| 86 | −Subject: feedback | |
| 87 | −To: %s | |
| 88 | − | |
| 89 | −I have the following comment: | |
| 90 | − | |
| 91 | −%s | |
| 92 | − | |
| 93 | −Thank You, | |
| 94 | − | |
| 95 | −%s | |
| 96 | − | |
| 97 | −""" % (email, WEBMASTER, comment, name) | |
| 98 | − # send it out | |
| 99 | − conn = smtplib.SMTP(SMTP_SERVER) | |
| 100 | − try: | |
| 101 | − conn.sendmail(email, [WEBMASTER], msg) | |
| 102 | − except smtplib.SMTPSenderRefused: | |
| 103 | − return """<html>please provide a valid email</html>""" | |
| 104 | − | |
| 105 | − conn.quit() | |
| 106 | − # provide feedback to the user | |
| 107 | − s = """\ | |
| 108 | −<html> | |
| 109 | −Dear %s,<br> | |
| 110 | −Thank You for your kind comments, we | |
| 111 | −will get back to you shortly. | |
| 112 | −</html>""" % name | |
| 113 | − return s | |
| @@ -0,0 +1,90 @@ | ||
| 1 | +#include "aubio-types.h" | |
| 2 | + | |
| 3 | +#define AUBIO_DECLARE(NAME, PARAMS...) \ | |
| 4 | +typedef struct { \ | |
| 5 | + PyObject_HEAD \ | |
| 6 | + aubio_ ## NAME ## _t * o; \ | |
| 7 | + PARAMS; \ | |
| 8 | +} Py_## NAME; | |
| 9 | + | |
| 10 | +#define AUBIO_INIT(NAME, PARAMS... ) \ | |
| 11 | +static int \ | |
| 12 | +Py_ ## NAME ## _init (Py_ ## NAME * self, PyObject * args, PyObject * kwds) \ | |
| 13 | +{ \ | |
| 14 | + self->o = new_aubio_## NAME ( PARAMS ); \ | |
| 15 | + if (self->o == NULL) { \ | |
| 16 | + PyErr_SetString (PyExc_StandardError, "error creating object"); \ | |
| 17 | + return -1; \ | |
| 18 | + } \ | |
| 19 | +\ | |
| 20 | + return 0; \ | |
| 21 | +} | |
| 22 | + | |
| 23 | +#define AUBIO_DEL(NAME) \ | |
| 24 | +static void \ | |
| 25 | +Py_ ## NAME ## _del ( Py_ ## NAME * self) \ | |
| 26 | +{ \ | |
| 27 | + del_aubio_ ## NAME (self->o); \ | |
| 28 | + self->ob_type->tp_free ((PyObject *) self); \ | |
| 29 | +} | |
| 30 | + | |
| 31 | +#define AUBIO_MEMBERS_START(NAME) \ | |
| 32 | +static PyMemberDef Py_ ## NAME ## _members[] = { | |
| 33 | + | |
| 34 | +#define AUBIO_MEMBERS_STOP(NAME) \ | |
| 35 | + {NULL} \ | |
| 36 | +}; | |
| 37 | + | |
| 38 | +#define AUBIO_METHODS(NAME) \ | |
| 39 | +static PyMethodDef Py_ ## NAME ## _methods[] = { \ | |
| 40 | + {NULL} \ | |
| 41 | +}; | |
| 42 | + | |
| 43 | + | |
| 44 | +#define AUBIO_TYPEOBJECT(NAME, PYNAME) \ | |
| 45 | +PyTypeObject Py_ ## NAME ## Type = { \ | |
| 46 | + PyObject_HEAD_INIT (NULL) \ | |
| 47 | + 0, \ | |
| 48 | + PYNAME, \ | |
| 49 | + sizeof (Py_ ## NAME), \ | |
| 50 | + 0, \ | |
| 51 | + (destructor) Py_ ## NAME ## _del, \ | |
| 52 | + 0, \ | |
| 53 | + 0, \ | |
| 54 | + 0, \ | |
| 55 | + 0, \ | |
| 56 | + 0, \ | |
| 57 | + 0, \ | |
| 58 | + 0, \ | |
| 59 | + 0, \ | |
| 60 | + 0, \ | |
| 61 | + (ternaryfunc)Py_ ## NAME ## _do, \ | |
| 62 | + 0, \ | |
| 63 | + 0, \ | |
| 64 | + 0, \ | |
| 65 | + 0, \ | |
| 66 | + Py_TPFLAGS_DEFAULT, \ | |
| 67 | + Py_ ## NAME ## _doc, \ | |
| 68 | + 0, \ | |
| 69 | + 0, \ | |
| 70 | + 0, \ | |
| 71 | + 0, \ | |
| 72 | + 0, \ | |
| 73 | + 0, \ | |
| 74 | + Py_ ## NAME ## _methods, \ | |
| 75 | + Py_ ## NAME ## _members, \ | |
| 76 | + 0, \ | |
| 77 | + 0, \ | |
| 78 | + 0, \ | |
| 79 | + 0, \ | |
| 80 | + 0, \ | |
| 81 | + 0, \ | |
| 82 | + (initproc) Py_ ## NAME ## _init, \ | |
| 83 | + 0, \ | |
| 84 | + Py_ ## NAME ## _new, \ | |
| 85 | +}; | |
| 86 | + | |
| 87 | +// some more helpers | |
| 88 | +#define AUBIO_NEW_VEC(name, type, lengthval) \ | |
| 89 | + name = (type *) PyObject_New (type, & type ## Type); \ | |
| 90 | + name->length = lengthval; | |
| @@ -1,9 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −from aubio.bench.broadcast import * | |
| 4 | − | |
| 5 | −run_broadcast(remote_sync,'/home/testing') | |
| 6 | −run_broadcast(remote_sync,'/home/testing','-n') | |
| 7 | −run_broadcast(fetch_results,'/home/testing','-n') | |
| 8 | − | |
| 9 | −run_broadcast(remote_queue,'echo coucou') | |
| @@ -1,13 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −from aubio.bench.node import * | |
| 4 | − | |
| 5 | −datapath = '/var/www' | |
| 6 | −respath = '/var/tmp' | |
| 7 | − | |
| 8 | −def my_print(input,output): | |
| 9 | − cmd = "%s %s %s" % ("time sleep 0.3; echo",input,output) | |
| 10 | − return runcommand(cmd,debug=0) | |
| 11 | − | |
| 12 | −act_on_results(mkdir,datapath,respath,filter='d') | |
| 13 | −act_on_data(my_print,datapath,respath,suffix='.txt') | |
| @@ -0,0 +1,9 @@ | ||
| 1 | +#! /bin/sh | |
| 2 | + | |
| 3 | +set -e | |
| 4 | +set -x | |
| 5 | + | |
| 6 | +python setup.py clean build | |
| 7 | +export PYTHONPATH=./build/lib.linux-x86_64-2.7/:./tests | |
| 8 | +export LD_LIBRARY_PATH=../build/src/ | |
| 9 | +./run_all_tests --verbose | |
| @@ -0,0 +1,9 @@ | ||
| 1 | +#! /bin/sh | |
| 2 | + | |
| 3 | +set -e | |
| 4 | +set -x | |
| 5 | + | |
| 6 | +python setup.py clean build | |
| 7 | +export PYTHONPATH=./build/lib.macosx-10.6-intel-2.7:$PYTHONPATH | |
| 8 | +export DYLD_LIBRARY_PATH=../build/src | |
| 9 | +./run_all_tests --verbose | |
| @@ -0,0 +1,2 @@ | ||
| 1 | + 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 | |
| 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 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 | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from aubio import tempo, source | |
| 5 | + | |
| 6 | +win_s = 512 # fft size | |
| 7 | +hop_s = win_s / 2 # hop size | |
| 8 | +samplerate = 44100 | |
| 9 | + | |
| 10 | +if len(sys.argv) < 2: | |
| 11 | + print "Usage: %s <filename>" % sys.argv[0] | |
| 12 | + sys.exit(1) | |
| 13 | + | |
| 14 | +filename = sys.argv[1] | |
| 15 | +beats = [] | |
| 16 | + | |
| 17 | +s = source(filename, samplerate, hop_s) | |
| 18 | +t = tempo("default", win_s, hop_s) | |
| 19 | + | |
| 20 | +block_read = 0 | |
| 21 | +while True: | |
| 22 | + samples, read = s() | |
| 23 | + isbeat = t(samples) | |
| 24 | + if isbeat: | |
| 25 | + thisbeat = (block_read * hop_s + isbeat[0]) / samplerate | |
| 26 | + print "%.4f" % thisbeat | |
| 27 | + beats.append (thisbeat) | |
| 28 | + block_read += 1 | |
| 29 | + if read < hop_s: break | |
| 30 | + | |
| 31 | +periods = [60./(b - a) for a,b in zip(beats[:-1],beats[1:])] | |
| 32 | + | |
| 33 | +from numpy import mean, median | |
| 34 | +print 'mean period:', mean(periods), 'bpm' | |
| 35 | +print 'median period:', median(periods), 'bpm' | |
| 36 | + | |
| 37 | +from pylab import plot, show | |
| 38 | +plot(beats[1:], periods) | |
| 39 | +show() | |
| @@ -0,0 +1,21 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from aubio import filterbank | |
| 4 | +from numpy import array, arange, vstack | |
| 5 | + | |
| 6 | +win_s = 8192 | |
| 7 | +samplerate = 16000 | |
| 8 | + | |
| 9 | +f = filterbank(40, win_s) | |
| 10 | +f.set_mel_coeffs_slaney(samplerate) | |
| 11 | + | |
| 12 | +from pylab import loglog, title, show, xlim, ylim, xlabel, ylabel | |
| 13 | +xlim([0,samplerate / 2]) | |
| 14 | +times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * 40) | |
| 15 | +loglog(times.T, f.get_coeffs().T, '.-') | |
| 16 | +title('Mel frequency bands coefficients') | |
| 17 | +xlim([100, 7500]) | |
| 18 | +ylim([1.0e-3, 2.0e-2]) | |
| 19 | +xlabel('Frequency (Hz)') | |
| 20 | +ylabel('Amplitude') | |
| 21 | +show() | |
| @@ -0,0 +1,47 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from aubio import filterbank, fvec | |
| 4 | +from pylab import loglog, show, subplot, xlim, ylim, xlabel, ylabel, title | |
| 5 | +from numpy import vstack, arange | |
| 6 | + | |
| 7 | +win_s = 2048 | |
| 8 | +samplerate = 48000 | |
| 9 | + | |
| 10 | +freq_list = [60, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 24000] | |
| 11 | +n_filters = len(freq_list) - 2 | |
| 12 | + | |
| 13 | +f = filterbank(n_filters, win_s) | |
| 14 | +freqs = fvec(freq_list) | |
| 15 | +f.set_triangle_bands(freqs, samplerate) | |
| 16 | + | |
| 17 | +subplot(211) | |
| 18 | +title('Examples of filterbank built with set_triangle_bands and set_coeffs') | |
| 19 | +times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters) | |
| 20 | +loglog(times.T, f.get_coeffs().T, '.-') | |
| 21 | +xlim([50, samplerate/2]) | |
| 22 | +ylim([1.0e-6, 2.0e-2]) | |
| 23 | +ylabel('Amplitude') | |
| 24 | + | |
| 25 | +## build a new filterbank | |
| 26 | + | |
| 27 | +freq_list = [60, 80, 200, 400, 800, 1200, 1600, 3200, 6400, 10000, 15000, 24000] | |
| 28 | +n_filters = len(freq_list) - 2 | |
| 29 | + | |
| 30 | +f = filterbank(n_filters, win_s) | |
| 31 | +freqs = fvec(freq_list) | |
| 32 | +f.set_triangle_bands(freqs, samplerate) | |
| 33 | + | |
| 34 | +coeffs = f.get_coeffs() | |
| 35 | +coeffs[4] *= 5. | |
| 36 | + | |
| 37 | +f.set_coeffs(coeffs) | |
| 38 | + | |
| 39 | +subplot(212) | |
| 40 | +times = vstack([arange(win_s / 2 + 1) * samplerate / win_s] * n_filters) | |
| 41 | +loglog(times.T, f.get_coeffs().T, '.-') | |
| 42 | +xlim([50, samplerate/2]) | |
| 43 | +ylim([1.0e-6, 2.0e-2]) | |
| 44 | +xlabel('Frequency (Hz)') | |
| 45 | +ylabel('Amplitude') | |
| 46 | + | |
| 47 | +show() | |
| @@ -0,0 +1,84 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy import random, sin, arange, ones, zeros | |
| 4 | +from math import pi | |
| 5 | +from aubio import fvec, onset | |
| 6 | + | |
| 7 | +def build_sinusoid(length, freqs, samplerate): | |
| 8 | + return sin( 2. * pi * arange(length) * freqs / samplerate) | |
| 9 | + | |
| 10 | +def run_onset(p, input_vec): | |
| 11 | + f = fvec (p.hop_size) | |
| 12 | + cands = [] | |
| 13 | + count = 0 | |
| 14 | + for vec_slice in input_vec.reshape((-1, p.hop_size)): | |
| 15 | + f[:] = vec_slice | |
| 16 | + cands.append(o(f)) | |
| 17 | + return cands | |
| 18 | + | |
| 19 | +methods = ['default', | |
| 20 | + 'energy', | |
| 21 | + 'complex', | |
| 22 | + 'phase', | |
| 23 | + 'specdiff', | |
| 24 | + 'kl', | |
| 25 | + 'mkl', | |
| 26 | + 'specflux', | |
| 27 | + 'centroid', | |
| 28 | + 'spread', | |
| 29 | + 'skewness', | |
| 30 | + 'kurtosis', | |
| 31 | + 'slope', | |
| 32 | + 'decrease', | |
| 33 | + 'rolloff', | |
| 34 | + ] | |
| 35 | + | |
| 36 | +cands = {} | |
| 37 | +buf_size = 2048 | |
| 38 | +hop_size = 512 | |
| 39 | +samplerate = 44100 | |
| 40 | +sin_length = (samplerate * 10) % 512 * 512 | |
| 41 | +freqs = zeros(sin_length) | |
| 42 | + | |
| 43 | +partition = sin_length / 8 | |
| 44 | +pointer = 0 | |
| 45 | + | |
| 46 | +pointer += partition | |
| 47 | +freqs[pointer: pointer + partition] = 440 | |
| 48 | + | |
| 49 | +pointer += partition | |
| 50 | +pointer += partition | |
| 51 | +freqs[ pointer : pointer + partition ] = 740 | |
| 52 | + | |
| 53 | +pointer += partition | |
| 54 | +freqs[ pointer : pointer + partition ] = 1480 | |
| 55 | + | |
| 56 | +pointer += partition | |
| 57 | +pointer += partition | |
| 58 | +freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8) | |
| 59 | + | |
| 60 | +a = build_sinusoid(sin_length, freqs, samplerate) | |
| 61 | + | |
| 62 | +for method in methods: | |
| 63 | + o = onset(method, buf_size, hop_size, samplerate) | |
| 64 | + cands[method] = run_onset(o, a) | |
| 65 | + | |
| 66 | +print "done computing" | |
| 67 | + | |
| 68 | +if 1: | |
| 69 | + from pylab import plot, show, xlabel, ylabel, legend, ylim, subplot | |
| 70 | + subplot (211) | |
| 71 | + legend(methods+['ground truth'], 'upper right') | |
| 72 | + xlabel('time (s)') | |
| 73 | + ylabel('amplitude') | |
| 74 | + ramp = arange(0, sin_length).astype('float') / samplerate | |
| 75 | + plot(ramp, a, ':') | |
| 76 | + subplot (212) | |
| 77 | + ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate | |
| 78 | + for method in methods: | |
| 79 | + plot(ramp, cands[method],'.-') | |
| 80 | + legend(methods, 'upper right') | |
| 81 | + xlabel('time (s)') | |
| 82 | + ylabel('spectral descriptor value') | |
| 83 | + show() | |
| 84 | + | |
| @@ -0,0 +1,68 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy import random, sin, arange, ones, zeros | |
| 4 | +from math import pi | |
| 5 | +from aubio import fvec, pitch | |
| 6 | + | |
| 7 | +def build_sinusoid(length, freqs, samplerate): | |
| 8 | + return sin( 2. * pi * arange(length) * freqs / samplerate) | |
| 9 | + | |
| 10 | +def run_pitch(p, input_vec): | |
| 11 | + f = fvec (p.hop_size) | |
| 12 | + cands = [] | |
| 13 | + count = 0 | |
| 14 | + for vec_slice in input_vec.reshape((-1, p.hop_size)): | |
| 15 | + f[:] = vec_slice | |
| 16 | + cands.append(p(f)) | |
| 17 | + return cands | |
| 18 | + | |
| 19 | +methods = ['default', 'schmitt', 'fcomb', 'mcomb', 'yin', 'yinfft'] | |
| 20 | + | |
| 21 | +cands = {} | |
| 22 | +buf_size = 2048 | |
| 23 | +hop_size = 512 | |
| 24 | +samplerate = 44100 | |
| 25 | +sin_length = (samplerate * 10) % 512 * 512 | |
| 26 | +freqs = zeros(sin_length) | |
| 27 | + | |
| 28 | +partition = sin_length / 8 | |
| 29 | +pointer = 0 | |
| 30 | + | |
| 31 | +pointer += partition | |
| 32 | +freqs[pointer: pointer + partition] = 440 | |
| 33 | + | |
| 34 | +pointer += partition | |
| 35 | +pointer += partition | |
| 36 | +freqs[ pointer : pointer + partition ] = 740 | |
| 37 | + | |
| 38 | +pointer += partition | |
| 39 | +freqs[ pointer : pointer + partition ] = 1480 | |
| 40 | + | |
| 41 | +pointer += partition | |
| 42 | +pointer += partition | |
| 43 | +freqs[ pointer : pointer + partition ] = 400 + 5 * random.random(sin_length/8) | |
| 44 | + | |
| 45 | +a = build_sinusoid(sin_length, freqs, samplerate) | |
| 46 | + | |
| 47 | +for method in methods: | |
| 48 | + p = pitch(method, buf_size, hop_size, samplerate) | |
| 49 | + cands[method] = run_pitch(p, a) | |
| 50 | + | |
| 51 | +print "done computing" | |
| 52 | + | |
| 53 | +if 1: | |
| 54 | + from pylab import plot, show, xlabel, ylabel, legend, ylim | |
| 55 | + ramp = arange(0, sin_length / hop_size).astype('float') * hop_size / samplerate | |
| 56 | + for method in methods: | |
| 57 | + plot(ramp, cands[method],'.-') | |
| 58 | + | |
| 59 | + # plot ground truth | |
| 60 | + ramp = arange(0, sin_length).astype('float') / samplerate | |
| 61 | + plot(ramp, freqs, ':') | |
| 62 | + | |
| 63 | + legend(methods+['ground truth'], 'upper right') | |
| 64 | + xlabel('time (s)') | |
| 65 | + ylabel('frequency (Hz)') | |
| 66 | + ylim([0,2000]) | |
| 67 | + show() | |
| 68 | + | |
| @@ -0,0 +1,29 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from aubio import source, sink, pvoc | |
| 5 | + | |
| 6 | +if __name__ == '__main__': | |
| 7 | + if len(sys.argv) < 2: | |
| 8 | + print 'usage: %s <inputfile> <outputfile>' % sys.argv[0] | |
| 9 | + sys.exit(1) | |
| 10 | + samplerate = 44100 | |
| 11 | + f = source(sys.argv[1], samplerate, 256) | |
| 12 | + g = sink(sys.argv[2], samplerate) | |
| 13 | + total_frames, read = 0, 256 | |
| 14 | + | |
| 15 | + win_s = 512 # fft size | |
| 16 | + hop_s = win_s / 2 # hop size | |
| 17 | + pv = pvoc(win_s, hop_s) # phase vocoder | |
| 18 | + | |
| 19 | + while read: | |
| 20 | + samples, read = f() | |
| 21 | + spectrum = pv(samples) # compute spectrum | |
| 22 | + spectrum.phas[:] = 0. # zero phase | |
| 23 | + new_samples = pv.rdo(spectrum) # compute modified samples | |
| 24 | + g(new_samples, read) # write to output | |
| 25 | + total_frames += read | |
| 26 | + | |
| 27 | + print "wrote", total_frames, "from", f.uri, "to", g.uri | |
| 28 | + | |
| 29 | + | |
| @@ -0,0 +1,17 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from aubio import source, sink | |
| 5 | + | |
| 6 | +if __name__ == '__main__': | |
| 7 | + if len(sys.argv) < 3: | |
| 8 | + print 'usage: %s <inputfile> <outputfile>' % sys.argv[0] | |
| 9 | + sys.exit(1) | |
| 10 | + f = source(sys.argv[1], 8000, 256) | |
| 11 | + g = sink(sys.argv[2], 8000) | |
| 12 | + total_frames, read = 0, 256 | |
| 13 | + while read: | |
| 14 | + vec, read = f() | |
| 15 | + g(vec, read) | |
| 16 | + total_frames += read | |
| 17 | + print "read", total_frames / float(f.samplerate), "seconds from", f.uri | |
| @@ -0,0 +1,38 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from math import sin, pi | |
| 5 | +from aubio import sink | |
| 6 | +from numpy import array | |
| 7 | + | |
| 8 | +if len(sys.argv) != 2: | |
| 9 | + print 'usage: %s <outputfile>' % sys.argv[0] | |
| 10 | + sys.exit(1) | |
| 11 | + | |
| 12 | +samplerate = 44100 # in Hz | |
| 13 | +pitch = 2200 # in Hz | |
| 14 | +blocksize = 256 # in samples | |
| 15 | +duration = 0.02 # in seconds | |
| 16 | + | |
| 17 | +twopi = pi * 2. | |
| 18 | + | |
| 19 | +duration = int ( 44100 * duration ) # convert to samples | |
| 20 | +attack = 3 | |
| 21 | + | |
| 22 | +period = int ( float(samplerate) / pitch ) | |
| 23 | +sinetone = [ 0.7 * sin(twopi * i/ period) for i in range(period) ] | |
| 24 | +sinetone *= int ( duration / period ) | |
| 25 | +sinetone = array(sinetone, dtype = 'float32') | |
| 26 | + | |
| 27 | +from math import exp, e | |
| 28 | +for i in range(len(sinetone)): | |
| 29 | + sinetone[i] *= exp( - e * float(i) / len(sinetone)) | |
| 30 | +for i in range(attack): | |
| 31 | + sinetone[i] *= exp( e * (float(i) / attack - 1 ) ) | |
| 32 | + | |
| 33 | +my_sink = sink(sys.argv[1], 44100) | |
| 34 | + | |
| 35 | +i = 0 | |
| 36 | +while i + blocksize < duration: | |
| 37 | + my_sink(sinetone[i:i+blocksize], blocksize) | |
| 38 | + i += blocksize | |
| @@ -0,0 +1,16 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from aubio import source | |
| 5 | + | |
| 6 | +if __name__ == '__main__': | |
| 7 | + if len(sys.argv) < 2: | |
| 8 | + print 'usage: %s <inputfile>' % sys.argv[0] | |
| 9 | + sys.exit(1) | |
| 10 | + f = source(sys.argv[1], 1, 256) | |
| 11 | + samplerate = f.get_samplerate() | |
| 12 | + total_frames, read = 0, 256 | |
| 13 | + while read: | |
| 14 | + vec, read = f() | |
| 15 | + total_frames += read | |
| 16 | + print "read", total_frames / float(samplerate), "seconds from", f.uri | |
| @@ -0,0 +1,63 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from aubio import pvoc, source | |
| 5 | +from numpy import array, arange, zeros, shape, log10, vstack | |
| 6 | +from pylab import imshow, show, cm, axis, ylabel, xlabel, xticks, yticks | |
| 7 | + | |
| 8 | +def get_spectrogram(filename): | |
| 9 | + samplerate = 44100 | |
| 10 | + win_s = 512 # fft window size | |
| 11 | + hop_s = win_s / 2 # hop size | |
| 12 | + fft_s = win_s / 2 + 1 # spectrum bins | |
| 13 | + | |
| 14 | + a = source(filename, samplerate, hop_s) # source file | |
| 15 | + pv = pvoc(win_s, hop_s) # phase vocoder | |
| 16 | + specgram = zeros([0, fft_s], dtype='float32') # numpy array to store spectrogram | |
| 17 | + | |
| 18 | + # analysis | |
| 19 | + while True: | |
| 20 | + samples, read = a() # read file | |
| 21 | + specgram = vstack((specgram,pv(samples).norm)) # store new norm vector | |
| 22 | + if read < a.hop_size: break | |
| 23 | + | |
| 24 | + # plotting | |
| 25 | + imshow(log10(specgram.T + .001), origin = 'bottom', aspect = 'auto', cmap=cm.gray_r) | |
| 26 | + axis([0, len(specgram), 0, len(specgram[0])]) | |
| 27 | + # show axes in Hz and seconds | |
| 28 | + time_step = hop_s / float(samplerate) | |
| 29 | + total_time = len(specgram) * time_step | |
| 30 | + print "total time: %0.2fs" % total_time, | |
| 31 | + print ", samplerate: %.2fkHz" % (samplerate / 1000.) | |
| 32 | + n_xticks = 10 | |
| 33 | + n_yticks = 10 | |
| 34 | + | |
| 35 | + def get_rounded_ticks( top_pos, step, n_ticks ): | |
| 36 | + top_label = top_pos * step | |
| 37 | + # get the first label | |
| 38 | + ticks_first_label = top_pos * step / n_ticks | |
| 39 | + # round to the closest .1 | |
| 40 | + ticks_first_label = round ( ticks_first_label * 10. ) / 10. | |
| 41 | + # compute all labels from the first rounded one | |
| 42 | + ticks_labels = [ ticks_first_label * n for n in range(n_ticks) ] + [ top_label ] | |
| 43 | + # get the corresponding positions | |
| 44 | + ticks_positions = [ ticks_labels[n] / step for n in range(n_ticks) ] + [ top_pos ] | |
| 45 | + # convert to string | |
| 46 | + ticks_labels = [ "%.1f" % x for x in ticks_labels ] | |
| 47 | + # return position, label tuple to use with x/yticks | |
| 48 | + return ticks_positions, ticks_labels | |
| 49 | + | |
| 50 | + # apply to the axis | |
| 51 | + xticks( *get_rounded_ticks ( len(specgram), time_step, n_xticks ) ) | |
| 52 | + yticks( *get_rounded_ticks ( len(specgram[0]), (samplerate / 2. / 1000.) / len(specgram[0]), n_yticks ) ) | |
| 53 | + ylabel('Frequency (kHz)') | |
| 54 | + xlabel('Time (s)') | |
| 55 | + | |
| 56 | +if __name__ == '__main__': | |
| 57 | + if len(sys.argv) < 2: | |
| 58 | + print "Usage: %s <filename>" % sys.argv[0] | |
| 59 | + else: | |
| 60 | + for soundfile in sys.argv[1:]: | |
| 61 | + get_spectrogram(soundfile) | |
| 62 | + # display graph | |
| 63 | + show() | |
| @@ -0,0 +1,47 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +import sys | |
| 4 | +from aubio import source, sink, pvoc, tss | |
| 5 | + | |
| 6 | +if __name__ == '__main__': | |
| 7 | + if len(sys.argv) < 2: | |
| 8 | + print 'usage: %s <inputfile> <outputfile_transient> <outputfile_steady>' % sys.argv[0] | |
| 9 | + sys.exit(1) | |
| 10 | + | |
| 11 | + samplerate = 44100 | |
| 12 | + win_s = 512 # fft size | |
| 13 | + hop_s = win_s / 2 # block size | |
| 14 | + threshold = 0.26 | |
| 15 | + | |
| 16 | + f = source(sys.argv[1], samplerate, hop_s) | |
| 17 | + g = sink(sys.argv[2], samplerate) | |
| 18 | + h = sink(sys.argv[3], samplerate) | |
| 19 | + | |
| 20 | + pv = pvoc(win_s, hop_s) # phase vocoder | |
| 21 | + pw = pvoc(win_s, hop_s) # another phase vocoder | |
| 22 | + t = tss(win_s, hop_s) # transient steady state separation | |
| 23 | + | |
| 24 | + t.set_threshold(threshold) | |
| 25 | + | |
| 26 | + read = hop_s | |
| 27 | + | |
| 28 | + while read: | |
| 29 | + samples, read = f() # read file | |
| 30 | + spec = pv(samples) # compute spectrum | |
| 31 | + trans_spec, stead_spec = t(spec) # transient steady-state separation | |
| 32 | + transients = pv.rdo(trans_spec) # overlap-add synthesis of transients | |
| 33 | + steadstate = pw.rdo(stead_spec) # overlap-add synthesis of steady states | |
| 34 | + g(transients, read) # write transients to output | |
| 35 | + h(steadstate, read) # write steady states to output | |
| 36 | + | |
| 37 | + del f, g, h # finish writing the files now | |
| 38 | + | |
| 39 | + from demo_spectrogram import get_spectrogram | |
| 40 | + from pylab import subplot, show | |
| 41 | + subplot(311) | |
| 42 | + get_spectrogram(sys.argv[1]) | |
| 43 | + subplot(312) | |
| 44 | + get_spectrogram(sys.argv[2]) | |
| 45 | + subplot(313) | |
| 46 | + get_spectrogram(sys.argv[3]) | |
| 47 | + show() | |
| @@ -0,0 +1,526 @@ | ||
| 1 | +#! /usr/bin/python | |
| 2 | + | |
| 3 | +""" This madness of code is used to generate the C code of the python interface | |
| 4 | +to aubio. Don't try this at home. | |
| 5 | + | |
| 6 | +The list of typedefs and functions is obtained from the command line 'cpp | |
| 7 | +aubio.h'. This list is then used to parse all the functions about this object. | |
| 8 | + | |
| 9 | +I hear the ones asking "why not use swig, or cython, or something like that?" | |
| 10 | + | |
| 11 | +The requirements for this extension are the following: | |
| 12 | + | |
| 13 | + - aubio vectors can be viewed as numpy arrays, and vice versa | |
| 14 | + - aubio 'object' should be python classes, not just a bunch of functions | |
| 15 | + | |
| 16 | +I haven't met any python interface generator that can meet both these | |
| 17 | +requirements. If you know of one, please let me know, it will spare me | |
| 18 | +maintaining this bizarre file. | |
| 19 | +""" | |
| 20 | + | |
| 21 | +param_numbers = { | |
| 22 | + 'source': [0, 2], | |
| 23 | + 'sink': [2, 0], | |
| 24 | +} | |
| 25 | + | |
| 26 | +# TODO | |
| 27 | +# do function: for now, only the following pattern is supported: | |
| 28 | +# void aubio_<foo>_do (aubio_foo_t * o, | |
| 29 | +# [input1_t * input, [output1_t * output, ..., output3_t * output]]); | |
| 30 | +# There is no way of knowing that output1 is actually input2. In the future, | |
| 31 | +# const could be used for the inputs in the C prototypes. | |
| 32 | + | |
| 33 | +def write_msg(*args): | |
| 34 | + pass | |
| 35 | + # uncomment out for debugging | |
| 36 | + #print args | |
| 37 | + | |
| 38 | +def split_type(arg): | |
| 39 | + """ arg = 'foo *name' | |
| 40 | + return ['foo*', 'name'] """ | |
| 41 | + l = arg.split() | |
| 42 | + type_arg = {'type': l[0], 'name': l[1]} | |
| 43 | + # ['foo', '*name'] -> ['foo*', 'name'] | |
| 44 | + if l[-1].startswith('*'): | |
| 45 | + #return [l[0]+'*', l[1][1:]] | |
| 46 | + type_arg['type'] = l[0] + '*' | |
| 47 | + type_arg['name'] = l[1][1:] | |
| 48 | + # ['foo', '*', 'name'] -> ['foo*', 'name'] | |
| 49 | + if len(l) == 3: | |
| 50 | + #return [l[0]+l[1], l[2]] | |
| 51 | + type_arg['type'] = l[0]+l[1] | |
| 52 | + type_arg['name'] = l[2] | |
| 53 | + else: | |
| 54 | + #return l | |
| 55 | + pass | |
| 56 | + return type_arg | |
| 57 | + | |
| 58 | +def get_params(proto): | |
| 59 | + """ get the list of parameters from a function prototype | |
| 60 | + example: proto = "int main (int argc, char ** argv)" | |
| 61 | + returns: ['int argc', 'char ** argv'] | |
| 62 | + """ | |
| 63 | + import re | |
| 64 | + paramregex = re.compile('[\(, ](\w+ \*?\*? ?\w+)[, \)]') | |
| 65 | + return paramregex.findall(proto) | |
| 66 | + | |
| 67 | +def get_params_types_names(proto): | |
| 68 | + """ get the list of parameters from a function prototype | |
| 69 | + example: proto = "int main (int argc, char ** argv)" | |
| 70 | + returns: [['int', 'argc'], ['char **','argv']] | |
| 71 | + """ | |
| 72 | + return map(split_type, get_params(proto)) | |
| 73 | + | |
| 74 | +def get_return_type(proto): | |
| 75 | + import re | |
| 76 | + paramregex = re.compile('(\w+ ?\*?).*') | |
| 77 | + outputs = paramregex.findall(proto) | |
| 78 | + assert len(outputs) == 1 | |
| 79 | + return outputs[0].replace(' ', '') | |
| 80 | + | |
| 81 | +def get_name(proto): | |
| 82 | + name = proto.split()[1].split('(')[0] | |
| 83 | + return name.replace('*','') | |
| 84 | + | |
| 85 | +# the important bits: the size of the output for each objects. this data should | |
| 86 | +# move into the C library at some point. | |
| 87 | +defaultsizes = { | |
| 88 | + 'resampler': ['input->length * self->ratio'], | |
| 89 | + 'specdesc': ['1'], | |
| 90 | + 'onset': ['1'], | |
| 91 | + 'pitchyin': ['1'], | |
| 92 | + 'pitchyinfft': ['1'], | |
| 93 | + 'pitchschmitt': ['1'], | |
| 94 | + 'pitchmcomb': ['1'], | |
| 95 | + 'pitchfcomb': ['1'], | |
| 96 | + 'pitch': ['1'], | |
| 97 | + 'tss': ['self->buf_size', 'self->buf_size'], | |
| 98 | + 'mfcc': ['self->n_coeffs'], | |
| 99 | + 'beattracking': ['self->hop_size'], | |
| 100 | + 'tempo': ['1'], | |
| 101 | + 'peakpicker': ['1'], | |
| 102 | + 'source': ['self->hop_size', '1'], | |
| 103 | +} | |
| 104 | + | |
| 105 | +# default value for variables | |
| 106 | +aubioinitvalue = { | |
| 107 | + 'uint_t': 0, | |
| 108 | + 'smpl_t': 0, | |
| 109 | + 'lsmp_t': 0., | |
| 110 | + 'char_t*': 'NULL', | |
| 111 | + } | |
| 112 | + | |
| 113 | +aubiodefvalue = { | |
| 114 | + # we have some clean up to do | |
| 115 | + 'buf_size': 'Py_default_vector_length', | |
| 116 | + # and here too | |
| 117 | + 'hop_size': 'Py_default_vector_length / 2', | |
| 118 | + # these should be alright | |
| 119 | + 'samplerate': 'Py_aubio_default_samplerate', | |
| 120 | + # now for the non obvious ones | |
| 121 | + 'n_filters': '40', | |
| 122 | + 'n_coeffs': '13', | |
| 123 | + 'nelems': '10', | |
| 124 | + 'flow': '0.', | |
| 125 | + 'fhig': '1.', | |
| 126 | + 'ilow': '0.', | |
| 127 | + 'ihig': '1.', | |
| 128 | + 'thrs': '0.5', | |
| 129 | + 'ratio': '0.5', | |
| 130 | + 'method': '"default"', | |
| 131 | + 'uri': '"none"', | |
| 132 | + } | |
| 133 | + | |
| 134 | +# aubio to python | |
| 135 | +aubio2pytypes = { | |
| 136 | + 'uint_t': 'I', | |
| 137 | + 'smpl_t': 'f', | |
| 138 | + 'lsmp_t': 'd', | |
| 139 | + 'fvec_t*': 'O', | |
| 140 | + 'cvec_t*': 'O', | |
| 141 | + 'char_t*': 's', | |
| 142 | +} | |
| 143 | + | |
| 144 | +# python to aubio | |
| 145 | +aubiovecfrompyobj = { | |
| 146 | + 'fvec_t*': 'PyAubio_ArrayToCFvec', | |
| 147 | + 'cvec_t*': 'PyAubio_ArrayToCCvec', | |
| 148 | + 'uint_t': '(uint_t)PyInt_AsLong', | |
| 149 | +} | |
| 150 | + | |
| 151 | +# aubio to python | |
| 152 | +aubiovectopyobj = { | |
| 153 | + 'fvec_t*': 'PyAubio_CFvecToArray', | |
| 154 | + 'cvec_t*': 'PyAubio_CCvecToPyCvec', | |
| 155 | + 'smpl_t': 'PyFloat_FromDouble', | |
| 156 | + 'uint_t*': 'PyInt_FromLong', | |
| 157 | + 'uint_t': 'PyInt_FromLong', | |
| 158 | +} | |
| 159 | + | |
| 160 | +def gen_new_init(newfunc, name): | |
| 161 | + newparams = get_params_types_names(newfunc) | |
| 162 | + # self->param1, self->param2, self->param3 | |
| 163 | + if len(newparams): | |
| 164 | + selfparams = ', self->'+', self->'.join([p['name'] for p in newparams]) | |
| 165 | + else: | |
| 166 | + selfparams = '' | |
| 167 | + # "param1", "param2", "param3" | |
| 168 | + paramnames = ", ".join(["\""+p['name']+"\"" for p in newparams]) | |
| 169 | + pyparams = "".join(map(lambda p: aubio2pytypes[p['type']], newparams)) | |
| 170 | + paramrefs = ", ".join(["&" + p['name'] for p in newparams]) | |
| 171 | + s = """\ | |
| 172 | +// WARNING: this file is generated, DO NOT EDIT | |
| 173 | + | |
| 174 | +// WARNING: if you haven't read the first line yet, please do so | |
| 175 | +#include "aubiowraphell.h" | |
| 176 | + | |
| 177 | +typedef struct | |
| 178 | +{ | |
| 179 | + PyObject_HEAD | |
| 180 | + aubio_%(name)s_t * o; | |
| 181 | +""" % locals() | |
| 182 | + for p in newparams: | |
| 183 | + ptype = p['type'] | |
| 184 | + pname = p['name'] | |
| 185 | + s += """\ | |
| 186 | + %(ptype)s %(pname)s; | |
| 187 | +""" % locals() | |
| 188 | + s += """\ | |
| 189 | +} Py_%(name)s; | |
| 190 | + | |
| 191 | +static char Py_%(name)s_doc[] = "%(name)s object"; | |
| 192 | + | |
| 193 | +static PyObject * | |
| 194 | +Py_%(name)s_new (PyTypeObject * pytype, PyObject * args, PyObject * kwds) | |
| 195 | +{ | |
| 196 | + Py_%(name)s *self; | |
| 197 | +""" % locals() | |
| 198 | + for p in newparams: | |
| 199 | + ptype = p['type'] | |
| 200 | + pname = p['name'] | |
| 201 | + initval = aubioinitvalue[ptype] | |
| 202 | + s += """\ | |
| 203 | + %(ptype)s %(pname)s = %(initval)s; | |
| 204 | +""" % locals() | |
| 205 | + # now the actual PyArg_Parse | |
| 206 | + if len(paramnames): | |
| 207 | + s += """\ | |
| 208 | + static char *kwlist[] = { %(paramnames)s, NULL }; | |
| 209 | + | |
| 210 | + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|%(pyparams)s", kwlist, | |
| 211 | + %(paramrefs)s)) { | |
| 212 | + return NULL; | |
| 213 | + } | |
| 214 | +""" % locals() | |
| 215 | + s += """\ | |
| 216 | + | |
| 217 | + self = (Py_%(name)s *) pytype->tp_alloc (pytype, 0); | |
| 218 | + | |
| 219 | + if (self == NULL) { | |
| 220 | + return NULL; | |
| 221 | + } | |
| 222 | +""" % locals() | |
| 223 | + for p in newparams: | |
| 224 | + ptype = p['type'] | |
| 225 | + pname = p['name'] | |
| 226 | + defval = aubiodefvalue[pname] | |
| 227 | + if ptype == 'char_t*': | |
| 228 | + s += """\ | |
| 229 | + | |
| 230 | + self->%(pname)s = %(defval)s; | |
| 231 | + if (%(pname)s != NULL) { | |
| 232 | + self->%(pname)s = %(pname)s; | |
| 233 | + } | |
| 234 | +""" % locals() | |
| 235 | + elif ptype == 'uint_t': | |
| 236 | + s += """\ | |
| 237 | + | |
| 238 | + self->%(pname)s = %(defval)s; | |
| 239 | + if (%(pname)s > 0) { | |
| 240 | + self->%(pname)s = %(pname)s; | |
| 241 | + } else if (%(pname)s < 0) { | |
| 242 | + PyErr_SetString (PyExc_ValueError, | |
| 243 | + "can not use negative value for %(pname)s"); | |
| 244 | + return NULL; | |
| 245 | + } | |
| 246 | +""" % locals() | |
| 247 | + elif ptype == 'smpl_t': | |
| 248 | + s += """\ | |
| 249 | + | |
| 250 | + self->%(pname)s = %(defval)s; | |
| 251 | + if (%(pname)s != %(defval)s) { | |
| 252 | + self->%(pname)s = %(pname)s; | |
| 253 | + } | |
| 254 | +""" % locals() | |
| 255 | + else: | |
| 256 | + write_msg ("ERROR, unknown type of parameter %s %s" % (ptype, pname) ) | |
| 257 | + s += """\ | |
| 258 | + | |
| 259 | + return (PyObject *) self; | |
| 260 | +} | |
| 261 | + | |
| 262 | +AUBIO_INIT(%(name)s %(selfparams)s) | |
| 263 | + | |
| 264 | +AUBIO_DEL(%(name)s) | |
| 265 | + | |
| 266 | +""" % locals() | |
| 267 | + return s | |
| 268 | + | |
| 269 | +def gen_do_input_params(inputparams): | |
| 270 | + inputdefs = '' | |
| 271 | + parseinput = '' | |
| 272 | + inputrefs = '' | |
| 273 | + inputvecs = '' | |
| 274 | + pytypes = '' | |
| 275 | + | |
| 276 | + if len(inputparams): | |
| 277 | + # build the parsing string for PyArg_ParseTuple | |
| 278 | + pytypes = "".join([aubio2pytypes[p['type']] for p in inputparams]) | |
| 279 | + | |
| 280 | + inputdefs = " /* input vectors python prototypes */\n" | |
| 281 | + for p in inputparams: | |
| 282 | + if p['type'] != 'uint_t': | |
| 283 | + inputdefs += " PyObject * " + p['name'] + "_obj;\n" | |
| 284 | + | |
| 285 | + inputvecs = " /* input vectors prototypes */\n " | |
| 286 | + inputvecs += "\n ".join(map(lambda p: p['type'] + ' ' + p['name'] + ";", inputparams)) | |
| 287 | + | |
| 288 | + parseinput = " /* input vectors parsing */\n " | |
| 289 | + for p in inputparams: | |
| 290 | + inputvec = p['name'] | |
| 291 | + if p['type'] != 'uint_t': | |
| 292 | + inputdef = p['name'] + "_obj" | |
| 293 | + else: | |
| 294 | + inputdef = p['name'] | |
| 295 | + converter = aubiovecfrompyobj[p['type']] | |
| 296 | + if p['type'] != 'uint_t': | |
| 297 | + parseinput += """%(inputvec)s = %(converter)s (%(inputdef)s); | |
| 298 | + | |
| 299 | + if (%(inputvec)s == NULL) { | |
| 300 | + return NULL; | |
| 301 | + } | |
| 302 | + | |
| 303 | + """ % locals() | |
| 304 | + | |
| 305 | + # build the string for the input objects references | |
| 306 | + inputreflist = [] | |
| 307 | + for p in inputparams: | |
| 308 | + if p['type'] != 'uint_t': | |
| 309 | + inputreflist += [ "&" + p['name'] + "_obj" ] | |
| 310 | + else: | |
| 311 | + inputreflist += [ "&" + p['name'] ] | |
| 312 | + inputrefs = ", ".join(inputreflist) | |
| 313 | + # end of inputs strings | |
| 314 | + return inputdefs, parseinput, inputrefs, inputvecs, pytypes | |
| 315 | + | |
| 316 | +def gen_do_output_params(outputparams, name): | |
| 317 | + outputvecs = "" | |
| 318 | + outputcreate = "" | |
| 319 | + if len(outputparams): | |
| 320 | + outputvecs = " /* output vectors prototypes */\n" | |
| 321 | + for p in outputparams: | |
| 322 | + params = { | |
| 323 | + 'name': p['name'], 'pytype': p['type'], 'autype': p['type'][:-3], | |
| 324 | + 'length': defaultsizes[name].pop(0) } | |
| 325 | + if (p['type'] == 'uint_t*'): | |
| 326 | + outputvecs += ' uint_t' + ' ' + p['name'] + ";\n" | |
| 327 | + outputcreate += " %(name)s = 0;\n" % params | |
| 328 | + else: | |
| 329 | + outputvecs += " " + p['type'] + ' ' + p['name'] + ";\n" | |
| 330 | + outputcreate += " /* creating output %(name)s as a new_%(autype)s of length %(length)s */\n" % params | |
| 331 | + outputcreate += " %(name)s = new_%(autype)s (%(length)s);\n" % params | |
| 332 | + | |
| 333 | + returnval = ""; | |
| 334 | + if len(outputparams) > 1: | |
| 335 | + returnval += " PyObject *outputs = PyList_New(0);\n" | |
| 336 | + for p in outputparams: | |
| 337 | + returnval += " PyList_Append( outputs, (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" +");\n" | |
| 338 | + returnval += " return outputs;" | |
| 339 | + elif len(outputparams) == 1: | |
| 340 | + if defaultsizes[name] == '1': | |
| 341 | + returnval += " return (PyObject *)PyFloat_FromDouble(" + p['name'] + "->data[0])" | |
| 342 | + else: | |
| 343 | + returnval += " return (PyObject *)" + aubiovectopyobj[p['type']] + " (" + p['name'] + ")" | |
| 344 | + else: | |
| 345 | + returnval = " return Py_None;"; | |
| 346 | + # end of output strings | |
| 347 | + return outputvecs, outputcreate, returnval | |
| 348 | + | |
| 349 | +def gen_do(dofunc, name): | |
| 350 | + funcname = dofunc.split()[1].split('(')[0] | |
| 351 | + doparams = get_params_types_names(dofunc) | |
| 352 | + # make sure the first parameter is the object | |
| 353 | + assert doparams[0]['type'] == "aubio_"+name+"_t*", \ | |
| 354 | + "method is not in 'aubio_<name>_t" | |
| 355 | + # and remove it | |
| 356 | + doparams = doparams[1:] | |
| 357 | + | |
| 358 | + n_param = len(doparams) | |
| 359 | + | |
| 360 | + if name in param_numbers.keys(): | |
| 361 | + n_input_param, n_output_param = param_numbers[name] | |
| 362 | + else: | |
| 363 | + n_input_param, n_output_param = 1, n_param - 1 | |
| 364 | + | |
| 365 | + assert n_output_param + n_input_param == n_param, "n_output_param + n_input_param != n_param for %s" % name | |
| 366 | + | |
| 367 | + inputparams = doparams[:n_input_param] | |
| 368 | + outputparams = doparams[n_input_param:n_input_param + n_output_param] | |
| 369 | + | |
| 370 | + inputdefs, parseinput, inputrefs, inputvecs, pytypes = gen_do_input_params(inputparams); | |
| 371 | + outputvecs, outputcreate, returnval = gen_do_output_params(outputparams, name) | |
| 372 | + | |
| 373 | + # build strings for outputs | |
| 374 | + # build the parameters for the _do() call | |
| 375 | + doparams_string = "self->o" | |
| 376 | + for p in doparams: | |
| 377 | + if p['type'] == 'uint_t*': | |
| 378 | + doparams_string += ", &" + p['name'] | |
| 379 | + else: | |
| 380 | + doparams_string += ", " + p['name'] | |
| 381 | + | |
| 382 | + if n_input_param: | |
| 383 | + arg_parse_tuple = """\ | |
| 384 | + if (!PyArg_ParseTuple (args, "%(pytypes)s", %(inputrefs)s)) { | |
| 385 | + return NULL; | |
| 386 | + } | |
| 387 | +""" % locals() | |
| 388 | + else: | |
| 389 | + arg_parse_tuple = "" | |
| 390 | + # put it all together | |
| 391 | + s = """\ | |
| 392 | +/* function Py_%(name)s_do */ | |
| 393 | +static PyObject * | |
| 394 | +Py_%(name)s_do(Py_%(name)s * self, PyObject * args) | |
| 395 | +{ | |
| 396 | +%(inputdefs)s | |
| 397 | +%(inputvecs)s | |
| 398 | +%(outputvecs)s | |
| 399 | + | |
| 400 | +%(arg_parse_tuple)s | |
| 401 | + | |
| 402 | +%(parseinput)s | |
| 403 | + | |
| 404 | +%(outputcreate)s | |
| 405 | + | |
| 406 | + /* compute _do function */ | |
| 407 | + %(funcname)s (%(doparams_string)s); | |
| 408 | + | |
| 409 | +%(returnval)s; | |
| 410 | +} | |
| 411 | +""" % locals() | |
| 412 | + return s | |
| 413 | + | |
| 414 | +def gen_members(new_method, name): | |
| 415 | + newparams = get_params_types_names(new_method) | |
| 416 | + s = """ | |
| 417 | +AUBIO_MEMBERS_START(%(name)s)""" % locals() | |
| 418 | + for param in newparams: | |
| 419 | + if param['type'] == 'char_t*': | |
| 420 | + s += """ | |
| 421 | + {"%(pname)s", T_STRING, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \ | |
| 422 | + % { 'pname': param['name'], 'ptype': param['type'], 'name': name} | |
| 423 | + elif param['type'] == 'uint_t': | |
| 424 | + s += """ | |
| 425 | + {"%(pname)s", T_INT, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \ | |
| 426 | + % { 'pname': param['name'], 'ptype': param['type'], 'name': name} | |
| 427 | + elif param['type'] == 'smpl_t': | |
| 428 | + s += """ | |
| 429 | + {"%(pname)s", T_FLOAT, offsetof (Py_%(name)s, %(pname)s), READONLY, ""},""" \ | |
| 430 | + % { 'pname': param['name'], 'ptype': param['type'], 'name': name} | |
| 431 | + else: | |
| 432 | + write_msg ("-- ERROR, unknown member type ", param ) | |
| 433 | + s += """ | |
| 434 | +AUBIO_MEMBERS_STOP(%(name)s) | |
| 435 | + | |
| 436 | +""" % locals() | |
| 437 | + return s | |
| 438 | + | |
| 439 | + | |
| 440 | +def gen_methods(get_methods, set_methods, name): | |
| 441 | + s = "" | |
| 442 | + method_defs = "" | |
| 443 | + for method in set_methods: | |
| 444 | + method_name = get_name(method) | |
| 445 | + params = get_params_types_names(method) | |
| 446 | + out_type = get_return_type(method) | |
| 447 | + assert params[0]['type'] == "aubio_"+name+"_t*", \ | |
| 448 | + "get method is not in 'aubio_<name>_t" | |
| 449 | + write_msg (method ) | |
| 450 | + write_msg (params[1:]) | |
| 451 | + setter_args = "self->o, " +",".join([p['name'] for p in params[1:]]) | |
| 452 | + parse_args = "" | |
| 453 | + for p in params[1:]: | |
| 454 | + parse_args += p['type'] + " " + p['name'] + ";\n" | |
| 455 | + argmap = "".join([aubio2pytypes[p['type']] for p in params[1:]]) | |
| 456 | + arglist = ", ".join(["&"+p['name'] for p in params[1:]]) | |
| 457 | + parse_args += """ | |
| 458 | + if (!PyArg_ParseTuple (args, "%(argmap)s", %(arglist)s)) { | |
| 459 | + return NULL; | |
| 460 | + } """ % locals() | |
| 461 | + s += """ | |
| 462 | +static PyObject * | |
| 463 | +Py%(funcname)s (Py_%(objname)s *self, PyObject *args) | |
| 464 | +{ | |
| 465 | + uint_t err = 0; | |
| 466 | + | |
| 467 | + %(parse_args)s | |
| 468 | + | |
| 469 | + err = %(funcname)s (%(setter_args)s); | |
| 470 | + | |
| 471 | + if (err > 0) { | |
| 472 | + PyErr_SetString (PyExc_ValueError, | |
| 473 | + "error running %(funcname)s"); | |
| 474 | + return NULL; | |
| 475 | + } | |
| 476 | + return Py_None; | |
| 477 | +} | |
| 478 | +""" % {'funcname': method_name, 'objname': name, | |
| 479 | + 'out_type': out_type, 'setter_args': setter_args, 'parse_args': parse_args } | |
| 480 | + shortname = method_name.split(name+'_')[-1] | |
| 481 | + method_defs += """\ | |
| 482 | + {"%(shortname)s", (PyCFunction) Py%(method_name)s, | |
| 483 | + METH_VARARGS, ""}, | |
| 484 | +""" % locals() | |
| 485 | + | |
| 486 | + for method in get_methods: | |
| 487 | + method_name = get_name(method) | |
| 488 | + params = get_params_types_names(method) | |
| 489 | + out_type = get_return_type(method) | |
| 490 | + assert params[0]['type'] == "aubio_"+name+"_t*", \ | |
| 491 | + "get method is not in 'aubio_<name>_t %s" % params[0]['type'] | |
| 492 | + assert len(params) == 1, \ | |
| 493 | + "get method has more than one parameter %s" % params | |
| 494 | + getter_args = "self->o" | |
| 495 | + returnval = "(PyObject *)" + aubiovectopyobj[out_type] + " (tmp)" | |
| 496 | + shortname = method_name.split(name+'_')[-1] | |
| 497 | + method_defs += """\ | |
| 498 | + {"%(shortname)s", (PyCFunction) Py%(method_name)s, | |
| 499 | + METH_NOARGS, ""}, | |
| 500 | +""" % locals() | |
| 501 | + s += """ | |
| 502 | +static PyObject * | |
| 503 | +Py%(funcname)s (Py_%(objname)s *self, PyObject *unused) | |
| 504 | +{ | |
| 505 | + %(out_type)s tmp = %(funcname)s (%(getter_args)s); | |
| 506 | + return %(returnval)s; | |
| 507 | +} | |
| 508 | +""" % {'funcname': method_name, 'objname': name, | |
| 509 | + 'out_type': out_type, 'getter_args': getter_args, 'returnval': returnval } | |
| 510 | + | |
| 511 | + s += """ | |
| 512 | +static PyMethodDef Py_%(name)s_methods[] = { | |
| 513 | +""" % locals() | |
| 514 | + s += method_defs | |
| 515 | + s += """\ | |
| 516 | + {NULL} /* sentinel */ | |
| 517 | +}; | |
| 518 | +""" % locals() | |
| 519 | + return s | |
| 520 | + | |
| 521 | +def gen_finish(name): | |
| 522 | + s = """\ | |
| 523 | + | |
| 524 | +AUBIO_TYPEOBJECT(%(name)s, "aubio.%(name)s") | |
| 525 | +""" % locals() | |
| 526 | + return s | |
| @@ -0,0 +1,187 @@ | ||
| 1 | +#! /usr/bin/python | |
| 2 | + | |
| 3 | +""" This file generates a c file from a list of cpp prototypes. """ | |
| 4 | + | |
| 5 | +import os, sys, shutil | |
| 6 | +from gen_pyobject import write_msg, gen_new_init, gen_do, gen_members, gen_methods, gen_finish | |
| 7 | + | |
| 8 | +def get_cpp_objects(): | |
| 9 | + | |
| 10 | + cpp_output = [l.strip() for l in os.popen('cpp -DAUBIO_UNSTABLE=1 -I../build/src ../src/aubio.h').readlines()] | |
| 11 | + | |
| 12 | + cpp_output = filter(lambda y: len(y) > 1, cpp_output) | |
| 13 | + cpp_output = filter(lambda y: not y.startswith('#'), cpp_output) | |
| 14 | + | |
| 15 | + i = 1 | |
| 16 | + while 1: | |
| 17 | + if i >= len(cpp_output): break | |
| 18 | + if cpp_output[i-1].endswith(',') or cpp_output[i-1].endswith('{') or cpp_output[i].startswith('}'): | |
| 19 | + cpp_output[i] = cpp_output[i-1] + ' ' + cpp_output[i] | |
| 20 | + cpp_output.pop(i-1) | |
| 21 | + else: | |
| 22 | + i += 1 | |
| 23 | + | |
| 24 | + typedefs = filter(lambda y: y.startswith ('typedef struct _aubio'), cpp_output) | |
| 25 | + | |
| 26 | + cpp_objects = [a.split()[3][:-1] for a in typedefs] | |
| 27 | + | |
| 28 | + return cpp_output, cpp_objects | |
| 29 | + | |
| 30 | +def generate_object_files(): | |
| 31 | + if os.path.isdir('generated'): shutil.rmtree('generated') | |
| 32 | + os.mkdir('generated') | |
| 33 | + | |
| 34 | + generated_objects = [] | |
| 35 | + cpp_output, cpp_objects = get_cpp_objects() | |
| 36 | + skip_objects = ['fft', | |
| 37 | + 'pvoc', | |
| 38 | + 'filter', | |
| 39 | + 'filterbank', | |
| 40 | + 'resampler', | |
| 41 | + 'sndfile', | |
| 42 | + 'sink_apple_audio', | |
| 43 | + 'sink_sndfile', | |
| 44 | + 'source_apple_audio', | |
| 45 | + 'source_sndfile'] | |
| 46 | + | |
| 47 | + write_msg("-- INFO: %d objects in total" % len(cpp_objects)) | |
| 48 | + | |
| 49 | + for this_object in cpp_objects: | |
| 50 | + lint = 0 | |
| 51 | + | |
| 52 | + if this_object[-2:] == '_t': | |
| 53 | + object_name = this_object[:-2] | |
| 54 | + else: | |
| 55 | + object_name = this_object | |
| 56 | + write_msg("-- WARNING: %s does not end in _t" % this_object) | |
| 57 | + | |
| 58 | + if object_name[:len('aubio_')] != 'aubio_': | |
| 59 | + write_msg("-- WARNING: %s does not start n aubio_" % this_object) | |
| 60 | + | |
| 61 | + write_msg("-- INFO: looking at", object_name) | |
| 62 | + object_methods = filter(lambda x: this_object in x, cpp_output) | |
| 63 | + object_methods = [a.strip() for a in object_methods] | |
| 64 | + object_methods = filter(lambda x: not x.startswith('typedef'), object_methods) | |
| 65 | + #for method in object_methods: | |
| 66 | + # write_msg(method) | |
| 67 | + new_methods = filter(lambda x: 'new_'+object_name in x, object_methods) | |
| 68 | + if len(new_methods) > 1: | |
| 69 | + write_msg("-- WARNING: more than one new method for", object_name) | |
| 70 | + for method in new_methods: | |
| 71 | + write_msg(method) | |
| 72 | + elif len(new_methods) < 1: | |
| 73 | + write_msg("-- WARNING: no new method for", object_name) | |
| 74 | + elif 0: | |
| 75 | + for method in new_methods: | |
| 76 | + write_msg(method) | |
| 77 | + | |
| 78 | + del_methods = filter(lambda x: 'del_'+object_name in x, object_methods) | |
| 79 | + if len(del_methods) > 1: | |
| 80 | + write_msg("-- WARNING: more than one del method for", object_name) | |
| 81 | + for method in del_methods: | |
| 82 | + write_msg(method) | |
| 83 | + elif len(del_methods) < 1: | |
| 84 | + write_msg("-- WARNING: no del method for", object_name) | |
| 85 | + | |
| 86 | + do_methods = filter(lambda x: object_name+'_do' in x, object_methods) | |
| 87 | + if len(do_methods) > 1: | |
| 88 | + pass | |
| 89 | + #write_msg("-- WARNING: more than one do method for", object_name) | |
| 90 | + #for method in do_methods: | |
| 91 | + # write_msg(method) | |
| 92 | + elif len(do_methods) < 1: | |
| 93 | + write_msg("-- WARNING: no do method for", object_name) | |
| 94 | + elif 0: | |
| 95 | + for method in do_methods: | |
| 96 | + write_msg(method) | |
| 97 | + | |
| 98 | + # check do methods return void | |
| 99 | + for method in do_methods: | |
| 100 | + if (method.split()[0] != 'void'): | |
| 101 | + write_msg("-- ERROR: _do method does not return void:", method ) | |
| 102 | + | |
| 103 | + get_methods = filter(lambda x: object_name+'_get_' in x, object_methods) | |
| 104 | + | |
| 105 | + set_methods = filter(lambda x: object_name+'_set_' in x, object_methods) | |
| 106 | + for method in set_methods: | |
| 107 | + if (method.split()[0] != 'uint_t'): | |
| 108 | + write_msg("-- ERROR: _set method does not return uint_t:", method ) | |
| 109 | + | |
| 110 | + other_methods = filter(lambda x: x not in new_methods, object_methods) | |
| 111 | + other_methods = filter(lambda x: x not in del_methods, other_methods) | |
| 112 | + other_methods = filter(lambda x: x not in do_methods, other_methods) | |
| 113 | + other_methods = filter(lambda x: x not in get_methods, other_methods) | |
| 114 | + other_methods = filter(lambda x: x not in set_methods, other_methods) | |
| 115 | + | |
| 116 | + if len(other_methods) > 0: | |
| 117 | + write_msg("-- WARNING: some methods for", object_name, "were unidentified") | |
| 118 | + for method in other_methods: | |
| 119 | + write_msg(method) | |
| 120 | + | |
| 121 | + | |
| 122 | + # generate this_object | |
| 123 | + short_name = object_name[len('aubio_'):] | |
| 124 | + if short_name in skip_objects: | |
| 125 | + write_msg("-- INFO: skipping object", short_name ) | |
| 126 | + continue | |
| 127 | + if 1: #try: | |
| 128 | + s = gen_new_init(new_methods[0], short_name) | |
| 129 | + s += gen_do(do_methods[0], short_name) | |
| 130 | + s += gen_members(new_methods[0], short_name) | |
| 131 | + s += gen_methods(get_methods, set_methods, short_name) | |
| 132 | + s += gen_finish(short_name) | |
| 133 | + generated_filepath = 'generated/gen-'+short_name+'.c' | |
| 134 | + fd = open(generated_filepath, 'w') | |
| 135 | + fd.write(s) | |
| 136 | + #except Exception, e: | |
| 137 | + # write_msg("-- ERROR:", type(e), str(e), "in", short_name) | |
| 138 | + # continue | |
| 139 | + generated_objects += [this_object] | |
| 140 | + | |
| 141 | + s = """// generated list of objects created with generator.py | |
| 142 | + | |
| 143 | +""" | |
| 144 | + | |
| 145 | + for each in generated_objects: | |
| 146 | + s += "extern PyTypeObject Py_%sType;\n" % \ | |
| 147 | + each.replace('aubio_','').replace('_t','') | |
| 148 | + | |
| 149 | + types_ready = [] | |
| 150 | + for each in generated_objects: | |
| 151 | + types_ready.append(" PyType_Ready (&Py_%sType) < 0" % \ | |
| 152 | + each.replace('aubio_','').replace('_t','') ) | |
| 153 | + | |
| 154 | + s += """ | |
| 155 | + int | |
| 156 | + generated_types_ready (void) | |
| 157 | + { | |
| 158 | + return ( | |
| 159 | + """ | |
| 160 | + s += ('\n ||').join(types_ready) | |
| 161 | + s += """); | |
| 162 | + } | |
| 163 | + """ | |
| 164 | + | |
| 165 | + s += """ | |
| 166 | + void | |
| 167 | + add_generated_objects ( PyObject *m ) | |
| 168 | + {""" | |
| 169 | + for each in generated_objects: | |
| 170 | + s += """ Py_INCREF (&Py_%(name)sType); | |
| 171 | + PyModule_AddObject (m, "%(name)s", (PyObject *) & Py_%(name)sType);""" % \ | |
| 172 | + { 'name': ( each.replace('aubio_','').replace('_t','') ) } | |
| 173 | + | |
| 174 | + s += """ | |
| 175 | + }""" | |
| 176 | + | |
| 177 | + fd = open('generated/aubio-generated.h', 'w') | |
| 178 | + fd.write(s) | |
| 179 | + | |
| 180 | + from os import listdir | |
| 181 | + generated_files = listdir('generated') | |
| 182 | + generated_files = filter(lambda x: x.endswith('.c'), generated_files) | |
| 183 | + generated_files = ['generated/'+f for f in generated_files] | |
| 184 | + return generated_files | |
| 185 | + | |
| 186 | +if __name__ == '__main__': | |
| 187 | + generate_object_files() | |
| @@ -0,0 +1,302 @@ | ||
| 1 | +#include "aubio-types.h" | |
| 2 | + | |
| 3 | +/* cvec type definition | |
| 4 | + | |
| 5 | +class cvec(): | |
| 6 | + def __init__(self, length = 1024): | |
| 7 | + self.length = length | |
| 8 | + self.norm = array(length) | |
| 9 | + self.phas = array(length) | |
| 10 | + | |
| 11 | +*/ | |
| 12 | + | |
| 13 | +static char Py_cvec_doc[] = "cvec object"; | |
| 14 | + | |
| 15 | +static PyObject * | |
| 16 | +Py_cvec_new (PyTypeObject * type, PyObject * args, PyObject * kwds) | |
| 17 | +{ | |
| 18 | + int length= 0; | |
| 19 | + Py_cvec *self; | |
| 20 | + static char *kwlist[] = { "length", NULL }; | |
| 21 | + | |
| 22 | + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, | |
| 23 | + &length)) { | |
| 24 | + return NULL; | |
| 25 | + } | |
| 26 | + | |
| 27 | + | |
| 28 | + self = (Py_cvec *) type->tp_alloc (type, 0); | |
| 29 | + | |
| 30 | + self->length = Py_default_vector_length / 2 + 1; | |
| 31 | + | |
| 32 | + if (self == NULL) { | |
| 33 | + return NULL; | |
| 34 | + } | |
| 35 | + | |
| 36 | + if (length > 0) { | |
| 37 | + self->length = length / 2 + 1; | |
| 38 | + } else if (length < 0) { | |
| 39 | + PyErr_SetString (PyExc_ValueError, | |
| 40 | + "can not use negative number of elements"); | |
| 41 | + return NULL; | |
| 42 | + } | |
| 43 | + | |
| 44 | + return (PyObject *) self; | |
| 45 | +} | |
| 46 | + | |
| 47 | +static int | |
| 48 | +Py_cvec_init (Py_cvec * self, PyObject * args, PyObject * kwds) | |
| 49 | +{ | |
| 50 | + self->o = new_cvec ((self->length - 1) * 2); | |
| 51 | + if (self->o == NULL) { | |
| 52 | + return -1; | |
| 53 | + } | |
| 54 | + | |
| 55 | + return 0; | |
| 56 | +} | |
| 57 | + | |
| 58 | +static void | |
| 59 | +Py_cvec_del (Py_cvec * self) | |
| 60 | +{ | |
| 61 | + del_cvec (self->o); | |
| 62 | + self->ob_type->tp_free ((PyObject *) self); | |
| 63 | +} | |
| 64 | + | |
| 65 | +static PyObject * | |
| 66 | +Py_cvec_repr (Py_cvec * self, PyObject * unused) | |
| 67 | +{ | |
| 68 | + PyObject *format = NULL; | |
| 69 | + PyObject *args = NULL; | |
| 70 | + PyObject *result = NULL; | |
| 71 | + | |
| 72 | + format = PyString_FromString ("aubio cvec of %d elements"); | |
| 73 | + if (format == NULL) { | |
| 74 | + goto fail; | |
| 75 | + } | |
| 76 | + | |
| 77 | + args = Py_BuildValue ("I", self->length); | |
| 78 | + if (args == NULL) { | |
| 79 | + goto fail; | |
| 80 | + } | |
| 81 | + cvec_print ( self->o ); | |
| 82 | + | |
| 83 | + result = PyString_Format (format, args); | |
| 84 | + | |
| 85 | +fail: | |
| 86 | + Py_XDECREF (format); | |
| 87 | + Py_XDECREF (args); | |
| 88 | + | |
| 89 | + return result; | |
| 90 | +} | |
| 91 | + | |
| 92 | +PyObject * | |
| 93 | +PyAubio_CvecNormToArray (Py_cvec * self) | |
| 94 | +{ | |
| 95 | + npy_intp dims[] = { self->o->length, 1 }; | |
| 96 | + return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->norm); | |
| 97 | +} | |
| 98 | + | |
| 99 | + | |
| 100 | +PyObject * | |
| 101 | +PyAubio_CvecPhasToArray (Py_cvec * self) | |
| 102 | +{ | |
| 103 | + npy_intp dims[] = { self->o->length, 1 }; | |
| 104 | + return PyArray_SimpleNewFromData (1, dims, NPY_FLOAT, self->o->phas); | |
| 105 | +} | |
| 106 | + | |
| 107 | +PyObject * | |
| 108 | +PyAubio_ArrayToCvecPhas (PyObject * self) | |
| 109 | +{ | |
| 110 | + return NULL; | |
| 111 | +} | |
| 112 | + | |
| 113 | +PyObject * | |
| 114 | +Py_cvec_get_norm (Py_cvec * self, void *closure) | |
| 115 | +{ | |
| 116 | + return PyAubio_CvecNormToArray(self); | |
| 117 | +} | |
| 118 | + | |
| 119 | +PyObject * | |
| 120 | +Py_cvec_get_phas (Py_cvec * self, void *closure) | |
| 121 | +{ | |
| 122 | + return PyAubio_CvecPhasToArray(self); | |
| 123 | +} | |
| 124 | + | |
| 125 | +static int | |
| 126 | +Py_cvec_set_norm (Py_cvec * vec, PyObject *input, void * closure) | |
| 127 | +{ | |
| 128 | + PyArrayObject * array; | |
| 129 | + if (input == NULL) { | |
| 130 | + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); | |
| 131 | + goto fail; | |
| 132 | + } | |
| 133 | + if (PyArray_Check(input)) { | |
| 134 | + | |
| 135 | + // we got an array, convert it to a cvec.norm | |
| 136 | + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { | |
| 137 | + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); | |
| 138 | + goto fail; | |
| 139 | + } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { | |
| 140 | + PyErr_SetString (PyExc_ValueError, | |
| 141 | + "input array has more than two dimensions"); | |
| 142 | + goto fail; | |
| 143 | + } | |
| 144 | + | |
| 145 | + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { | |
| 146 | + PyErr_SetString (PyExc_ValueError, "input array should be float"); | |
| 147 | + goto fail; | |
| 148 | + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { | |
| 149 | + PyErr_SetString (PyExc_ValueError, "input array should be float32"); | |
| 150 | + goto fail; | |
| 151 | + } | |
| 152 | + array = (PyArrayObject *)input; | |
| 153 | + | |
| 154 | + // check input array dimensions | |
| 155 | + if (PyArray_NDIM (array) != 1) { | |
| 156 | + PyErr_Format (PyExc_ValueError, | |
| 157 | + "input array has %d dimensions, not 1", | |
| 158 | + PyArray_NDIM (array)); | |
| 159 | + goto fail; | |
| 160 | + } else { | |
| 161 | + if (vec->o->length != PyArray_SIZE (array)) { | |
| 162 | + PyErr_Format (PyExc_ValueError, | |
| 163 | + "input array has length %d, but cvec has length %d", | |
| 164 | + (int)PyArray_SIZE (array), vec->o->length); | |
| 165 | + goto fail; | |
| 166 | + } | |
| 167 | + } | |
| 168 | + | |
| 169 | + vec->o->norm = (smpl_t *) PyArray_GETPTR1 (array, 0); | |
| 170 | + | |
| 171 | + } else { | |
| 172 | + PyErr_SetString (PyExc_ValueError, "can only accept array as input"); | |
| 173 | + return 1; | |
| 174 | + } | |
| 175 | + | |
| 176 | + Py_INCREF(array); | |
| 177 | + return 0; | |
| 178 | + | |
| 179 | +fail: | |
| 180 | + return 1; | |
| 181 | +} | |
| 182 | + | |
| 183 | +static int | |
| 184 | +Py_cvec_set_phas (Py_cvec * vec, PyObject *input, void * closure) | |
| 185 | +{ | |
| 186 | + PyArrayObject * array; | |
| 187 | + if (input == NULL) { | |
| 188 | + PyErr_SetString (PyExc_ValueError, "input array is not a python object"); | |
| 189 | + goto fail; | |
| 190 | + } | |
| 191 | + if (PyArray_Check(input)) { | |
| 192 | + | |
| 193 | + // we got an array, convert it to a cvec.phas | |
| 194 | + if (PyArray_NDIM ((PyArrayObject *)input) == 0) { | |
| 195 | + PyErr_SetString (PyExc_ValueError, "input array is a scalar"); | |
| 196 | + goto fail; | |
| 197 | + } else if (PyArray_NDIM ((PyArrayObject *)input) > 2) { | |
| 198 | + PyErr_SetString (PyExc_ValueError, | |
| 199 | + "input array has more than two dimensions"); | |
| 200 | + goto fail; | |
| 201 | + } | |
| 202 | + | |
| 203 | + if (!PyArray_ISFLOAT ((PyArrayObject *)input)) { | |
| 204 | + PyErr_SetString (PyExc_ValueError, "input array should be float"); | |
| 205 | + goto fail; | |
| 206 | + } else if (PyArray_TYPE ((PyArrayObject *)input) != AUBIO_NPY_SMPL) { | |
| 207 | + PyErr_SetString (PyExc_ValueError, "input array should be float32"); | |
| 208 | + goto fail; | |
| 209 | + } | |
| 210 | + array = (PyArrayObject *)input; | |
| 211 | + | |
| 212 | + // check input array dimensions | |
| 213 | + if (PyArray_NDIM (array) != 1) { | |
| 214 | + PyErr_Format (PyExc_ValueError, | |
| 215 | + "input array has %d dimensions, not 1", | |
| 216 | + PyArray_NDIM (array)); | |
| 217 | + goto fail; | |
| 218 | + } else { | |
| 219 | + if (vec->o->length != PyArray_SIZE (array)) { | |
| 220 | + PyErr_Format (PyExc_ValueError, | |
| 221 | + "input array has length %d, but cvec has length %d", | |
| 222 | + (int)PyArray_SIZE (array), vec->o->length); | |
| 223 | + goto fail; | |
| 224 | + } | |
| 225 | + } | |
| 226 | + | |
| 227 | + vec->o->phas = (smpl_t *) PyArray_GETPTR1 (array, 0); | |
| 228 | + | |
| 229 | + } else { | |
| 230 | + PyErr_SetString (PyExc_ValueError, "can only accept array as input"); | |
| 231 | + return 1; | |
| 232 | + } | |
| 233 | + | |
| 234 | + Py_INCREF(array); | |
| 235 | + return 0; | |
| 236 | + | |
| 237 | +fail: | |
| 238 | + return 1; | |
| 239 | +} | |
| 240 | + | |
| 241 | +static PyMemberDef Py_cvec_members[] = { | |
| 242 | + // TODO remove READONLY flag and define getter/setter | |
| 243 | + {"length", T_INT, offsetof (Py_cvec, length), READONLY, | |
| 244 | + "length attribute"}, | |
| 245 | + {NULL} /* Sentinel */ | |
| 246 | +}; | |
| 247 | + | |
| 248 | +static PyMethodDef Py_cvec_methods[] = { | |
| 249 | + {NULL} | |
| 250 | +}; | |
| 251 | + | |
| 252 | +static PyGetSetDef Py_cvec_getseters[] = { | |
| 253 | + {"norm", (getter)Py_cvec_get_norm, (setter)Py_cvec_set_norm, | |
| 254 | + "Numpy vector of shape (length,) containing the magnitude", | |
| 255 | + NULL}, | |
| 256 | + {"phas", (getter)Py_cvec_get_phas, (setter)Py_cvec_set_phas, | |
| 257 | + "Numpy vector of shape (length,) containing the phase", | |
| 258 | + NULL}, | |
| 259 | + {NULL} /* sentinel */ | |
| 260 | +}; | |
| 261 | + | |
| 262 | +PyTypeObject Py_cvecType = { | |
| 263 | + PyObject_HEAD_INIT (NULL) | |
| 264 | + 0, /* ob_size */ | |
| 265 | + "aubio.cvec", /* tp_name */ | |
| 266 | + sizeof (Py_cvec), /* tp_basicsize */ | |
| 267 | + 0, /* tp_itemsize */ | |
| 268 | + (destructor) Py_cvec_del, /* tp_dealloc */ | |
| 269 | + 0, /* tp_print */ | |
| 270 | + 0, /* tp_getattr */ | |
| 271 | + 0, /* tp_setattr */ | |
| 272 | + 0, /* tp_compare */ | |
| 273 | + (reprfunc) Py_cvec_repr, /* tp_repr */ | |
| 274 | + 0, /* tp_as_number */ | |
| 275 | + 0, //&Py_cvec_tp_as_sequence, /* tp_as_sequence */ | |
| 276 | + 0, /* tp_as_mapping */ | |
| 277 | + 0, /* tp_hash */ | |
| 278 | + 0, /* tp_call */ | |
| 279 | + 0, /* tp_str */ | |
| 280 | + 0, /* tp_getattro */ | |
| 281 | + 0, /* tp_setattro */ | |
| 282 | + 0, /* tp_as_buffer */ | |
| 283 | + Py_TPFLAGS_DEFAULT, /* tp_flags */ | |
| 284 | + Py_cvec_doc, /* tp_doc */ | |
| 285 | + 0, /* tp_traverse */ | |
| 286 | + 0, /* tp_clear */ | |
| 287 | + 0, /* tp_richcompare */ | |
| 288 | + 0, /* tp_weaklistoffset */ | |
| 289 | + 0, /* tp_iter */ | |
| 290 | + 0, /* tp_iternext */ | |
| 291 | + Py_cvec_methods, /* tp_methods */ | |
| 292 | + Py_cvec_members, /* tp_members */ | |
| 293 | + Py_cvec_getseters, /* tp_getset */ | |
| 294 | + 0, /* tp_base */ | |
| 295 | + 0, /* tp_dict */ | |
| 296 | + 0, /* tp_descr_get */ | |
| 297 | + 0, /* tp_descr_set */ | |
| 298 | + 0, /* tp_dictoffset */ | |
| 299 | + (initproc) Py_cvec_init, /* tp_init */ | |
| 300 | + 0, /* tp_alloc */ | |
| 301 | + Py_cvec_new, /* tp_new */ | |
| 302 | +}; | |
| @@ -0,0 +1,107 @@ | ||
| 1 | +#include "aubiowraphell.h" | |
| 2 | + | |
| 3 | +static char Py_fft_doc[] = "fft object"; | |
| 4 | + | |
| 5 | +AUBIO_DECLARE(fft, uint_t win_s) | |
| 6 | + | |
| 7 | +//AUBIO_NEW(fft) | |
| 8 | +static PyObject * | |
| 9 | +Py_fft_new (PyTypeObject * type, PyObject * args, PyObject * kwds) | |
| 10 | +{ | |
| 11 | + int win_s = 0; | |
| 12 | + Py_fft *self; | |
| 13 | + static char *kwlist[] = { "win_s", NULL }; | |
| 14 | + | |
| 15 | + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, | |
| 16 | + &win_s)) { | |
| 17 | + return NULL; | |
| 18 | + } | |
| 19 | + | |
| 20 | + self = (Py_fft *) type->tp_alloc (type, 0); | |
| 21 | + | |
| 22 | + if (self == NULL) { | |
| 23 | + return NULL; | |
| 24 | + } | |
| 25 | + | |
| 26 | + self->win_s = Py_default_vector_length; | |
| 27 | + | |
| 28 | + if (self == NULL) { | |
| 29 | + return NULL; | |
| 30 | + } | |
| 31 | + | |
| 32 | + if (win_s > 0) { | |
| 33 | + self->win_s = win_s; | |
| 34 | + } else if (win_s < 0) { | |
| 35 | + PyErr_SetString (PyExc_ValueError, | |
| 36 | + "can not use negative window size"); | |
| 37 | + return NULL; | |
| 38 | + } | |
| 39 | + | |
| 40 | + return (PyObject *) self; | |
| 41 | +} | |
| 42 | + | |
| 43 | + | |
| 44 | +AUBIO_INIT(fft, self->win_s) | |
| 45 | + | |
| 46 | +AUBIO_DEL(fft) | |
| 47 | + | |
| 48 | +static PyObject * | |
| 49 | +Py_fft_do(PyObject * self, PyObject * args) | |
| 50 | +{ | |
| 51 | + PyObject *input; | |
| 52 | + fvec_t *vec; | |
| 53 | + cvec_t *output; | |
| 54 | + | |
| 55 | + if (!PyArg_ParseTuple (args, "O", &input)) { | |
| 56 | + return NULL; | |
| 57 | + } | |
| 58 | + | |
| 59 | + vec = PyAubio_ArrayToCFvec (input); | |
| 60 | + | |
| 61 | + if (vec == NULL) { | |
| 62 | + return NULL; | |
| 63 | + } | |
| 64 | + | |
| 65 | + output = new_cvec(((Py_fft *) self)->win_s); | |
| 66 | + | |
| 67 | + // compute the function | |
| 68 | + aubio_fft_do (((Py_fft *)self)->o, vec, output); | |
| 69 | + return (PyObject *)PyAubio_CCvecToPyCvec(output); | |
| 70 | +} | |
| 71 | + | |
| 72 | +AUBIO_MEMBERS_START(fft) | |
| 73 | + {"win_s", T_INT, offsetof (Py_fft, win_s), READONLY, | |
| 74 | + "size of the window"}, | |
| 75 | +AUBIO_MEMBERS_STOP(fft) | |
| 76 | + | |
| 77 | +static PyObject * | |
| 78 | +Py_fft_rdo(Py_fft * self, PyObject * args) | |
| 79 | +{ | |
| 80 | + PyObject *input; | |
| 81 | + cvec_t *vec; | |
| 82 | + fvec_t *output; | |
| 83 | + | |
| 84 | + if (!PyArg_ParseTuple (args, "O", &input)) { | |
| 85 | + return NULL; | |
| 86 | + } | |
| 87 | + | |
| 88 | + vec = PyAubio_ArrayToCCvec (input); | |
| 89 | + | |
| 90 | + if (vec == NULL) { | |
| 91 | + return NULL; | |
| 92 | + } | |
| 93 | + | |
| 94 | + output = new_fvec(self->win_s); | |
| 95 | + | |
| 96 | + // compute the function | |
| 97 | + aubio_fft_rdo (((Py_fft *)self)->o, vec, output); | |
| 98 | + return (PyObject *)PyAubio_CFvecToArray(output); | |
| 99 | +} | |
| 100 | + | |
| 101 | +static PyMethodDef Py_fft_methods[] = { | |
| 102 | + {"rdo", (PyCFunction) Py_fft_rdo, METH_VARARGS, | |
| 103 | + "synthesis of spectral grain"}, | |
| 104 | + {NULL} | |
| 105 | +}; | |
| 106 | + | |
| 107 | +AUBIO_TYPEOBJECT(fft, "aubio.fft") | |
| @@ -0,0 +1,198 @@ | ||
| 1 | +#include "aubio-types.h" | |
| 2 | + | |
| 3 | +typedef struct | |
| 4 | +{ | |
| 5 | + PyObject_HEAD | |
| 6 | + aubio_filter_t * o; | |
| 7 | + uint_t order; | |
| 8 | +} Py_filter; | |
| 9 | + | |
| 10 | +static char Py_filter_doc[] = "filter object"; | |
| 11 | + | |
| 12 | +static PyObject * | |
| 13 | +Py_filter_new (PyTypeObject * type, PyObject * args, PyObject * kwds) | |
| 14 | +{ | |
| 15 | + int order= 0; | |
| 16 | + Py_filter *self; | |
| 17 | + static char *kwlist[] = { "order", NULL }; | |
| 18 | + | |
| 19 | + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|I", kwlist, | |
| 20 | + &order)) { | |
| 21 | + return NULL; | |
| 22 | + } | |
| 23 | + | |
| 24 | + self = (Py_filter *) type->tp_alloc (type, 0); | |
| 25 | + | |
| 26 | + if (self == NULL) { | |
| 27 | + return NULL; | |
| 28 | + } | |
| 29 | + | |
| 30 | + self->order = 7; | |
| 31 | + | |
| 32 | + if (order > 0) { | |
| 33 | + self->order = order; | |
| 34 | + } else if (order < 0) { | |
| 35 | + PyErr_SetString (PyExc_ValueError, | |
| 36 | + "can not use negative order"); | |
| 37 | + return NULL; | |
| 38 | + } | |
| 39 | + | |
| 40 | + return (PyObject *) self; | |
| 41 | +} | |
| 42 | + | |
| 43 | +static int | |
| 44 | +Py_filter_init (Py_filter * self, PyObject * args, PyObject * kwds) | |
| 45 | +{ | |
| 46 | + self->o = new_aubio_filter (self->order); | |
| 47 | + if (self->o == NULL) { | |
| 48 | + return -1; | |
| 49 | + } | |
| 50 | + | |
| 51 | + return 0; | |
| 52 | +} | |
| 53 | + | |
| 54 | +static void | |
| 55 | +Py_filter_del (Py_filter * self) | |
| 56 | +{ | |
| 57 | + del_aubio_filter (self->o); | |
| 58 | + self->ob_type->tp_free ((PyObject *) self); | |
| 59 | +} | |
| 60 | + | |
| 61 | +static PyObject * | |
| 62 | +Py_filter_do(Py_filter * self, PyObject * args) | |
| 63 | +{ | |
| 64 | + PyObject *input; | |
| 65 | + fvec_t *vec; | |
| 66 | + | |
| 67 | + if (!PyArg_ParseTuple (args, "O:digital_filter.do", &input)) { | |
| 68 | + return NULL; | |
| 69 | + } | |
| 70 | + | |
| 71 | + if (input == NULL) { | |
| 72 | + return NULL; | |
| 73 | + } | |
| 74 | + | |
| 75 | + vec = PyAubio_ArrayToCFvec (input); | |
| 76 | + | |
| 77 | + if (vec == NULL) { | |
| 78 | + return NULL; | |
| 79 | + } | |
| 80 | + | |
| 81 | + // compute the function | |
| 82 | + fvec_t * out = new_fvec(vec->length); | |
| 83 | + aubio_filter_do_outplace (self->o, vec, out); | |
| 84 | + return PyAubio_CFvecToArray(out); | |
| 85 | +} | |
| 86 | + | |
| 87 | +static PyObject * | |
| 88 | +Py_filter_set_c_weighting (Py_filter * self, PyObject *args) | |
| 89 | +{ | |
| 90 | + uint_t err = 0; | |
| 91 | + uint_t samplerate; | |
| 92 | + if (!PyArg_ParseTuple (args, "I", &samplerate)) { | |
| 93 | + return NULL; | |
| 94 | + } | |
| 95 | + | |
| 96 | + err = aubio_filter_set_c_weighting (self->o, samplerate); | |
| 97 | + if (err > 0) { | |
| 98 | + PyErr_SetString (PyExc_ValueError, | |
| 99 | + "error when setting filter to C-weighting"); | |
| 100 | + return NULL; | |
| 101 | + } | |
| 102 | + return Py_None; | |
| 103 | +} | |
| 104 | + | |
| 105 | +static PyObject * | |
| 106 | +Py_filter_set_a_weighting (Py_filter * self, PyObject *args) | |
| 107 | +{ | |
| 108 | + uint_t err = 0; | |
| 109 | + uint_t samplerate; | |
| 110 | + if (!PyArg_ParseTuple (args, "I", &samplerate)) { | |
| 111 | + return NULL; | |
| 112 | + } | |
| 113 | + | |
| 114 | + err = aubio_filter_set_a_weighting (self->o, samplerate); | |
| 115 | + if (err > 0) { | |
| 116 | + PyErr_SetString (PyExc_ValueError, | |
| 117 | + "error when setting filter to A-weighting"); | |
| 118 | + return NULL; | |
| 119 | + } | |
| 120 | + return Py_None; | |
| 121 | +} | |
| 122 | + | |
| 123 | +static PyObject * | |
| 124 | +Py_filter_set_biquad(Py_filter * self, PyObject *args) | |
| 125 | +{ | |
| 126 | + uint_t err = 0; | |
| 127 | + lsmp_t b0, b1, b2, a1, a2; | |
| 128 | + if (!PyArg_ParseTuple (args, "ddddd", &b0, &b1, &b2, &a1, &a2)) { | |
| 129 | + return NULL; | |
| 130 | + } | |
| 131 | + | |
| 132 | + err = aubio_filter_set_biquad (self->o, b0, b1, b2, a1, a2); | |
| 133 | + if (err > 0) { | |
| 134 | + PyErr_SetString (PyExc_ValueError, | |
| 135 | + "error when setting filter with biquad coefficients"); | |
| 136 | + return NULL; | |
| 137 | + } | |
| 138 | + return Py_None; | |
| 139 | +} | |
| 140 | + | |
| 141 | +static PyMemberDef Py_filter_members[] = { | |
| 142 | + // TODO remove READONLY flag and define getter/setter | |
| 143 | + {"order", T_INT, offsetof (Py_filter, order), READONLY, | |
| 144 | + "order of the filter"}, | |
| 145 | + {NULL} /* Sentinel */ | |
| 146 | +}; | |
| 147 | + | |
| 148 | +static PyMethodDef Py_filter_methods[] = { | |
| 149 | + {"set_c_weighting", (PyCFunction) Py_filter_set_c_weighting, METH_VARARGS, | |
| 150 | + "set filter coefficients to C-weighting"}, | |
| 151 | + {"set_a_weighting", (PyCFunction) Py_filter_set_a_weighting, METH_VARARGS, | |
| 152 | + "set filter coefficients to A-weighting"}, | |
| 153 | + {"set_biquad", (PyCFunction) Py_filter_set_biquad, METH_VARARGS, | |
| 154 | + "set b0, b1, b2, a1, a2 biquad coefficients"}, | |
| 155 | + {NULL} | |
| 156 | +}; | |
| 157 | + | |
| 158 | +PyTypeObject Py_filterType = { | |
| 159 | + PyObject_HEAD_INIT (NULL) | |
| 160 | + 0, /* ob_size */ | |
| 161 | + "aubio.digital_filter", /* tp_name */ | |
| 162 | + sizeof (Py_filter), /* tp_basicsize */ | |
| 163 | + 0, /* tp_itemsize */ | |
| 164 | + (destructor) Py_filter_del, /* tp_dealloc */ | |
| 165 | + 0, /* tp_print */ | |
| 166 | + 0, /* tp_getattr */ | |
| 167 | + 0, /* tp_setattr */ | |
| 168 | + 0, /* tp_compare */ | |
| 169 | + 0, //(reprfunc) Py_filter_repr, /* tp_repr */ | |
| 170 | + 0, /* tp_as_number */ | |
| 171 | + 0, /* tp_as_sequence */ | |
| 172 | + 0, /* tp_as_mapping */ | |
| 173 | + 0, /* tp_hash */ | |
| 174 | + (ternaryfunc)Py_filter_do, /* tp_call */ | |
| 175 | + 0, /* tp_str */ | |
| 176 | + 0, /* tp_getattro */ | |
| 177 | + 0, /* tp_setattro */ | |
| 178 | + 0, /* tp_as_buffer */ | |
| 179 | + Py_TPFLAGS_DEFAULT, /* tp_flags */ | |
| 180 | + Py_filter_doc, /* tp_doc */ | |
| 181 | + 0, /* tp_traverse */ | |
| 182 | + 0, /* tp_clear */ | |
| 183 | + 0, /* tp_richcompare */ | |
| 184 | + 0, /* tp_weaklistoffset */ | |
| 185 | + 0, /* tp_iter */ | |
| 186 | + 0, /* tp_iternext */ | |
| 187 | + Py_filter_methods, /* tp_methods */ | |
| 188 | + Py_filter_members, /* tp_members */ | |
| 189 | + 0, /* tp_getset */ | |
| 190 | + 0, /* tp_base */ | |
| 191 | + 0, /* tp_dict */ | |
| 192 | + 0, /* tp_descr_get */ | |
| 193 | + 0, /* tp_descr_set */ | |
| 194 | + 0, /* tp_dictoffset */ | |
| 195 | + (initproc) Py_filter_init, /* tp_init */ | |
| 196 | + 0, /* tp_alloc */ | |
| 197 | + Py_filter_new, /* tp_new */ | |
| 198 | +}; | |
| @@ -0,0 +1,183 @@ | ||
| 1 | +#include "aubiowraphell.h" | |
| 2 | + | |
| 3 | +static char Py_filterbank_doc[] = "filterbank object"; | |
| 4 | + | |
| 5 | +AUBIO_DECLARE(filterbank, uint_t n_filters; uint_t win_s) | |
| 6 | + | |
| 7 | +//AUBIO_NEW(filterbank) | |
| 8 | +static PyObject * | |
| 9 | +Py_filterbank_new (PyTypeObject * type, PyObject * args, PyObject * kwds) | |
| 10 | +{ | |
| 11 | + int win_s = 0, n_filters = 0; | |
| 12 | + Py_filterbank *self; | |
| 13 | + static char *kwlist[] = { "n_filters", "win_s", NULL }; | |
| 14 | + | |
| 15 | + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, | |
| 16 | + &n_filters, &win_s)) { | |
| 17 | + return NULL; | |
| 18 | + } | |
| 19 | + | |
| 20 | + self = (Py_filterbank *) type->tp_alloc (type, 0); | |
| 21 | + | |
| 22 | + if (self == NULL) { | |
| 23 | + return NULL; | |
| 24 | + } | |
| 25 | + | |
| 26 | + self->win_s = Py_default_vector_length; | |
| 27 | + if (win_s > 0) { | |
| 28 | + self->win_s = win_s; | |
| 29 | + } else if (win_s < 0) { | |
| 30 | + PyErr_SetString (PyExc_ValueError, | |
| 31 | + "can not use negative window size"); | |
| 32 | + return NULL; | |
| 33 | + } | |
| 34 | + | |
| 35 | + self->n_filters = 40; | |
| 36 | + if (n_filters > 0) { | |
| 37 | + self->n_filters = n_filters; | |
| 38 | + } else if (n_filters < 0) { | |
| 39 | + PyErr_SetString (PyExc_ValueError, | |
| 40 | + "can not use negative number of filters"); | |
| 41 | + return NULL; | |
| 42 | + } | |
| 43 | + | |
| 44 | + return (PyObject *) self; | |
| 45 | +} | |
| 46 | + | |
| 47 | + | |
| 48 | +AUBIO_INIT(filterbank, self->n_filters, self->win_s) | |
| 49 | + | |
| 50 | +AUBIO_DEL(filterbank) | |
| 51 | + | |
| 52 | +static PyObject * | |
| 53 | +Py_filterbank_do(Py_filterbank * self, PyObject * args) | |
| 54 | +{ | |
| 55 | + PyObject *input; | |
| 56 | + cvec_t *vec; | |
| 57 | + fvec_t *out; | |
| 58 | + | |
| 59 | + if (!PyArg_ParseTuple (args, "O", &input)) { | |
| 60 | + return NULL; | |
| 61 | + } | |
| 62 | + | |
| 63 | + vec = PyAubio_ArrayToCCvec (input); | |
| 64 | + | |
| 65 | + if (vec == NULL) { | |
| 66 | + return NULL; | |
| 67 | + } | |
| 68 | + | |
| 69 | + out = new_fvec (self->n_filters); | |
| 70 | + | |
| 71 | + // compute the function | |
| 72 | + aubio_filterbank_do (self->o, vec, out); | |
| 73 | + return (PyObject *)PyAubio_CFvecToArray(out); | |
| 74 | +} | |
| 75 | + | |
| 76 | +AUBIO_MEMBERS_START(filterbank) | |
| 77 | + {"win_s", T_INT, offsetof (Py_filterbank, win_s), READONLY, | |
| 78 | + "size of the window"}, | |
| 79 | + {"n_filters", T_INT, offsetof (Py_filterbank, n_filters), READONLY, | |
| 80 | + "number of filters"}, | |
| 81 | +AUBIO_MEMBERS_STOP(filterbank) | |
| 82 | + | |
| 83 | +static PyObject * | |
| 84 | +Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) | |
| 85 | +{ | |
| 86 | + uint_t err = 0; | |
| 87 | + | |
| 88 | + PyObject *input; | |
| 89 | + uint_t samplerate; | |
| 90 | + fvec_t *freqs; | |
| 91 | + if (!PyArg_ParseTuple (args, "OI", &input, &samplerate)) { | |
| 92 | + return NULL; | |
| 93 | + } | |
| 94 | + | |
| 95 | + if (input == NULL) { | |
| 96 | + return NULL; | |
| 97 | + } | |
| 98 | + | |
| 99 | + freqs = PyAubio_ArrayToCFvec (input); | |
| 100 | + | |
| 101 | + if (freqs == NULL) { | |
| 102 | + return NULL; | |
| 103 | + } | |
| 104 | + | |
| 105 | + err = aubio_filterbank_set_triangle_bands (self->o, | |
| 106 | + freqs, samplerate); | |
| 107 | + if (err > 0) { | |
| 108 | + PyErr_SetString (PyExc_ValueError, | |
| 109 | + "error when setting filter to A-weighting"); | |
| 110 | + return NULL; | |
| 111 | + } | |
| 112 | + return Py_None; | |
| 113 | +} | |
| 114 | + | |
| 115 | +static PyObject * | |
| 116 | +Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) | |
| 117 | +{ | |
| 118 | + uint_t err = 0; | |
| 119 | + | |
| 120 | + uint_t samplerate; | |
| 121 | + if (!PyArg_ParseTuple (args, "I", &samplerate)) { | |
| 122 | + return NULL; | |
| 123 | + } | |
| 124 | + | |
| 125 | + err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate); | |
| 126 | + if (err > 0) { | |
| 127 | + PyErr_SetString (PyExc_ValueError, | |
| 128 | + "error when setting filter to A-weighting"); | |
| 129 | + return NULL; | |
| 130 | + } | |
| 131 | + return Py_None; | |
| 132 | +} | |
| 133 | + | |
| 134 | +static PyObject * | |
| 135 | +Py_filterbank_set_coeffs (Py_filterbank * self, PyObject *args) | |
| 136 | +{ | |
| 137 | + uint_t err = 0; | |
| 138 | + | |
| 139 | + PyObject *input; | |
| 140 | + fmat_t *coeffs; | |
| 141 | + | |
| 142 | + if (!PyArg_ParseTuple (args, "O", &input)) { | |
| 143 | + return NULL; | |
| 144 | + } | |
| 145 | + | |
| 146 | + coeffs = PyAubio_ArrayToCFmat (input); | |
| 147 | + | |
| 148 | + if (coeffs == NULL) { | |
| 149 | + PyErr_SetString (PyExc_ValueError, | |
| 150 | + "unable to parse input array"); | |
| 151 | + return NULL; | |
| 152 | + } | |
| 153 | + | |
| 154 | + err = aubio_filterbank_set_coeffs (self->o, coeffs); | |
| 155 | + | |
| 156 | + if (err > 0) { | |
| 157 | + PyErr_SetString (PyExc_ValueError, | |
| 158 | + "error when setting filter coefficients"); | |
| 159 | + return NULL; | |
| 160 | + } | |
| 161 | + return Py_None; | |
| 162 | +} | |
| 163 | + | |
| 164 | +static PyObject * | |
| 165 | +Py_filterbank_get_coeffs (Py_filterbank * self, PyObject *unused) | |
| 166 | +{ | |
| 167 | + return (PyObject *)PyAubio_CFmatToArray( | |
| 168 | + aubio_filterbank_get_coeffs (self->o) ); | |
| 169 | +} | |
| 170 | + | |
| 171 | +static PyMethodDef Py_filterbank_methods[] = { | |
| 172 | + {"set_triangle_bands", (PyCFunction) Py_filterbank_set_triangle_bands, | |
| 173 | + METH_VARARGS, "set coefficients of filterbanks"}, | |
| 174 | + {"set_mel_coeffs_slaney", (PyCFunction) Py_filterbank_set_mel_coeffs_slaney, | |
| 175 | + METH_VARARGS, "set coefficients of filterbank as in Auditory Toolbox"}, | |
| 176 | + {"get_coeffs", (PyCFunction) Py_filterbank_get_coeffs, | |
| 177 | + METH_NOARGS, "get coefficients of filterbank"}, | |
| 178 | + {"set_coeffs", (PyCFunction) Py_filterbank_set_coeffs, | |
| 179 | + METH_VARARGS, "set coefficients of filterbank"}, | |
| 180 | + {NULL} | |
| 181 | +}; | |
| 182 | + | |
| 183 | +AUBIO_TYPEOBJECT(filterbank, "aubio.filterbank") | |
| @@ -0,0 +1,118 @@ | ||
| 1 | +#include "aubiowraphell.h" | |
| 2 | + | |
| 3 | +static char Py_pvoc_doc[] = "pvoc object"; | |
| 4 | + | |
| 5 | +AUBIO_DECLARE(pvoc, uint_t win_s; uint_t hop_s) | |
| 6 | + | |
| 7 | +//AUBIO_NEW(pvoc) | |
| 8 | +static PyObject * | |
| 9 | +Py_pvoc_new (PyTypeObject * type, PyObject * args, PyObject * kwds) | |
| 10 | +{ | |
| 11 | + int win_s = 0, hop_s = 0; | |
| 12 | + Py_pvoc *self; | |
| 13 | + static char *kwlist[] = { "win_s", "hop_s", NULL }; | |
| 14 | + | |
| 15 | + if (!PyArg_ParseTupleAndKeywords (args, kwds, "|II", kwlist, | |
| 16 | + &win_s, &hop_s)) { | |
| 17 | + return NULL; | |
| 18 | + } | |
| 19 | + | |
| 20 | + self = (Py_pvoc *) type->tp_alloc (type, 0); | |
| 21 | + | |
| 22 | + if (self == NULL) { | |
| 23 | + return NULL; | |
| 24 | + } | |
| 25 | + | |
| 26 | + self->win_s = Py_default_vector_length; | |
| 27 | + self->hop_s = Py_default_vector_length/2; | |
| 28 | + | |
| 29 | + if (self == NULL) { | |
| 30 | + return NULL; | |
| 31 | + } | |
| 32 | + | |
| 33 | + if (win_s > 0) { | |
| 34 | + self->win_s = win_s; | |
| 35 | + } else if (win_s < 0) { | |
| 36 | + PyErr_SetString (PyExc_ValueError, | |
| 37 | + "can not use negative window size"); | |
| 38 | + return NULL; | |
| 39 | + } | |
| 40 | + | |
| 41 | + if (hop_s > 0) { | |
| 42 | + self->hop_s = hop_s; | |
| 43 | + } else if (hop_s < 0) { | |
| 44 | + PyErr_SetString (PyExc_ValueError, | |
| 45 | + "can not use negative hop size"); | |
| 46 | + return NULL; | |
| 47 | + } | |
| 48 | + | |
| 49 | + return (PyObject *) self; | |
| 50 | +} | |
| 51 | + | |
| 52 | + | |
| 53 | +AUBIO_INIT(pvoc, self->win_s, self->hop_s) | |
| 54 | + | |
| 55 | +AUBIO_DEL(pvoc) | |
| 56 | + | |
| 57 | +static PyObject * | |
| 58 | +Py_pvoc_do(Py_pvoc * self, PyObject * args) | |
| 59 | +{ | |
| 60 | + PyObject *input; | |
| 61 | + fvec_t *vec; | |
| 62 | + cvec_t *output; | |
| 63 | + | |
| 64 | + if (!PyArg_ParseTuple (args, "O", &input)) { | |
| 65 | + return NULL; | |
| 66 | + } | |
| 67 | + | |
| 68 | + vec = PyAubio_ArrayToCFvec (input); | |
| 69 | + | |
| 70 | + if (vec == NULL) { | |
| 71 | + return NULL; | |
| 72 | + } | |
| 73 | + | |
| 74 | + output = new_cvec(self->win_s); | |
| 75 | + | |
| 76 | + // compute the function | |
| 77 | + aubio_pvoc_do (self->o, vec, output); | |
| 78 | + return (PyObject *)PyAubio_CCvecToPyCvec(output); | |
| 79 | +} | |
| 80 | + | |
| 81 | +AUBIO_MEMBERS_START(pvoc) | |
| 82 | + {"win_s", T_INT, offsetof (Py_pvoc, win_s), READONLY, | |
| 83 | + "size of the window"}, | |
| 84 | + {"hop_s", T_INT, offsetof (Py_pvoc, hop_s), READONLY, | |
| 85 | + "size of the hop"}, | |
| 86 | +AUBIO_MEMBERS_STOP(pvoc) | |
| 87 | + | |
| 88 | +static PyObject * | |
| 89 | +Py_pvoc_rdo(Py_pvoc * self, PyObject * args) | |
| 90 | +{ | |
| 91 | + PyObject *input; | |
| 92 | + cvec_t *vec; | |
| 93 | + fvec_t *output; | |
| 94 | + | |
| 95 | + if (!PyArg_ParseTuple (args, "O", &input)) { | |
| 96 | + return NULL; | |
| 97 | + } | |
| 98 | + | |
| 99 | + vec = PyAubio_ArrayToCCvec (input); | |
| 100 | + | |
| 101 | + if (vec == NULL) { | |
| 102 | + return NULL; | |
| 103 | + } | |
| 104 | + | |
| 105 | + output = new_fvec(self->hop_s); | |
| 106 | + | |
| 107 | + // compute the function | |
| 108 | + aubio_pvoc_rdo (self->o, vec, output); | |
| 109 | + return (PyObject *)PyAubio_CFvecToArray(output); | |
| 110 | +} | |
| 111 | + | |
| 112 | +static PyMethodDef Py_pvoc_methods[] = { | |
| 113 | + {"rdo", (PyCFunction) Py_pvoc_rdo, METH_VARARGS, | |
| 114 | + "synthesis of spectral grain"}, | |
| 115 | + {NULL} | |
| 116 | +}; | |
| 117 | + | |
| 118 | +AUBIO_TYPEOBJECT(pvoc, "aubio.pvoc") | |
| @@ -0,0 +1,20 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +if __name__ == '__main__': | |
| 4 | + import os, sys, unittest | |
| 5 | + def load_test(): | |
| 6 | + # get relevant files | |
| 7 | + curdir = os.path.dirname(sys.argv[0]) | |
| 8 | + if curdir == '': curdir = '.' | |
| 9 | + files = os.listdir(os.path.join(curdir, 'tests')) | |
| 10 | + modfiles = filter (lambda y: y.endswith('.py'), files) | |
| 11 | + modfiles = filter (lambda f: f.startswith('test_'), modfiles) | |
| 12 | + # get module names | |
| 13 | + modnames = map (lambda x: os.path.splitext(x)[0], modfiles) | |
| 14 | + # import them | |
| 15 | + modules = map (__import__, modnames) | |
| 16 | + # create a test suites from the imported module | |
| 17 | + load_from_module = unittest.defaultTestLoader.loadTestsFromModule | |
| 18 | + tests = map(load_from_module, modules) | |
| 19 | + return unittest.TestSuite(tests) | |
| 20 | + unittest.main(defaultTest = 'load_test') | |
| @@ -0,0 +1,41 @@ | ||
| 1 | +#! /usr/bin/python | |
| 2 | + | |
| 3 | +from distutils.core import setup, Extension | |
| 4 | +from generator import generate_object_files | |
| 5 | +import os.path | |
| 6 | +import numpy | |
| 7 | + | |
| 8 | +library_dirs = ['../build/src', '../src/.libs'] | |
| 9 | +include_dirs = ['../build/src', '../src', '.' ] | |
| 10 | +library_dirs = filter (lambda x: os.path.isdir(x), library_dirs) | |
| 11 | +include_dirs = filter (lambda x: os.path.isdir(x), include_dirs) | |
| 12 | + | |
| 13 | +aubio_extension = Extension("_aubio", | |
| 14 | + ["aubiomodule.c", | |
| 15 | + "aubioproxy.c", | |
| 16 | + "py-cvec.c", | |
| 17 | + # example without macro | |
| 18 | + "py-filter.c", | |
| 19 | + # macroised | |
| 20 | + "py-filterbank.c", | |
| 21 | + "py-fft.c", | |
| 22 | + "py-phasevoc.c", | |
| 23 | + # generated files | |
| 24 | + ] + generate_object_files(), | |
| 25 | + include_dirs = include_dirs + [ numpy.get_include() ], | |
| 26 | + library_dirs = library_dirs, | |
| 27 | + libraries=['aubio']) | |
| 28 | + | |
| 29 | +setup(name='aubio', | |
| 30 | + version = '0.4.0alpha', | |
| 31 | + packages = ['aubio'], | |
| 32 | + description = 'interface to the aubio library', | |
| 33 | + long_description = 'interface to the aubio library', | |
| 34 | + license = 'GNU/GPL version 3', | |
| 35 | + author = 'Paul Brossier', | |
| 36 | + author_email = 'piem@aubio.org', | |
| 37 | + maintainer = 'Paul Brossier', | |
| 38 | + maintainer_email = 'piem@aubio.org', | |
| 39 | + url = 'http://aubio.org/', | |
| 40 | + ext_modules = [aubio_extension]) | |
| 41 | + | |
| @@ -0,0 +1,14 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | + | |
| 5 | +class aubiomodule_test_case(TestCase): | |
| 6 | + | |
| 7 | + def test_import(self): | |
| 8 | + """ try importing aubio """ | |
| 9 | + import aubio | |
| 10 | + | |
| 11 | +if __name__ == '__main__': | |
| 12 | + from unittest import main | |
| 13 | + main() | |
| 14 | + | |
| @@ -0,0 +1,50 @@ | ||
| 1 | +from numpy.testing import TestCase, run_module_suite | |
| 2 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 3 | +from aubio import cvec | |
| 4 | +from numpy import array, shape, pi | |
| 5 | + | |
| 6 | +class aubio_cvec_test_case(TestCase): | |
| 7 | + | |
| 8 | + def test_vector_created_with_zeroes(self): | |
| 9 | + a = cvec(10) | |
| 10 | + a | |
| 11 | + shape(a.norm) | |
| 12 | + shape(a.phas) | |
| 13 | + a.norm[0] | |
| 14 | + assert_equal(a.norm, 0.) | |
| 15 | + assert_equal(a.phas, 0.) | |
| 16 | + | |
| 17 | + def test_vector_assign_element(self): | |
| 18 | + a = cvec() | |
| 19 | + a.norm[0] = 1 | |
| 20 | + assert_equal(a.norm[0], 1) | |
| 21 | + a.phas[0] = 1 | |
| 22 | + assert_equal(a.phas[0], 1) | |
| 23 | + | |
| 24 | + def test_vector_assign_element_end(self): | |
| 25 | + a = cvec() | |
| 26 | + a.norm[-1] = 1 | |
| 27 | + assert_equal(a.norm[-1], 1) | |
| 28 | + assert_equal(a.norm[len(a.norm)-1], 1) | |
| 29 | + a.phas[-1] = 1 | |
| 30 | + assert_equal(a.phas[-1], 1) | |
| 31 | + assert_equal(a.phas[len(a.phas)-1], 1) | |
| 32 | + | |
| 33 | + def test_assign_cvec_norm_slice(self): | |
| 34 | + spec = cvec(1024) | |
| 35 | + spec.norm[40:100] = 100 | |
| 36 | + assert_equal (spec.norm[0:40], 0) | |
| 37 | + assert_equal (spec.norm[40:100], 100) | |
| 38 | + assert_equal (spec.norm[100:-1], 0) | |
| 39 | + assert_equal (spec.phas, 0) | |
| 40 | + | |
| 41 | + def test_assign_cvec_phas_slice(self): | |
| 42 | + spec = cvec(1024) | |
| 43 | + spec.phas[39:-1] = -pi | |
| 44 | + assert_equal (spec.phas[0:39], 0) | |
| 45 | + assert_equal (spec.phas[39:-1], -pi) | |
| 46 | + assert_equal (spec.norm, 0) | |
| 47 | + | |
| 48 | +if __name__ == '__main__': | |
| 49 | + from unittest import main | |
| 50 | + main() | |
| @@ -0,0 +1,113 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +# WARNING: numpy also has an fft object | |
| 6 | +from aubio import fvec, fft, cvec | |
| 7 | +from numpy import array, shape | |
| 8 | +from math import pi | |
| 9 | + | |
| 10 | +class aubio_fft_test_case(TestCase): | |
| 11 | + | |
| 12 | + def test_members(self): | |
| 13 | + f = fft() | |
| 14 | + assert_equal (f.win_s, 1024) | |
| 15 | + | |
| 16 | + def test_output_dimensions(self): | |
| 17 | + """ check the dimensions of output """ | |
| 18 | + win_s = 1024 | |
| 19 | + timegrain = fvec(win_s) | |
| 20 | + f = fft(win_s) | |
| 21 | + fftgrain = f (timegrain) | |
| 22 | + assert_equal (fftgrain.norm, 0) | |
| 23 | + assert_equal (shape(fftgrain.norm), (win_s/2+1,)) | |
| 24 | + assert_equal (fftgrain.phas, 0) | |
| 25 | + assert_equal (shape(fftgrain.phas), (win_s/2+1,)) | |
| 26 | + | |
| 27 | + def test_zeros(self): | |
| 28 | + """ check the transform of zeros """ | |
| 29 | + win_s = 512 | |
| 30 | + timegrain = fvec(win_s) | |
| 31 | + f = fft(win_s) | |
| 32 | + fftgrain = f(timegrain) | |
| 33 | + assert_equal ( fftgrain.norm == 0, True ) | |
| 34 | + assert_equal ( fftgrain.phas == 0, True ) | |
| 35 | + | |
| 36 | + def test_impulse(self): | |
| 37 | + """ check the transform of one impulse at a random place """ | |
| 38 | + from random import random | |
| 39 | + from math import floor | |
| 40 | + win_s = 256 | |
| 41 | + i = floor(random()*win_s) | |
| 42 | + impulse = pi * random() | |
| 43 | + f = fft(win_s) | |
| 44 | + timegrain = fvec(win_s) | |
| 45 | + timegrain[i] = impulse | |
| 46 | + fftgrain = f ( timegrain ) | |
| 47 | + #self.plot_this ( fftgrain.phas ) | |
| 48 | + assert_almost_equal ( fftgrain.norm, impulse, decimal = 6 ) | |
| 49 | + assert_equal ( fftgrain.phas <= pi, True) | |
| 50 | + assert_equal ( fftgrain.phas >= -pi, True) | |
| 51 | + | |
| 52 | + def test_impulse_negative(self): | |
| 53 | + """ check the transform of one impulse at a random place """ | |
| 54 | + from random import random | |
| 55 | + from math import floor | |
| 56 | + win_s = 256 | |
| 57 | + i = 0 | |
| 58 | + impulse = -10. | |
| 59 | + f = fft(win_s) | |
| 60 | + timegrain = fvec(win_s) | |
| 61 | + timegrain[i] = impulse | |
| 62 | + fftgrain = f ( timegrain ) | |
| 63 | + #self.plot_this ( fftgrain.phas ) | |
| 64 | + assert_almost_equal ( fftgrain.norm, abs(impulse), decimal = 6 ) | |
| 65 | + if impulse < 0: | |
| 66 | + # phase can be pi or -pi, as it is not unwrapped | |
| 67 | + assert_almost_equal ( abs(fftgrain.phas[1:-1]) , pi, decimal = 6 ) | |
| 68 | + assert_almost_equal ( fftgrain.phas[0], pi, decimal = 6) | |
| 69 | + assert_almost_equal ( fftgrain.phas[-1], pi, decimal = 6) | |
| 70 | + else: | |
| 71 | + assert_equal ( fftgrain.phas[1:-1] == 0, True) | |
| 72 | + assert_equal ( fftgrain.phas[0] == 0, True) | |
| 73 | + assert_equal ( fftgrain.phas[-1] == 0, True) | |
| 74 | + # now check the resynthesis | |
| 75 | + synthgrain = f.rdo ( fftgrain ) | |
| 76 | + #self.plot_this ( fftgrain.phas.T ) | |
| 77 | + assert_equal ( fftgrain.phas <= pi, True) | |
| 78 | + assert_equal ( fftgrain.phas >= -pi, True) | |
| 79 | + #self.plot_this ( synthgrain - timegrain ) | |
| 80 | + assert_almost_equal ( synthgrain, timegrain, decimal = 6 ) | |
| 81 | + | |
| 82 | + def test_impulse_at_zero(self): | |
| 83 | + """ check the transform of one impulse at a index 0 """ | |
| 84 | + win_s = 1024 | |
| 85 | + impulse = pi | |
| 86 | + f = fft(win_s) | |
| 87 | + timegrain = fvec(win_s) | |
| 88 | + timegrain[0] = impulse | |
| 89 | + fftgrain = f ( timegrain ) | |
| 90 | + #self.plot_this ( fftgrain.phas ) | |
| 91 | + assert_equal ( fftgrain.phas[0], 0) | |
| 92 | + # could be 0 or -0 depending on fft implementation (0 for fftw3, -0 for ooura) | |
| 93 | + assert_almost_equal ( fftgrain.phas[1], 0) | |
| 94 | + assert_almost_equal ( fftgrain.norm[0], impulse, decimal = 6 ) | |
| 95 | + | |
| 96 | + def test_rdo_before_do(self): | |
| 97 | + """ check running fft.rdo before fft.do works """ | |
| 98 | + win_s = 1024 | |
| 99 | + impulse = pi | |
| 100 | + f = fft(win_s) | |
| 101 | + fftgrain = cvec(win_s) | |
| 102 | + t = f.rdo( fftgrain ) | |
| 103 | + assert_equal ( t, 0 ) | |
| 104 | + | |
| 105 | + def plot_this(self, this): | |
| 106 | + from pylab import plot, show | |
| 107 | + plot ( this ) | |
| 108 | + show () | |
| 109 | + | |
| 110 | +if __name__ == '__main__': | |
| 111 | + from unittest import main | |
| 112 | + main() | |
| 113 | + | |
| @@ -0,0 +1,68 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, assert_equal, assert_almost_equal | |
| 4 | +from aubio import fvec, digital_filter | |
| 5 | +from numpy import array | |
| 6 | + | |
| 7 | +def array_from_text_file(filename, dtype = 'float'): | |
| 8 | + return array([line.split() for line in open(filename).readlines()], | |
| 9 | + dtype = dtype) | |
| 10 | + | |
| 11 | +class aubio_filter_test_case(TestCase): | |
| 12 | + | |
| 13 | + def test_members(self): | |
| 14 | + f = digital_filter() | |
| 15 | + assert_equal (f.order, 7) | |
| 16 | + f = digital_filter(5) | |
| 17 | + assert_equal (f.order, 5) | |
| 18 | + f(fvec()) | |
| 19 | + | |
| 20 | + def test_cweighting_error(self): | |
| 21 | + f = digital_filter (2) | |
| 22 | + self.assertRaises ( ValueError, f.set_c_weighting, 44100 ) | |
| 23 | + f = digital_filter (8) | |
| 24 | + self.assertRaises ( ValueError, f.set_c_weighting, 44100 ) | |
| 25 | + f = digital_filter (5) | |
| 26 | + self.assertRaises ( ValueError, f.set_c_weighting, 4000 ) | |
| 27 | + f = digital_filter (5) | |
| 28 | + self.assertRaises ( ValueError, f.set_c_weighting, 193000 ) | |
| 29 | + f = digital_filter (7) | |
| 30 | + self.assertRaises ( ValueError, f.set_a_weighting, 193000 ) | |
| 31 | + f = digital_filter (5) | |
| 32 | + self.assertRaises ( ValueError, f.set_a_weighting, 192000 ) | |
| 33 | + | |
| 34 | + def test_c_weighting(self): | |
| 35 | + expected = array_from_text_file('c_weighting_test_simple.expected') | |
| 36 | + f = digital_filter(5) | |
| 37 | + f.set_c_weighting(44100) | |
| 38 | + v = fvec(32) | |
| 39 | + v[12] = .5 | |
| 40 | + u = f(v) | |
| 41 | + assert_almost_equal (expected[1], u) | |
| 42 | + | |
| 43 | + def test_a_weighting(self): | |
| 44 | + expected = array_from_text_file('a_weighting_test_simple.expected') | |
| 45 | + f = digital_filter(7) | |
| 46 | + f.set_a_weighting(44100) | |
| 47 | + v = fvec(32) | |
| 48 | + v[12] = .5 | |
| 49 | + u = f(v) | |
| 50 | + assert_almost_equal (expected[1], u) | |
| 51 | + | |
| 52 | + def test_a_weighting_parted(self): | |
| 53 | + expected = array_from_text_file('a_weighting_test_simple.expected') | |
| 54 | + f = digital_filter(7) | |
| 55 | + f.set_a_weighting(44100) | |
| 56 | + v = fvec(16) | |
| 57 | + v[12] = .5 | |
| 58 | + u = f(v) | |
| 59 | + assert_almost_equal (expected[1][:16], u) | |
| 60 | + # one more time | |
| 61 | + v = fvec(16) | |
| 62 | + u = f(v) | |
| 63 | + assert_almost_equal (expected[1][16:], u) | |
| 64 | + | |
| 65 | +if __name__ == '__main__': | |
| 66 | + from unittest import main | |
| 67 | + main() | |
| 68 | + | |
| @@ -0,0 +1,23 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +from numpy import random | |
| 6 | +from aubio import cvec, filterbank | |
| 7 | + | |
| 8 | +class aubio_filterbank_test_case(TestCase): | |
| 9 | + | |
| 10 | + def test_members(self): | |
| 11 | + f = filterbank(40, 512) | |
| 12 | + assert_equal ([f.n_filters, f.win_s], [40, 512]) | |
| 13 | + | |
| 14 | + def test_set_coeffs(self): | |
| 15 | + f = filterbank(40, 512) | |
| 16 | + r = random.random([40, 512 / 2 + 1]).astype('float32') | |
| 17 | + f.set_coeffs(r) | |
| 18 | + assert_equal (r, f.get_coeffs()) | |
| 19 | + | |
| 20 | +if __name__ == '__main__': | |
| 21 | + from unittest import main | |
| 22 | + main() | |
| 23 | + | |
| @@ -0,0 +1,51 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +from numpy import array, shape | |
| 6 | +from aubio import cvec, filterbank | |
| 7 | + | |
| 8 | +class aubio_filterbank_mel_test_case(TestCase): | |
| 9 | + | |
| 10 | + def test_slaney(self): | |
| 11 | + f = filterbank(40, 512) | |
| 12 | + f.set_mel_coeffs_slaney(16000) | |
| 13 | + a = f.get_coeffs() | |
| 14 | + assert_equal(shape (a), (40, 512/2 + 1) ) | |
| 15 | + | |
| 16 | + def test_other_slaney(self): | |
| 17 | + f = filterbank(40, 512*2) | |
| 18 | + f.set_mel_coeffs_slaney(44100) | |
| 19 | + a = f.get_coeffs() | |
| 20 | + #print "sum is", sum(sum(a)) | |
| 21 | + for win_s in [256, 512, 1024, 2048, 4096]: | |
| 22 | + f = filterbank(40, win_s) | |
| 23 | + f.set_mel_coeffs_slaney(320000) | |
| 24 | + a = f.get_coeffs() | |
| 25 | + #print "sum is", sum(sum(a)) | |
| 26 | + | |
| 27 | + def test_triangle_freqs_zeros(self): | |
| 28 | + f = filterbank(9, 1024) | |
| 29 | + freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] | |
| 30 | + freqs = array(freq_list, dtype = 'float32') | |
| 31 | + f.set_triangle_bands(freqs, 48000) | |
| 32 | + f.get_coeffs().T | |
| 33 | + assert_equal ( f(cvec(1024)), 0) | |
| 34 | + | |
| 35 | + def test_triangle_freqs_ones(self): | |
| 36 | + f = filterbank(9, 1024) | |
| 37 | + freq_list = [40, 80, 200, 400, 800, 1600, 3200, 6400, 12800, 15000, 24000] | |
| 38 | + freqs = array(freq_list, dtype = 'float32') | |
| 39 | + f.set_triangle_bands(freqs, 48000) | |
| 40 | + f.get_coeffs().T | |
| 41 | + spec = cvec(1024) | |
| 42 | + spec.norm[:] = 1 | |
| 43 | + assert_almost_equal ( f(spec), | |
| 44 | + [ 0.02070313, 0.02138672, 0.02127604, 0.02135417, | |
| 45 | + 0.02133301, 0.02133301, 0.02133311, 0.02133334, 0.02133345]) | |
| 46 | + | |
| 47 | +if __name__ == '__main__': | |
| 48 | + from unittest import main | |
| 49 | + main() | |
| 50 | + | |
| 51 | + | |
| @@ -0,0 +1,135 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +from aubio import fvec, zero_crossing_rate, alpha_norm, min_removal | |
| 6 | +from numpy import array, shape | |
| 7 | + | |
| 8 | +class aubio_fvec_test_case(TestCase): | |
| 9 | + | |
| 10 | + def test_vector_created_with_zeroes(self): | |
| 11 | + a = fvec(10) | |
| 12 | + a | |
| 13 | + shape(a) | |
| 14 | + a[0] | |
| 15 | + #del a | |
| 16 | + assert_equal(array(a), 0.) | |
| 17 | + | |
| 18 | + def test_vector_create_with_list(self): | |
| 19 | + a = fvec([0,1,2,3]) | |
| 20 | + assert_equal (range(4), a) | |
| 21 | + | |
| 22 | + def test_vector_assign_element(self): | |
| 23 | + a = fvec() | |
| 24 | + a[0] = 1 | |
| 25 | + assert_equal(a[0], 1) | |
| 26 | + | |
| 27 | + def test_vector_assign_element_end(self): | |
| 28 | + a = fvec() | |
| 29 | + a[-1] = 1 | |
| 30 | + assert_equal(a[-1], 1) | |
| 31 | + assert_equal(a[len(a)-1], 1) | |
| 32 | + | |
| 33 | + def test_vector(self): | |
| 34 | + a = fvec() | |
| 35 | + a, len(a) #a.length | |
| 36 | + a[0] | |
| 37 | + array(a) | |
| 38 | + a = fvec(10) | |
| 39 | + a = fvec(1) | |
| 40 | + a.T | |
| 41 | + array(a).T | |
| 42 | + a = range(len(a)) | |
| 43 | + | |
| 44 | + def test_wrong_values(self): | |
| 45 | + self.assertRaises (ValueError, fvec, -10) | |
| 46 | + | |
| 47 | + a = fvec(2) | |
| 48 | + self.assertRaises (IndexError, a.__getitem__, 3) | |
| 49 | + self.assertRaises (IndexError, a.__getitem__, 2) | |
| 50 | + | |
| 51 | + def test_alpha_norm_of_fvec(self): | |
| 52 | + a = fvec(2) | |
| 53 | + self.assertEquals (alpha_norm(a, 1), 0) | |
| 54 | + a[0] = 1 | |
| 55 | + self.assertEquals (alpha_norm(a, 1), 0.5) | |
| 56 | + a[1] = 1 | |
| 57 | + self.assertEquals (alpha_norm(a, 1), 1) | |
| 58 | + a = array([0, 1], dtype='float32') | |
| 59 | + from math import sqrt | |
| 60 | + assert_almost_equal (alpha_norm(a, 2), sqrt(2)/2.) | |
| 61 | + | |
| 62 | + def test_alpha_norm_of_none(self): | |
| 63 | + self.assertRaises (ValueError, alpha_norm, None, 1) | |
| 64 | + | |
| 65 | + def test_alpha_norm_of_array_of_float32(self): | |
| 66 | + # check scalar fails | |
| 67 | + a = array(1, dtype = 'float32') | |
| 68 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 69 | + # check 2d array fails | |
| 70 | + a = array([[2],[4]], dtype = 'float32') | |
| 71 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 72 | + # check 1d array | |
| 73 | + a = array(range(10), dtype = 'float32') | |
| 74 | + self.assertEquals (alpha_norm(a, 1), 4.5) | |
| 75 | + | |
| 76 | + def test_alpha_norm_of_array_of_int(self): | |
| 77 | + a = array(1, dtype = 'int') | |
| 78 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 79 | + a = array([[[1,2],[3,4]]], dtype = 'int') | |
| 80 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 81 | + a = array(range(10), dtype = 'int') | |
| 82 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 83 | + | |
| 84 | + def test_alpha_norm_of_array_of_string (self): | |
| 85 | + a = "hello" | |
| 86 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 87 | + | |
| 88 | + def test_zero_crossing_rate(self): | |
| 89 | + a = array([0,1,-1], dtype='float32') | |
| 90 | + assert_almost_equal (zero_crossing_rate(a), 1./3. ) | |
| 91 | + a = array([0.]*100, dtype='float32') | |
| 92 | + self.assertEquals (zero_crossing_rate(a), 0 ) | |
| 93 | + a = array([-1.]*100, dtype='float32') | |
| 94 | + self.assertEquals (zero_crossing_rate(a), 0 ) | |
| 95 | + a = array([1.]*100, dtype='float32') | |
| 96 | + self.assertEquals (zero_crossing_rate(a), 0 ) | |
| 97 | + | |
| 98 | + def test_alpha_norm_of_array_of_float64(self): | |
| 99 | + # check scalar fail | |
| 100 | + a = array(1, dtype = 'float64') | |
| 101 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 102 | + # check 3d array fail | |
| 103 | + a = array([[[1,2],[3,4]]], dtype = 'float64') | |
| 104 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 105 | + # check float64 1d array fail | |
| 106 | + a = array(range(10), dtype = 'float64') | |
| 107 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 108 | + # check float64 2d array fail | |
| 109 | + a = array([range(10), range(10)], dtype = 'float64') | |
| 110 | + self.assertRaises (ValueError, alpha_norm, a, 1) | |
| 111 | + | |
| 112 | + def test_fvec_min_removal_of_array(self): | |
| 113 | + a = array([20,1,19], dtype='float32') | |
| 114 | + b = min_removal(a) | |
| 115 | + assert_equal (array(b), [19, 0, 18]) | |
| 116 | + assert_equal (b, [19, 0, 18]) | |
| 117 | + assert_equal (a, b) | |
| 118 | + a[0] = 0 | |
| 119 | + assert_equal (a, b) | |
| 120 | + | |
| 121 | + def test_fvec_min_removal_of_array_float64(self): | |
| 122 | + a = array([20,1,19], dtype='float64') | |
| 123 | + self.assertRaises (ValueError, min_removal, a) | |
| 124 | + | |
| 125 | + def test_fvec_min_removal_of_fvec(self): | |
| 126 | + a = fvec(3) | |
| 127 | + a = array([20, 1, 19], dtype = 'float32') | |
| 128 | + b = min_removal(a) | |
| 129 | + assert_equal (array(b), [19, 0, 18]) | |
| 130 | + assert_equal (b, [19, 0, 18]) | |
| 131 | + assert_equal (a, b) | |
| 132 | + | |
| 133 | +if __name__ == '__main__': | |
| 134 | + from unittest import main | |
| 135 | + main() | |
| @@ -0,0 +1,20 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +# WARNING: numpy also has an fft object | |
| 6 | +from aubio import onset, cvec | |
| 7 | +from numpy import array, shape, arange, zeros, log | |
| 8 | +from math import pi | |
| 9 | + | |
| 10 | +class aubio_onset(TestCase): | |
| 11 | + | |
| 12 | + def test_members(self): | |
| 13 | + o = onset() | |
| 14 | + assert_equal ([o.buf_size, o.hop_size, o.method, o.samplerate], | |
| 15 | + [1024,512,'default',44100]) | |
| 16 | + | |
| 17 | + | |
| 18 | +if __name__ == '__main__': | |
| 19 | + from unittest import main | |
| 20 | + main() | |
| @@ -0,0 +1,115 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, assert_equal, assert_almost_equal | |
| 4 | +from aubio import peakpicker, fvec | |
| 5 | + | |
| 6 | +class aubio_peakpicker(TestCase): | |
| 7 | + | |
| 8 | + def test_members(self): | |
| 9 | + o = peakpicker() | |
| 10 | + | |
| 11 | + def test_peakpicker_zeroes(self): | |
| 12 | + o = peakpicker() | |
| 13 | + assert_equal(o.get_thresholded_input(), 0.) | |
| 14 | + | |
| 15 | + def test_peakpick_set_threshold(self): | |
| 16 | + o = peakpicker() | |
| 17 | + new_threshold = threshold | |
| 18 | + o.set_threshold(new_threshold) | |
| 19 | + assert_almost_equal(new_threshold, o.get_threshold()) | |
| 20 | + | |
| 21 | + def test_peakpicker_get_threshold(self): | |
| 22 | + o = peakpicker() | |
| 23 | + new_threshold = o.get_threshold() | |
| 24 | + o.set_threshold(new_threshold) | |
| 25 | + assert_equal(new_threshold, o.get_threshold()) | |
| 26 | + | |
| 27 | +buf_size = 1024 | |
| 28 | +slice_size = 5 | |
| 29 | +delay = 1 | |
| 30 | +threshold = .9 | |
| 31 | + | |
| 32 | +class aubio_peakpicker_peaks(TestCase): | |
| 33 | + | |
| 34 | + def setUp(self): | |
| 35 | + self.o = peakpicker() | |
| 36 | + self.o.set_threshold (threshold) | |
| 37 | + self.vec = fvec(buf_size) | |
| 38 | + | |
| 39 | + def test_peakpicker_impulse(self): | |
| 40 | + vec = self.vec; o = self.o | |
| 41 | + a = 345 | |
| 42 | + vec[a] = 1000. | |
| 43 | + self.peaks = [a] | |
| 44 | + | |
| 45 | + def test_peakpicker_ramp_up(self): | |
| 46 | + vec = self.vec; o = self.o | |
| 47 | + a = 345 | |
| 48 | + vec[a] = 1000. / 4. * 1. | |
| 49 | + vec[a+1] = 1000. / 4. * 2. | |
| 50 | + vec[a+2] = 1000. / 4. * 3. | |
| 51 | + vec[a+3] = 1000. | |
| 52 | + self.peaks = [a+1] | |
| 53 | + | |
| 54 | + def test_peakpicker_ramp_down(self): | |
| 55 | + vec = self.vec; o = self.o | |
| 56 | + a = 345 | |
| 57 | + vec[a] = 1000. | |
| 58 | + vec[a+1] = 1000. / 4. * 3. | |
| 59 | + vec[a+2] = 1000. / 4. * 2. | |
| 60 | + vec[a+3] = 1000. / 4. * 1. | |
| 61 | + self.peaks = [a] | |
| 62 | + | |
| 63 | + def test_peakpicker_plateau(self): | |
| 64 | + vec = self.vec; o = self.o | |
| 65 | + a = 345 | |
| 66 | + vec[a] = 1000. / 2 | |
| 67 | + vec[a+1] = 1000. | |
| 68 | + vec[a+2] = 1000. | |
| 69 | + vec[a+3] = 1000. | |
| 70 | + vec[a+4] = 1000. / 2 | |
| 71 | + self.peaks = [a+1] | |
| 72 | + | |
| 73 | + def test_peakpicker_consecutive_peaks(self): | |
| 74 | + vec = self.vec; o = self.o | |
| 75 | + a = 345 | |
| 76 | + vec[a] = 1000. / 2 | |
| 77 | + vec[a+1] = 1000. | |
| 78 | + vec[a+3] = 1000. | |
| 79 | + vec[a+4] = 1000. / 2 | |
| 80 | + self.peaks = [a] | |
| 81 | + | |
| 82 | + def test_peakpicker_distant_peaks(self): | |
| 83 | + vec = self.vec; o = self.o | |
| 84 | + a = 345 | |
| 85 | + vec[a] = 1000. | |
| 86 | + vec[a+7] = 1000. | |
| 87 | + self.peaks = [a, a+7] | |
| 88 | + | |
| 89 | + def test_peakpicker_very_distant_peaks(self): | |
| 90 | + vec = self.vec; o = self.o | |
| 91 | + a = 345 | |
| 92 | + vec[a] = 1000. | |
| 93 | + vec[a+67] = 1000. | |
| 94 | + self.peaks = [a, a+67] | |
| 95 | + | |
| 96 | + def tearDown(self): | |
| 97 | + fpeaks = [] | |
| 98 | + for index in range(0,buf_size-slice_size): | |
| 99 | + sliced = self.vec[index:index+slice_size] | |
| 100 | + findex = self.o(sliced) | |
| 101 | + if findex: | |
| 102 | + # we found a peak | |
| 103 | + fpeak = index - findex - delay | |
| 104 | + #print self.peaks, index, '-', findex, '-', delay, '=', fpeak | |
| 105 | + if not round(index - findex - delay) in self.peaks: | |
| 106 | + self.fail('missing peak ' + str(fpeak)) | |
| 107 | + fpeaks.append(fpeak) | |
| 108 | + if len(fpeaks) != len(self.peaks): | |
| 109 | + self.fail('some peaks of ' + str(self.peaks) + 'were not found, got only ' + str(fpeaks)) | |
| 110 | ||
| 111 | + #print fpeaks, self.peaks | |
| 112 | + | |
| 113 | +if __name__ == '__main__': | |
| 114 | + from unittest import main | |
| 115 | + main() | |
| @@ -0,0 +1,65 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, run_module_suite | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +from aubio import fvec, cvec, pvoc | |
| 6 | +from numpy import array, shape | |
| 7 | + | |
| 8 | +class aubio_pvoc_test_case(TestCase): | |
| 9 | + | |
| 10 | + def test_members(self): | |
| 11 | + f = pvoc() | |
| 12 | + assert_equal ([f.win_s, f.hop_s], [1024, 512]) | |
| 13 | + f = pvoc(2048, 128) | |
| 14 | + assert_equal ([f.win_s, f.hop_s], [2048, 128]) | |
| 15 | + | |
| 16 | + def test_zeros(self): | |
| 17 | + win_s, hop_s = 1024, 256 | |
| 18 | + f = pvoc (win_s, hop_s) | |
| 19 | + t = fvec (hop_s) | |
| 20 | + for time in range( 4 * win_s / hop_s ): | |
| 21 | + s = f(t) | |
| 22 | + r = f.rdo(s) | |
| 23 | + assert_equal ( array(t), 0) | |
| 24 | + assert_equal ( s.norm, 0) | |
| 25 | + assert_equal ( s.phas, 0) | |
| 26 | + assert_equal ( r, 0) | |
| 27 | + | |
| 28 | + def test_steps_two_channels(self): | |
| 29 | + """ check the resynthesis of steps is correct """ | |
| 30 | + f = pvoc(1024, 512) | |
| 31 | + t1 = fvec(512) | |
| 32 | + t2 = fvec(512) | |
| 33 | + # positive step in first channel | |
| 34 | + t1[100:200] = .1 | |
| 35 | + # positive step in second channel | |
| 36 | + t1[20:50] = -.1 | |
| 37 | + s1 = f(t1) | |
| 38 | + r1 = f.rdo(s1) | |
| 39 | + s2 = f(t2) | |
| 40 | + r2 = f.rdo(s2) | |
| 41 | + #self.plot_this ( s1.norm.T ) | |
| 42 | + assert_almost_equal ( t1, r2, decimal = 6 ) | |
| 43 | + | |
| 44 | + def test_steps_three_random_channels(self): | |
| 45 | + from random import random | |
| 46 | + f = pvoc(64, 16) | |
| 47 | + t0 = fvec(16) | |
| 48 | + t1 = fvec(16) | |
| 49 | + for i in xrange(16): | |
| 50 | + t1[i] = random() * 2. - 1. | |
| 51 | + t2 = f.rdo(f(t1)) | |
| 52 | + t2 = f.rdo(f(t0)) | |
| 53 | + t2 = f.rdo(f(t0)) | |
| 54 | + t2 = f.rdo(f(t0)) | |
| 55 | + assert_almost_equal( t1, t2, decimal = 6 ) | |
| 56 | + | |
| 57 | + def plot_this( self, this ): | |
| 58 | + from pylab import semilogy, show | |
| 59 | + semilogy ( this ) | |
| 60 | + show () | |
| 61 | + | |
| 62 | +if __name__ == '__main__': | |
| 63 | + from unittest import main | |
| 64 | + main() | |
| 65 | + | |
| @@ -0,0 +1,101 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase | |
| 4 | +from numpy.testing import assert_equal, assert_almost_equal | |
| 5 | +from numpy import random, sin, arange, mean, median | |
| 6 | +from math import pi | |
| 7 | +from aubio import fvec, pitch | |
| 8 | + | |
| 9 | +class aubio_mathutils_test_case(TestCase): | |
| 10 | + | |
| 11 | + def test_members(self): | |
| 12 | + p = pitch() | |
| 13 | + assert_equal ( [p.method, p.buf_size, p.hop_size, p.samplerate], | |
| 14 | + ['default', 1024, 512, 44100]) | |
| 15 | + | |
| 16 | + def test_members_not_default(self): | |
| 17 | + p = pitch('mcomb', 2048, 512, 32000) | |
| 18 | + assert_equal ( [p.method, p.buf_size, p.hop_size, p.samplerate], | |
| 19 | + ['mcomb', 2048, 512, 32000]) | |
| 20 | + | |
| 21 | + def test_run_on_zeros(self): | |
| 22 | + p = pitch('mcomb', 2048, 512, 32000) | |
| 23 | + f = fvec (512) | |
| 24 | + assert_equal ( p(f), 0. ) | |
| 25 | + | |
| 26 | + def test_run_on_ones(self): | |
| 27 | + p = pitch('mcomb', 2048, 512, 32000) | |
| 28 | + f = fvec (512) | |
| 29 | + f[:] = 1 | |
| 30 | + assert( p(f) != 0. ) | |
| 31 | + | |
| 32 | + def test_run_default_on_sinusoid(self): | |
| 33 | + method = 'default' | |
| 34 | + buf_size = 2048 | |
| 35 | + hop_size = 512 | |
| 36 | + samplerate = 32000 | |
| 37 | + freq = 450. | |
| 38 | + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) | |
| 39 | + | |
| 40 | + def test_run_schmitt_on_sinusoid(self): | |
| 41 | + method = 'schmitt' | |
| 42 | + buf_size = 4096 | |
| 43 | + hop_size = 512 | |
| 44 | + samplerate = 44100 | |
| 45 | + freq = 800. | |
| 46 | + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) | |
| 47 | + | |
| 48 | + def test_run_mcomb_on_sinusoid(self): | |
| 49 | + method = 'mcomb' | |
| 50 | + buf_size = 2048 | |
| 51 | + hop_size = 512 | |
| 52 | + samplerate = 44100 | |
| 53 | + freq = 10000. | |
| 54 | + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) | |
| 55 | + | |
| 56 | + def test_run_fcomb_on_sinusoid(self): | |
| 57 | + method = 'fcomb' | |
| 58 | + buf_size = 2048 | |
| 59 | + hop_size = 512 | |
| 60 | + samplerate = 32000 | |
| 61 | + freq = 440. | |
| 62 | + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) | |
| 63 | + | |
| 64 | + def test_run_yin_on_sinusoid(self): | |
| 65 | + method = 'yin' | |
| 66 | + buf_size = 4096 | |
| 67 | + hop_size = 512 | |
| 68 | + samplerate = 32000 | |
| 69 | + freq = 880. | |
| 70 | + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) | |
| 71 | + | |
| 72 | + def test_run_yinfft_on_sinusoid(self): | |
| 73 | + method = 'yinfft' | |
| 74 | + buf_size = 2048 | |
| 75 | + hop_size = 512 | |
| 76 | + samplerate = 32000 | |
| 77 | + freq = 640. | |
| 78 | + self.run_pitch_on_sinusoid(method, buf_size, hop_size, samplerate, freq) | |
| 79 | + | |
| 80 | + def run_pitch_on_sinusoid(self, method, buf_size, hop_size, samplerate, freq): | |
| 81 | + p = pitch(method, buf_size, hop_size, samplerate) | |
| 82 | + sinvec = self.build_sinusoid(hop_size * 100, freq, samplerate) | |
| 83 | + self.run_pitch(p, sinvec, freq) | |
| 84 | + | |
| 85 | + def build_sinusoid(self, length, freq, samplerate): | |
| 86 | + return sin( 2. * pi * arange(length).astype('float32') * freq / samplerate) | |
| 87 | + | |
| 88 | + def run_pitch(self, p, input_vec, freq): | |
| 89 | + count = 0 | |
| 90 | + pitches, errors = [], [] | |
| 91 | + for vec_slice in input_vec.reshape((-1, p.hop_size)): | |
| 92 | + pitch = p(vec_slice) | |
| 93 | + pitches.append(pitch) | |
| 94 | + errors.append(1. - pitch / freq) | |
| 95 | + # check that the mean of all relative errors is less than 10% | |
| 96 | + assert_almost_equal (mean(errors), 0., decimal = 2) | |
| 97 | + | |
| 98 | +if __name__ == '__main__': | |
| 99 | + from unittest import main | |
| 100 | + main() | |
| 101 | + | |
| @@ -0,0 +1,27 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, assert_equal, assert_almost_equal | |
| 4 | +from aubio import fvec, source | |
| 5 | +from numpy import array | |
| 6 | + | |
| 7 | +path = "/Users/piem/archives/sounds/loops/drum_Chocolate_Milk_-_Ation_Speaks_Louder_Than_Words.wav" | |
| 8 | + | |
| 9 | +class aubio_filter_test_case(TestCase): | |
| 10 | + | |
| 11 | + def test_members(self): | |
| 12 | + f = source(path) | |
| 13 | + print dir(f) | |
| 14 | + | |
| 15 | + def test_read(self): | |
| 16 | + f = source(path) | |
| 17 | + total_frames = 0 | |
| 18 | + while True: | |
| 19 | + vec, read = f() | |
| 20 | + total_frames += read | |
| 21 | + if read < f.hop_size: break | |
| 22 | + print "read", total_frames / float(f.samplerate), " seconds from", path | |
| 23 | + | |
| 24 | +if __name__ == '__main__': | |
| 25 | + from unittest import main | |
| 26 | + main() | |
| 27 | + | |
| @@ -0,0 +1,238 @@ | ||
| 1 | +#! /usr/bin/env python | |
| 2 | + | |
| 3 | +from numpy.testing import TestCase, assert_equal, assert_almost_equal | |
| 4 | +from numpy import random, arange, log, zeros | |
| 5 | +from aubio import specdesc, cvec | |
| 6 | +from math import pi | |
| 7 | + | |
| 8 | +methods = ["default", | |
| 9 | + "energy", | |
| 10 | + "hfc", | |
| 11 | + "complex", | |
| 12 | + "phase", | |
| 13 | + "specdiff", | |
| 14 | + "kl", | |
| 15 | + "mkl", | |
| 16 | + "specflux", | |
| 17 | + "centroid", | |
| 18 | + "spread", | |
| 19 | + "skewness", | |
| 20 | + "kurtosis", | |
| 21 | + "slope", | |
| 22 | + "decrease", | |
| 23 | + "rolloff"] | |
| 24 | +buf_size = 2048 | |
| 25 | + | |
| 26 | +class aubio_specdesc(TestCase): | |
| 27 | + | |
| 28 | + def test_members(self): | |
| 29 | + o = specdesc() | |
| 30 | + | |
| 31 | + for method in methods: | |
| 32 | + o = specdesc(method, buf_size) | |
| 33 | + assert_equal ([o.buf_size, o.method], [buf_size, method]) | |
| 34 | + | |
| 35 | + spec = cvec(buf_size) | |
| 36 | + spec.norm[0] = 1 | |
| 37 | + spec.norm[1] = 1./2. | |
| 38 | + #print "%20s" % method, str(o(spec)) | |
| 39 | + o(spec) | |
| 40 | + spec.norm = random.random_sample((len(spec.norm),)).astype('float32') | |
| 41 | + spec.phas = random.random_sample((len(spec.phas),)).astype('float32') | |
| 42 | + #print "%20s" % method, str(o(spec)) | |
| 43 | + assert (o(spec) != 0.) | |
| 44 | + | |
| 45 | + def test_hfc(self): | |
| 46 | + o = specdesc("hfc", buf_size) | |
| 47 | + spec = cvec(buf_size) | |
| 48 | + # hfc of zeros is zero | |
| 49 | + assert_equal (o(spec), 0.) | |
| 50 | + # hfc of ones is sum of all bin numbers | |
| 51 | + spec.norm[:] = 1 | |
| 52 | + expected = sum(range(buf_size/2 + 2)) | |
| 53 | + assert_equal (o(spec), expected) | |
| 54 | + # changing phase doesn't change anything | |
| 55 | + spec.phas[:] = 1 | |
| 56 | + assert_equal (o(spec), sum(range(buf_size/2 + 2))) | |
| 57 | + | |
| 58 | + def test_phase(self): | |
| 59 | + o = specdesc("phase", buf_size) | |
| 60 | + spec = cvec(buf_size) | |
| 61 | + # phase of zeros is zero | |
| 62 | + assert_equal (o(spec), 0.) | |
| 63 | + spec.phas = random.random_sample((len(spec.phas),)).astype('float32') | |
| 64 | + # phase of random is not zero | |
| 65 | + spec.norm[:] = 1 | |
| 66 | + assert (o(spec) != 0.) | |
| 67 | + | |
| 68 | + def test_specdiff(self): | |
| 69 | + o = specdesc("phase", buf_size) | |
| 70 | + spec = cvec(buf_size) | |
| 71 | + # specdiff of zeros is zero | |
| 72 | + assert_equal (o(spec), 0.) | |
| 73 | + spec.phas = random.random_sample((len(spec.phas),)).astype('float32') | |
| 74 | + # phase of random is not zero | |
| 75 | + spec.norm[:] = 1 | |
| 76 | + assert (o(spec) != 0.) | |
| 77 | + | |
| 78 | + def test_hfc(self): | |
| 79 | + o = specdesc("hfc") | |
| 80 | + c = cvec() | |
| 81 | + assert_equal( 0., o(c)) | |
| 82 | + a = arange(c.length, dtype='float32') | |
| 83 | + c.norm = a | |
| 84 | + assert_equal (a, c.norm) | |
| 85 | + assert_equal ( sum(a*(a+1)), o(c)) | |
| 86 | + | |
| 87 | + def test_complex(self): | |
| 88 | + o = specdesc("complex") | |
| 89 | + c = cvec() | |
| 90 | + assert_equal( 0., o(c)) | |
| 91 | + a = arange(c.length, dtype='float32') | |
| 92 | + c.norm = a | |
| 93 | + assert_equal (a, c.norm) | |
| 94 | + # the previous run was on zeros, so previous frames are still 0 | |
| 95 | + # so we have sqrt ( abs ( r2 ^ 2) ) == r2 | |
| 96 | + assert_equal ( sum(a), o(c)) | |
| 97 | + # second time. c.norm = a, so, r1 = r2, and the euclidian distance is 0 | |
| 98 | + assert_equal ( 0, o(c)) | |
| 99 | + | |
| 100 | + def test_kl(self): | |
| 101 | + o = specdesc("kl") | |
| 102 | + c = cvec() | |
| 103 | + assert_equal( 0., o(c)) | |
| 104 | + a = arange(c.length, dtype='float32') | |
| 105 | + c.norm = a | |
| 106 | + assert_almost_equal( sum(a * log(1.+ a/1.e-10 ) ) / o(c), 1., decimal=6) | |
| 107 | + | |
| 108 | + def test_mkl(self): | |
| 109 | + o = specdesc("mkl") | |
| 110 | + c = cvec() | |
| 111 | + assert_equal( 0., o(c)) | |
| 112 | + a = arange(c.length, dtype='float32') | |
| 113 | + c.norm = a | |
| 114 | + assert_almost_equal( sum(log(1.+ a/1.e-10 ) ) / o(c), 1, decimal=6) | |
| 115 | + | |
| 116 | + def test_specflux(self): | |
| 117 | + o = specdesc("specflux") | |
| 118 | + c = cvec() | |
| 119 | + assert_equal( 0., o(c)) | |
| 120 | + a = arange(c.length, dtype='float32') | |
| 121 | + c.norm = a | |
| 122 | + assert_equal( sum(a), o(c)) | |
| 123 | + assert_equal( 0, o(c)) | |
| 124 | + c.norm = zeros(c.length, dtype='float32') | |
| 125 | + assert_equal( 0, o(c)) | |
| 126 | + | |
| 127 | + def test_centroid(self): | |
| 128 | + o = specdesc("centroid") | |
| 129 | + c = cvec() | |
| 130 | + # make sure centroid of zeros is zero | |
| 131 | + assert_equal( 0., o(c)) | |
| 132 | + a = arange(c.length, dtype='float32') | |
| 133 | + c.norm = a | |
| 134 | + centroid = sum(a*a) / sum(a) | |
| 135 | + assert_almost_equal (centroid, o(c), decimal = 2) | |
| 136 | + | |
| 137 | + c.norm = a * .5 | |
| 138 | + assert_almost_equal (centroid, o(c), decimal = 2) | |
| 139 | + | |
| 140 | + def test_spread(self): | |
| 141 | + o = specdesc("spread") | |
| 142 | + c = cvec(2048) | |
| 143 | + ramp = arange(c.length, dtype='float32') | |
| 144 | + assert_equal( 0., o(c)) | |
| 145 | + | |
| 146 | + a = ramp | |
| 147 | + c.norm = a | |
| 148 | + centroid = sum(a*a) / sum(a) | |
| 149 | + spread = sum( a * pow(ramp - centroid, 2.) ) / sum(a) | |
| 150 | + assert_almost_equal (o(c), spread, decimal = 1) | |
| 151 | + | |
| 152 | + def test_skewness(self): | |
| 153 | + o = specdesc("skewness") | |
| 154 | + c = cvec() | |
| 155 | + assert_equal( 0., o(c)) | |
| 156 | + a = arange(c.length, dtype='float32') | |
| 157 | + c.norm = a | |
| 158 | + centroid = sum(a*a) / sum(a) | |
| 159 | + spread = sum( (a - centroid)**2 *a) / sum(a) | |
| 160 | + skewness = sum( (a - centroid)**3 *a) / sum(a) / spread **1.5 | |
| 161 | + assert_almost_equal (skewness, o(c), decimal = 2) | |
| 162 | + | |
| 163 | + c.norm = a * 3 | |
| 164 | + assert_almost_equal (skewness, o(c), decimal = 2) | |
| 165 | + | |
| 166 | + def test_kurtosis(self): | |
| 167 | + o = specdesc("kurtosis") | |
| 168 | + c = cvec() | |
| 169 | + assert_equal( 0., o(c)) | |
| 170 | + a = arange(c.length, dtype='float32') | |
| 171 | + c.norm = a | |
| 172 | + centroid = sum(a*a) / sum(a) | |
| 173 | + spread = sum( (a - centroid)**2 *a) / sum(a) | |
| 174 | + kurtosis = sum( (a - centroid)**4 *a) / sum(a) / spread **2 | |
| 175 | + assert_almost_equal (kurtosis, o(c), decimal = 2) | |
| 176 | + | |
| 177 | + def test_slope(self): | |
| 178 | + o = specdesc("slope") | |
| 179 | + c = cvec() | |
| 180 | + assert_equal( 0., o(c)) | |
| 181 | + a = arange(c.length * 2, 0, -2, dtype='float32') | |
| 182 | + k = arange(c.length, dtype='float32') | |
| 183 | + c.norm = a | |
| 184 | + num = len(a) * sum(k*a) - sum(k)*sum(a) | |
| 185 | + den = (len(a) * sum(k**2) - sum(k)**2) | |
| 186 | + slope = num/den/sum(a) | |
| 187 | + assert_almost_equal (slope, o(c), decimal = 5) | |
| 188 | + | |
| 189 | + a = arange(0, c.length * 2, +2, dtype='float32') | |
| 190 | + c.norm = a | |
| 191 | + num = len(a) * sum(k*a) - sum(k)*sum(a) | |
| 192 | + den = (len(a) * sum(k**2) - sum(k)**2) | |
| 193 | + slope = num/den/sum(a) | |
| 194 | + assert_almost_equal (slope, o(c), decimal = 5) | |
| 195 | + | |
| 196 | + a = arange(0, c.length * 2, +2, dtype='float32') | |
| 197 | + c.norm = a * 2 | |
| 198 | + assert_almost_equal (slope, o(c), decimal = 5) | |
| 199 | + | |
| 200 | + def test_decrease(self): | |
| 201 | + o = specdesc("decrease") | |
| 202 | + c = cvec() | |
| 203 | + assert_equal( 0., o(c)) | |
| 204 | + a = arange(c.length * 2, 0, -2, dtype='float32') | |
| 205 | + k = arange(c.length, dtype='float32') | |
| 206 | + c.norm = a | |
| 207 | + decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) | |
| 208 | + assert_almost_equal (decrease, o(c), decimal = 5) | |
| 209 | + | |
| 210 | + a = arange(0, c.length * 2, +2, dtype='float32') | |
| 211 | + c.norm = a | |
| 212 | + decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) | |
| 213 | + assert_almost_equal (decrease, o(c), decimal = 5) | |
| 214 | + | |
| 215 | + a = arange(0, c.length * 2, +2, dtype='float32') | |
| 216 | + c.norm = a * 2 | |
| 217 | + decrease = sum((a[1:] - a [0]) / k[1:]) / sum(a[1:]) | |
| 218 | + assert_almost_equal (decrease, o(c), decimal = 5) | |
| 219 | + | |
| 220 | + def test_rolloff(self): | |
| 221 | + o = specdesc("rolloff") | |
| 222 | + c = cvec() | |
| 223 | + assert_equal( 0., o(c)) | |
| 224 | + a = arange(c.length * 2, 0, -2, dtype='float32') | |
| 225 | + k = arange(c.length, dtype='float32') | |
| 226 | + c.norm = a | |
| 227 | + cumsum = .95*sum(a*a) | |
| 228 | + i = 0; rollsum = 0 | |
| 229 | + while rollsum < cumsum: | |
| 230 | + rollsum += a[i]*a[i] | |
| 231 | + i+=1 | |
| 232 | + rolloff = i | |
| 233 | + assert_equal (rolloff, o(c)) | |
| 234 | + | |
| 235 | + | |
| 236 | +if __name__ == '__main__': | |
| 237 | + from unittest import main | |
| 238 | + main() | |
| @@ -1,6 +0,0 @@ | ||
| 1 | −# vim:set syntax=python: | |
| 2 | − | |
| 3 | −ctx.add_subdirs('aubio') | |
| 4 | −# install headers | |
| 5 | −for file in ['aubiocut', 'aubiopitch']: | |
| 6 | − ctx.install_as('${PREFIX}/bin/' + file, file, chmod = 0755) | |