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_FEEDER_MONO_H Chris@181: #define AGENT_FEEDER_MONO_H Chris@181: Chris@181: #include "AgentFeeder.h" Chris@181: Chris@181: //#define DEBUG_FEEDER 1 Chris@181: Chris@181: /** Chris@181: * Take a series of observations or estimates (one at a time) and feed Chris@181: * them to a set of agent hypotheses, creating a new candidate agent Chris@181: * for each observation and also testing the observation against the Chris@181: * existing set of hypotheses. Chris@181: * Chris@181: * One satisfied hypothesis is considered to be "accepted" at any Chris@181: * moment (that is, the earliest contemporary hypothesis to have Chris@181: * become satisfied). The series of accepted and completed hypotheses Chris@181: * from construction to the present time can be queried through Chris@181: * getAcceptedHypotheses(). Chris@181: * Chris@181: * Call feed() to provide a new observation. Call finish() when all Chris@181: * observations have been provided. The set of hypotheses returned by Chris@181: * getAcceptedHypotheses() will not be complete unless finish() has Chris@181: * been called. Chris@181: */ Chris@181: template Chris@181: class AgentFeederMono : public AgentFeeder Chris@181: { Chris@181: public: Chris@181: AgentFeederMono() { } Chris@181: Chris@181: typedef std::set Hypotheses; Chris@181: Chris@181: virtual void feed(AgentHypothesis::Observation o) { Chris@181: Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "feed: have observation [value = " << o.value << ", time = " << o.time << "]" << std::endl; Chris@181: #endif Chris@181: Chris@181: if (!m_current.accept(o)) { Chris@181: Chris@181: if (m_current.getState() == Hypothesis::Expired) { Chris@181: m_accepted.insert(m_current); Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "current has expired, pushing to accepted" << std::endl; Chris@181: #endif Chris@181: } Chris@181: Chris@181: bool swallowed = false; Chris@181: Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "not swallowed by current" << std::endl; Chris@181: #endif Chris@181: Chris@181: Hypotheses newCandidates; Chris@181: Chris@181: for (typename Hypotheses::iterator i = m_candidates.begin(); Chris@181: i != m_candidates.end(); ++i) { Chris@181: Chris@181: Hypothesis h = *i; Chris@181: Chris@181: if (swallowed) { Chris@181: Chris@181: // don't offer: each observation can only belong to one Chris@181: // satisfied hypothesis Chris@181: newCandidates.insert(h); Chris@181: Chris@181: } else { Chris@181: Chris@181: if (h.accept(o)) { Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "accepted, state is " << h.getState() << std::endl; Chris@181: #endif Chris@181: if (h.getState() == Hypothesis::Satisfied) { Chris@181: Chris@181: swallowed = true; Chris@181: Chris@181: if (m_current.getState() == Hypothesis::Expired || Chris@181: m_current.getState() == Hypothesis::Rejected) { Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "current has ended, updating from candidate" << std::endl; Chris@181: #endif Chris@181: m_current = h; Chris@181: } else { Chris@181: newCandidates.insert(h); Chris@181: } Chris@181: Chris@181: } else { Chris@181: newCandidates.insert(h); Chris@181: } Chris@181: } Chris@181: } Chris@181: } Chris@181: Chris@181: if (!swallowed) { Chris@181: Hypothesis h; Chris@181: h.accept(o); // must succeed, as h is new Chris@181: newCandidates.insert(h); Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "not swallowed, creating new hypothesis" << std::endl; Chris@181: #endif Chris@181: } Chris@181: Chris@181: // reap rejected/expired hypotheses from candidates list, Chris@181: // and assign back to m_candidates Chris@181: Chris@181: m_candidates.clear(); Chris@181: Chris@181: for (typename Hypotheses::const_iterator i = newCandidates.begin(); Chris@181: i != newCandidates.end(); ++i) { Chris@181: Hypothesis h = *i; Chris@181: if (h.getState() != Hypothesis::Rejected && Chris@181: h.getState() != Hypothesis::Expired) { Chris@181: m_candidates.insert(h); Chris@181: } else { Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "reaping a candidate" << std::endl; Chris@181: #endif Chris@181: } Chris@181: } Chris@181: } Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "have " << m_candidates.size() << " candidates" << std::endl; Chris@181: #endif Chris@181: } Chris@181: Chris@181: virtual void finish() { Chris@181: if (m_current.getState() == Hypothesis::Satisfied) { Chris@181: #ifdef DEBUG_FEEDER Chris@181: std::cerr << "finish: current is satisfied, pushing to accepted" << std::endl; Chris@181: #endif Chris@181: m_accepted.insert(m_current); Chris@181: } Chris@181: } Chris@181: Chris@187: Hypotheses retrieveAcceptedHypotheses() { Chris@187: Hypotheses aa = m_accepted; Chris@187: m_accepted.clear(); Chris@187: return aa; Chris@181: } Chris@181: Chris@181: private: Chris@181: Hypotheses m_candidates; Chris@181: Hypothesis m_current; Chris@181: Hypotheses m_accepted; Chris@181: }; Chris@181: Chris@181: #endif