Mercurial > hg > beatroot-vamp
diff AgentList.cpp @ 15:887c629502a9
refactor: pull method implementations into .cpp files
author | Chris Cannam |
---|---|
date | Wed, 12 Oct 2011 10:55:52 +0100 |
parents | f04f87b5e643 |
children | 33d0b18b2509 |
line wrap: on
line diff
--- a/AgentList.cpp Fri Oct 07 14:07:42 2011 +0100 +++ b/AgentList.cpp Wed Oct 12 10:55:52 2011 +0100 @@ -19,3 +19,117 @@ const double AgentList::DEFAULT_BI = 0.02; const double AgentList::DEFAULT_BT = 0.04; +void AgentList::removeDuplicates() +{ + sort(); + for (iterator itr = begin(); itr != end(); ++itr) { + if (itr->phaseScore < 0.0) // already flagged for deletion + continue; + iterator itr2 = itr; + for (++itr2; itr2 != end(); ++itr2) { + if (itr2->beatInterval - itr->beatInterval > DEFAULT_BI) + break; + if (fabs(itr->beatTime - itr2->beatTime) > DEFAULT_BT) + continue; + if (itr->phaseScore < itr2->phaseScore) { + itr->phaseScore = -1.0; // flag for deletion + if (itr2->topScoreTime < itr->topScoreTime) + itr2->topScoreTime = itr->topScoreTime; + break; + } else { + itr2->phaseScore = -1.0; // flag for deletion + if (itr->topScoreTime < itr2->topScoreTime) + itr->topScoreTime = itr2->topScoreTime; + } + } + } + int removed = 0; + for (iterator itr = begin(); itr != end(); ) { + if (itr->phaseScore < 0.0) { + ++removed; + list.erase(itr); + } else { + ++itr; + } + } +#ifdef DEBUG_BEATROOT + if (removed > 0) { + std::cerr << "removeDuplicates: removed " << removed << ", have " + << list.size() << " agent(s) remaining" << std::endl; + } + int n = 0; + for (Container::iterator i = list.begin(); i != list.end(); ++i) { + std::cerr << "agent " << n++ << ": time " << i->beatTime << std::endl; + } +#endif +} // removeDuplicates() + + +void AgentList::beatTrack(EventList el, double stop) +{ + EventList::iterator ei = el.begin(); + bool phaseGiven = !empty() && (begin()->beatTime >= 0); // if given for one, assume given for others + while (ei != el.end()) { + Event ev = *ei; + ++ei; + if ((stop > 0) && (ev.time > stop)) + break; + bool created = phaseGiven; + double prevBeatInterval = -1.0; + // cc: Duplicate our list of agents, and scan through the + // copy. This means we can safely add agents to our own + // list while scanning without disrupting our scan. Each + // agent needs to be re-added to our own list explicitly + // (since it is modified by e.g. considerAsBeat) + Container currentAgents = list; + list.clear(); + for (Container::iterator ai = currentAgents.begin(); + ai != currentAgents.end(); ++ai) { + Agent currentAgent = *ai; + if (currentAgent.beatInterval != prevBeatInterval) { + if ((prevBeatInterval>=0) && !created && (ev.time<5.0)) { +#ifdef DEBUG_BEATROOT + std::cerr << "Creating a new agent" << std::endl; +#endif + // Create new agent with different phase + Agent newAgent(prevBeatInterval); + // This may add another agent to our list as well + newAgent.considerAsBeat(ev, *this); + add(newAgent); + } + prevBeatInterval = currentAgent.beatInterval; + created = phaseGiven; + } + if (currentAgent.considerAsBeat(ev, *this)) + created = true; + add(currentAgent); + } // loop for each agent + removeDuplicates(); + } // loop for each event +} // beatTrack() + +Agent *AgentList::bestAgent() +{ + double best = -1.0; + Agent *bestAg = 0; + for (iterator itr = begin(); itr != end(); ++itr) { + if (itr->events.empty()) continue; + double startTime = itr->events.begin()->time; + double conf = (itr->phaseScore + itr->tempoScore) / + (useAverageSalience? (double)itr->beatCount: 1.0); + if (conf > best) { + bestAg = &(*itr); + best = conf; + } + } +#ifdef DEBUG_BEATROOT + if (bestAg) { + std::cerr << "Best agent: Ag#" << bestAg->idNumber << std::endl; + std::cerr << " Av-salience = " << best << std::endl; + } else { + std::cerr << "No surviving agent - beat tracking failed" << std::endl; + } +#endif + return bestAg; +} // bestAgent() +