c@277: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ c@277: c@277: /* c@277: QM DSP Library c@277: c@277: Centre for Digital Music, Queen Mary, University of London. c@277: This file copyright 2008-2009 Matthew Davies and QMUL. c@309: c@309: This program is free software; you can redistribute it and/or c@309: modify it under the terms of the GNU General Public License as c@309: published by the Free Software Foundation; either version 2 of the c@309: License, or (at your option) any later version. See the file c@309: COPYING included with this distribution for more information. c@277: */ c@277: cannam@489: #ifndef QM_DSP_TEMPOTRACKV2_H cannam@489: #define QM_DSP_TEMPOTRACKV2_H c@277: c@277: #include c@277: c@279: //!!! Question: how far is this actually sample rate dependent? I c@279: // think it does produce plausible results for e.g. 48000 as well as c@279: // 44100, but surely the fixed window sizes and comb filtering will c@279: // make it prefer double or half time when run at e.g. 96000? c@279: luis@327: class TempoTrackV2 c@277: { c@277: public: c@279: /** c@279: * Construct a tempo tracker that will operate on beat detection c@279: * function data calculated from audio at the given sample rate c@279: * with the given frame increment. c@279: * c@279: * Currently the sample rate and increment are used only for the c@279: * conversion from beat frame location to bpm in the tempo array. c@279: */ cannam@493: TempoTrackV2(float sampleRate, int dfIncrement); c@277: ~TempoTrackV2(); c@277: luis@327: // Returned beat periods are given in df increment units; inputtempo and tempi in bpm cannam@493: void calculateBeatPeriod(const std::vector &df, cannam@493: std::vector &beatPeriod, cannam@493: std::vector &tempi) { c@386: calculateBeatPeriod(df, beatPeriod, tempi, 120.0, false); c@386: } c@386: c@386: // Returned beat periods are given in df increment units; inputtempo and tempi in bpm c@386: // MEPD 28/11/12 Expose inputtempo and constraintempo parameters c@386: // Note, if inputtempo = 120 and constraintempo = false, then functionality is as it was before cannam@493: void calculateBeatPeriod(const std::vector &df, cannam@493: std::vector &beatPeriod, cannam@493: std::vector &tempi, c@386: double inputtempo, bool constraintempo); c@386: c@386: // Returned beat positions are given in df increment units cannam@493: void calculateBeats(const std::vector &df, cannam@493: const std::vector &beatPeriod, cannam@493: std::vector &beats) { c@386: calculateBeats(df, beatPeriod, beats, 0.9, 4.0); c@386: } c@277: c@279: // Returned beat positions are given in df increment units luis@327: // MEPD 28/11/12 Expose alpha and tightness parameters c@386: // Note, if alpha = 0.9 and tightness = 4, then functionality is as it was before cannam@493: void calculateBeats(const std::vector &df, cannam@493: const std::vector &beatPeriod, cannam@493: std::vector &beats, c@386: double alpha, double tightness); c@277: c@277: private: cannam@493: typedef std::vector i_vec_t; cannam@493: typedef std::vector > i_mat_t; cannam@493: typedef std::vector d_vec_t; cannam@493: typedef std::vector > d_mat_t; c@277: c@279: float m_rate; cannam@493: int m_increment; c@279: c@277: void adapt_thresh(d_vec_t &df); c@277: double mean_array(const d_vec_t &dfin, int start, int end); c@277: void filter_df(d_vec_t &df); c@277: void get_rcf(const d_vec_t &dfframe, const d_vec_t &wv, d_vec_t &rcf); c@278: void viterbi_decode(const d_mat_t &rcfmat, const d_vec_t &wv, c@278: d_vec_t &bp, d_vec_t &tempi); c@277: double get_max_val(const d_vec_t &df); c@277: int get_max_ind(const d_vec_t &df); c@277: void normalise_vec(d_vec_t &df); c@277: }; c@277: c@277: #endif