cannam@54: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@54: cannam@54: /* cannam@54: QM DSP Library cannam@54: cannam@54: Centre for Digital Music, Queen Mary, University of London. cannam@54: This file copyright 2008-2009 Matthew Davies and QMUL. Chris@84: Chris@84: This program is free software; you can redistribute it and/or Chris@84: modify it under the terms of the GNU General Public License as Chris@84: published by the Free Software Foundation; either version 2 of the Chris@84: License, or (at your option) any later version. See the file Chris@84: COPYING included with this distribution for more information. cannam@54: */ cannam@54: cannam@54: #ifndef DOWNBEAT_H cannam@54: #define DOWNBEAT_H cannam@54: cannam@54: #include Chris@98: #include cannam@54: cannam@54: #include "dsp/rateconversion/Decimator.h" cannam@54: cannam@54: using std::vector; cannam@54: cannam@64: class FFTReal; cannam@64: cannam@54: /** cannam@54: * This class takes an input audio signal and a sequence of beat cannam@54: * locations (calculated e.g. by TempoTrackV2) and estimates which of cannam@54: * the beat locations are downbeats (first beat of the bar). cannam@54: * cannam@54: * The input audio signal is expected to have been downsampled to a cannam@54: * very low sampling rate (e.g. 2700Hz). A utility function for cannam@54: * downsampling and buffering incoming block-by-block audio is cannam@54: * provided. cannam@54: */ cannam@54: class DownBeat cannam@54: { cannam@54: public: cannam@54: /** cannam@54: * Construct a downbeat locator that will operate on audio at the cannam@54: * downsampled by the given decimation factor from the given cannam@54: * original sample rate, plus beats extracted from the same audio cannam@54: * at the given original sample rate with the given frame cannam@54: * increment. cannam@54: * cannam@54: * decimationFactor must be a power of two no greater than 64, and cannam@54: * dfIncrement must be a multiple of decimationFactor. cannam@54: */ cannam@54: DownBeat(float originalSampleRate, cannam@54: size_t decimationFactor, cannam@54: size_t dfIncrement); cannam@54: ~DownBeat(); cannam@54: cannam@55: void setBeatsPerBar(int bpb); cannam@55: cannam@54: /** cannam@54: * Estimate which beats are down-beats. cannam@54: * cannam@54: * audio contains the input audio stream after downsampling, and cannam@54: * audioLength contains the number of samples in this downsampled cannam@54: * stream. cannam@54: * cannam@54: * beats contains a series of beat positions expressed in cannam@54: * multiples of the df increment at the audio's original sample cannam@54: * rate, as described to the constructor. cannam@54: * cannam@54: * The returned downbeat array contains a series of indices to the cannam@54: * beats array. cannam@54: */ cannam@55: void findDownBeats(const float *audio, // downsampled cannam@54: size_t audioLength, // after downsampling cannam@54: const vector &beats, cannam@54: vector &downbeats); cannam@56: cannam@56: /** cannam@56: * Return the beat spectral difference function. This is cannam@56: * calculated during findDownBeats, so this function can only be cannam@56: * meaningfully called after that has completed. The returned cannam@56: * vector contains one value for each of the beat times passed in cannam@56: * to findDownBeats, less one. Each value contains the spectral cannam@56: * difference between region prior to the beat's nominal position cannam@56: * and the region following it. cannam@56: */ cannam@56: void getBeatSD(vector &beatsd) const; cannam@54: cannam@54: /** cannam@54: * For your downsampling convenience: call this function cannam@54: * repeatedly with input audio blocks containing dfIncrement cannam@54: * samples at the original sample rate, to decimate them to the cannam@54: * downsampled rate and buffer them within the DownBeat class. cannam@54: * cannam@54: * Call getBufferedAudio() to retrieve the results after all cannam@54: * blocks have been processed. cannam@54: */ cannam@55: void pushAudioBlock(const float *audio); cannam@54: cannam@54: /** cannam@54: * Retrieve the accumulated audio produced by pushAudioBlock calls. cannam@54: */ cannam@55: const float *getBufferedAudio(size_t &length) const; cannam@55: cannam@55: /** cannam@55: * Clear any buffered downsampled audio data. cannam@55: */ cannam@55: void resetAudioBuffer(); cannam@54: cannam@54: private: cannam@54: typedef vector i_vec_t; cannam@54: typedef vector > i_mat_t; cannam@54: typedef vector d_vec_t; cannam@54: typedef vector > d_mat_t; cannam@54: cannam@54: void makeDecimators(); cannam@54: double measureSpecDiff(d_vec_t oldspec, d_vec_t newspec); cannam@54: cannam@55: int m_bpb; cannam@54: float m_rate; cannam@54: size_t m_factor; cannam@54: size_t m_increment; cannam@54: Decimator *m_decimator1; cannam@54: Decimator *m_decimator2; cannam@55: float *m_buffer; cannam@55: float *m_decbuf; cannam@54: size_t m_bufsiz; cannam@54: size_t m_buffill; cannam@54: size_t m_beatframesize; cannam@54: double *m_beatframe; cannam@64: FFTReal *m_fft; cannam@54: double *m_fftRealOut; cannam@54: double *m_fftImagOut; cannam@56: d_vec_t m_beatsd; cannam@54: }; cannam@54: cannam@54: #endif