Chris@181: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@181: Chris@181: /* Chris@181: Silvet Chris@181: Chris@181: A Vamp plugin for note transcription. Chris@181: Centre for Digital Music, Queen Mary University of London. Chris@181: This file Copyright 2012 Chris Cannam. Chris@181: Chris@181: This program is free software; you can redistribute it and/or Chris@181: modify it under the terms of the GNU General Public License as Chris@181: published by the Free Software Foundation; either version 2 of the Chris@181: License, or (at your option) any later version. See the file Chris@181: COPYING included with this distribution for more information. Chris@181: */ Chris@181: Chris@181: #ifndef AGENT_HYPOTHESIS_H Chris@181: #define AGENT_HYPOTHESIS_H Chris@181: Chris@181: #include "vamp-sdk/RealTime.h" Chris@181: Chris@181: #include Chris@181: #include Chris@181: Chris@181: /** Chris@181: * An agent used to test an incoming series of timed observations or Chris@181: * estimates to see whether they fit a consistent single-object Chris@181: * relationship. Chris@181: * Chris@181: * A freshly constructed hypothesis object should be in New state and Chris@181: * should accept any observation. Chris@181: */ Chris@181: Chris@181: class AgentHypothesis Chris@181: { Chris@181: public: Chris@181: virtual ~AgentHypothesis() { } Chris@181: Chris@181: enum State { Chris@181: Chris@181: /// Just constructed, will provisionally accept any observation Chris@181: New, Chris@181: Chris@181: /// Accepted at least one observation, but not enough evidence to satisfy Chris@181: Provisional, Chris@181: Chris@181: /// Could not find enough consistency in offered observations Chris@181: Rejected, Chris@181: Chris@181: /// Have accepted enough consistent observations to satisfy hypothesis Chris@181: Satisfied, Chris@181: Chris@181: /// Have been satisfied, but evidence has now changed: we're done Chris@181: Expired Chris@181: }; Chris@181: Chris@181: struct Observation { Chris@181: Chris@181: Observation() : value(0), time(), confidence(1) { } Chris@181: Chris@181: Observation(double _f, Vamp::RealTime _t, double _c) : Chris@181: value(_f), time(_t), confidence(_c) { } Chris@181: Chris@181: bool operator==(const Observation &o) const { Chris@181: return o.value == value && o.time == time && o.confidence == confidence; Chris@181: } Chris@181: bool operator<(const Observation &o) const { Chris@181: return Chris@181: (time < o.time || Chris@181: (time == o.time && value < o.value) || Chris@181: (time == o.time && value == o.value && confidence < o.confidence)); Chris@181: } Chris@181: Chris@181: double value; Chris@181: Vamp::RealTime time; Chris@181: double confidence; Chris@181: }; Chris@181: typedef std::set Observations; Chris@181: Chris@181: /** Chris@181: * Test the given observation to see whether it is consistent with Chris@181: * this hypothesis, and adjust the hypothesis' internal state Chris@181: * accordingly. If the observation is not inconsistent with the Chris@181: * hypothesis, return true. Chris@181: *!!! should be called e.g. test? Chris@181: */ Chris@181: virtual bool accept(Observation) = 0; Chris@181: Chris@181: /** Chris@181: * Return the current state of this hypothesis. Chris@181: */ Chris@181: virtual State getState() const = 0; Chris@181: Chris@181: /** Chris@181: * If the hypothesis has been satisfied (i.e. is in Satisfied or Chris@181: * Expired state), return the set of observations that it Chris@181: * accepted. Otherwise return an empty set Chris@181: */ Chris@181: virtual Observations getAcceptedObservations() const = 0; Chris@181: Chris@181: /** Chris@181: * Convert the given set of accepted hypotheses (of type Chris@181: * subclassed from AgentHypothesis) into a flattened set of their Chris@181: * accepted observations. Chris@181: * Chris@181: * That is, only one is included for at any given moment, so in Chris@181: * the case of overlapping hypotheses, the observations for the Chris@181: * earlier are taken until the next hypothesis begins and then the Chris@181: * latter's observations begin instead. Chris@181: * Chris@181: * (If there are gaps between hypotheses, the gaps remain in the Chris@181: * output.) Chris@181: */ Chris@181: template Chris@181: static Observations flatten(const std::set &agents) { Chris@181: Chris@181: typedef typename std::set::const_iterator Itr; Chris@181: Observations flattened; Chris@181: Chris@181: if (agents.empty()) return flattened; Chris@181: Observations obs = agents.begin()->getAcceptedObservations(); Chris@181: Chris@181: for (Itr i = agents.begin(); i != agents.end(); ++i) { Chris@181: Chris@181: Itr j = i; Chris@181: ++j; Chris@181: Chris@181: Observations nextObs; Chris@181: if (j != agents.end()) nextObs = j->getAcceptedObservations(); Chris@181: Chris@181: for (Observations::const_iterator i = obs.begin(); Chris@181: i != obs.end(); ++i) { Chris@181: if (!nextObs.empty() && i->time >= nextObs.begin()->time) { Chris@181: break; Chris@181: } Chris@181: flattened.insert(*i); Chris@181: } Chris@181: Chris@181: obs = nextObs; Chris@181: } Chris@181: Chris@181: return flattened; Chris@181: } Chris@181: }; Chris@181: Chris@181: #endif