From: Paul Brossier Date: Sat, 24 Nov 2007 20:08:04 +0000 (+0100) Subject: src/: move tempo files to src/tempo, continue moving pitch and onset files X-Git-Tag: 0.4.0-beta1~966 X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=bcf38fe01822c610831591851df8abd76bfaacf7;p=aubio.git src/: move tempo files to src/tempo, continue moving pitch and onset files --- diff --git a/src/Makefile.am b/src/Makefile.am index 5e256613..f29dd3bd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,19 +10,19 @@ pkginclude_HEADERS = aubio.h \ hist.h \ scale.h \ resample.h \ - onset/onsetdetection.h \ tss.h \ - peakpick.h \ biquad.h \ - pitchdetection.h \ + pitch/pitchdetection.h \ pitch/pitchmcomb.h \ pitch/pitchyin.h \ pitch/pitchschmitt.h \ pitch/pitchfcomb.h \ pitch/pitchyinfft.h \ - beattracking.h \ - onset.h \ - tempo.h \ + onset/onset.h \ + onset/onsetdetection.h \ + onset/peakpick.h \ + tempo/tempo.h \ + tempo/beattracking.h \ filter.h \ filterbank.h \ mfcc.h @@ -48,16 +48,12 @@ libaubio_la_SOURCES = aubio.h \ scale.h \ resample.c \ resample.h \ - onset/onsetdetection.c \ - onset/onsetdetection.h \ tss.c \ tss.h \ - peakpick.c \ - peakpick.h \ biquad.c \ biquad.h \ - pitchdetection.c \ - pitchdetection.h \ + pitch/pitchdetection.c \ + pitch/pitchdetection.h \ pitch/pitchmcomb.c \ pitch/pitchmcomb.h \ pitch/pitchyin.c \ @@ -68,12 +64,16 @@ libaubio_la_SOURCES = aubio.h \ pitch/pitchfcomb.h \ pitch/pitchyinfft.c \ pitch/pitchyinfft.h \ - beattracking.c \ - beattracking.h \ - onset.c \ - onset.h \ - tempo.c \ - tempo.h \ + onset/onset.c \ + onset/onset.h \ + onset/onsetdetection.c \ + onset/onsetdetection.h \ + onset/peakpick.c \ + onset/peakpick.h \ + tempo/tempo.c \ + tempo/tempo.h \ + tempo/beattracking.c \ + tempo/beattracking.h \ filter.c \ filter.h \ filterbank.c \ diff --git a/src/aubio.h b/src/aubio.h index c0a1acf2..73af8bbf 100644 --- a/src/aubio.h +++ b/src/aubio.h @@ -66,19 +66,19 @@ extern "C" { #include "hist.h" #include "tss.h" #include "resample.h" -#include "peakpick.h" #include "biquad.h" #include "filter.h" -#include "pitchdetection.h" +#include "pitch/pitchdetection.h" #include "pitch/pitchmcomb.h" #include "pitch/pitchyin.h" #include "pitch/pitchyinfft.h" #include "pitch/pitchschmitt.h" #include "pitch/pitchfcomb.h" -#include "beattracking.h" -#include "onset/detection.h" -#include "onset.h" -#include "tempo.h" +#include "onset/onsetdetection.h" +#include "onset/onset.h" +#include "onset/peakpick.h" +#include "tempo/beattracking.h" +#include "tempo/tempo.h" #include "filterbank.h" #include "mfcc.h" diff --git a/src/beattracking.c b/src/beattracking.c deleted file mode 100644 index e67a6082..00000000 --- a/src/beattracking.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - Copyright (C) 2005 Matthew Davies and Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "aubio_priv.h" -#include "sample.h" -#include "mathutils.h" -#include "beattracking.h" - -uint_t fvec_gettimesig(smpl_t * acf, uint_t acflen, uint_t gp); -void aubio_beattracking_checkstate(aubio_beattracking_t * bt); -smpl_t fvec_getperiod(aubio_beattracking_t * bt); - -struct _aubio_beattracking_t { - fvec_t * rwv; /** rayleigh weight vector - rayleigh distribution function */ - fvec_t * gwv; /** rayleigh weight vector - rayleigh distribution function */ - fvec_t * dfwv; /** detection function weighting - exponential curve */ - fvec_t * dfrev; /** reversed onset detection function */ - fvec_t * acf; /** vector for autocorrelation function (of current detection function frame) */ - fvec_t * acfout; /** store result of passing acf through s.i.c.f.b. */ - fvec_t * phwv; /** beat expectation alignment weighting */ - fvec_t * phout; - uint_t timesig; /** time signature of input, set to zero until context dependent model activated */ - uint_t step; - fvec_t * locacf; /** vector to store harmonics of filterbank of acf */ - fvec_t * inds; /** vector for max index outputs for each harmonic */ - uint_t rayparam; /** Rayleigh parameter */ - uint_t lastbeat; - sint_t counter; - uint_t flagstep; - smpl_t g_var; - uint_t gp; - uint_t bp; - uint_t rp; - uint_t rp1; - uint_t rp2; -}; - -aubio_beattracking_t * new_aubio_beattracking(uint_t winlen, - uint_t channels) { - - aubio_beattracking_t * p = AUBIO_NEW(aubio_beattracking_t); - uint_t i = 0; - /* parameter for rayleigh weight vector - sets preferred tempo to - * 120bpm [43] */ - smpl_t rayparam = 48./512. * winlen; - smpl_t dfwvnorm = EXP((LOG(2.0)/rayparam)*(winlen+2)); - /** length over which beat period is found [128] */ - uint_t laglen = winlen/4; - /** step increment - both in detection function samples -i.e. 11.6ms or - * 1 onset frame [128] */ - uint_t step = winlen/4; /* 1.5 seconds */ - - uint_t maxnumelem = 4; /* max number of index output */ - p->lastbeat = 0; - p->counter = 0; - p->flagstep = 0; - p->g_var = 3.901; // constthresh empirically derived! - p->rp = 1; - p->gp = 0; - - p->rayparam = rayparam; - p->step = step; - p->rwv = new_fvec(laglen,channels); - p->gwv = new_fvec(laglen,channels); - p->dfwv = new_fvec(winlen,channels); - p->dfrev = new_fvec(winlen,channels); - p->acf = new_fvec(winlen,channels); - p->acfout = new_fvec(laglen,channels); - p->phwv = new_fvec(2*laglen,channels); - p->phout = new_fvec(winlen,channels); - - p->timesig = 0; - - p->inds = new_fvec(maxnumelem,channels); - p->locacf = new_fvec(winlen,channels); - - /* exponential weighting, dfwv = 0.5 when i = 43 */ - for (i=0;idfwv->data[0][i] = (EXP((LOG(2.0)/rayparam)*(i+1))) - / dfwvnorm; - } - - for (i=0;i<(laglen);i++){ - p->rwv->data[0][i] = ((smpl_t)(i+1.) / SQR((smpl_t)rayparam)) * - EXP((-SQR((smpl_t)(i+1.)) / (2.*SQR((smpl_t)rayparam)))); - } - - return p; - -} - -void del_aubio_beattracking(aubio_beattracking_t * p) { - del_fvec(p->rwv); - del_fvec(p->gwv); - del_fvec(p->dfwv); - del_fvec(p->dfrev); - del_fvec(p->acf); - del_fvec(p->acfout); - del_fvec(p->phwv); - del_fvec(p->phout); - del_fvec(p->locacf); - del_fvec(p->inds); - AUBIO_FREE(p); -} - - -void aubio_beattracking_do(aubio_beattracking_t * bt, fvec_t * dfframe, fvec_t * output) { - - uint_t i,k; - /* current beat period value found using gaussian weighting (from context dependent model) */ - uint_t step = bt->step; - uint_t laglen = bt->rwv->length; - uint_t winlen = bt->dfwv->length; - smpl_t * phout = bt->phout->data[0]; - smpl_t * phwv = bt->phwv->data[0]; - smpl_t * dfrev = bt->dfrev->data[0]; - smpl_t * dfwv = bt->dfwv->data[0]; - smpl_t * rwv = bt->rwv->data[0]; - smpl_t * acfout = bt->acfout->data[0]; - smpl_t * acf = bt->acf->data[0]; - uint_t maxindex = 0; - //number of harmonics in shift invariant comb filterbank - uint_t numelem = 4; - - //smpl_t myperiod = 0.; - //smpl_t * out = output->data[0]; - - //parameters for making s.i.c.f.b. - uint_t a,b; - //beat alignment - uint_t phase; - uint_t kmax; - sint_t beat; - uint_t bp; - - for (i = 0; i < winlen; i++){ - dfrev[winlen-1-i] = 0.; - dfrev[winlen-1-i] = dfframe->data[0][i]*dfwv[i]; - } - - /* find autocorrelation function */ - aubio_autocorr(dfframe,bt->acf); - /* - for (i = 0; i < winlen; i++){ - AUBIO_DBG("%f,",acf[i]); - } - AUBIO_DBG("\n"); - */ - - /* get acfout - assume Rayleigh weightvector only */ - /* if timesig is unknown, use metrically unbiased version of filterbank */ - if(!bt->timesig) - numelem = 4; - // AUBIO_DBG("using unbiased filterbank, timesig: %d\n", timesig); - else - numelem = bt->timesig; - // AUBIO_DBG("using biased filterbank, timesig: %d\n", timesig); - - /* first and last output values are left intentionally as zero */ - for (i=0; i < bt->acfout->length; i++) - acfout[i] = 0.; - - for(i=1;iacfout); - bt->rp = maxindex ? maxindex : 1; - //rp = (maxindex==127) ? 43 : maxindex; //rayparam - bt->rp = (maxindex==bt->acfout->length-1) ? bt->rayparam : maxindex; //rayparam - - // get float period - //myperiod = fvec_getperiod(bt); - //AUBIO_DBG("\nrp = %d myperiod = %f\n",bt->rp,myperiod); - //AUBIO_DBG("accurate tempo is %f bpm\n",5168./myperiod); - - /* activate biased filterbank */ - aubio_beattracking_checkstate(bt); - bp = bt->bp; - /* end of biased filterbank */ - - /* initialize output */ - for(i=0;iphout->length;i++) {phout[i] = 0.;} - - /* deliberate integer operation, could be set to 3 max eventually */ - kmax = winlen/bp; - - for(i=0;iphout); - if (maxindex == winlen-1) maxindex = 0; - phase = 1 + maxindex; - - /* debug */ - //AUBIO_DBG("beat period = %d, rp1 = %d, rp2 = %d\n", bp, rp1, rp2); - //AUBIO_DBG("rp = %d, gp = %d, phase = %d\n", bt->rp, bt->gp, phase); - - /* reset output */ - for (i = 0; i < laglen; i++) - output->data[0][i] = 0.; - - i = 1; - beat = bp - phase; - /* start counting the beats */ - if(beat >= 0) - { - output->data[0][i] = (smpl_t)beat; - i++; - } - - while( beat+bp < step ) - { - beat += bp; - output->data[0][i] = (smpl_t)beat; - i++; - } - - bt->lastbeat = beat; - /* store the number of beat found in this frame as the first element */ - output->data[0][0] = i; -} - -uint_t fvec_gettimesig(smpl_t * acf, uint_t acflen, uint_t gp){ - sint_t k = 0; - smpl_t three_energy = 0., four_energy = 0.; - if( acflen > 6 * gp + 2 ){ - for(k=-2;k<2;k++){ - three_energy += acf[3*gp+k]; - four_energy += acf[4*gp+k]; - } - } - else{ /*Expanded to be more accurate in time sig estimation*/ - for(k=-2;k<2;k++){ - three_energy += acf[3*gp+k]+acf[6*gp+k]; - four_energy += acf[4*gp+k]+acf[2*gp+k]; - } - } - return (three_energy > four_energy) ? 3 : 4; -} - -smpl_t fvec_getperiod(aubio_beattracking_t * bt){ - /*function to make a more accurate beat period measurement.*/ - - smpl_t period = 0.; - smpl_t maxval = 0.; - uint_t numelem = 4; - - sint_t a,b; - uint_t i,j; - uint_t acfmi = bt->rp; //acfout max index - uint_t maxind = 0; - - if(!bt->timesig) - numelem = 4; - else - numelem = bt->timesig; - - for (i=0;iinds->data[0][i] = 0.; - - for (i=0;ilocacf->length;i++) // initialize - bt->locacf->data[0][i] = 0.; - - // get appropriate acf elements from acf and store in locacf - for (a=1;a<=4;a++){ - for(b=(1-a);blocacf->data[0][a*(acfmi)+b-1] = - bt->acf->data[0][a*(acfmi)+b-1]; - } - } - - for(i=0;ilocacf->data[0][j]>maxval){ - maxval = bt->locacf->data[0][j]; - maxind = j; - } - //bt->locacf->data[0][maxind] = 0.; - bt->locacf->data[0][j] = 0.; - } - //AUBIO_DBG("\n maxind is %d\n",maxind); - bt->inds->data[0][i] = maxind; - - } - - for (i=0;iinds->data[0][i]/(i+1.);} - - period = period/numelem; - - return (period); -} - - -void aubio_beattracking_checkstate(aubio_beattracking_t * bt) { - uint_t i,j,a,b; - uint_t flagconst = 0; - sint_t counter = bt->counter; - uint_t flagstep = bt->flagstep; - uint_t gp = bt->gp; - uint_t bp = bt->bp; - uint_t rp = bt->rp; - uint_t rp1 = bt->rp1; - uint_t rp2 = bt->rp2; - uint_t laglen = bt->rwv->length; - uint_t acflen = bt->acf->length; - uint_t step = bt->step; - smpl_t * acf = bt->acf->data[0]; - smpl_t * acfout = bt->acfout->data[0]; - smpl_t * gwv = bt->gwv->data[0]; - smpl_t * phwv = bt->phwv->data[0]; - - if (gp) { - // doshiftfbank again only if context dependent model is in operation - //acfout = doshiftfbank(acf,gwv,timesig,laglen,acfout); - //don't need acfout now, so can reuse vector - // gwv is, in first loop, definitely all zeros, but will have - // proper values when context dependent model is activated - for (i=0; i < bt->acfout->length; i++) - acfout[i] = 0.; - for(i=1;itimesig;a++){ - for(b=(1-a);bacfout); - /* - while(gp<32) gp =gp*2; - while(gp>64) gp = gp/2; - */ - } else { - //still only using general model - gp = 0; - } - - //now look for step change - i.e. a difference between gp and rp that - // is greater than 2*constthresh - always true in first case, since gp = 0 - if(counter == 0){ - if(ABS(gp - rp) > 2.*bt->g_var) { - flagstep = 1; // have observed step change. - counter = 3; // setup 3 frame counter - } else { - flagstep = 0; - } - } - - //i.e. 3rd frame after flagstep initially set - if (counter==1 && flagstep==1) { - //check for consistency between previous beatperiod values - if(ABS(2.*rp - rp1 -rp2) < bt->g_var) { - //if true, can activate context dependent model - flagconst = 1; - counter = 0; // reset counter and flagstep - } else { - //if not consistent, then don't flag consistency! - flagconst = 0; - counter = 2; // let it look next time - } - } else if (counter > 0) { - //if counter doesn't = 1, - counter = counter-1; - } - - rp2 = rp1; rp1 = rp; - - if (flagconst) { - /* first run of new hypothesis */ - gp = rp; - bt->timesig = fvec_gettimesig(acf,acflen, gp); - for(j=0;jg_var)); - flagconst = 0; - bp = gp; - /* flat phase weighting */ - for(j=0;j<2*laglen;j++) {phwv[j] = 1.;} - } else if (bt->timesig) { - /* context dependant model */ - bp = gp; - /* gaussian phase weighting */ - if (step > bt->lastbeat) { - for(j=0;j<2*laglen;j++) { - phwv[j] = EXP(-.5*SQR((smpl_t)(1.+j-step+bt->lastbeat))/(bp/8.)); - } - } else { - //AUBIO_DBG("NOT using phase weighting as step is %d and lastbeat %d \n", - // step,bt->lastbeat); - for(j=0;j<2*laglen;j++) {phwv[j] = 1.;} - } - } else { - /* initial state */ - bp = rp; - /* flat phase weighting */ - for(j=0;j<2*laglen;j++) {phwv[j] = 1.;} - } - - /* do some further checks on the final bp value */ - - /* if tempo is > 206 bpm, half it */ - while (bp < 25) { - //AUBIO_DBG("warning, doubling the beat period from %d\n", bp); - //AUBIO_DBG("warning, halving the tempo from %f\n", 60.*samplerate/hopsize/bp); - bp = bp*2; - } - - //AUBIO_DBG("tempo:\t%3.5f bpm | ", 5168./bp); - - /* smoothing */ - //bp = (uint_t) (0.8 * (smpl_t)bp + 0.2 * (smpl_t)bp2); - //AUBIO_DBG("tempo:\t%3.5f bpm smoothed | bp2 %d | bp %d | ", 5168./bp, bp2, bp); - //bp2 = bp; - //AUBIO_DBG("time signature: %d \n", bt->timesig); - bt->counter = counter; - bt->flagstep = flagstep; - bt->gp = gp; - bt->bp = bp; - bt->rp1 = rp1; - bt->rp2 = rp2; - -} - -smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt) { - if (bt->timesig != 0 && bt->counter == 0 && bt->flagstep == 0) { - return 5168. / (smpl_t)bt->gp; - } else { - return 0.; - } -} - -smpl_t aubio_beattracking_get_confidence(aubio_beattracking_t * bt) { - if (bt->gp) return vec_max(bt->acfout); - else return 0.; -} diff --git a/src/beattracking.h b/src/beattracking.h deleted file mode 100644 index c6964e9c..00000000 --- a/src/beattracking.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 2003 Matthew Davies and Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** \file - - Beat tracking using a context dependant model - - This file implement the causal beat tracking algorithm designed by Matthew - Davies and described in the following articles: - - Matthew E. P. Davies and Mark D. Plumbley. Causal tempo tracking of audio. - In Proceedings of the International Symposium on Music Information Retrieval - (ISMIR), pages 164­169, Barcelona, Spain, 2004. - - Matthew E. P. Davies, Paul Brossier, and Mark D. Plumbley. Beat tracking - towards automatic musical accompaniment. In Proceedings of the Audio - Engeeniring Society 118th Convention, Barcelona, Spain, May 2005. - -*/ -#ifndef BEATTRACKING_H -#define BEATTRACKING_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** beat tracking object */ -typedef struct _aubio_beattracking_t aubio_beattracking_t; - -/** create beat tracking object - - \param winlen: frame size [512] - \param channels number (not functionnal) [1] - -*/ -aubio_beattracking_t * new_aubio_beattracking(uint_t winlen, uint_t channels); -/** track the beat - - \param bt beat tracking object - \param dfframes current input detection function frame, smoothed by - adaptive median threshold. - \param out stored detected beat locations - -*/ -void aubio_beattracking_do(aubio_beattracking_t * bt, fvec_t * dfframes, fvec_t * out); -/** get current tempo in bpm - - \param bt beat tracking object - - Returns the currently observed tempo, in beats per minutes, or 0 if no - consistent value is found. - -*/ -smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt); -/** get current tempo confidence - - \param bt beat tracking object - - Returns the confidence with which the tempo has been observed, 0 if no - consistent value is found. - -*/ -smpl_t aubio_beattracking_get_confidence(aubio_beattracking_t * bt); -/** delete beat tracking object - - \param p beat tracking object - -*/ -void del_aubio_beattracking(aubio_beattracking_t * p); - -#ifdef __cplusplus -} -#endif - -#endif /* BEATTRACKING_H */ diff --git a/src/onset.c b/src/onset.c deleted file mode 100644 index 26445bd9..00000000 --- a/src/onset.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright (C) 2006 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "aubio_priv.h" -#include "sample.h" -#include "onset/detection.h" -#include "phasevoc.h" -#include "peakpick.h" -#include "mathutils.h" -#include "onset.h" - -/** structure to store object state */ -struct _aubio_onset_t { - aubio_pvoc_t * pv; /**< phase vocoder */ - aubio_onsetdetection_t * od; /**< onset detection */ - aubio_pickpeak_t * pp; /**< peak picker */ - cvec_t * fftgrain; /**< phase vocoder output */ - fvec_t * of; /**< onset detection function */ - smpl_t threshold; /**< onset peak picking threshold */ - smpl_t silence; /**< silence threhsold */ - uint_t minioi; /**< minimum inter onset interval */ - uint_t wasonset; /**< number of frames since last onset */ -}; - -/* execute onset detection function on iput buffer */ -void aubio_onset(aubio_onset_t *o, fvec_t * input, fvec_t * onset) -{ - uint_t isonset = 0; - uint_t wasonset = o->wasonset; - aubio_pvoc_do (o->pv,input, o->fftgrain); - aubio_onsetdetection(o->od,o->fftgrain, o->of); - /*if (usedoubled) { - aubio_onsetdetection(o2,fftgrain, onset2); - onset->data[0][0] *= onset2->data[0][0]; - }*/ - isonset = aubio_peakpick_pimrt(o->of,o->pp); - if (isonset) { - if (aubio_silence_detection(input, o->silence)==1) { - isonset = 0; - wasonset++; - } else { - if (wasonset > o->minioi) { - wasonset = 0; - } else { - isonset = 0; - wasonset++; - } - } - } else { - wasonset++; - } - o->wasonset = wasonset; - onset->data[0][0] = isonset; - return; -} - -void aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence) { - o->silence = silence; - return; -} - -void aubio_onset_set_threshold(aubio_onset_t * o, smpl_t threshold) { - o->threshold = threshold; - aubio_peakpicker_set_threshold(o->pp, o->threshold); - return; -} - -void aubio_onset_set_minioi(aubio_onset_t * o, uint_t minioi) { - o->minioi = minioi; - return; -} - -/* Allocate memory for an onset detection */ -aubio_onset_t * new_aubio_onset (aubio_onsetdetection_type type_onset, - uint_t buf_size, uint_t hop_size, uint_t channels) -{ - aubio_onset_t * o = AUBIO_NEW(aubio_onset_t); - /** set some default parameter */ - o->threshold = 0.3; - o->minioi = 4; - o->silence = -70; - o->wasonset = 0; - o->pv = new_aubio_pvoc(buf_size, hop_size, channels); - o->pp = new_aubio_peakpicker(o->threshold); - o->od = new_aubio_onsetdetection(type_onset,buf_size,channels); - o->fftgrain = new_cvec(buf_size,channels); - o->of = new_fvec(1, channels); - /*if (usedoubled) { - o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels); - onset2 = new_fvec(1 , channels); - }*/ - return o; -} - -void del_aubio_onset (aubio_onset_t *o) -{ - del_aubio_onsetdetection(o->od); - del_aubio_peakpicker(o->pp); - del_aubio_pvoc(o->pv); - del_fvec(o->of); - del_cvec(o->fftgrain); - AUBIO_FREE(o); -} diff --git a/src/onset.h b/src/onset.h deleted file mode 100644 index aa67bd1f..00000000 --- a/src/onset.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (C) 2006 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** \file - - Onset detection driver - - The following routines compute the onset detection function and detect peaks - in these functions. When onsets are found above a given silence threshold, - and after a minimum inter-onset interval, the output vector returned by - aubio_onset is filled with 1. Otherwise, the output vector remains 0. - - The peak-picking threshold, the silence threshold, and the minimum - inter-onset interval can be adjusted during the execution of the aubio_onset - routine using the corresponding functions. - -*/ - - -#ifndef ONSET_H -#define ONSET_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** onset detection object */ -typedef struct _aubio_onset_t aubio_onset_t; - -/** create onset detection object - - \param type_onset onset detection type as specified in onsetdetection.h - \param buf_size buffer size for phase vocoder - \param hop_size hop size for phase vocoder - \param channels number of channels - -*/ -aubio_onset_t * new_aubio_onset (aubio_onsetdetection_type type_onset, - uint_t buf_size, uint_t hop_size, uint_t channels); - -/** execute onset detection - - \param o onset detection object as returned by new_aubio_onset - \param input new audio vector of length hop_size - \param onset output vector, 1 if onset is found, 0 otherwise - -*/ -void aubio_onset(aubio_onset_t *o, fvec_t * input, fvec_t * onset); - -/** set onset detection silence threshold - - \param o onset detection object as returned by new_aubio_onset - \param silence new silence detection threshold - -*/ -void aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence); - -/** set onset detection peak picking threshold - - \param o onset detection object as returned by new_aubio_onset - \param threshold new peak-picking threshold - -*/ -void aubio_onset_set_threshold(aubio_onset_t * o, smpl_t threshold); - -/** set minimum inter onset interval - - \param o onset detection object as returned by new_aubio_onset - \param minioi minimum number of frames between onsets (in multiple of - hop_size/samplerare) - -*/ -void aubio_onset_set_minioi(aubio_onset_t * o, uint_t minioi); - -/** delete onset detection object - - \param o onset detection object to delete - -*/ -void del_aubio_onset(aubio_onset_t * o); - -#ifdef __cplusplus -} -#endif - -#endif /* ONSET_H */ diff --git a/src/onset/onset.c b/src/onset/onset.c new file mode 100644 index 00000000..e4bc5dde --- /dev/null +++ b/src/onset/onset.c @@ -0,0 +1,119 @@ +/* + Copyright (C) 2006 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "aubio_priv.h" +#include "sample.h" +#include "onset/onsetdetection.h" +#include "phasevoc.h" +#include "peakpick.h" +#include "mathutils.h" +#include "onset.h" + +/** structure to store object state */ +struct _aubio_onset_t { + aubio_pvoc_t * pv; /**< phase vocoder */ + aubio_onsetdetection_t * od; /**< onset detection */ + aubio_pickpeak_t * pp; /**< peak picker */ + cvec_t * fftgrain; /**< phase vocoder output */ + fvec_t * of; /**< onset detection function */ + smpl_t threshold; /**< onset peak picking threshold */ + smpl_t silence; /**< silence threhsold */ + uint_t minioi; /**< minimum inter onset interval */ + uint_t wasonset; /**< number of frames since last onset */ +}; + +/* execute onset detection function on iput buffer */ +void aubio_onset(aubio_onset_t *o, fvec_t * input, fvec_t * onset) +{ + uint_t isonset = 0; + uint_t wasonset = o->wasonset; + aubio_pvoc_do (o->pv,input, o->fftgrain); + aubio_onsetdetection(o->od,o->fftgrain, o->of); + /*if (usedoubled) { + aubio_onsetdetection(o2,fftgrain, onset2); + onset->data[0][0] *= onset2->data[0][0]; + }*/ + isonset = aubio_peakpick_pimrt(o->of,o->pp); + if (isonset) { + if (aubio_silence_detection(input, o->silence)==1) { + isonset = 0; + wasonset++; + } else { + if (wasonset > o->minioi) { + wasonset = 0; + } else { + isonset = 0; + wasonset++; + } + } + } else { + wasonset++; + } + o->wasonset = wasonset; + onset->data[0][0] = isonset; + return; +} + +void aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence) { + o->silence = silence; + return; +} + +void aubio_onset_set_threshold(aubio_onset_t * o, smpl_t threshold) { + o->threshold = threshold; + aubio_peakpicker_set_threshold(o->pp, o->threshold); + return; +} + +void aubio_onset_set_minioi(aubio_onset_t * o, uint_t minioi) { + o->minioi = minioi; + return; +} + +/* Allocate memory for an onset detection */ +aubio_onset_t * new_aubio_onset (aubio_onsetdetection_type type_onset, + uint_t buf_size, uint_t hop_size, uint_t channels) +{ + aubio_onset_t * o = AUBIO_NEW(aubio_onset_t); + /** set some default parameter */ + o->threshold = 0.3; + o->minioi = 4; + o->silence = -70; + o->wasonset = 0; + o->pv = new_aubio_pvoc(buf_size, hop_size, channels); + o->pp = new_aubio_peakpicker(o->threshold); + o->od = new_aubio_onsetdetection(type_onset,buf_size,channels); + o->fftgrain = new_cvec(buf_size,channels); + o->of = new_fvec(1, channels); + /*if (usedoubled) { + o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels); + onset2 = new_fvec(1 , channels); + }*/ + return o; +} + +void del_aubio_onset (aubio_onset_t *o) +{ + del_aubio_onsetdetection(o->od); + del_aubio_peakpicker(o->pp); + del_aubio_pvoc(o->pv); + del_fvec(o->of); + del_cvec(o->fftgrain); + AUBIO_FREE(o); +} diff --git a/src/onset/onset.h b/src/onset/onset.h new file mode 100644 index 00000000..aa67bd1f --- /dev/null +++ b/src/onset/onset.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2006 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** \file + + Onset detection driver + + The following routines compute the onset detection function and detect peaks + in these functions. When onsets are found above a given silence threshold, + and after a minimum inter-onset interval, the output vector returned by + aubio_onset is filled with 1. Otherwise, the output vector remains 0. + + The peak-picking threshold, the silence threshold, and the minimum + inter-onset interval can be adjusted during the execution of the aubio_onset + routine using the corresponding functions. + +*/ + + +#ifndef ONSET_H +#define ONSET_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** onset detection object */ +typedef struct _aubio_onset_t aubio_onset_t; + +/** create onset detection object + + \param type_onset onset detection type as specified in onsetdetection.h + \param buf_size buffer size for phase vocoder + \param hop_size hop size for phase vocoder + \param channels number of channels + +*/ +aubio_onset_t * new_aubio_onset (aubio_onsetdetection_type type_onset, + uint_t buf_size, uint_t hop_size, uint_t channels); + +/** execute onset detection + + \param o onset detection object as returned by new_aubio_onset + \param input new audio vector of length hop_size + \param onset output vector, 1 if onset is found, 0 otherwise + +*/ +void aubio_onset(aubio_onset_t *o, fvec_t * input, fvec_t * onset); + +/** set onset detection silence threshold + + \param o onset detection object as returned by new_aubio_onset + \param silence new silence detection threshold + +*/ +void aubio_onset_set_silence(aubio_onset_t * o, smpl_t silence); + +/** set onset detection peak picking threshold + + \param o onset detection object as returned by new_aubio_onset + \param threshold new peak-picking threshold + +*/ +void aubio_onset_set_threshold(aubio_onset_t * o, smpl_t threshold); + +/** set minimum inter onset interval + + \param o onset detection object as returned by new_aubio_onset + \param minioi minimum number of frames between onsets (in multiple of + hop_size/samplerare) + +*/ +void aubio_onset_set_minioi(aubio_onset_t * o, uint_t minioi); + +/** delete onset detection object + + \param o onset detection object to delete + +*/ +void del_aubio_onset(aubio_onset_t * o); + +#ifdef __cplusplus +} +#endif + +#endif /* ONSET_H */ diff --git a/src/onset/peakpick.c b/src/onset/peakpick.c new file mode 100644 index 00000000..9f128e87 --- /dev/null +++ b/src/onset/peakpick.c @@ -0,0 +1,184 @@ +/* + Copyright (C) 2003 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "aubio_priv.h" +#include "sample.h" +#include "mathutils.h" +#include "biquad.h" +#include "peakpick.h" + +/* peak picking parameters, default values in brackets + * + * [<----post----|--pre-->] + * .................|............. + * time-> ^now + */ +struct _aubio_pickpeak_t { + /** thresh: offset threshold [0.033 or 0.01] */ + smpl_t threshold; + /** win_post: median filter window length (causal part) [8] */ + uint_t win_post; + /** pre: median filter window (anti-causal part) [post-1] */ + uint_t win_pre; + /** threshfn: name or handle of fn for computing adaptive threshold [median] */ + aubio_thresholdfn_t thresholdfn; + /** picker: name or handle of fn for picking event times [peakpick] */ + aubio_pickerfn_t pickerfn; + + /** biquad lowpass filter */ + aubio_biquad_t * biquad; + /** original onsets */ + fvec_t * onset_keep; + /** modified onsets */ + fvec_t * onset_proc; + /** peak picked window [3] */ + fvec_t * onset_peek; + /** scratch pad for biquad and median */ + fvec_t * scratch; + + /** \bug should be used to calculate filter coefficients */ + /* cutoff: low-pass filter cutoff [0.34, 1] */ + /* smpl_t cutoff; */ + + /* not used anymore */ + /* time precision [512/44100 winlength/samplerate, fs/buffer_size */ + /* smpl_t tau; */ + /* alpha: normalisation exponent [9] */ + /* smpl_t alpha; */ +}; + + +/** modified version for real time, moving mean adaptive threshold this method + * is slightly more permissive than the offline one, and yelds to an increase + * of false positives. best */ +uint_t aubio_peakpick_pimrt(fvec_t * onset, aubio_pickpeak_t * p) { + fvec_t * onset_keep = (fvec_t *)p->onset_keep; + fvec_t * onset_proc = (fvec_t *)p->onset_proc; + fvec_t * onset_peek = (fvec_t *)p->onset_peek; + fvec_t * scratch = (fvec_t *)p->scratch; + smpl_t mean = 0., median = 0.; + uint_t length = p->win_post + p->win_pre + 1; + uint_t i = 0, j; + + /* store onset in onset_keep */ + /* shift all elements but last, then write last */ + /* for (i=0;idata[i][j] = onset_keep->data[i][j+1]; + onset_proc->data[i][j] = onset_keep->data[i][j]; + } + onset_keep->data[i][length-1] = onset->data[i][0]; + onset_proc->data[i][length-1] = onset->data[i][0]; + /* } */ + + /* filter onset_proc */ + /** \bug filtfilt calculated post+pre times, should be only once !? */ + aubio_biquad_do_filtfilt(p->biquad,onset_proc,scratch); + + /* calculate mean and median for onset_proc */ + /* for (i=0;ichannels;i++) { */ + mean = vec_mean(onset_proc); + /* copy to scratch */ + for (j = 0; j < length; j++) + scratch->data[i][j] = onset_proc->data[i][j]; + median = p->thresholdfn(scratch); + /* } */ + + /* for (i=0;ichannels;i++) { */ + /* shift peek array */ + for (j=0;j<3-1;j++) + onset_peek->data[i][j] = onset_peek->data[i][j+1]; + /* calculate new peek value */ + onset_peek->data[i][2] = + onset_proc->data[i][p->win_post] - median - mean * p->threshold; + /* } */ + //AUBIO_DBG("%f\n", onset_peek->data[0][2]); + return (p->pickerfn)(onset_peek,1); +} + +/** this method returns the current value in the pick peaking buffer + * after smoothing + */ +smpl_t aubio_peakpick_pimrt_getval(aubio_pickpeak_t * p) +{ + uint_t i = 0; + return p->onset_peek->data[i][1]; +} + +/** function added by Miguel Ramirez to return the onset detection amplitude in peakval */ +uint_t aubio_peakpick_pimrt_wt(fvec_t * onset, aubio_pickpeak_t * p, smpl_t* peakval) +{ + uint_t isonset = 0; + isonset = aubio_peakpick_pimrt(onset,p); + + //if ( isonset && peakval != NULL ) + if ( peakval != NULL ) + *peakval = aubio_peakpick_pimrt_getval(p); + + return isonset; +} + +void aubio_peakpicker_set_threshold(aubio_pickpeak_t * p, smpl_t threshold) { + p->threshold = threshold; + return; +} + +smpl_t aubio_peakpicker_get_threshold(aubio_pickpeak_t * p) { + return p->threshold; +} + +void aubio_peakpicker_set_thresholdfn(aubio_pickpeak_t * p, aubio_thresholdfn_t thresholdfn) { + p->thresholdfn = thresholdfn; + return; +} + +aubio_thresholdfn_t aubio_peakpicker_get_thresholdfn(aubio_pickpeak_t * p) { + return (aubio_thresholdfn_t) (p->thresholdfn); +} + +aubio_pickpeak_t * new_aubio_peakpicker(smpl_t threshold) { + aubio_pickpeak_t * t = AUBIO_NEW(aubio_pickpeak_t); + t->threshold = 0.1; /* 0.0668; 0.33; 0.082; 0.033; */ + if (threshold > 0. && threshold < 10.) + t->threshold = threshold; + t->win_post = 5; + t->win_pre = 1; + + t->thresholdfn = (aubio_thresholdfn_t)(vec_median); /* (vec_mean); */ + t->pickerfn = (aubio_pickerfn_t)(vec_peakpick); + + t->scratch = new_fvec(t->win_post+t->win_pre+1,1); + t->onset_keep = new_fvec(t->win_post+t->win_pre+1,1); + t->onset_proc = new_fvec(t->win_post+t->win_pre+1,1); + t->onset_peek = new_fvec(3,1); + + /* cutoff: low-pass filter cutoff [0.34, 1] */ + /* t->cutoff=0.34; */ + t->biquad = new_aubio_biquad(0.1600,0.3200,0.1600,-0.5949,0.2348); + return t; +} + +void del_aubio_peakpicker(aubio_pickpeak_t * p) { + del_aubio_biquad(p->biquad); + del_fvec(p->onset_keep); + del_fvec(p->onset_proc); + del_fvec(p->onset_peek); + del_fvec(p->scratch); + AUBIO_FREE(p); +} diff --git a/src/onset/peakpick.h b/src/onset/peakpick.h new file mode 100644 index 00000000..3d391f48 --- /dev/null +++ b/src/onset/peakpick.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2003 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** \file + * peak picking utilities function + * + * \todo check/fix peak picking + */ + +#ifndef PEAKPICK_H +#define PEAKPICK_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** function pointer to thresholding function */ +typedef smpl_t (*aubio_thresholdfn_t)(fvec_t *input); +/** function pointer to peak-picking function */ +typedef uint_t (*aubio_pickerfn_t)(fvec_t *input, uint_t pos); +/** peak-picker structure */ +typedef struct _aubio_pickpeak_t aubio_pickpeak_t; + +/** peak-picker creation function */ +aubio_pickpeak_t * new_aubio_peakpicker(smpl_t threshold); +/** real time peak picking function */ +uint_t aubio_peakpick_pimrt(fvec_t * DF, aubio_pickpeak_t * p); +/** function added by Miguel Ramirez to return the onset detection amplitude in peakval */ +uint_t aubio_peakpick_pimrt_wt( fvec_t* DF, aubio_pickpeak_t* p, smpl_t* peakval ); +/** get current peak value */ +smpl_t aubio_peakpick_pimrt_getval(aubio_pickpeak_t * p); +/** destroy peak picker structure */ +void del_aubio_peakpicker(aubio_pickpeak_t * p); + +/** set peak picking threshold */ +void aubio_peakpicker_set_threshold(aubio_pickpeak_t * p, smpl_t threshold); +/** get peak picking threshold */ +smpl_t aubio_peakpicker_get_threshold(aubio_pickpeak_t * p); +/** set peak picker thresholding function */ +void aubio_peakpicker_set_thresholdfn(aubio_pickpeak_t * p, aubio_thresholdfn_t thresholdfn); +/** get peak picker thresholding function */ +aubio_thresholdfn_t aubio_peakpicker_get_thresholdfn(aubio_pickpeak_t * p); + +#ifdef __cplusplus +} +#endif + +#endif /* PEAKPICK_H */ diff --git a/src/peakpick.c b/src/peakpick.c deleted file mode 100644 index 9f128e87..00000000 --- a/src/peakpick.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - Copyright (C) 2003 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "aubio_priv.h" -#include "sample.h" -#include "mathutils.h" -#include "biquad.h" -#include "peakpick.h" - -/* peak picking parameters, default values in brackets - * - * [<----post----|--pre-->] - * .................|............. - * time-> ^now - */ -struct _aubio_pickpeak_t { - /** thresh: offset threshold [0.033 or 0.01] */ - smpl_t threshold; - /** win_post: median filter window length (causal part) [8] */ - uint_t win_post; - /** pre: median filter window (anti-causal part) [post-1] */ - uint_t win_pre; - /** threshfn: name or handle of fn for computing adaptive threshold [median] */ - aubio_thresholdfn_t thresholdfn; - /** picker: name or handle of fn for picking event times [peakpick] */ - aubio_pickerfn_t pickerfn; - - /** biquad lowpass filter */ - aubio_biquad_t * biquad; - /** original onsets */ - fvec_t * onset_keep; - /** modified onsets */ - fvec_t * onset_proc; - /** peak picked window [3] */ - fvec_t * onset_peek; - /** scratch pad for biquad and median */ - fvec_t * scratch; - - /** \bug should be used to calculate filter coefficients */ - /* cutoff: low-pass filter cutoff [0.34, 1] */ - /* smpl_t cutoff; */ - - /* not used anymore */ - /* time precision [512/44100 winlength/samplerate, fs/buffer_size */ - /* smpl_t tau; */ - /* alpha: normalisation exponent [9] */ - /* smpl_t alpha; */ -}; - - -/** modified version for real time, moving mean adaptive threshold this method - * is slightly more permissive than the offline one, and yelds to an increase - * of false positives. best */ -uint_t aubio_peakpick_pimrt(fvec_t * onset, aubio_pickpeak_t * p) { - fvec_t * onset_keep = (fvec_t *)p->onset_keep; - fvec_t * onset_proc = (fvec_t *)p->onset_proc; - fvec_t * onset_peek = (fvec_t *)p->onset_peek; - fvec_t * scratch = (fvec_t *)p->scratch; - smpl_t mean = 0., median = 0.; - uint_t length = p->win_post + p->win_pre + 1; - uint_t i = 0, j; - - /* store onset in onset_keep */ - /* shift all elements but last, then write last */ - /* for (i=0;idata[i][j] = onset_keep->data[i][j+1]; - onset_proc->data[i][j] = onset_keep->data[i][j]; - } - onset_keep->data[i][length-1] = onset->data[i][0]; - onset_proc->data[i][length-1] = onset->data[i][0]; - /* } */ - - /* filter onset_proc */ - /** \bug filtfilt calculated post+pre times, should be only once !? */ - aubio_biquad_do_filtfilt(p->biquad,onset_proc,scratch); - - /* calculate mean and median for onset_proc */ - /* for (i=0;ichannels;i++) { */ - mean = vec_mean(onset_proc); - /* copy to scratch */ - for (j = 0; j < length; j++) - scratch->data[i][j] = onset_proc->data[i][j]; - median = p->thresholdfn(scratch); - /* } */ - - /* for (i=0;ichannels;i++) { */ - /* shift peek array */ - for (j=0;j<3-1;j++) - onset_peek->data[i][j] = onset_peek->data[i][j+1]; - /* calculate new peek value */ - onset_peek->data[i][2] = - onset_proc->data[i][p->win_post] - median - mean * p->threshold; - /* } */ - //AUBIO_DBG("%f\n", onset_peek->data[0][2]); - return (p->pickerfn)(onset_peek,1); -} - -/** this method returns the current value in the pick peaking buffer - * after smoothing - */ -smpl_t aubio_peakpick_pimrt_getval(aubio_pickpeak_t * p) -{ - uint_t i = 0; - return p->onset_peek->data[i][1]; -} - -/** function added by Miguel Ramirez to return the onset detection amplitude in peakval */ -uint_t aubio_peakpick_pimrt_wt(fvec_t * onset, aubio_pickpeak_t * p, smpl_t* peakval) -{ - uint_t isonset = 0; - isonset = aubio_peakpick_pimrt(onset,p); - - //if ( isonset && peakval != NULL ) - if ( peakval != NULL ) - *peakval = aubio_peakpick_pimrt_getval(p); - - return isonset; -} - -void aubio_peakpicker_set_threshold(aubio_pickpeak_t * p, smpl_t threshold) { - p->threshold = threshold; - return; -} - -smpl_t aubio_peakpicker_get_threshold(aubio_pickpeak_t * p) { - return p->threshold; -} - -void aubio_peakpicker_set_thresholdfn(aubio_pickpeak_t * p, aubio_thresholdfn_t thresholdfn) { - p->thresholdfn = thresholdfn; - return; -} - -aubio_thresholdfn_t aubio_peakpicker_get_thresholdfn(aubio_pickpeak_t * p) { - return (aubio_thresholdfn_t) (p->thresholdfn); -} - -aubio_pickpeak_t * new_aubio_peakpicker(smpl_t threshold) { - aubio_pickpeak_t * t = AUBIO_NEW(aubio_pickpeak_t); - t->threshold = 0.1; /* 0.0668; 0.33; 0.082; 0.033; */ - if (threshold > 0. && threshold < 10.) - t->threshold = threshold; - t->win_post = 5; - t->win_pre = 1; - - t->thresholdfn = (aubio_thresholdfn_t)(vec_median); /* (vec_mean); */ - t->pickerfn = (aubio_pickerfn_t)(vec_peakpick); - - t->scratch = new_fvec(t->win_post+t->win_pre+1,1); - t->onset_keep = new_fvec(t->win_post+t->win_pre+1,1); - t->onset_proc = new_fvec(t->win_post+t->win_pre+1,1); - t->onset_peek = new_fvec(3,1); - - /* cutoff: low-pass filter cutoff [0.34, 1] */ - /* t->cutoff=0.34; */ - t->biquad = new_aubio_biquad(0.1600,0.3200,0.1600,-0.5949,0.2348); - return t; -} - -void del_aubio_peakpicker(aubio_pickpeak_t * p) { - del_aubio_biquad(p->biquad); - del_fvec(p->onset_keep); - del_fvec(p->onset_proc); - del_fvec(p->onset_peek); - del_fvec(p->scratch); - AUBIO_FREE(p); -} diff --git a/src/peakpick.h b/src/peakpick.h deleted file mode 100644 index 3d391f48..00000000 --- a/src/peakpick.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright (C) 2003 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** \file - * peak picking utilities function - * - * \todo check/fix peak picking - */ - -#ifndef PEAKPICK_H -#define PEAKPICK_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** function pointer to thresholding function */ -typedef smpl_t (*aubio_thresholdfn_t)(fvec_t *input); -/** function pointer to peak-picking function */ -typedef uint_t (*aubio_pickerfn_t)(fvec_t *input, uint_t pos); -/** peak-picker structure */ -typedef struct _aubio_pickpeak_t aubio_pickpeak_t; - -/** peak-picker creation function */ -aubio_pickpeak_t * new_aubio_peakpicker(smpl_t threshold); -/** real time peak picking function */ -uint_t aubio_peakpick_pimrt(fvec_t * DF, aubio_pickpeak_t * p); -/** function added by Miguel Ramirez to return the onset detection amplitude in peakval */ -uint_t aubio_peakpick_pimrt_wt( fvec_t* DF, aubio_pickpeak_t* p, smpl_t* peakval ); -/** get current peak value */ -smpl_t aubio_peakpick_pimrt_getval(aubio_pickpeak_t * p); -/** destroy peak picker structure */ -void del_aubio_peakpicker(aubio_pickpeak_t * p); - -/** set peak picking threshold */ -void aubio_peakpicker_set_threshold(aubio_pickpeak_t * p, smpl_t threshold); -/** get peak picking threshold */ -smpl_t aubio_peakpicker_get_threshold(aubio_pickpeak_t * p); -/** set peak picker thresholding function */ -void aubio_peakpicker_set_thresholdfn(aubio_pickpeak_t * p, aubio_thresholdfn_t thresholdfn); -/** get peak picker thresholding function */ -aubio_thresholdfn_t aubio_peakpicker_get_thresholdfn(aubio_pickpeak_t * p); - -#ifdef __cplusplus -} -#endif - -#endif /* PEAKPICK_H */ diff --git a/src/pitch/pitchdetection.c b/src/pitch/pitchdetection.c new file mode 100644 index 00000000..18cc89bc --- /dev/null +++ b/src/pitch/pitchdetection.c @@ -0,0 +1,246 @@ +/* + Copyright (C) 2003 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "aubio_priv.h" +#include "sample.h" +#include "phasevoc.h" +#include "mathutils.h" +#include "filter.h" +#include "pitch/pitchmcomb.h" +#include "pitch/pitchyin.h" +#include "pitch/pitchfcomb.h" +#include "pitch/pitchschmitt.h" +#include "pitch/pitchyinfft.h" +#include "pitchdetection.h" + +typedef smpl_t (*aubio_pitchdetection_func_t) + (aubio_pitchdetection_t *p, fvec_t * ibuf); +typedef smpl_t (*aubio_pitchdetection_conv_t) + (smpl_t value, uint_t srate, uint_t bufsize); + +void aubio_pitchdetection_slideblock(aubio_pitchdetection_t *p, fvec_t *ibuf); + +smpl_t aubio_pitchdetection_mcomb (aubio_pitchdetection_t *p, fvec_t *ibuf); +smpl_t aubio_pitchdetection_yin (aubio_pitchdetection_t *p, fvec_t *ibuf); +smpl_t aubio_pitchdetection_schmitt (aubio_pitchdetection_t *p, fvec_t *ibuf); +smpl_t aubio_pitchdetection_fcomb (aubio_pitchdetection_t *p, fvec_t *ibuf); +smpl_t aubio_pitchdetection_yinfft (aubio_pitchdetection_t *p, fvec_t *ibuf); + +/** generic pitch detection structure */ +struct _aubio_pitchdetection_t { + aubio_pitchdetection_type type; /**< pitch detection mode */ + aubio_pitchdetection_mode mode; /**< pitch detection output mode */ + uint_t srate; /**< samplerate */ + uint_t bufsize; /**< buffer size */ + aubio_pitchmcomb_t * mcomb; /**< mcomb object */ + aubio_pitchfcomb_t * fcomb; /**< fcomb object */ + aubio_pitchschmitt_t * schmitt; /**< schmitt object */ + aubio_pitchyinfft_t * yinfft; /**< yinfft object */ + aubio_filter_t * filter; /**< filter */ + aubio_pvoc_t * pv; /**< phase vocoder for mcomb */ + cvec_t * fftgrain; /**< spectral frame for mcomb */ + fvec_t * buf; /**< temporary buffer for yin */ + fvec_t * yin; /**< yin function */ + smpl_t yinthres; /**< yin peak picking threshold parameter */ + aubio_pitchdetection_func_t callback; /**< pointer to current pitch detection method */ + aubio_pitchdetection_conv_t freqconv; /**< pointer to current pitch conversion method */ +}; + +/* convenience wrapper function for frequency unit conversions + * should probably be rewritten with #defines */ +smpl_t freqconvbin(smpl_t f,uint_t srate,uint_t bufsize); +smpl_t freqconvbin(smpl_t f,uint_t srate,uint_t bufsize){ + return aubio_freqtobin(f,srate,bufsize); +} + +smpl_t freqconvmidi(smpl_t f,uint_t srate,uint_t bufsize); +smpl_t freqconvmidi(smpl_t f,uint_t srate UNUSED,uint_t bufsize UNUSED){ + return aubio_freqtomidi(f); +} + +smpl_t freqconvpass(smpl_t f,uint_t srate,uint_t bufsize); +smpl_t freqconvpass(smpl_t f,uint_t srate UNUSED,uint_t bufsize UNUSED){ + return f; +} + +aubio_pitchdetection_t * new_aubio_pitchdetection(uint_t bufsize, + uint_t hopsize, + uint_t channels, + uint_t samplerate, + aubio_pitchdetection_type type, + aubio_pitchdetection_mode mode) +{ + aubio_pitchdetection_t *p = AUBIO_NEW(aubio_pitchdetection_t); + p->srate = samplerate; + p->type = type; + p->mode = mode; + p->bufsize = bufsize; + switch(p->type) { + case aubio_pitch_yin: + p->buf = new_fvec(bufsize,channels); + p->yin = new_fvec(bufsize/2,channels); + p->callback = aubio_pitchdetection_yin; + p->yinthres = 0.15; + break; + case aubio_pitch_mcomb: + p->pv = new_aubio_pvoc(bufsize, hopsize, channels); + p->fftgrain = new_cvec(bufsize, channels); + p->mcomb = new_aubio_pitchmcomb(bufsize,hopsize,channels,samplerate); + p->filter = new_aubio_cdsgn_filter(samplerate); + p->callback = aubio_pitchdetection_mcomb; + break; + case aubio_pitch_fcomb: + p->buf = new_fvec(bufsize,channels); + p->fcomb = new_aubio_pitchfcomb(bufsize,hopsize,samplerate); + p->callback = aubio_pitchdetection_fcomb; + break; + case aubio_pitch_schmitt: + p->buf = new_fvec(bufsize,channels); + p->schmitt = new_aubio_pitchschmitt(bufsize,samplerate); + p->callback = aubio_pitchdetection_schmitt; + break; + case aubio_pitch_yinfft: + p->buf = new_fvec(bufsize,channels); + p->yinfft = new_aubio_pitchyinfft(bufsize); + p->callback = aubio_pitchdetection_yinfft; + p->yinthres = 0.85; + break; + default: + break; + } + switch(p->mode) { + case aubio_pitchm_freq: + p->freqconv = freqconvpass; + break; + case aubio_pitchm_midi: + p->freqconv = freqconvmidi; + break; + case aubio_pitchm_cent: + /* bug: not implemented */ + p->freqconv = freqconvmidi; + break; + case aubio_pitchm_bin: + p->freqconv = freqconvbin; + break; + default: + break; + } + return p; +} + +void del_aubio_pitchdetection(aubio_pitchdetection_t * p) { + switch(p->type) { + case aubio_pitch_yin: + del_fvec(p->yin); + del_fvec(p->buf); + break; + case aubio_pitch_mcomb: + del_aubio_pvoc(p->pv); + del_cvec(p->fftgrain); + del_aubio_filter(p->filter); + del_aubio_pitchmcomb(p->mcomb); + break; + case aubio_pitch_schmitt: + del_fvec(p->buf); + del_aubio_pitchschmitt(p->schmitt); + break; + case aubio_pitch_fcomb: + del_fvec(p->buf); + del_aubio_pitchfcomb(p->fcomb); + break; + case aubio_pitch_yinfft: + del_fvec(p->buf); + del_aubio_pitchyinfft(p->yinfft); + break; + default: + break; + } + AUBIO_FREE(p); +} + +void aubio_pitchdetection_slideblock(aubio_pitchdetection_t *p, fvec_t *ibuf){ + uint_t i,j = 0, overlap_size = 0; + overlap_size = p->buf->length-ibuf->length; + for (i=0;ibuf->channels;i++){ + for (j=0;jbuf->data[i][j] = p->buf->data[i][j+ibuf->length]; + } + } + for (i=0;ichannels;i++){ + for (j=0;jlength;j++){ + p->buf->data[i][j+overlap_size] = ibuf->data[i][j]; + } + } +} + +void aubio_pitchdetection_set_yinthresh(aubio_pitchdetection_t *p, smpl_t thres) { + p->yinthres = thres; +} + +smpl_t aubio_pitchdetection(aubio_pitchdetection_t *p, fvec_t * ibuf) { + return p->freqconv(p->callback(p,ibuf),p->srate,p->bufsize); +} + +smpl_t aubio_pitchdetection_mcomb(aubio_pitchdetection_t *p, fvec_t *ibuf) { + smpl_t pitch = 0.; + aubio_filter_do(p->filter,ibuf); + aubio_pvoc_do(p->pv,ibuf,p->fftgrain); + pitch = aubio_pitchmcomb_detect(p->mcomb,p->fftgrain); + /** \bug should move the >0 check within aubio_bintofreq */ + if (pitch>0.) { + pitch = aubio_bintofreq(pitch,p->srate,p->bufsize); + } else { + pitch = 0.; + } + return pitch; +} + +smpl_t aubio_pitchdetection_yin(aubio_pitchdetection_t *p, fvec_t *ibuf) { + smpl_t pitch = 0.; + aubio_pitchdetection_slideblock(p,ibuf); + pitch = aubio_pitchyin_getpitchfast(p->buf,p->yin, p->yinthres); + if (pitch>0) { + pitch = p->srate/(pitch+0.); + } else { + pitch = 0.; + } + return pitch; +} + + +smpl_t aubio_pitchdetection_yinfft(aubio_pitchdetection_t *p, fvec_t *ibuf){ + smpl_t pitch = 0.; + aubio_pitchdetection_slideblock(p,ibuf); + pitch = aubio_pitchyinfft_detect(p->yinfft,p->buf,p->yinthres); + if (pitch>0) { + pitch = p->srate/(pitch+0.); + } else { + pitch = 0.; + } + return pitch; +} + +smpl_t aubio_pitchdetection_fcomb(aubio_pitchdetection_t *p, fvec_t *ibuf){ + aubio_pitchdetection_slideblock(p,ibuf); + return aubio_pitchfcomb_detect(p->fcomb,p->buf); +} + +smpl_t aubio_pitchdetection_schmitt(aubio_pitchdetection_t *p, fvec_t *ibuf){ + aubio_pitchdetection_slideblock(p,ibuf); + return aubio_pitchschmitt_detect(p->schmitt,p->buf); +} diff --git a/src/pitch/pitchdetection.h b/src/pitch/pitchdetection.h new file mode 100644 index 00000000..164b1f53 --- /dev/null +++ b/src/pitch/pitchdetection.h @@ -0,0 +1,98 @@ +/* + Copyright (C) 2003 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PITCHAUTOTCORR_H +#define PITCHAUTOTCORR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file + + Generic method for pitch detection + + This file creates the objects required for the computation of the selected + pitch detection algorithm and output the results, in midi note or Hz. + +*/ + +/** pitch detection algorithm */ +typedef enum { + aubio_pitch_yin, /**< YIN algorithm */ + aubio_pitch_mcomb, /**< Multi-comb filter */ + aubio_pitch_schmitt, /**< Schmitt trigger */ + aubio_pitch_fcomb, /**< Fast comb filter */ + aubio_pitch_yinfft /**< Spectral YIN */ +} aubio_pitchdetection_type; + +/** pitch detection output mode */ +typedef enum { + aubio_pitchm_freq, /**< Frequency (Hz) */ + aubio_pitchm_midi, /**< MIDI note (0.,127) */ + aubio_pitchm_cent, /**< Cent */ + aubio_pitchm_bin /**< Frequency bin (0,bufsize) */ +} aubio_pitchdetection_mode; + +/** pitch detection object */ +typedef struct _aubio_pitchdetection_t aubio_pitchdetection_t; + +/** execute pitch detection on an input signal frame + + \param p pitch detection object as returned by new_aubio_pitchdetection + \param ibuf input signal of length hopsize + +*/ +smpl_t aubio_pitchdetection(aubio_pitchdetection_t * p, fvec_t * ibuf); + +/** change yin or yinfft tolerance threshold + + default is 0.15 for yin and 0.85 for yinfft + +*/ +void aubio_pitchdetection_set_yinthresh(aubio_pitchdetection_t *p, smpl_t thres); + +/** deletion of the pitch detection object + + \param p pitch detection object as returned by new_aubio_pitchdetection + +*/ +void del_aubio_pitchdetection(aubio_pitchdetection_t * p); + +/** creation of the pitch detection object + + \param bufsize size of the input buffer to analyse + \param hopsize step size between two consecutive analysis instant + \param channels number of channels to analyse + \param samplerate sampling rate of the signal + \param type set pitch detection algorithm + \param mode set pitch units for output + +*/ +aubio_pitchdetection_t * new_aubio_pitchdetection(uint_t bufsize, + uint_t hopsize, + uint_t channels, + uint_t samplerate, + aubio_pitchdetection_type type, + aubio_pitchdetection_mode mode); + +#ifdef __cplusplus +} +#endif + +#endif /*PITCHDETECTION_H*/ diff --git a/src/pitchdetection.c b/src/pitchdetection.c deleted file mode 100644 index 18cc89bc..00000000 --- a/src/pitchdetection.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - Copyright (C) 2003 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "aubio_priv.h" -#include "sample.h" -#include "phasevoc.h" -#include "mathutils.h" -#include "filter.h" -#include "pitch/pitchmcomb.h" -#include "pitch/pitchyin.h" -#include "pitch/pitchfcomb.h" -#include "pitch/pitchschmitt.h" -#include "pitch/pitchyinfft.h" -#include "pitchdetection.h" - -typedef smpl_t (*aubio_pitchdetection_func_t) - (aubio_pitchdetection_t *p, fvec_t * ibuf); -typedef smpl_t (*aubio_pitchdetection_conv_t) - (smpl_t value, uint_t srate, uint_t bufsize); - -void aubio_pitchdetection_slideblock(aubio_pitchdetection_t *p, fvec_t *ibuf); - -smpl_t aubio_pitchdetection_mcomb (aubio_pitchdetection_t *p, fvec_t *ibuf); -smpl_t aubio_pitchdetection_yin (aubio_pitchdetection_t *p, fvec_t *ibuf); -smpl_t aubio_pitchdetection_schmitt (aubio_pitchdetection_t *p, fvec_t *ibuf); -smpl_t aubio_pitchdetection_fcomb (aubio_pitchdetection_t *p, fvec_t *ibuf); -smpl_t aubio_pitchdetection_yinfft (aubio_pitchdetection_t *p, fvec_t *ibuf); - -/** generic pitch detection structure */ -struct _aubio_pitchdetection_t { - aubio_pitchdetection_type type; /**< pitch detection mode */ - aubio_pitchdetection_mode mode; /**< pitch detection output mode */ - uint_t srate; /**< samplerate */ - uint_t bufsize; /**< buffer size */ - aubio_pitchmcomb_t * mcomb; /**< mcomb object */ - aubio_pitchfcomb_t * fcomb; /**< fcomb object */ - aubio_pitchschmitt_t * schmitt; /**< schmitt object */ - aubio_pitchyinfft_t * yinfft; /**< yinfft object */ - aubio_filter_t * filter; /**< filter */ - aubio_pvoc_t * pv; /**< phase vocoder for mcomb */ - cvec_t * fftgrain; /**< spectral frame for mcomb */ - fvec_t * buf; /**< temporary buffer for yin */ - fvec_t * yin; /**< yin function */ - smpl_t yinthres; /**< yin peak picking threshold parameter */ - aubio_pitchdetection_func_t callback; /**< pointer to current pitch detection method */ - aubio_pitchdetection_conv_t freqconv; /**< pointer to current pitch conversion method */ -}; - -/* convenience wrapper function for frequency unit conversions - * should probably be rewritten with #defines */ -smpl_t freqconvbin(smpl_t f,uint_t srate,uint_t bufsize); -smpl_t freqconvbin(smpl_t f,uint_t srate,uint_t bufsize){ - return aubio_freqtobin(f,srate,bufsize); -} - -smpl_t freqconvmidi(smpl_t f,uint_t srate,uint_t bufsize); -smpl_t freqconvmidi(smpl_t f,uint_t srate UNUSED,uint_t bufsize UNUSED){ - return aubio_freqtomidi(f); -} - -smpl_t freqconvpass(smpl_t f,uint_t srate,uint_t bufsize); -smpl_t freqconvpass(smpl_t f,uint_t srate UNUSED,uint_t bufsize UNUSED){ - return f; -} - -aubio_pitchdetection_t * new_aubio_pitchdetection(uint_t bufsize, - uint_t hopsize, - uint_t channels, - uint_t samplerate, - aubio_pitchdetection_type type, - aubio_pitchdetection_mode mode) -{ - aubio_pitchdetection_t *p = AUBIO_NEW(aubio_pitchdetection_t); - p->srate = samplerate; - p->type = type; - p->mode = mode; - p->bufsize = bufsize; - switch(p->type) { - case aubio_pitch_yin: - p->buf = new_fvec(bufsize,channels); - p->yin = new_fvec(bufsize/2,channels); - p->callback = aubio_pitchdetection_yin; - p->yinthres = 0.15; - break; - case aubio_pitch_mcomb: - p->pv = new_aubio_pvoc(bufsize, hopsize, channels); - p->fftgrain = new_cvec(bufsize, channels); - p->mcomb = new_aubio_pitchmcomb(bufsize,hopsize,channels,samplerate); - p->filter = new_aubio_cdsgn_filter(samplerate); - p->callback = aubio_pitchdetection_mcomb; - break; - case aubio_pitch_fcomb: - p->buf = new_fvec(bufsize,channels); - p->fcomb = new_aubio_pitchfcomb(bufsize,hopsize,samplerate); - p->callback = aubio_pitchdetection_fcomb; - break; - case aubio_pitch_schmitt: - p->buf = new_fvec(bufsize,channels); - p->schmitt = new_aubio_pitchschmitt(bufsize,samplerate); - p->callback = aubio_pitchdetection_schmitt; - break; - case aubio_pitch_yinfft: - p->buf = new_fvec(bufsize,channels); - p->yinfft = new_aubio_pitchyinfft(bufsize); - p->callback = aubio_pitchdetection_yinfft; - p->yinthres = 0.85; - break; - default: - break; - } - switch(p->mode) { - case aubio_pitchm_freq: - p->freqconv = freqconvpass; - break; - case aubio_pitchm_midi: - p->freqconv = freqconvmidi; - break; - case aubio_pitchm_cent: - /* bug: not implemented */ - p->freqconv = freqconvmidi; - break; - case aubio_pitchm_bin: - p->freqconv = freqconvbin; - break; - default: - break; - } - return p; -} - -void del_aubio_pitchdetection(aubio_pitchdetection_t * p) { - switch(p->type) { - case aubio_pitch_yin: - del_fvec(p->yin); - del_fvec(p->buf); - break; - case aubio_pitch_mcomb: - del_aubio_pvoc(p->pv); - del_cvec(p->fftgrain); - del_aubio_filter(p->filter); - del_aubio_pitchmcomb(p->mcomb); - break; - case aubio_pitch_schmitt: - del_fvec(p->buf); - del_aubio_pitchschmitt(p->schmitt); - break; - case aubio_pitch_fcomb: - del_fvec(p->buf); - del_aubio_pitchfcomb(p->fcomb); - break; - case aubio_pitch_yinfft: - del_fvec(p->buf); - del_aubio_pitchyinfft(p->yinfft); - break; - default: - break; - } - AUBIO_FREE(p); -} - -void aubio_pitchdetection_slideblock(aubio_pitchdetection_t *p, fvec_t *ibuf){ - uint_t i,j = 0, overlap_size = 0; - overlap_size = p->buf->length-ibuf->length; - for (i=0;ibuf->channels;i++){ - for (j=0;jbuf->data[i][j] = p->buf->data[i][j+ibuf->length]; - } - } - for (i=0;ichannels;i++){ - for (j=0;jlength;j++){ - p->buf->data[i][j+overlap_size] = ibuf->data[i][j]; - } - } -} - -void aubio_pitchdetection_set_yinthresh(aubio_pitchdetection_t *p, smpl_t thres) { - p->yinthres = thres; -} - -smpl_t aubio_pitchdetection(aubio_pitchdetection_t *p, fvec_t * ibuf) { - return p->freqconv(p->callback(p,ibuf),p->srate,p->bufsize); -} - -smpl_t aubio_pitchdetection_mcomb(aubio_pitchdetection_t *p, fvec_t *ibuf) { - smpl_t pitch = 0.; - aubio_filter_do(p->filter,ibuf); - aubio_pvoc_do(p->pv,ibuf,p->fftgrain); - pitch = aubio_pitchmcomb_detect(p->mcomb,p->fftgrain); - /** \bug should move the >0 check within aubio_bintofreq */ - if (pitch>0.) { - pitch = aubio_bintofreq(pitch,p->srate,p->bufsize); - } else { - pitch = 0.; - } - return pitch; -} - -smpl_t aubio_pitchdetection_yin(aubio_pitchdetection_t *p, fvec_t *ibuf) { - smpl_t pitch = 0.; - aubio_pitchdetection_slideblock(p,ibuf); - pitch = aubio_pitchyin_getpitchfast(p->buf,p->yin, p->yinthres); - if (pitch>0) { - pitch = p->srate/(pitch+0.); - } else { - pitch = 0.; - } - return pitch; -} - - -smpl_t aubio_pitchdetection_yinfft(aubio_pitchdetection_t *p, fvec_t *ibuf){ - smpl_t pitch = 0.; - aubio_pitchdetection_slideblock(p,ibuf); - pitch = aubio_pitchyinfft_detect(p->yinfft,p->buf,p->yinthres); - if (pitch>0) { - pitch = p->srate/(pitch+0.); - } else { - pitch = 0.; - } - return pitch; -} - -smpl_t aubio_pitchdetection_fcomb(aubio_pitchdetection_t *p, fvec_t *ibuf){ - aubio_pitchdetection_slideblock(p,ibuf); - return aubio_pitchfcomb_detect(p->fcomb,p->buf); -} - -smpl_t aubio_pitchdetection_schmitt(aubio_pitchdetection_t *p, fvec_t *ibuf){ - aubio_pitchdetection_slideblock(p,ibuf); - return aubio_pitchschmitt_detect(p->schmitt,p->buf); -} diff --git a/src/pitchdetection.h b/src/pitchdetection.h deleted file mode 100644 index 164b1f53..00000000 --- a/src/pitchdetection.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright (C) 2003 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef PITCHAUTOTCORR_H -#define PITCHAUTOTCORR_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file - - Generic method for pitch detection - - This file creates the objects required for the computation of the selected - pitch detection algorithm and output the results, in midi note or Hz. - -*/ - -/** pitch detection algorithm */ -typedef enum { - aubio_pitch_yin, /**< YIN algorithm */ - aubio_pitch_mcomb, /**< Multi-comb filter */ - aubio_pitch_schmitt, /**< Schmitt trigger */ - aubio_pitch_fcomb, /**< Fast comb filter */ - aubio_pitch_yinfft /**< Spectral YIN */ -} aubio_pitchdetection_type; - -/** pitch detection output mode */ -typedef enum { - aubio_pitchm_freq, /**< Frequency (Hz) */ - aubio_pitchm_midi, /**< MIDI note (0.,127) */ - aubio_pitchm_cent, /**< Cent */ - aubio_pitchm_bin /**< Frequency bin (0,bufsize) */ -} aubio_pitchdetection_mode; - -/** pitch detection object */ -typedef struct _aubio_pitchdetection_t aubio_pitchdetection_t; - -/** execute pitch detection on an input signal frame - - \param p pitch detection object as returned by new_aubio_pitchdetection - \param ibuf input signal of length hopsize - -*/ -smpl_t aubio_pitchdetection(aubio_pitchdetection_t * p, fvec_t * ibuf); - -/** change yin or yinfft tolerance threshold - - default is 0.15 for yin and 0.85 for yinfft - -*/ -void aubio_pitchdetection_set_yinthresh(aubio_pitchdetection_t *p, smpl_t thres); - -/** deletion of the pitch detection object - - \param p pitch detection object as returned by new_aubio_pitchdetection - -*/ -void del_aubio_pitchdetection(aubio_pitchdetection_t * p); - -/** creation of the pitch detection object - - \param bufsize size of the input buffer to analyse - \param hopsize step size between two consecutive analysis instant - \param channels number of channels to analyse - \param samplerate sampling rate of the signal - \param type set pitch detection algorithm - \param mode set pitch units for output - -*/ -aubio_pitchdetection_t * new_aubio_pitchdetection(uint_t bufsize, - uint_t hopsize, - uint_t channels, - uint_t samplerate, - aubio_pitchdetection_type type, - aubio_pitchdetection_mode mode); - -#ifdef __cplusplus -} -#endif - -#endif /*PITCHDETECTION_H*/ diff --git a/src/tempo.c b/src/tempo.c deleted file mode 100644 index 18d9a549..00000000 --- a/src/tempo.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - Copyright (C) 2006 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "aubio_priv.h" -#include "sample.h" -#include "onset/detection.h" -#include "beattracking.h" -#include "phasevoc.h" -#include "peakpick.h" -#include "mathutils.h" -#include "tempo.h" - -/* structure to store object state */ -struct _aubio_tempo_t { - aubio_onsetdetection_t * od; /** onset detection */ - aubio_pvoc_t * pv; /** phase vocoder */ - aubio_pickpeak_t * pp; /** peak picker */ - aubio_beattracking_t * bt; /** beat tracking */ - cvec_t * fftgrain; /** spectral frame */ - fvec_t * of; /** onset detection function value */ - fvec_t * dfframe; /** peak picked detection function buffer */ - fvec_t * out; /** beat tactus candidates */ - smpl_t silence; /** silence parameter */ - smpl_t threshold; /** peak picking threshold */ - sint_t blockpos; /** current position in dfframe */ - uint_t winlen; /** dfframe bufsize */ - uint_t step; /** dfframe hopsize */ -}; - -/* execute tempo detection function on iput buffer */ -void aubio_tempo(aubio_tempo_t *o, fvec_t * input, fvec_t * tempo) -{ - uint_t i; - uint_t winlen = o->winlen; - uint_t step = o->step; - aubio_pvoc_do (o->pv, input, o->fftgrain); - aubio_onsetdetection(o->od, o->fftgrain, o->of); - /*if (usedoubled) { - aubio_onsetdetection(o2,fftgrain, onset2); - onset->data[0][0] *= onset2->data[0][0]; - }*/ - /* execute every overlap_size*step */ - if (o->blockpos == (signed)step -1 ) { - /* check dfframe */ - aubio_beattracking_do(o->bt,o->dfframe,o->out); - /* rotate dfframe */ - for (i = 0 ; i < winlen - step; i++ ) - o->dfframe->data[0][i] = o->dfframe->data[0][i+step]; - for (i = winlen - step ; i < winlen; i++ ) - o->dfframe->data[0][i] = 0.; - o->blockpos = -1; - } - o->blockpos++; - tempo->data[0][1] = aubio_peakpick_pimrt_wt(o->of,o->pp, - &(o->dfframe->data[0][winlen - step + o->blockpos])); - /* end of second level loop */ - tempo->data[0][0] = 0; /* reset tactus */ - i=0; - for (i = 1; i < o->out->data[0][0]; i++ ) { - /* if current frame is a predicted tactus */ - if (o->blockpos == o->out->data[0][i]) { - /* test for silence */ - if (aubio_silence_detection(input, o->silence)==1) { - tempo->data[0][1] = 0; /* unset onset */ - tempo->data[0][0] = 0; /* unset tactus */ - } else { - tempo->data[0][0] = 1; /* set tactus */ - } - } - } -} - -void aubio_tempo_set_silence(aubio_tempo_t * o, smpl_t silence) { - o->silence = silence; - return; -} - -void aubio_tempo_set_threshold(aubio_tempo_t * o, smpl_t threshold) { - o->threshold = threshold; - aubio_peakpicker_set_threshold(o->pp, o->threshold); - return; -} - -/* Allocate memory for an tempo detection */ -aubio_tempo_t * new_aubio_tempo (aubio_onsetdetection_type type_onset, - uint_t buf_size, uint_t hop_size, uint_t channels) -{ - aubio_tempo_t * o = AUBIO_NEW(aubio_tempo_t); - o->winlen = SQR(512)/hop_size; - o->step = o->winlen/4; - o->blockpos = 0; - o->threshold = 0.3; - o->silence = -90; - o->blockpos = 0; - o->dfframe = new_fvec(o->winlen,channels); - o->fftgrain = new_cvec(buf_size, channels); - o->out = new_fvec(o->step,channels); - o->pv = new_aubio_pvoc(buf_size, hop_size, channels); - o->pp = new_aubio_peakpicker(o->threshold); - o->od = new_aubio_onsetdetection(type_onset,buf_size,channels); - o->of = new_fvec(1, channels); - o->bt = new_aubio_beattracking(o->winlen,channels); - /*if (usedoubled) { - o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels); - onset2 = new_fvec(1 , channels); - }*/ - return o; -} - -smpl_t aubio_tempo_get_bpm(aubio_tempo_t *o) { - return aubio_beattracking_get_bpm(o->bt); -} - -smpl_t aubio_tempo_get_confidence(aubio_tempo_t *o) { - return aubio_beattracking_get_confidence(o->bt); -} - -void del_aubio_tempo (aubio_tempo_t *o) -{ - del_aubio_onsetdetection(o->od); - del_aubio_beattracking(o->bt); - del_aubio_peakpicker(o->pp); - del_aubio_pvoc(o->pv); - del_fvec(o->out); - del_fvec(o->of); - del_cvec(o->fftgrain); - del_fvec(o->dfframe); - AUBIO_FREE(o); - return; -} diff --git a/src/tempo.h b/src/tempo.h deleted file mode 100644 index ef302189..00000000 --- a/src/tempo.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2006 Paul Brossier - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** \file - - Tempo detection driver - - This object stores all the memory required for tempo detection algorithm - and returns the estimated beat locations. - -*/ - -#ifndef TEMPO_H -#define TEMPO_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** tempo detection structure */ -typedef struct _aubio_tempo_t aubio_tempo_t; - -/** create tempo detection object */ -aubio_tempo_t * new_aubio_tempo (aubio_onsetdetection_type type_onset, - uint_t buf_size, uint_t hop_size, uint_t channels); - -/** execute tempo detection */ -void aubio_tempo(aubio_tempo_t *o, fvec_t * input, fvec_t * tempo); - -/** set tempo detection silence threshold */ -void aubio_tempo_set_silence(aubio_tempo_t * o, smpl_t silence); - -/** set tempo detection peak picking threshold */ -void aubio_tempo_set_threshold(aubio_tempo_t * o, smpl_t threshold); - -/** get current tempo - - \param bt beat tracking object - - Returns the currently observed tempo, or 0 if no consistent value is found - -*/ -smpl_t aubio_tempo_get_bpm(aubio_tempo_t * bt); - -/** get current tempo confidence - - \param bt beat tracking object - - Returns the confidence with which the tempo has been observed, 0 if no - consistent value is found. - -*/ -smpl_t aubio_tempo_get_confidence(aubio_tempo_t * bt); - -/** delete tempo detection object */ -void del_aubio_tempo(aubio_tempo_t * o); - -#ifdef __cplusplus -} -#endif - -#endif /* TEMPO_H */ diff --git a/src/tempo/beattracking.c b/src/tempo/beattracking.c new file mode 100644 index 00000000..e67a6082 --- /dev/null +++ b/src/tempo/beattracking.c @@ -0,0 +1,467 @@ +/* + Copyright (C) 2005 Matthew Davies and Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "aubio_priv.h" +#include "sample.h" +#include "mathutils.h" +#include "beattracking.h" + +uint_t fvec_gettimesig(smpl_t * acf, uint_t acflen, uint_t gp); +void aubio_beattracking_checkstate(aubio_beattracking_t * bt); +smpl_t fvec_getperiod(aubio_beattracking_t * bt); + +struct _aubio_beattracking_t { + fvec_t * rwv; /** rayleigh weight vector - rayleigh distribution function */ + fvec_t * gwv; /** rayleigh weight vector - rayleigh distribution function */ + fvec_t * dfwv; /** detection function weighting - exponential curve */ + fvec_t * dfrev; /** reversed onset detection function */ + fvec_t * acf; /** vector for autocorrelation function (of current detection function frame) */ + fvec_t * acfout; /** store result of passing acf through s.i.c.f.b. */ + fvec_t * phwv; /** beat expectation alignment weighting */ + fvec_t * phout; + uint_t timesig; /** time signature of input, set to zero until context dependent model activated */ + uint_t step; + fvec_t * locacf; /** vector to store harmonics of filterbank of acf */ + fvec_t * inds; /** vector for max index outputs for each harmonic */ + uint_t rayparam; /** Rayleigh parameter */ + uint_t lastbeat; + sint_t counter; + uint_t flagstep; + smpl_t g_var; + uint_t gp; + uint_t bp; + uint_t rp; + uint_t rp1; + uint_t rp2; +}; + +aubio_beattracking_t * new_aubio_beattracking(uint_t winlen, + uint_t channels) { + + aubio_beattracking_t * p = AUBIO_NEW(aubio_beattracking_t); + uint_t i = 0; + /* parameter for rayleigh weight vector - sets preferred tempo to + * 120bpm [43] */ + smpl_t rayparam = 48./512. * winlen; + smpl_t dfwvnorm = EXP((LOG(2.0)/rayparam)*(winlen+2)); + /** length over which beat period is found [128] */ + uint_t laglen = winlen/4; + /** step increment - both in detection function samples -i.e. 11.6ms or + * 1 onset frame [128] */ + uint_t step = winlen/4; /* 1.5 seconds */ + + uint_t maxnumelem = 4; /* max number of index output */ + p->lastbeat = 0; + p->counter = 0; + p->flagstep = 0; + p->g_var = 3.901; // constthresh empirically derived! + p->rp = 1; + p->gp = 0; + + p->rayparam = rayparam; + p->step = step; + p->rwv = new_fvec(laglen,channels); + p->gwv = new_fvec(laglen,channels); + p->dfwv = new_fvec(winlen,channels); + p->dfrev = new_fvec(winlen,channels); + p->acf = new_fvec(winlen,channels); + p->acfout = new_fvec(laglen,channels); + p->phwv = new_fvec(2*laglen,channels); + p->phout = new_fvec(winlen,channels); + + p->timesig = 0; + + p->inds = new_fvec(maxnumelem,channels); + p->locacf = new_fvec(winlen,channels); + + /* exponential weighting, dfwv = 0.5 when i = 43 */ + for (i=0;idfwv->data[0][i] = (EXP((LOG(2.0)/rayparam)*(i+1))) + / dfwvnorm; + } + + for (i=0;i<(laglen);i++){ + p->rwv->data[0][i] = ((smpl_t)(i+1.) / SQR((smpl_t)rayparam)) * + EXP((-SQR((smpl_t)(i+1.)) / (2.*SQR((smpl_t)rayparam)))); + } + + return p; + +} + +void del_aubio_beattracking(aubio_beattracking_t * p) { + del_fvec(p->rwv); + del_fvec(p->gwv); + del_fvec(p->dfwv); + del_fvec(p->dfrev); + del_fvec(p->acf); + del_fvec(p->acfout); + del_fvec(p->phwv); + del_fvec(p->phout); + del_fvec(p->locacf); + del_fvec(p->inds); + AUBIO_FREE(p); +} + + +void aubio_beattracking_do(aubio_beattracking_t * bt, fvec_t * dfframe, fvec_t * output) { + + uint_t i,k; + /* current beat period value found using gaussian weighting (from context dependent model) */ + uint_t step = bt->step; + uint_t laglen = bt->rwv->length; + uint_t winlen = bt->dfwv->length; + smpl_t * phout = bt->phout->data[0]; + smpl_t * phwv = bt->phwv->data[0]; + smpl_t * dfrev = bt->dfrev->data[0]; + smpl_t * dfwv = bt->dfwv->data[0]; + smpl_t * rwv = bt->rwv->data[0]; + smpl_t * acfout = bt->acfout->data[0]; + smpl_t * acf = bt->acf->data[0]; + uint_t maxindex = 0; + //number of harmonics in shift invariant comb filterbank + uint_t numelem = 4; + + //smpl_t myperiod = 0.; + //smpl_t * out = output->data[0]; + + //parameters for making s.i.c.f.b. + uint_t a,b; + //beat alignment + uint_t phase; + uint_t kmax; + sint_t beat; + uint_t bp; + + for (i = 0; i < winlen; i++){ + dfrev[winlen-1-i] = 0.; + dfrev[winlen-1-i] = dfframe->data[0][i]*dfwv[i]; + } + + /* find autocorrelation function */ + aubio_autocorr(dfframe,bt->acf); + /* + for (i = 0; i < winlen; i++){ + AUBIO_DBG("%f,",acf[i]); + } + AUBIO_DBG("\n"); + */ + + /* get acfout - assume Rayleigh weightvector only */ + /* if timesig is unknown, use metrically unbiased version of filterbank */ + if(!bt->timesig) + numelem = 4; + // AUBIO_DBG("using unbiased filterbank, timesig: %d\n", timesig); + else + numelem = bt->timesig; + // AUBIO_DBG("using biased filterbank, timesig: %d\n", timesig); + + /* first and last output values are left intentionally as zero */ + for (i=0; i < bt->acfout->length; i++) + acfout[i] = 0.; + + for(i=1;iacfout); + bt->rp = maxindex ? maxindex : 1; + //rp = (maxindex==127) ? 43 : maxindex; //rayparam + bt->rp = (maxindex==bt->acfout->length-1) ? bt->rayparam : maxindex; //rayparam + + // get float period + //myperiod = fvec_getperiod(bt); + //AUBIO_DBG("\nrp = %d myperiod = %f\n",bt->rp,myperiod); + //AUBIO_DBG("accurate tempo is %f bpm\n",5168./myperiod); + + /* activate biased filterbank */ + aubio_beattracking_checkstate(bt); + bp = bt->bp; + /* end of biased filterbank */ + + /* initialize output */ + for(i=0;iphout->length;i++) {phout[i] = 0.;} + + /* deliberate integer operation, could be set to 3 max eventually */ + kmax = winlen/bp; + + for(i=0;iphout); + if (maxindex == winlen-1) maxindex = 0; + phase = 1 + maxindex; + + /* debug */ + //AUBIO_DBG("beat period = %d, rp1 = %d, rp2 = %d\n", bp, rp1, rp2); + //AUBIO_DBG("rp = %d, gp = %d, phase = %d\n", bt->rp, bt->gp, phase); + + /* reset output */ + for (i = 0; i < laglen; i++) + output->data[0][i] = 0.; + + i = 1; + beat = bp - phase; + /* start counting the beats */ + if(beat >= 0) + { + output->data[0][i] = (smpl_t)beat; + i++; + } + + while( beat+bp < step ) + { + beat += bp; + output->data[0][i] = (smpl_t)beat; + i++; + } + + bt->lastbeat = beat; + /* store the number of beat found in this frame as the first element */ + output->data[0][0] = i; +} + +uint_t fvec_gettimesig(smpl_t * acf, uint_t acflen, uint_t gp){ + sint_t k = 0; + smpl_t three_energy = 0., four_energy = 0.; + if( acflen > 6 * gp + 2 ){ + for(k=-2;k<2;k++){ + three_energy += acf[3*gp+k]; + four_energy += acf[4*gp+k]; + } + } + else{ /*Expanded to be more accurate in time sig estimation*/ + for(k=-2;k<2;k++){ + three_energy += acf[3*gp+k]+acf[6*gp+k]; + four_energy += acf[4*gp+k]+acf[2*gp+k]; + } + } + return (three_energy > four_energy) ? 3 : 4; +} + +smpl_t fvec_getperiod(aubio_beattracking_t * bt){ + /*function to make a more accurate beat period measurement.*/ + + smpl_t period = 0.; + smpl_t maxval = 0.; + uint_t numelem = 4; + + sint_t a,b; + uint_t i,j; + uint_t acfmi = bt->rp; //acfout max index + uint_t maxind = 0; + + if(!bt->timesig) + numelem = 4; + else + numelem = bt->timesig; + + for (i=0;iinds->data[0][i] = 0.; + + for (i=0;ilocacf->length;i++) // initialize + bt->locacf->data[0][i] = 0.; + + // get appropriate acf elements from acf and store in locacf + for (a=1;a<=4;a++){ + for(b=(1-a);blocacf->data[0][a*(acfmi)+b-1] = + bt->acf->data[0][a*(acfmi)+b-1]; + } + } + + for(i=0;ilocacf->data[0][j]>maxval){ + maxval = bt->locacf->data[0][j]; + maxind = j; + } + //bt->locacf->data[0][maxind] = 0.; + bt->locacf->data[0][j] = 0.; + } + //AUBIO_DBG("\n maxind is %d\n",maxind); + bt->inds->data[0][i] = maxind; + + } + + for (i=0;iinds->data[0][i]/(i+1.);} + + period = period/numelem; + + return (period); +} + + +void aubio_beattracking_checkstate(aubio_beattracking_t * bt) { + uint_t i,j,a,b; + uint_t flagconst = 0; + sint_t counter = bt->counter; + uint_t flagstep = bt->flagstep; + uint_t gp = bt->gp; + uint_t bp = bt->bp; + uint_t rp = bt->rp; + uint_t rp1 = bt->rp1; + uint_t rp2 = bt->rp2; + uint_t laglen = bt->rwv->length; + uint_t acflen = bt->acf->length; + uint_t step = bt->step; + smpl_t * acf = bt->acf->data[0]; + smpl_t * acfout = bt->acfout->data[0]; + smpl_t * gwv = bt->gwv->data[0]; + smpl_t * phwv = bt->phwv->data[0]; + + if (gp) { + // doshiftfbank again only if context dependent model is in operation + //acfout = doshiftfbank(acf,gwv,timesig,laglen,acfout); + //don't need acfout now, so can reuse vector + // gwv is, in first loop, definitely all zeros, but will have + // proper values when context dependent model is activated + for (i=0; i < bt->acfout->length; i++) + acfout[i] = 0.; + for(i=1;itimesig;a++){ + for(b=(1-a);bacfout); + /* + while(gp<32) gp =gp*2; + while(gp>64) gp = gp/2; + */ + } else { + //still only using general model + gp = 0; + } + + //now look for step change - i.e. a difference between gp and rp that + // is greater than 2*constthresh - always true in first case, since gp = 0 + if(counter == 0){ + if(ABS(gp - rp) > 2.*bt->g_var) { + flagstep = 1; // have observed step change. + counter = 3; // setup 3 frame counter + } else { + flagstep = 0; + } + } + + //i.e. 3rd frame after flagstep initially set + if (counter==1 && flagstep==1) { + //check for consistency between previous beatperiod values + if(ABS(2.*rp - rp1 -rp2) < bt->g_var) { + //if true, can activate context dependent model + flagconst = 1; + counter = 0; // reset counter and flagstep + } else { + //if not consistent, then don't flag consistency! + flagconst = 0; + counter = 2; // let it look next time + } + } else if (counter > 0) { + //if counter doesn't = 1, + counter = counter-1; + } + + rp2 = rp1; rp1 = rp; + + if (flagconst) { + /* first run of new hypothesis */ + gp = rp; + bt->timesig = fvec_gettimesig(acf,acflen, gp); + for(j=0;jg_var)); + flagconst = 0; + bp = gp; + /* flat phase weighting */ + for(j=0;j<2*laglen;j++) {phwv[j] = 1.;} + } else if (bt->timesig) { + /* context dependant model */ + bp = gp; + /* gaussian phase weighting */ + if (step > bt->lastbeat) { + for(j=0;j<2*laglen;j++) { + phwv[j] = EXP(-.5*SQR((smpl_t)(1.+j-step+bt->lastbeat))/(bp/8.)); + } + } else { + //AUBIO_DBG("NOT using phase weighting as step is %d and lastbeat %d \n", + // step,bt->lastbeat); + for(j=0;j<2*laglen;j++) {phwv[j] = 1.;} + } + } else { + /* initial state */ + bp = rp; + /* flat phase weighting */ + for(j=0;j<2*laglen;j++) {phwv[j] = 1.;} + } + + /* do some further checks on the final bp value */ + + /* if tempo is > 206 bpm, half it */ + while (bp < 25) { + //AUBIO_DBG("warning, doubling the beat period from %d\n", bp); + //AUBIO_DBG("warning, halving the tempo from %f\n", 60.*samplerate/hopsize/bp); + bp = bp*2; + } + + //AUBIO_DBG("tempo:\t%3.5f bpm | ", 5168./bp); + + /* smoothing */ + //bp = (uint_t) (0.8 * (smpl_t)bp + 0.2 * (smpl_t)bp2); + //AUBIO_DBG("tempo:\t%3.5f bpm smoothed | bp2 %d | bp %d | ", 5168./bp, bp2, bp); + //bp2 = bp; + //AUBIO_DBG("time signature: %d \n", bt->timesig); + bt->counter = counter; + bt->flagstep = flagstep; + bt->gp = gp; + bt->bp = bp; + bt->rp1 = rp1; + bt->rp2 = rp2; + +} + +smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt) { + if (bt->timesig != 0 && bt->counter == 0 && bt->flagstep == 0) { + return 5168. / (smpl_t)bt->gp; + } else { + return 0.; + } +} + +smpl_t aubio_beattracking_get_confidence(aubio_beattracking_t * bt) { + if (bt->gp) return vec_max(bt->acfout); + else return 0.; +} diff --git a/src/tempo/beattracking.h b/src/tempo/beattracking.h new file mode 100644 index 00000000..c6964e9c --- /dev/null +++ b/src/tempo/beattracking.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2003 Matthew Davies and Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** \file + + Beat tracking using a context dependant model + + This file implement the causal beat tracking algorithm designed by Matthew + Davies and described in the following articles: + + Matthew E. P. Davies and Mark D. Plumbley. Causal tempo tracking of audio. + In Proceedings of the International Symposium on Music Information Retrieval + (ISMIR), pages 164­169, Barcelona, Spain, 2004. + + Matthew E. P. Davies, Paul Brossier, and Mark D. Plumbley. Beat tracking + towards automatic musical accompaniment. In Proceedings of the Audio + Engeeniring Society 118th Convention, Barcelona, Spain, May 2005. + +*/ +#ifndef BEATTRACKING_H +#define BEATTRACKING_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** beat tracking object */ +typedef struct _aubio_beattracking_t aubio_beattracking_t; + +/** create beat tracking object + + \param winlen: frame size [512] + \param channels number (not functionnal) [1] + +*/ +aubio_beattracking_t * new_aubio_beattracking(uint_t winlen, uint_t channels); +/** track the beat + + \param bt beat tracking object + \param dfframes current input detection function frame, smoothed by + adaptive median threshold. + \param out stored detected beat locations + +*/ +void aubio_beattracking_do(aubio_beattracking_t * bt, fvec_t * dfframes, fvec_t * out); +/** get current tempo in bpm + + \param bt beat tracking object + + Returns the currently observed tempo, in beats per minutes, or 0 if no + consistent value is found. + +*/ +smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt); +/** get current tempo confidence + + \param bt beat tracking object + + Returns the confidence with which the tempo has been observed, 0 if no + consistent value is found. + +*/ +smpl_t aubio_beattracking_get_confidence(aubio_beattracking_t * bt); +/** delete beat tracking object + + \param p beat tracking object + +*/ +void del_aubio_beattracking(aubio_beattracking_t * p); + +#ifdef __cplusplus +} +#endif + +#endif /* BEATTRACKING_H */ diff --git a/src/tempo/tempo.c b/src/tempo/tempo.c new file mode 100644 index 00000000..1794bae3 --- /dev/null +++ b/src/tempo/tempo.c @@ -0,0 +1,146 @@ +/* + Copyright (C) 2006 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "aubio_priv.h" +#include "sample.h" +#include "onset/onsetdetection.h" +#include "tempo/beattracking.h" +#include "phasevoc.h" +#include "onset/peakpick.h" +#include "mathutils.h" +#include "tempo.h" + +/* structure to store object state */ +struct _aubio_tempo_t { + aubio_onsetdetection_t * od; /** onset detection */ + aubio_pvoc_t * pv; /** phase vocoder */ + aubio_pickpeak_t * pp; /** peak picker */ + aubio_beattracking_t * bt; /** beat tracking */ + cvec_t * fftgrain; /** spectral frame */ + fvec_t * of; /** onset detection function value */ + fvec_t * dfframe; /** peak picked detection function buffer */ + fvec_t * out; /** beat tactus candidates */ + smpl_t silence; /** silence parameter */ + smpl_t threshold; /** peak picking threshold */ + sint_t blockpos; /** current position in dfframe */ + uint_t winlen; /** dfframe bufsize */ + uint_t step; /** dfframe hopsize */ +}; + +/* execute tempo detection function on iput buffer */ +void aubio_tempo(aubio_tempo_t *o, fvec_t * input, fvec_t * tempo) +{ + uint_t i; + uint_t winlen = o->winlen; + uint_t step = o->step; + aubio_pvoc_do (o->pv, input, o->fftgrain); + aubio_onsetdetection(o->od, o->fftgrain, o->of); + /*if (usedoubled) { + aubio_onsetdetection(o2,fftgrain, onset2); + onset->data[0][0] *= onset2->data[0][0]; + }*/ + /* execute every overlap_size*step */ + if (o->blockpos == (signed)step -1 ) { + /* check dfframe */ + aubio_beattracking_do(o->bt,o->dfframe,o->out); + /* rotate dfframe */ + for (i = 0 ; i < winlen - step; i++ ) + o->dfframe->data[0][i] = o->dfframe->data[0][i+step]; + for (i = winlen - step ; i < winlen; i++ ) + o->dfframe->data[0][i] = 0.; + o->blockpos = -1; + } + o->blockpos++; + tempo->data[0][1] = aubio_peakpick_pimrt_wt(o->of,o->pp, + &(o->dfframe->data[0][winlen - step + o->blockpos])); + /* end of second level loop */ + tempo->data[0][0] = 0; /* reset tactus */ + i=0; + for (i = 1; i < o->out->data[0][0]; i++ ) { + /* if current frame is a predicted tactus */ + if (o->blockpos == o->out->data[0][i]) { + /* test for silence */ + if (aubio_silence_detection(input, o->silence)==1) { + tempo->data[0][1] = 0; /* unset onset */ + tempo->data[0][0] = 0; /* unset tactus */ + } else { + tempo->data[0][0] = 1; /* set tactus */ + } + } + } +} + +void aubio_tempo_set_silence(aubio_tempo_t * o, smpl_t silence) { + o->silence = silence; + return; +} + +void aubio_tempo_set_threshold(aubio_tempo_t * o, smpl_t threshold) { + o->threshold = threshold; + aubio_peakpicker_set_threshold(o->pp, o->threshold); + return; +} + +/* Allocate memory for an tempo detection */ +aubio_tempo_t * new_aubio_tempo (aubio_onsetdetection_type type_onset, + uint_t buf_size, uint_t hop_size, uint_t channels) +{ + aubio_tempo_t * o = AUBIO_NEW(aubio_tempo_t); + o->winlen = SQR(512)/hop_size; + o->step = o->winlen/4; + o->blockpos = 0; + o->threshold = 0.3; + o->silence = -90; + o->blockpos = 0; + o->dfframe = new_fvec(o->winlen,channels); + o->fftgrain = new_cvec(buf_size, channels); + o->out = new_fvec(o->step,channels); + o->pv = new_aubio_pvoc(buf_size, hop_size, channels); + o->pp = new_aubio_peakpicker(o->threshold); + o->od = new_aubio_onsetdetection(type_onset,buf_size,channels); + o->of = new_fvec(1, channels); + o->bt = new_aubio_beattracking(o->winlen,channels); + /*if (usedoubled) { + o2 = new_aubio_onsetdetection(type_onset2,buffer_size,channels); + onset2 = new_fvec(1 , channels); + }*/ + return o; +} + +smpl_t aubio_tempo_get_bpm(aubio_tempo_t *o) { + return aubio_beattracking_get_bpm(o->bt); +} + +smpl_t aubio_tempo_get_confidence(aubio_tempo_t *o) { + return aubio_beattracking_get_confidence(o->bt); +} + +void del_aubio_tempo (aubio_tempo_t *o) +{ + del_aubio_onsetdetection(o->od); + del_aubio_beattracking(o->bt); + del_aubio_peakpicker(o->pp); + del_aubio_pvoc(o->pv); + del_fvec(o->out); + del_fvec(o->of); + del_cvec(o->fftgrain); + del_fvec(o->dfframe); + AUBIO_FREE(o); + return; +} diff --git a/src/tempo/tempo.h b/src/tempo/tempo.h new file mode 100644 index 00000000..ef302189 --- /dev/null +++ b/src/tempo/tempo.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2006 Paul Brossier + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** \file + + Tempo detection driver + + This object stores all the memory required for tempo detection algorithm + and returns the estimated beat locations. + +*/ + +#ifndef TEMPO_H +#define TEMPO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** tempo detection structure */ +typedef struct _aubio_tempo_t aubio_tempo_t; + +/** create tempo detection object */ +aubio_tempo_t * new_aubio_tempo (aubio_onsetdetection_type type_onset, + uint_t buf_size, uint_t hop_size, uint_t channels); + +/** execute tempo detection */ +void aubio_tempo(aubio_tempo_t *o, fvec_t * input, fvec_t * tempo); + +/** set tempo detection silence threshold */ +void aubio_tempo_set_silence(aubio_tempo_t * o, smpl_t silence); + +/** set tempo detection peak picking threshold */ +void aubio_tempo_set_threshold(aubio_tempo_t * o, smpl_t threshold); + +/** get current tempo + + \param bt beat tracking object + + Returns the currently observed tempo, or 0 if no consistent value is found + +*/ +smpl_t aubio_tempo_get_bpm(aubio_tempo_t * bt); + +/** get current tempo confidence + + \param bt beat tracking object + + Returns the confidence with which the tempo has been observed, 0 if no + consistent value is found. + +*/ +smpl_t aubio_tempo_get_confidence(aubio_tempo_t * bt); + +/** delete tempo detection object */ +void del_aubio_tempo(aubio_tempo_t * o); + +#ifdef __cplusplus +} +#endif + +#endif /* TEMPO_H */