Mercurial > hg > beatroot-vamp
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 |