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> | 1 | import numpy |
| 2 | print aubio.__LICENSE__ for the terms of use | 2 | from _aubio import * |
| 3 | """ | ||
| 4 | 3 | ||
| 5 | __LICENSE__ = """\ | 4 | class fvec(numpy.ndarray): |
| 6 | Copyright (C) 2004-2009 Paul Brossier <piem@aubio.org> | ||
| 7 | 5 | ||
| 8 | This file is part of aubio. | 6 | def __new__(self, length = 1024, **kwargs): |
| 9 | 7 | if type(length) == type([]): | |
| 10 | aubio is free software: you can redistribute it and/or modify | 8 | return numpy.array(length, dtype='float32', **kwargs) |
| 11 | it under the terms of the GNU General Public License as published by | 9 | return numpy.zeros(length, dtype='float32', **kwargs) |
| 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 * | ||
| @@ -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) | ||