annotate src/AgentHypothesis.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
rev   line source
Chris@181 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@181 2
Chris@181 3 /*
Chris@181 4 Silvet
Chris@181 5
Chris@181 6 A Vamp plugin for note transcription.
Chris@181 7 Centre for Digital Music, Queen Mary University of London.
Chris@181 8 This file Copyright 2012 Chris Cannam.
Chris@181 9
Chris@181 10 This program is free software; you can redistribute it and/or
Chris@181 11 modify it under the terms of the GNU General Public License as
Chris@181 12 published by the Free Software Foundation; either version 2 of the
Chris@181 13 License, or (at your option) any later version. See the file
Chris@181 14 COPYING included with this distribution for more information.
Chris@181 15 */
Chris@181 16
Chris@181 17 #ifndef AGENT_HYPOTHESIS_H
Chris@181 18 #define AGENT_HYPOTHESIS_H
Chris@181 19
Chris@181 20 #include "vamp-sdk/RealTime.h"
Chris@181 21
Chris@181 22 #include <set>
Chris@181 23 #include <map>
Chris@181 24
Chris@181 25 /**
Chris@181 26 * An agent used to test an incoming series of timed observations or
Chris@181 27 * estimates to see whether they fit a consistent single-object
Chris@181 28 * relationship.
Chris@181 29 *
Chris@181 30 * A freshly constructed hypothesis object should be in New state and
Chris@181 31 * should accept any observation.
Chris@181 32 */
Chris@181 33
Chris@181 34 class AgentHypothesis
Chris@181 35 {
Chris@181 36 public:
Chris@181 37 virtual ~AgentHypothesis() { }
Chris@181 38
Chris@181 39 enum State {
Chris@181 40
Chris@181 41 /// Just constructed, will provisionally accept any observation
Chris@181 42 New,
Chris@181 43
Chris@181 44 /// Accepted at least one observation, but not enough evidence to satisfy
Chris@181 45 Provisional,
Chris@181 46
Chris@181 47 /// Could not find enough consistency in offered observations
Chris@181 48 Rejected,
Chris@181 49
Chris@181 50 /// Have accepted enough consistent observations to satisfy hypothesis
Chris@181 51 Satisfied,
Chris@181 52
Chris@181 53 /// Have been satisfied, but evidence has now changed: we're done
Chris@181 54 Expired
Chris@181 55 };
Chris@181 56
Chris@181 57 struct Observation {
Chris@181 58
Chris@181 59 Observation() : value(0), time(), confidence(1) { }
Chris@181 60
Chris@181 61 Observation(double _f, Vamp::RealTime _t, double _c) :
Chris@181 62 value(_f), time(_t), confidence(_c) { }
Chris@181 63
Chris@181 64 bool operator==(const Observation &o) const {
Chris@181 65 return o.value == value && o.time == time && o.confidence == confidence;
Chris@181 66 }
Chris@181 67 bool operator<(const Observation &o) const {
Chris@181 68 return
Chris@181 69 (time < o.time ||
Chris@181 70 (time == o.time && value < o.value) ||
Chris@181 71 (time == o.time && value == o.value && confidence < o.confidence));
Chris@181 72 }
Chris@181 73
Chris@181 74 double value;
Chris@181 75 Vamp::RealTime time;
Chris@181 76 double confidence;
Chris@181 77 };
Chris@181 78 typedef std::set<Observation> Observations;
Chris@181 79
Chris@181 80 /**
Chris@181 81 * Test the given observation to see whether it is consistent with
Chris@181 82 * this hypothesis, and adjust the hypothesis' internal state
Chris@181 83 * accordingly. If the observation is not inconsistent with the
Chris@181 84 * hypothesis, return true.
Chris@181 85 *!!! should be called e.g. test?
Chris@181 86 */
Chris@181 87 virtual bool accept(Observation) = 0;
Chris@181 88
Chris@181 89 /**
Chris@181 90 * Return the current state of this hypothesis.
Chris@181 91 */
Chris@181 92 virtual State getState() const = 0;
Chris@181 93
Chris@181 94 /**
Chris@181 95 * If the hypothesis has been satisfied (i.e. is in Satisfied or
Chris@181 96 * Expired state), return the set of observations that it
Chris@181 97 * accepted. Otherwise return an empty set
Chris@181 98 */
Chris@181 99 virtual Observations getAcceptedObservations() const = 0;
Chris@181 100
Chris@181 101 /**
Chris@181 102 * Convert the given set of accepted hypotheses (of type
Chris@181 103 * subclassed from AgentHypothesis) into a flattened set of their
Chris@181 104 * accepted observations.
Chris@181 105 *
Chris@181 106 * That is, only one is included for at any given moment, so in
Chris@181 107 * the case of overlapping hypotheses, the observations for the
Chris@181 108 * earlier are taken until the next hypothesis begins and then the
Chris@181 109 * latter's observations begin instead.
Chris@181 110 *
Chris@181 111 * (If there are gaps between hypotheses, the gaps remain in the
Chris@181 112 * output.)
Chris@181 113 */
Chris@181 114 template <typename HypothesisType>
Chris@181 115 static Observations flatten(const std::set<HypothesisType> &agents) {
Chris@181 116
Chris@181 117 typedef typename std::set<HypothesisType>::const_iterator Itr;
Chris@181 118 Observations flattened;
Chris@181 119
Chris@181 120 if (agents.empty()) return flattened;
Chris@181 121 Observations obs = agents.begin()->getAcceptedObservations();
Chris@181 122
Chris@181 123 for (Itr i = agents.begin(); i != agents.end(); ++i) {
Chris@181 124
Chris@181 125 Itr j = i;
Chris@181 126 ++j;
Chris@181 127
Chris@181 128 Observations nextObs;
Chris@181 129 if (j != agents.end()) nextObs = j->getAcceptedObservations();
Chris@181 130
Chris@181 131 for (Observations::const_iterator i = obs.begin();
Chris@181 132 i != obs.end(); ++i) {
Chris@181 133 if (!nextObs.empty() && i->time >= nextObs.begin()->time) {
Chris@181 134 break;
Chris@181 135 }
Chris@181 136 flattened.insert(*i);
Chris@181 137 }
Chris@181 138
Chris@181 139 obs = nextObs;
Chris@181 140 }
Chris@181 141
Chris@181 142 return flattened;
Chris@181 143 }
Chris@181 144 };
Chris@181 145
Chris@181 146 #endif