Mercurial > hg > silvet
diff src/AgentFeederMono.h @ 181:10e7c3ff575e noteagent
Experimental branch toward note-agent stuff (not actually plumbed in yet)
author | Chris Cannam |
---|---|
date | Fri, 23 May 2014 12:40:18 +0100 |
parents | |
children | 1697457458b7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/AgentFeederMono.h Fri May 23 12:40:18 2014 +0100 @@ -0,0 +1,161 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Silvet + + A Vamp plugin for note transcription. + Centre for Digital Music, Queen Mary University of London. + This file Copyright 2012 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef AGENT_FEEDER_MONO_H +#define AGENT_FEEDER_MONO_H + +#include "AgentFeeder.h" + +//#define DEBUG_FEEDER 1 + +/** + * Take a series of observations or estimates (one at a time) and feed + * them to a set of agent hypotheses, creating a new candidate agent + * for each observation and also testing the observation against the + * existing set of hypotheses. + * + * One satisfied hypothesis is considered to be "accepted" at any + * moment (that is, the earliest contemporary hypothesis to have + * become satisfied). The series of accepted and completed hypotheses + * from construction to the present time can be queried through + * getAcceptedHypotheses(). + * + * Call feed() to provide a new observation. Call finish() when all + * observations have been provided. The set of hypotheses returned by + * getAcceptedHypotheses() will not be complete unless finish() has + * been called. + */ +template <typename Hypothesis> +class AgentFeederMono : public AgentFeeder +{ +public: + AgentFeederMono() { } + + typedef std::set<Hypothesis> Hypotheses; + + virtual void feed(AgentHypothesis::Observation o) { + +#ifdef DEBUG_FEEDER + std::cerr << "feed: have observation [value = " << o.value << ", time = " << o.time << "]" << std::endl; +#endif + + if (!m_current.accept(o)) { + + if (m_current.getState() == Hypothesis::Expired) { + m_accepted.insert(m_current); +#ifdef DEBUG_FEEDER + std::cerr << "current has expired, pushing to accepted" << std::endl; +#endif + } + + bool swallowed = false; + +#ifdef DEBUG_FEEDER + std::cerr << "not swallowed by current" << std::endl; +#endif + + Hypotheses newCandidates; + + for (typename Hypotheses::iterator i = m_candidates.begin(); + i != m_candidates.end(); ++i) { + + Hypothesis h = *i; + + if (swallowed) { + + // don't offer: each observation can only belong to one + // satisfied hypothesis + newCandidates.insert(h); + + } else { + + if (h.accept(o)) { +#ifdef DEBUG_FEEDER + std::cerr << "accepted, state is " << h.getState() << std::endl; +#endif + if (h.getState() == Hypothesis::Satisfied) { + + swallowed = true; + + if (m_current.getState() == Hypothesis::Expired || + m_current.getState() == Hypothesis::Rejected) { +#ifdef DEBUG_FEEDER + std::cerr << "current has ended, updating from candidate" << std::endl; +#endif + m_current = h; + } else { + newCandidates.insert(h); + } + + } else { + newCandidates.insert(h); + } + } + } + } + + if (!swallowed) { + Hypothesis h; + h.accept(o); // must succeed, as h is new + newCandidates.insert(h); +#ifdef DEBUG_FEEDER + std::cerr << "not swallowed, creating new hypothesis" << std::endl; +#endif + } + + // reap rejected/expired hypotheses from candidates list, + // and assign back to m_candidates + + m_candidates.clear(); + + for (typename Hypotheses::const_iterator i = newCandidates.begin(); + i != newCandidates.end(); ++i) { + Hypothesis h = *i; + if (h.getState() != Hypothesis::Rejected && + h.getState() != Hypothesis::Expired) { + m_candidates.insert(h); + } else { +#ifdef DEBUG_FEEDER + std::cerr << "reaping a candidate" << std::endl; +#endif + } + } + } +#ifdef DEBUG_FEEDER + std::cerr << "have " << m_candidates.size() << " candidates" << std::endl; +#endif + } + + virtual void finish() { + if (m_current.getState() == Hypothesis::Satisfied) { +#ifdef DEBUG_FEEDER + std::cerr << "finish: current is satisfied, pushing to accepted" << std::endl; +#endif + m_accepted.insert(m_current); + } + } + + Hypotheses getAcceptedHypotheses() const { + return m_accepted; + } + +private: + Hypotheses m_candidates; + Hypothesis m_current; + Hypotheses m_accepted; +}; + +#endif