Mercurial > hg > btrack
diff src/BTrack.h @ 36:5bd9ae503dcf master 1.0.0
flow: Merged <release> '1.0.0' to <master> ('master').
author | Adam Stark <adamstark.uk@gmail.com> |
---|---|
date | Tue, 08 Jul 2014 12:32:27 +0100 |
parents | 7af87d3f2ce2 |
children |
line wrap: on
line diff
--- a/src/BTrack.h Tue Jan 21 01:45:36 2014 +0000 +++ b/src/BTrack.h Tue Jul 08 12:32:27 2014 +0100 @@ -22,77 +22,213 @@ #ifndef __BTRACK_H #define __BTRACK_H -//#include "fftw3.h" +#include "OnsetDetectionFunction.h" +#include <vector> +//======================================================================= +/** The main beat tracking class and the interface to the BTrack + * beat tracking algorithm. The algorithm can process either + * audio frames or onset detection function samples and also + * contains some static functions for calculating beat times in seconds + */ class BTrack { public: - BTrack(); // constructor - ~BTrack(); // destructor + + //======================================================================= + /** Constructor assuming hop size of 512 and frame size of 1024 */ + BTrack(); + + /** Constructor assuming frame size will be double the hopSize + * @param hopSize the hop size in audio samples + */ + BTrack(int hopSize_); + + /** Constructor taking both hopSize and frameSize + * @param hopSize the hop size in audio samples + * @param frameSize the frame size in audio samples + */ + BTrack(int hopSize_,int frameSize_); + + //======================================================================= + /** Updates the hop and frame size used by the beat tracker + * @param hopSize the hop size in audio samples + * @param frameSize the frame size in audio samples + */ + void updateHopAndFrameSize(int hopSize_,int frameSize_); + + //======================================================================= + /** Process a single audio frame + * @param frame a pointer to an array containing an audio frame. The number of samples should + * match the frame size that the algorithm was initialised with. + */ + void processAudioFrame(double *frame); + + /** Add new onset detection function sample to buffer and apply beat tracking + * @param sample an onset detection function sample + */ + void processOnsetDetectionFunctionSample(double sample); + + //======================================================================= + /** @returns the current hop size being used by the beat tracker */ + int getHopSize(); + + /** @returns true if a beat should occur in the current audio frame */ + bool beatDueInCurrentFrame(); + + /** @returns the current tempo estimate being used by the beat tracker */ + double getCurrentTempoEstimate(); + + /** @returns the most recent value of the cumulative score function */ + double getLatestCumulativeScoreValue(); + + //======================================================================= + /** Set the tempo of the beat tracker + * @param tempo the tempo in beats per minute (bpm) + */ + void setTempo(double tempo); + + /** Fix tempo to roughly around some value, so that the algorithm will only try to track + * tempi around the given tempo + * @param tempo the tempo in beats per minute (bpm) + */ + void fixTempo(double tempo); + + /** Tell the algorithm to not fix the tempo anymore */ + void doNotFixTempo(); + + //======================================================================= + /** Calculates a beat time in seconds, given the frame number, hop size and sampling frequency. + * This version uses a long to represent the frame number + * @param frameNumber the index of the current frame + * @param hopSize the hop size in audio samples + * @param fs the sampling frequency in Hz + * @returns a beat time in seconds + */ + static double getBeatTimeInSeconds(long frameNumber,int hopSize,int fs); + + /** Calculates a beat time in seconds, given the frame number, hop size and sampling frequency. + * This version uses an int to represent the frame number + * @param frameNumber the index of the current frame + * @param hopSize the hop size in audio samples + * @param fs the sampling frequency in Hz + * @returns a beat time in seconds + */ + static double getBeatTimeInSeconds(int frameNumber,int hopSize,int fs); + + +private: + + /** Initialises the algorithm, setting internal parameters and creating weighting vectors + * @param hopSize_ the hop size in audio samples + * @param frameSize_ the frame size in audio samples + */ + void initialise(int hopSize_,int frameSize_); + + /** Initialise with hop size and set all array sizes accordingly + * @param hopSize_ the hop size in audio samples + */ + void setHopSize(int hopSize_); + + /** Resamples the onset detection function from an arbitrary number of samples to 512 */ + void resampleOnsetDetectionFunction(); + + /** Updates the cumulative score function with a new onset detection function sample + * @param odfSample an onset detection function sample + */ + void updateCumulativeScore(double odfSample); - void initialise(int fsize); - void process(float df_sample); - void plotdfbuffer(); - void updatecumscore(float df_sample); - void predictbeat(); - void dfconvert(); - void calcTempo(); - void adapt_thresh(float x[],int N); - float mean_array(float array[],int start,int end); - void normalise(float array[],int N); - void acf_bal(float df_thresh[]); - void getrcfoutput(); - void settempo(float tempo); - void fixtempo(float tempo); - void unfixtempo(); + /** Predicts the next beat, based upon the internal program state */ + void predictBeat(); + + /** Calculates the current tempo expressed as the beat period in detection function samples */ + void calculateTempo(); + + /** Calculates an adaptive threshold which is used to remove low level energy from detection + * function and emphasise peaks + * @param x a pointer to an array containing onset detection function samples + * @param N the length of the array, x + */ + void adaptiveThreshold(double *x,int N); + + /** Calculates the mean of values in an array between index locations [startIndex,endIndex] + * @param array a pointer to an array that contains the values we wish to find the mean from + * @param startIndex the start index from which we would like to calculate the mean + * @param endIndex the final index to which we would like to calculate the mean + * @returns the mean of the sub-section of the array + */ + double calculateMeanOfArray(double *array,int startIndex,int endIndex); + + /** Normalises a given array + * @param array a pointer to the array we wish to normalise + * @param N the length of the array + */ + void normaliseArray(double *array,int N); + + /** Calculates the balanced autocorrelation of the smoothed onset detection function + * @param onsetDetectionFunction a pointer to an array containing the onset detection function + */ + void calculateBalancedACF(double *onsetDetectionFunction); + + /** Calculates the output of the comb filter bank */ + void calculateOutputOfCombFilterBank(); - int playbeat; - float cscoreval; - float est_tempo; - -private: + //======================================================================= + + /** An OnsetDetectionFunction instance for calculating onset detection functions */ + OnsetDetectionFunction odf; + + //======================================================================= + // buffers + + std::vector<double> onsetDF; /**< to hold onset detection function */ + std::vector<double> cumulativeScore; /**< to hold cumulative score */ + + double resampledOnsetDF[512]; /**< to hold resampled detection function */ - // buffers - float *dfbuffer; // to hold detection function - float df512[512]; // to hold resampled detection function - float *cumscore; // to hold cumulative score + double acf[512]; /**< to hold autocorrelation function */ - float acf[512]; // to hold autocorrelation function + double weightingVector[128]; /**< to hold weighting vector */ - float wv[128]; // to hold weighting vector + double combFilterBankOutput[128]; /**< to hold comb filter output */ + double tempoObservationVector[41]; /**< to hold tempo version of comb filter output */ - float rcf[128]; // to hold comb filter output - float t_obs[41]; // to hold tempo version of comb filter output + double delta[41]; /**< to hold final tempo candidate array */ + double prevDelta[41]; /**< previous delta */ + double prevDeltaFixed[41]; /**< fixed tempo version of previous delta */ - float delta[41]; // to hold final tempo candidate array - float prev_delta[41]; // previous delta - float prev_delta_fix[41]; // fixed tempo version of previous delta + double tempoTransitionMatrix[41][41]; /**< tempo transition matrix */ - float t_tmat[41][41]; // transition matrix + + //======================================================================= + // parameters + + + double tightness; /**< the tightness of the weighting used to calculate cumulative score */ + + double alpha; /**< the mix between the current detection function sample and the cumulative score's "momentum" */ + + double beatPeriod; /**< the beat period, in detection function samples */ + + double tempo; /**< the tempo in beats per minute */ + double estimatedTempo; /**< the current tempo estimation being used by the algorithm */ + + double latestCumulativeScoreValue; /**< holds the latest value of the cumulative score function */ + + double tempoToLagFactor; /**< factor for converting between lag and tempo */ - // parameters - float tightness; - float alpha; - float bperiod; - float tempo; + int m0; /**< indicates when the next point to predict the next beat is */ + + int beatCounter; /**< keeps track of when the next beat is - will be zero when the beat is due, and is set elsewhere in the algorithm to be positive once a beat prediction is made */ + int hopSize; /**< the hop size being used by the algorithm */ + + int onsetDFBufferSize; /**< the onset detection function buffer size */ - float p_fact; - - - // - int m0; // indicates when the next point to predict the next beat is - int beat; - - int dfbuffer_size; - - - int framesize; - - - int tempofix; - + bool tempoFixed; /**< indicates whether the tempo should be fixed or not */ + + bool beatDueInFrame; /**< indicates whether a beat is due in the current frame */ };