Chris@6
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@6
|
2
|
Chris@6
|
3 /*
|
Chris@6
|
4 Vamp feature extraction plugin for the BeatRoot beat tracker.
|
Chris@6
|
5
|
Chris@6
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@6
|
7 This file copyright 2011 Simon Dixon, Chris Cannam and QMUL.
|
Chris@6
|
8
|
Chris@6
|
9 This program is free software; you can redistribute it and/or
|
Chris@6
|
10 modify it under the terms of the GNU General Public License as
|
Chris@6
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@6
|
12 License, or (at your option) any later version. See the file
|
Chris@6
|
13 COPYING included with this distribution for more information.
|
Chris@6
|
14 */
|
Chris@6
|
15
|
Chris@6
|
16 #include "Agent.h"
|
Chris@6
|
17 #include "BeatTracker.h"
|
Chris@6
|
18
|
Chris@6
|
19 double Agent::POST_MARGIN_FACTOR = 0.3;
|
Chris@6
|
20 double Agent::PRE_MARGIN_FACTOR = 0.15;
|
Chris@6
|
21 const double Agent::INNER_MARGIN = 0.040;
|
Chris@6
|
22 double Agent::MAX_CHANGE = 0.2;
|
Chris@6
|
23 double Agent::CONF_FACTOR = 0.5;
|
Chris@6
|
24 const double Agent::DEFAULT_CORRECTION_FACTOR = 50.0;
|
Chris@6
|
25 const double Agent::DEFAULT_EXPIRY_TIME = 10.0;
|
Chris@6
|
26
|
Chris@6
|
27 int Agent::idCounter = 0;
|
Chris@6
|
28
|
Chris@6
|
29 double Agent::innerMargin = 0.0;
|
Chris@6
|
30 double Agent::correctionFactor = 0.0;
|
Chris@6
|
31 double Agent::expiryTime = 0.0;
|
Chris@6
|
32 double Agent::decayFactor = 0.0;
|
Chris@6
|
33
|
Chris@8
|
34 bool Agent::considerAsBeat(Event e, AgentList &a) {
|
Chris@6
|
35 double err;
|
Chris@6
|
36 if (beatTime < 0) { // first event
|
Chris@6
|
37 accept(e, 0, 1);
|
Chris@6
|
38 return true;
|
Chris@6
|
39 } else { // subsequent events
|
Chris@9
|
40 EventList::iterator last = events.end();
|
Chris@9
|
41 --last;
|
Chris@9
|
42 if (e.time - last->time > expiryTime) {
|
Chris@6
|
43 phaseScore = -1.0; // flag agent to be deleted
|
Chris@6
|
44 return false;
|
Chris@6
|
45 }
|
Chris@8
|
46 double beats = nearbyint((e.time - beatTime) / beatInterval);
|
Chris@8
|
47 err = e.time - beatTime - beats * beatInterval;
|
Chris@6
|
48 if ((beats > 0) && (-preMargin <= err) && (err <= postMargin)) {
|
Chris@8
|
49 if (fabs(err) > innerMargin) // Create new agent that skips this
|
Chris@9
|
50 a.add(Agent(*this)); // event (avoids large phase jump)
|
Chris@6
|
51 accept(e, err, (int)beats);
|
Chris@6
|
52 return true;
|
Chris@6
|
53 }
|
Chris@6
|
54 }
|
Chris@6
|
55 return false;
|
Chris@6
|
56 } // considerAsBeat()
|
Chris@6
|
57
|
Chris@6
|
58
|
Chris@9
|
59 void Agent::fillBeats(double start) {
|
Chris@6
|
60 double prevBeat = 0, nextBeat, currentInterval, beats;
|
Chris@9
|
61 EventList::iterator ei = events.begin();
|
Chris@9
|
62 if (ei != events.end()) {
|
Chris@9
|
63 ++ei;
|
Chris@9
|
64 prevBeat = ei->time;
|
Chris@9
|
65 --ei;
|
Chris@6
|
66 }
|
Chris@9
|
67 for ( ; ei != events.end(); ++ei) {
|
Chris@9
|
68 ++ei;
|
Chris@9
|
69 nextBeat = ei->time;
|
Chris@9
|
70 --ei; // so as to insert before nextBeat
|
Chris@6
|
71 beats = nearbyint((nextBeat - prevBeat) / beatInterval - 0.01); //prefer slow
|
Chris@6
|
72 currentInterval = (nextBeat - prevBeat) / beats;
|
Chris@6
|
73 for ( ; (nextBeat > start) && (beats > 1.5); beats--) {
|
Chris@6
|
74 prevBeat += currentInterval;
|
Chris@9
|
75 events.insert(ei, BeatTracker::newBeat(prevBeat, 0));
|
Chris@9
|
76 ++ei;
|
Chris@6
|
77 }
|
Chris@6
|
78 prevBeat = nextBeat;
|
Chris@6
|
79 }
|
Chris@6
|
80 } // fillBeats()
|