comparison AgentList.h @ 11:7169eb47b1bc

formatting only
author Chris Cannam
date Fri, 30 Sep 2011 23:11:14 +0100
parents 1c1e98cd1b2e
children 59520cd6abac
comparison
equal deleted inserted replaced
10:1c1e98cd1b2e 11:7169eb47b1bc
38 bool empty() const { return list.empty(); } 38 bool empty() const { return list.empty(); }
39 Container::iterator begin() { return list.begin(); } 39 Container::iterator begin() { return list.begin(); }
40 Container::iterator end() { return list.end(); } 40 Container::iterator end() { return list.end(); }
41 void push_back(const Agent &a) { list.push_back(a); } 41 void push_back(const Agent &a) { list.push_back(a); }
42 42
43 /** Flag for choice between sum and average beat salience values for Agent scores. 43 /** Flag for choice between sum and average beat salience values for Agent scores.
44 * The use of summed saliences favours faster tempi or lower metrical levels. */ 44 * The use of summed saliences favours faster tempi or lower metrical levels. */
45 static bool useAverageSalience; 45 static bool useAverageSalience;
46 46
47 /** For the purpose of removing duplicate agents, the default JND of IBI */ 47 /** For the purpose of removing duplicate agents, the default JND of IBI */
48 static const double DEFAULT_BI; 48 static const double DEFAULT_BI;
49 49
50 /** For the purpose of removing duplicate agents, the default JND of phase */ 50 /** For the purpose of removing duplicate agents, the default JND of phase */
51 static const double DEFAULT_BT; 51 static const double DEFAULT_BT;
52 52
53 /** Inserts newAgent into the list in ascending order of beatInterval */ 53 /** Inserts newAgent into the list in ascending order of beatInterval */
54 void add(Agent a) { 54 void add(Agent a) {
55 add(a, true); 55 add(a, true);
56 } // add()/1 56 } // add()/1
57 57
58 /** Appends newAgent to list (sort==false), or inserts newAgent into the list 58 /** Appends newAgent to list (sort==false), or inserts newAgent into the list
59 * in ascending order of beatInterval 59 * in ascending order of beatInterval
60 * @param newAgent The agent to be added to the list 60 * @param newAgent The agent to be added to the list
61 * @param sort Flag indicating whether the list is sorted or not 61 * @param sort Flag indicating whether the list is sorted or not
62 */ 62 */
63 void add(Agent newAgent, bool sort){ 63 void add(Agent newAgent, bool sort){
64 list.push_back(newAgent); 64 list.push_back(newAgent);
65 if (sort) this->sort(); 65 if (sort) this->sort();
66 } // add()/2 66 } // add()/2
67 67
68 /** Sorts the AgentList by increasing beatInterval. */ 68 /** Sorts the AgentList by increasing beatInterval. */
69 void sort() { 69 void sort() {
70 std::sort(list.begin(), list.end()); 70 std::sort(list.begin(), list.end());
71 } // sort() 71 } // sort()
72 72
73 /** Removes the given item from the list. 73 /** Removes the given item from the list.
74 * @param ptr Points to the Agent which is removed from the list 74 * @param ptr Points to the Agent which is removed from the list
75 */ 75 */
76 void remove(iterator itr) { 76 void remove(iterator itr) {
77 list.erase(itr); 77 list.erase(itr);
78 } // remove() 78 } // remove()
79 79
80 protected: 80 protected:
81 /** Removes Agents from the list which are duplicates of other Agents. 81 /** Removes Agents from the list which are duplicates of other Agents.
82 * A duplicate is defined by the tempo and phase thresholds 82 * A duplicate is defined by the tempo and phase thresholds
83 * thresholdBI and thresholdBT respectively. 83 * thresholdBI and thresholdBT respectively.
84 */ 84 */
85 void removeDuplicates() { 85 void removeDuplicates() {
86 sort(); 86 sort();
87 for (iterator itr = begin(); itr != end(); ++itr) { 87 for (iterator itr = begin(); itr != end(); ++itr) {
88 if (itr->phaseScore < 0.0) // already flagged for deletion 88 if (itr->phaseScore < 0.0) // already flagged for deletion
89 continue; 89 continue;
90 iterator itr2 = itr; 90 iterator itr2 = itr;
91 for (++itr2; itr2 != end(); ++itr2) { 91 for (++itr2; itr2 != end(); ++itr2) {
92 if (itr2->beatInterval - itr->beatInterval > DEFAULT_BI) 92 if (itr2->beatInterval - itr->beatInterval > DEFAULT_BI)
93 break; 93 break;
94 if (fabs(itr->beatTime - itr2->beatTime) > DEFAULT_BT) 94 if (fabs(itr->beatTime - itr2->beatTime) > DEFAULT_BT)
95 continue; 95 continue;
96 if (itr->phaseScore < itr2->phaseScore) { 96 if (itr->phaseScore < itr2->phaseScore) {
97 itr->phaseScore = -1.0; // flag for deletion 97 itr->phaseScore = -1.0; // flag for deletion
98 if (itr2->topScoreTime < itr->topScoreTime) 98 if (itr2->topScoreTime < itr->topScoreTime)
99 itr2->topScoreTime = itr->topScoreTime; 99 itr2->topScoreTime = itr->topScoreTime;
100 break; 100 break;
101 } else { 101 } else {
102 itr2->phaseScore = -1.0; // flag for deletion 102 itr2->phaseScore = -1.0; // flag for deletion
103 if (itr->topScoreTime < itr2->topScoreTime) 103 if (itr->topScoreTime < itr2->topScoreTime)
104 itr->topScoreTime = itr2->topScoreTime; 104 itr->topScoreTime = itr2->topScoreTime;
105 } 105 }
106 } 106 }
107 } 107 }
108 for (iterator itr = begin(); itr != end(); ) { 108 for (iterator itr = begin(); itr != end(); ) {
109 if (itr->phaseScore < 0.0) { 109 if (itr->phaseScore < 0.0) {
110 list.erase(itr); 110 list.erase(itr);
111 } else { 111 } else {
112 ++itr; 112 ++itr;
113 } 113 }
114 } 114 }
115 } // removeDuplicates() 115 } // removeDuplicates()
116 116
117 public: 117 public:
118 /** Perform beat tracking on a list of events (onsets). 118 /** Perform beat tracking on a list of events (onsets).
119 * @param el The list of onsets (or events or peaks) to beat track 119 * @param el The list of onsets (or events or peaks) to beat track
120 */ 120 */
121 void beatTrack(EventList el) { 121 void beatTrack(EventList el) {
122 beatTrack(el, -1.0); 122 beatTrack(el, -1.0);
123 } // beatTrack()/1 123 } // beatTrack()/1
124 124
125 /** Perform beat tracking on a list of events (onsets). 125 /** Perform beat tracking on a list of events (onsets).
126 * @param el The list of onsets (or events or peaks) to beat track. 126 * @param el The list of onsets (or events or peaks) to beat track.
127 * @param stop Do not find beats after <code>stop</code> seconds. 127 * @param stop Do not find beats after <code>stop</code> seconds.
128 */ 128 */
129 void beatTrack(EventList el, double stop) { 129 void beatTrack(EventList el, double stop) {
130 EventList::iterator ei = el.begin(); 130 EventList::iterator ei = el.begin();
131 bool phaseGiven = !empty() && (begin()->beatTime >= 0); // if given for one, assume given for others 131 bool phaseGiven = !empty() && (begin()->beatTime >= 0); // if given for one, assume given for others
132 while (ei != el.end()) { 132 while (ei != el.end()) {
133 Event ev = *ei; 133 Event ev = *ei;
134 ++ei; 134 ++ei;
135 if ((stop > 0) && (ev.time > stop)) 135 if ((stop > 0) && (ev.time > stop))
136 break; 136 break;
137 bool created = phaseGiven; 137 bool created = phaseGiven;
138 double prevBeatInterval = -1.0; 138 double prevBeatInterval = -1.0;
139 // cc: Duplicate our list of agents, and scan through 139 // cc: Duplicate our list of agents, and scan through
140 // the (now immutable) copy. This means we can safely 140 // the (now immutable) copy. This means we can safely
141 // add agents to our own list while scanning without 141 // add agents to our own list while scanning without
142 // disrupting our scan. 142 // disrupting our scan.
143 Container currentAgents = list; 143 Container currentAgents = list;
144 for (Container::iterator ai = currentAgents.begin(); 144 for (Container::iterator ai = currentAgents.begin();
145 ai != currentAgents.end(); ++ai) { 145 ai != currentAgents.end(); ++ai) {
146 Agent currentAgent = *ai; 146 Agent currentAgent = *ai;
147 if (currentAgent.beatInterval != prevBeatInterval) { 147 if (currentAgent.beatInterval != prevBeatInterval) {
148 if ((prevBeatInterval>=0) && !created && (ev.time<5.0)) { 148 if ((prevBeatInterval>=0) && !created && (ev.time<5.0)) {
149 // Create new agent with different phase 149 // Create new agent with different phase
150 Agent newAgent(prevBeatInterval); 150 Agent newAgent(prevBeatInterval);
151 // This may add an agent to our list 151 // This may add an agent to our list
152 newAgent.considerAsBeat(ev, *this); 152 newAgent.considerAsBeat(ev, *this);
153 }
154 prevBeatInterval = currentAgent.beatInterval;
155 created = phaseGiven;
156 } 153 }
157 if (currentAgent.considerAsBeat(ev, *this)) 154 prevBeatInterval = currentAgent.beatInterval;
158 created = true; 155 created = phaseGiven;
159 } // loop for each agent 156 }
160 removeDuplicates(); 157 if (currentAgent.considerAsBeat(ev, *this))
161 } // loop for each event 158 created = true;
162 } // beatTrack() 159 } // loop for each agent
160 removeDuplicates();
161 } // loop for each event
162 } // beatTrack()
163 163
164 /** Finds the Agent with the highest score in the list, or NULL if beat tracking has failed. 164 /** Finds the Agent with the highest score in the list, or NULL if beat tracking has failed.
165 * @return The Agent with the highest score 165 * @return The Agent with the highest score
166 */ 166 */
167 Agent *bestAgent() { 167 Agent *bestAgent() {
168 double best = -1.0; 168 double best = -1.0;
169 Agent *bestAg = 0; 169 Agent *bestAg = 0;
170 for (iterator itr = begin(); itr != end(); ++itr) { 170 for (iterator itr = begin(); itr != end(); ++itr) {
171 if (itr->events.empty()) continue; 171 if (itr->events.empty()) continue;
172 double startTime = itr->events.begin()->time; 172 double startTime = itr->events.begin()->time;
173 double conf = (itr->phaseScore + itr->tempoScore) / 173 double conf = (itr->phaseScore + itr->tempoScore) /
174 (useAverageSalience? (double)itr->beatCount: 1.0); 174 (useAverageSalience? (double)itr->beatCount: 1.0);
175 if (conf > best) { 175 if (conf > best) {
176 bestAg = &(*itr); 176 bestAg = &(*itr);
177 best = conf; 177 best = conf;
178 }
179 } 178 }
180 return bestAg; 179 }
181 } // bestAgent() 180 return bestAg;
181 } // bestAgent()
182 182
183 183
184 }; // class AgentList 184 }; // class AgentList
185 185
186 #endif 186 #endif