adamstark@5: //======================================================================= adamstark@5: /** @file BTrack.h adamstark@6: * @brief BTrack - a real-time beat tracker adamstark@5: * @author Adam Stark adamstark@5: * @copyright Copyright (C) 2008-2014 Queen Mary University of London adamstark@5: * adamstark@5: * This program is free software: you can redistribute it and/or modify adamstark@5: * it under the terms of the GNU General Public License as published by adamstark@5: * the Free Software Foundation, either version 3 of the License, or adamstark@5: * (at your option) any later version. adamstark@5: * adamstark@5: * This program is distributed in the hope that it will be useful, adamstark@5: * but WITHOUT ANY WARRANTY; without even the implied warranty of adamstark@5: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the adamstark@5: * GNU General Public License for more details. adamstark@5: * adamstark@5: * You should have received a copy of the GNU General Public License adamstark@5: * along with this program. If not, see . adamstark@5: */ adamstark@5: //======================================================================= adamstark@5: adamstark@5: #ifndef __BTRACK_H adamstark@5: #define __BTRACK_H adamstark@5: adamstark@18: #include "OnsetDetectionFunction.h" adamstark@18: adamstark@5: class BTrack { adamstark@5: adamstark@5: public: adamstark@14: adamstark@21: //======================================================================= adamstark@18: /** constructor assuming hop size of 512 and frame size of 1024 */ adamstark@19: BTrack(); adamstark@14: adamstark@18: /** constructor assuming frame size will be double hopSize adamstark@18: * @param hopSize the step size in audio samples by which we will receive audio frames adamstark@18: */ adamstark@20: BTrack(int hopSize_); adamstark@18: adamstark@18: /** constructor taking both hopSize and frameSize adamstark@18: * @param hopSize the step size in audio samples by which we will receive audio frames adamstark@18: * @param frameSize the audio frame size in audio samples adamstark@18: */ adamstark@20: BTrack(int hopSize_,int frameSize_); adamstark@18: adamstark@21: //======================================================================= adamstark@18: /** Process a single audio frame */ adamstark@19: void processAudioFrame(double *frame); adamstark@18: adamstark@18: /** Add new onset detection function sample to buffer and apply beat tracking */ adamstark@19: void processOnsetDetectionFunctionSample(double sample); adamstark@14: adamstark@21: //======================================================================= adamstark@20: /** @returns the current hop size being used by the beat tracker */ adamstark@20: int getHopSize(); adamstark@20: adamstark@21: /** @returns true if a beat should occur in the current audio frame */ adamstark@21: bool beatDueInCurrentFrame(); adamstark@21: adamstark@21: /** @returns the current tempo estimate being used by the beat tracker */ adamstark@21: double getCurrentTempoEstimate(); adamstark@21: adamstark@21: /** @returns the most recent value of the cumulative score function */ adamstark@21: double getLatestCumulativeScoreValue(); adamstark@21: adamstark@21: //======================================================================= adamstark@14: /** Set the tempo of the beat tracker */ adamstark@20: void setTempo(double tempo); adamstark@14: adamstark@14: /** fix tempo to roughly around some value */ adamstark@20: void fixTempo(double tempo); adamstark@14: adamstark@14: /** do not fix the tempo anymore */ adamstark@20: void doNotFixTempo(); adamstark@18: adamstark@21: //======================================================================= adamstark@18: static double getBeatTimeInSeconds(long frameNumber,int hopSize,int fs); adamstark@18: adamstark@18: static double getBeatTimeInSeconds(int frameNumber,int hopSize,int fs); adamstark@18: adamstark@21: adamstark@5: private: adamstark@14: adamstark@20: void initialise(int hopSize_,int frameSize_); adamstark@19: adamstark@19: /** Initialise with hop size and set all frame sizes accordingly */ adamstark@20: void setHopSize(int hopSize_); adamstark@19: adamstark@14: /** Convert detection function from N samples to 512 */ adamstark@20: void resampleOnsetDetectionFunction(); adamstark@14: adamstark@14: /** update the cumulative score */ adamstark@22: void updateCumulativeScore(double odfSample); adamstark@14: adamstark@14: /** predicts the next beat */ adamstark@20: void predictBeat(); adamstark@14: adamstark@14: /** Calculates the current tempo expressed as the beat period in detection function samples */ adamstark@20: void calculateTempo(); adamstark@14: adamstark@14: /** calculates an adaptive threshold which is used to remove low level energy from detection adamstark@14: * function and emphasise peaks adamstark@14: */ adamstark@20: void adaptiveThreshold(double *x,int N); adamstark@14: adamstark@22: /** calculates the mean of values in an array from index locations [startIndex,endIndex] */ adamstark@22: double calculateMeanOfArray(double *array,int startIndex,int endIndex); adamstark@14: adamstark@14: /** normalises a given array */ adamstark@20: void normaliseArray(double *array,int N); adamstark@14: adamstark@14: /** calculates the balanced autocorrelation of the smoothed detection function */ adamstark@20: void calculateBalancedACF(double *df_thresh); adamstark@14: adamstark@20: /** calculates the output of the comb filter bank */ adamstark@20: void calculateOutputOfCombFilterBank(); adamstark@5: adamstark@21: //======================================================================= adamstark@21: adamstark@21: OnsetDetectionFunction odf; adamstark@21: adamstark@21: //======================================================================= adamstark@5: // buffers adamstark@21: double *onsetDF; /**< to hold detection function */ adamstark@21: double resampledOnsetDF[512]; /**< to hold resampled detection function */ adamstark@21: double *cumulativeScore; /**< to hold cumulative score */ adamstark@5: adamstark@21: double acf[512]; /**< to hold autocorrelation function */ adamstark@5: adamstark@21: double weightingVector[128]; /**< to hold weighting vector */ adamstark@5: adamstark@21: double combFilterBankOutput[128]; /**< to hold comb filter output */ adamstark@21: double tempoObservationVector[41]; /**< to hold tempo version of comb filter output */ adamstark@5: adamstark@21: double delta[41]; /**< to hold final tempo candidate array */ adamstark@21: double prevDelta[41]; /**< previous delta */ adamstark@21: double prevDeltaFixed[41]; /**< fixed tempo version of previous delta */ adamstark@5: adamstark@21: double tempoTransitionMatrix[41][41]; /**< tempo transition matrix */ adamstark@5: adamstark@21: adamstark@5: adamstark@19: // parameters adamstark@19: double tightness; adamstark@19: double alpha; adamstark@20: double beatPeriod; adamstark@19: double tempo; adamstark@5: adamstark@21: double estimatedTempo; /**< the current tempo estimation being used by the algorithm */ adamstark@21: adamstark@21: double latestCumulativeScoreValue; /**< holds the latest value of the cumulative score function */ adamstark@21: adamstark@22: double tempoToLagFactor; /**< factor for converting between lag and tempo */ adamstark@5: adamstark@22: int m0; /**< indicates when the next point to predict the next beat is */ adamstark@21: adamstark@21: 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 */ adamstark@5: adamstark@21: int hopSize; /**< the hop size being used by the algorithm */ adamstark@21: adamstark@21: int onsetDFBufferSize; /**< the onset detection function buffer size */ adamstark@5: adamstark@21: bool tempoFixed; /**< indicates whether the tempo should be fixed or not */ adamstark@20: adamstark@21: bool beatDueInFrame; /**< indicates whether a beat is due in the current frame */ adamstark@5: adamstark@5: }; adamstark@5: adamstark@5: #endif