Chris@8
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@8
|
2
|
Chris@8
|
3 /*
|
Chris@8
|
4 Vamp feature extraction plugin for the BeatRoot beat tracker.
|
Chris@8
|
5
|
Chris@8
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@8
|
7 This file copyright 2011 Simon Dixon, Chris Cannam and QMUL.
|
Chris@8
|
8
|
Chris@8
|
9 This program is free software; you can redistribute it and/or
|
Chris@8
|
10 modify it under the terms of the GNU General Public License as
|
Chris@8
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@8
|
12 License, or (at your option) any later version. See the file
|
Chris@8
|
13 COPYING included with this distribution for more information.
|
Chris@8
|
14 */
|
Chris@8
|
15
|
Chris@8
|
16 #ifndef _AGENT_LIST_H_
|
Chris@8
|
17 #define _AGENT_LIST_H_
|
Chris@8
|
18
|
Chris@8
|
19 #include "Agent.h"
|
Chris@8
|
20 #include "Event.h"
|
Chris@8
|
21
|
Chris@13
|
22 #include <vector>
|
Chris@8
|
23 #include <algorithm>
|
Chris@8
|
24
|
Chris@12
|
25 #ifdef DEBUG_BEATROOT
|
Chris@12
|
26 #include <iostream>
|
Chris@12
|
27 #endif
|
Chris@12
|
28
|
Chris@8
|
29 /** Class for maintaining the set of all Agents involved in beat tracking a piece of music.
|
Chris@8
|
30 */
|
Chris@8
|
31 class AgentList
|
Chris@8
|
32 {
|
Chris@8
|
33 public:
|
Chris@16
|
34 typedef std::vector<Agent *> Container;
|
Chris@8
|
35 typedef Container::iterator iterator;
|
Chris@8
|
36
|
Chris@8
|
37 protected:
|
Chris@8
|
38 Container list;
|
Chris@8
|
39
|
Chris@20
|
40 static bool agentComparator(const Agent *a, const Agent *b) {
|
Chris@20
|
41 if (a->beatInterval == b->beatInterval) {
|
Chris@20
|
42 return a->idNumber < b->idNumber; // ensure stable ordering
|
Chris@20
|
43 } else {
|
Chris@20
|
44 return a->beatInterval < b->beatInterval;
|
Chris@20
|
45 }
|
Chris@20
|
46 }
|
Chris@20
|
47
|
Chris@8
|
48 public:
|
Chris@8
|
49 // expose some vector methods
|
Chris@8
|
50 //!!! can we remove these again once the rest of AgentList is implemented?
|
Chris@8
|
51 bool empty() const { return list.empty(); }
|
Chris@8
|
52 Container::iterator begin() { return list.begin(); }
|
Chris@8
|
53 Container::iterator end() { return list.end(); }
|
Chris@12
|
54 size_t size() { return list.size(); }
|
Chris@16
|
55 void push_back(Agent *a) {
|
Chris@12
|
56 list.push_back(a);
|
Chris@12
|
57 #ifdef DEBUG_BEATROOT
|
Chris@16
|
58 std::cerr << " Added Ag#" << a->idNumber << ", have " << list.size() << " agent(s)" << std::endl;
|
Chris@12
|
59 #endif
|
Chris@12
|
60 }
|
Chris@8
|
61
|
Chris@11
|
62 /** Flag for choice between sum and average beat salience values for Agent scores.
|
Chris@11
|
63 * The use of summed saliences favours faster tempi or lower metrical levels. */
|
Chris@11
|
64 static bool useAverageSalience;
|
Chris@8
|
65
|
Chris@11
|
66 /** For the purpose of removing duplicate agents, the default JND of IBI */
|
Chris@11
|
67 static const double DEFAULT_BI;
|
Chris@8
|
68
|
Chris@11
|
69 /** For the purpose of removing duplicate agents, the default JND of phase */
|
Chris@11
|
70 static const double DEFAULT_BT;
|
Chris@8
|
71
|
Chris@11
|
72 /** Inserts newAgent into the list in ascending order of beatInterval */
|
Chris@16
|
73 void add(Agent *a) {
|
Chris@11
|
74 add(a, true);
|
Chris@11
|
75 } // add()/1
|
Chris@8
|
76
|
Chris@11
|
77 /** Appends newAgent to list (sort==false), or inserts newAgent into the list
|
Chris@11
|
78 * in ascending order of beatInterval
|
Chris@11
|
79 * @param newAgent The agent to be added to the list
|
Chris@11
|
80 * @param sort Flag indicating whether the list is sorted or not
|
Chris@11
|
81 */
|
Chris@16
|
82 void add(Agent *newAgent, bool sort){
|
Chris@12
|
83 push_back(newAgent);
|
Chris@11
|
84 if (sort) this->sort();
|
Chris@11
|
85 } // add()/2
|
Chris@8
|
86
|
Chris@11
|
87 /** Sorts the AgentList by increasing beatInterval. */
|
Chris@11
|
88 void sort() {
|
Chris@20
|
89 #ifdef DEBUG_BEATROOT
|
Chris@20
|
90 std::cerr << "sort: before: ";
|
Chris@20
|
91 for (iterator i = list.begin(); i != list.end(); ++i) {
|
Chris@20
|
92 std::cerr << (*i)->idNumber << " ";
|
Chris@20
|
93 }
|
Chris@20
|
94 std::cerr << std::endl;
|
Chris@20
|
95 #endif
|
Chris@20
|
96 std::sort(list.begin(), list.end(), agentComparator);
|
Chris@20
|
97 #ifdef DEBUG_BEATROOT
|
Chris@20
|
98 std::cerr << "sort: after: ";
|
Chris@20
|
99 for (iterator i = list.begin(); i != list.end(); ++i) {
|
Chris@20
|
100 std::cerr << (*i)->idNumber << " ";
|
Chris@20
|
101 }
|
Chris@20
|
102 std::cerr << std::endl;
|
Chris@20
|
103 #endif
|
Chris@11
|
104 } // sort()
|
Chris@8
|
105
|
Chris@11
|
106 /** Removes the given item from the list.
|
Chris@11
|
107 * @param ptr Points to the Agent which is removed from the list
|
Chris@11
|
108 */
|
Chris@11
|
109 void remove(iterator itr) {
|
Chris@11
|
110 list.erase(itr);
|
Chris@11
|
111 } // remove()
|
Chris@8
|
112
|
Chris@8
|
113 protected:
|
Chris@11
|
114 /** Removes Agents from the list which are duplicates of other Agents.
|
Chris@11
|
115 * A duplicate is defined by the tempo and phase thresholds
|
Chris@11
|
116 * thresholdBI and thresholdBT respectively.
|
Chris@11
|
117 */
|
Chris@15
|
118 void removeDuplicates();
|
Chris@8
|
119
|
Chris@8
|
120 public:
|
Chris@11
|
121 /** Perform beat tracking on a list of events (onsets).
|
Chris@11
|
122 * @param el The list of onsets (or events or peaks) to beat track
|
Chris@11
|
123 */
|
Chris@23
|
124 void beatTrack(EventList el, AgentParameters params) {
|
Chris@23
|
125 beatTrack(el, params, -1.0);
|
Chris@11
|
126 } // beatTrack()/1
|
Chris@8
|
127
|
Chris@11
|
128 /** Perform beat tracking on a list of events (onsets).
|
Chris@11
|
129 * @param el The list of onsets (or events or peaks) to beat track.
|
Chris@11
|
130 * @param stop Do not find beats after <code>stop</code> seconds.
|
Chris@11
|
131 */
|
Chris@23
|
132 void beatTrack(EventList el, AgentParameters params, double stop);
|
Chris@8
|
133
|
Chris@11
|
134 /** Finds the Agent with the highest score in the list, or NULL if beat tracking has failed.
|
Chris@11
|
135 * @return The Agent with the highest score
|
Chris@11
|
136 */
|
Chris@15
|
137 Agent *bestAgent();
|
Chris@8
|
138
|
Chris@8
|
139 }; // class AgentList
|
Chris@8
|
140
|
Chris@8
|
141 #endif
|
Chris@8
|
142
|