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_FEEDER_MONO_H
|
Chris@181
|
18 #define AGENT_FEEDER_MONO_H
|
Chris@181
|
19
|
Chris@181
|
20 #include "AgentFeeder.h"
|
Chris@181
|
21
|
Chris@181
|
22 //#define DEBUG_FEEDER 1
|
Chris@181
|
23
|
Chris@181
|
24 /**
|
Chris@181
|
25 * Take a series of observations or estimates (one at a time) and feed
|
Chris@181
|
26 * them to a set of agent hypotheses, creating a new candidate agent
|
Chris@181
|
27 * for each observation and also testing the observation against the
|
Chris@181
|
28 * existing set of hypotheses.
|
Chris@181
|
29 *
|
Chris@181
|
30 * One satisfied hypothesis is considered to be "accepted" at any
|
Chris@181
|
31 * moment (that is, the earliest contemporary hypothesis to have
|
Chris@181
|
32 * become satisfied). The series of accepted and completed hypotheses
|
Chris@181
|
33 * from construction to the present time can be queried through
|
Chris@189
|
34 * retrieveAcceptedHypotheses(), which detaches them from the current
|
Chris@189
|
35 * feeder (i.e. hypotheses returned from one call to this function
|
Chris@189
|
36 * will not be returned by any subsequent call).
|
Chris@181
|
37 *
|
Chris@181
|
38 * Call feed() to provide a new observation. Call finish() when all
|
Chris@181
|
39 * observations have been provided. The set of hypotheses returned by
|
Chris@181
|
40 * getAcceptedHypotheses() will not be complete unless finish() has
|
Chris@181
|
41 * been called.
|
Chris@181
|
42 */
|
Chris@181
|
43 template <typename Hypothesis>
|
Chris@181
|
44 class AgentFeederMono : public AgentFeeder
|
Chris@181
|
45 {
|
Chris@189
|
46 private:
|
Chris@189
|
47 typedef std::vector<Hypothesis> Hypotheses;
|
Chris@189
|
48
|
Chris@181
|
49 public:
|
Chris@189
|
50 AgentFeederMono() : m_haveCurrent(false) { }
|
Chris@181
|
51
|
Chris@181
|
52 virtual void feed(AgentHypothesis::Observation o) {
|
Chris@181
|
53
|
Chris@181
|
54 #ifdef DEBUG_FEEDER
|
Chris@181
|
55 std::cerr << "feed: have observation [value = " << o.value << ", time = " << o.time << "]" << std::endl;
|
Chris@181
|
56 #endif
|
Chris@181
|
57
|
Chris@189
|
58 if (m_haveCurrent) {
|
Chris@189
|
59 if (m_current.accept(o)) {
|
Chris@189
|
60 return;
|
Chris@189
|
61 }
|
Chris@181
|
62 if (m_current.getState() == Hypothesis::Expired) {
|
Chris@189
|
63 m_accepted.push_back(m_current);
|
Chris@181
|
64 #ifdef DEBUG_FEEDER
|
Chris@181
|
65 std::cerr << "current has expired, pushing to accepted" << std::endl;
|
Chris@181
|
66 #endif
|
Chris@189
|
67 m_haveCurrent = false;
|
Chris@181
|
68 }
|
Chris@189
|
69 }
|
Chris@181
|
70
|
Chris@189
|
71 bool swallowed = false;
|
Chris@181
|
72
|
Chris@181
|
73 #ifdef DEBUG_FEEDER
|
Chris@189
|
74 std::cerr << "not swallowed by current" << std::endl;
|
Chris@181
|
75 #endif
|
Chris@181
|
76
|
Chris@189
|
77 Hypotheses newCandidates;
|
Chris@181
|
78
|
Chris@189
|
79 for (typename Hypotheses::iterator i = m_candidates.begin();
|
Chris@189
|
80 i != m_candidates.end(); ++i) {
|
Chris@181
|
81
|
Chris@189
|
82 Hypothesis h = *i;
|
Chris@181
|
83
|
Chris@189
|
84 if (swallowed) {
|
Chris@181
|
85
|
Chris@189
|
86 // don't offer: each observation can only belong to one
|
Chris@189
|
87 // satisfied hypothesis
|
Chris@189
|
88 newCandidates.push_back(h);
|
Chris@181
|
89
|
Chris@189
|
90 } else {
|
Chris@181
|
91
|
Chris@189
|
92 if (h.accept(o)) {
|
Chris@181
|
93 #ifdef DEBUG_FEEDER
|
Chris@189
|
94 std::cerr << "accepted, state is " << h.getState() << std::endl;
|
Chris@181
|
95 #endif
|
Chris@189
|
96 if (h.getState() == Hypothesis::Satisfied) {
|
Chris@181
|
97
|
Chris@189
|
98 swallowed = true;
|
Chris@181
|
99
|
Chris@189
|
100 if (!m_haveCurrent ||
|
Chris@189
|
101 m_current.getState() == Hypothesis::Expired ||
|
Chris@189
|
102 m_current.getState() == Hypothesis::Rejected) {
|
Chris@181
|
103 #ifdef DEBUG_FEEDER
|
Chris@189
|
104 std::cerr << "current has ended, updating from candidate" << std::endl;
|
Chris@181
|
105 #endif
|
Chris@189
|
106 m_current = h;
|
Chris@189
|
107 m_haveCurrent = true;
|
Chris@181
|
108 } else {
|
Chris@189
|
109 newCandidates.push_back(h);
|
Chris@181
|
110 }
|
Chris@189
|
111
|
Chris@189
|
112 } else {
|
Chris@189
|
113 newCandidates.push_back(h);
|
Chris@181
|
114 }
|
Chris@181
|
115 }
|
Chris@181
|
116 }
|
Chris@189
|
117 }
|
Chris@181
|
118
|
Chris@189
|
119 if (!swallowed) {
|
Chris@189
|
120 Hypothesis h;
|
Chris@189
|
121 h.accept(o); // must succeed, as h is new
|
Chris@189
|
122 newCandidates.push_back(h);
|
Chris@181
|
123 #ifdef DEBUG_FEEDER
|
Chris@189
|
124 std::cerr << "not swallowed, creating new hypothesis" << std::endl;
|
Chris@181
|
125 #endif
|
Chris@189
|
126 }
|
Chris@181
|
127
|
Chris@189
|
128 // reap rejected/expired hypotheses from candidates list,
|
Chris@189
|
129 // and assign back to m_candidates
|
Chris@189
|
130
|
Chris@189
|
131 m_candidates.clear();
|
Chris@181
|
132
|
Chris@189
|
133 for (typename Hypotheses::const_iterator i = newCandidates.begin();
|
Chris@189
|
134 i != newCandidates.end(); ++i) {
|
Chris@189
|
135 Hypothesis h = *i;
|
Chris@189
|
136 if (h.getState() != Hypothesis::Rejected &&
|
Chris@189
|
137 h.getState() != Hypothesis::Expired) {
|
Chris@189
|
138 m_candidates.push_back(h);
|
Chris@189
|
139 } else {
|
Chris@181
|
140 #ifdef DEBUG_FEEDER
|
Chris@189
|
141 std::cerr << "reaping a candidate" << std::endl;
|
Chris@181
|
142 #endif
|
Chris@181
|
143 }
|
Chris@181
|
144 }
|
Chris@181
|
145 #ifdef DEBUG_FEEDER
|
Chris@181
|
146 std::cerr << "have " << m_candidates.size() << " candidates" << std::endl;
|
Chris@181
|
147 #endif
|
Chris@181
|
148 }
|
Chris@181
|
149
|
Chris@181
|
150 virtual void finish() {
|
Chris@189
|
151 if (m_haveCurrent &&
|
Chris@189
|
152 (m_current.getState() == Hypothesis::Satisfied)) {
|
Chris@181
|
153 #ifdef DEBUG_FEEDER
|
Chris@181
|
154 std::cerr << "finish: current is satisfied, pushing to accepted" << std::endl;
|
Chris@181
|
155 #endif
|
Chris@189
|
156 m_accepted.push_back(m_current);
|
Chris@181
|
157 }
|
Chris@181
|
158 }
|
Chris@181
|
159
|
Chris@189
|
160 std::set<Hypothesis> retrieveAcceptedHypotheses() {
|
Chris@189
|
161 std::set<Hypothesis> hs;
|
Chris@189
|
162 #ifdef DEBUG_FEEDER
|
Chris@189
|
163 std::cerr << "retrieveAcceptedHypotheses: returning " << m_accepted.size() << " accepted" << std::endl;
|
Chris@189
|
164 #endif
|
Chris@189
|
165 for (typename Hypotheses::const_iterator i = m_accepted.begin();
|
Chris@189
|
166 i != m_accepted.end(); ++i) {
|
Chris@189
|
167 hs.insert(*i);
|
Chris@189
|
168 }
|
Chris@187
|
169 m_accepted.clear();
|
Chris@189
|
170 return hs;
|
Chris@181
|
171 }
|
Chris@181
|
172
|
Chris@181
|
173 private:
|
Chris@181
|
174 Hypotheses m_candidates;
|
Chris@181
|
175 Hypothesis m_current;
|
Chris@189
|
176 bool m_haveCurrent;
|
Chris@181
|
177 Hypotheses m_accepted;
|
Chris@181
|
178 };
|
Chris@181
|
179
|
Chris@181
|
180 #endif
|