comparison dsp/tempotracking/TempoTrackV2.cpp @ 279:c8908cdc8c32

* First cut at Matthew's downbeat estimator -- untested so far
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 10 Feb 2009 12:52:43 +0000
parents 833ca65b0820
children 7fe29d8a7eaf
comparison
equal deleted inserted replaced
278:833ca65b0820 279:c8908cdc8c32
12 12
13 #include <cmath> 13 #include <cmath>
14 #include <cstdlib> 14 #include <cstdlib>
15 #include <iostream> 15 #include <iostream>
16 16
17 17 #include "maths/MathUtilities.h"
18 //#define FRAMESIZE 512 18
19 //#define BIGFRAMESIZE 1024
20 #define TWOPI 6.283185307179586232
21 #define EPS 0.0000008 // just some arbitrary small number 19 #define EPS 0.0000008 // just some arbitrary small number
22 20
23 TempoTrackV2::TempoTrackV2() { } 21 TempoTrackV2::TempoTrackV2(float rate, size_t increment) :
22 m_rate(rate), m_increment(increment) { }
24 TempoTrackV2::~TempoTrackV2() { } 23 TempoTrackV2::~TempoTrackV2() { }
25
26 void
27 TempoTrackV2::adapt_thresh(d_vec_t &df)
28 {
29 d_vec_t smoothed(df.size());
30
31 int p_post = 7;
32 int p_pre = 8;
33
34 int t = std::min(static_cast<int>(df.size()),p_post); // what is smaller, p_post of df size. This is to avoid accessing outside of arrays
35
36 // find threshold for first 't' samples, where a full average cannot be computed yet
37 for (int i = 0;i <= t;i++)
38 {
39 int k = std::min((i+p_pre),static_cast<int>(df.size()));
40 smoothed[i] = mean_array(df,1,k);
41 }
42 // find threshold for bulk of samples across a moving average from [i-p_pre,i+p_post]
43 for (uint i = t+1;i < df.size()-p_post;i++)
44 {
45 smoothed[i] = mean_array(df,i-p_pre,i+p_post);
46 }
47 // for last few samples calculate threshold, again, not enough samples to do as above
48 for (uint i = df.size()-p_post;i < df.size();i++)
49 {
50 int k = std::max((static_cast<int> (i) -p_post),1);
51 smoothed[i] = mean_array(df,k,df.size());
52 }
53
54 // subtract the threshold from the detection function and check that it is not less than 0
55 for (uint i = 0;i < df.size();i++)
56 {
57 df[i] -= smoothed[i];
58 if (df[i] < 0)
59 {
60 df[i] = 0;
61 }
62 }
63 }
64
65 double
66 TempoTrackV2::mean_array(const d_vec_t &dfin,int start,int end)
67 {
68 double sum = 0.;
69
70 // find sum
71 for (int i = start;i < end;i++)
72 {
73 sum += dfin[i];
74 }
75
76 return static_cast<double> (sum / (end - start + 1) ); // average and return
77 }
78 24
79 void 25 void
80 TempoTrackV2::filter_df(d_vec_t &df) 26 TempoTrackV2::filter_df(d_vec_t &df)
81 { 27 {
82 d_vec_t a(3); 28 d_vec_t a(3);
203 149
204 // make acf 150 // make acf
205 151
206 d_vec_t dfframe(dfframe_in); 152 d_vec_t dfframe(dfframe_in);
207 153
208 adapt_thresh(dfframe); 154 MathUtilities::adaptiveThreshold(dfframe);
209 155
210 d_vec_t acf(dfframe.size()); 156 d_vec_t acf(dfframe.size());
211 157
212 158
213 for (uint lag=0; lag<dfframe.size(); lag++) 159 for (uint lag=0; lag<dfframe.size(); lag++)
236 } 182 }
237 } 183 }
238 } 184 }
239 185
240 // apply adaptive threshold to rcf 186 // apply adaptive threshold to rcf
241 adapt_thresh(rcf); 187 MathUtilities::adaptiveThreshold(rcf);
242 188
243 double rcfsum =0.; 189 double rcfsum =0.;
244 for (uint i=0; i<rcf.size(); i++) 190 for (uint i=0; i<rcf.size(); i++)
245 { 191 {
246 rcf[i] += EPS ; 192 rcf[i] += EPS ;
388 beat_period[i] = beat_period[lastind]; 334 beat_period[i] = beat_period[lastind];
389 } 335 }
390 336
391 for (uint i = 0; i < beat_period.size(); i++) 337 for (uint i = 0; i < beat_period.size(); i++)
392 { 338 {
393 tempi.push_back((60.*44100./512.)/beat_period[i]); 339 tempi.push_back((60. * m_rate / m_increment)/beat_period[i]);
394 } 340 }
395 } 341 }
396 342
397 double 343 double
398 TempoTrackV2::get_max_val(const d_vec_t &df) 344 TempoTrackV2::get_max_val(const d_vec_t &df)