comparison src/NoteHypothesis.cpp @ 184:9b9cdfccbd14 noteagent

Wire up note agent code -- results are not very good, so far
author Chris Cannam
date Wed, 28 May 2014 14:54:01 +0100
parents e1718e64a921
children 462b165c8c0f
comparison
equal deleted inserted replaced
182:e1718e64a921 184:9b9cdfccbd14
19 19
20 #include <cmath> 20 #include <cmath>
21 #include <cassert> 21 #include <cassert>
22 22
23 #include <map> 23 #include <map>
24 #include <algorithm>
24 25
25 using Vamp::RealTime; 26 using Vamp::RealTime;
26 27
27 //#define DEBUG_NOTE_HYPOTHESIS 1 28 using std::cerr;
29 using std::endl;
30
31 #define DEBUG_NOTE_HYPOTHESIS 1
28 32
29 NoteHypothesis::NoteHypothesis() 33 NoteHypothesis::NoteHypothesis()
30 { 34 {
31 m_state = New; 35 m_state = New;
32 } 36 }
48 --i; 52 --i;
49 Observation last = *i; 53 Observation last = *i;
50 double r = s.value / last.value; 54 double r = s.value / last.value;
51 int cents = lrint(1200.0 * (log(r) / log(2.0))); 55 int cents = lrint(1200.0 * (log(r) / log(2.0)));
52 #ifdef DEBUG_NOTE_HYPOTHESIS 56 #ifdef DEBUG_NOTE_HYPOTHESIS
53 std::cerr << "isWithinTolerance: this " << s.value << " is " << cents 57 cerr << "isWithinTolerance: this " << s.value << " is " << cents
54 << " cents from prior " << last.value << std::endl; 58 << " cents from prior " << last.value << endl;
55 #endif 59 #endif
56 if (cents < -60 || cents > 60) return false; 60 if (cents < -60 || cents > 60) return false;
57 61
58 // and within a slightly bigger tolerance of the current mean 62 // and within a slightly bigger tolerance of the current mean
59 double meanFreq = getMeanFrequency(); 63 double meanFreq = getMeanFrequency();
60 r = s.value / meanFreq; 64 r = s.value / meanFreq;
61 cents = lrint(1200.0 * (log(r) / log(2.0))); 65 cents = lrint(1200.0 * (log(r) / log(2.0)));
62 #ifdef DEBUG_NOTE_HYPOTHESIS 66 #ifdef DEBUG_NOTE_HYPOTHESIS
63 std::cerr << "isWithinTolerance: this " << s.value << " is " << cents 67 cerr << "isWithinTolerance: this " << s.value << " is " << cents
64 << " cents from mean " << meanFreq << std::endl; 68 << " cents from mean " << meanFreq << endl;
65 #endif 69 #endif
66 if (cents < -80 || cents > 80) return false; 70 if (cents < -80 || cents > 80) return false;
67 71
68 return true; 72 return true;
69 } 73 }
76 Observations::const_iterator i = m_pending.end(); 80 Observations::const_iterator i = m_pending.end();
77 --i; 81 --i;
78 Observation last = *i; 82 Observation last = *i;
79 83
80 #ifdef DEBUG_NOTE_HYPOTHESIS 84 #ifdef DEBUG_NOTE_HYPOTHESIS
81 std::cerr << "isOutOfDateFor: this " << s.time << " is " 85 cerr << "isOutOfDateFor: this " << s.time << " is "
82 << (s.time - last.time) << " from last " << last.time 86 << (s.time - last.time) << " from last " << last.time
83 << " (threshold " << RealTime::fromMilliseconds(40) << ")" 87 << " (threshold " << RealTime::fromMilliseconds(40) << ")"
84 << std::endl; 88 << endl;
85 #endif 89 #endif
86 90
87 return ((s.time - last.time) > RealTime::fromMilliseconds(40)); 91 return ((s.time - last.time) > RealTime::fromMilliseconds(40));
88 } 92 }
89 93
97 i != m_pending.end(); ++i) { 101 i != m_pending.end(); ++i) {
98 meanConfidence += i->confidence; 102 meanConfidence += i->confidence;
99 } 103 }
100 meanConfidence /= m_pending.size(); 104 meanConfidence /= m_pending.size();
101 105
106 //!!! surely this depends on the hop size?
102 int lengthRequired = 100; 107 int lengthRequired = 100;
103 if (meanConfidence > 0.0) { 108 if (meanConfidence > 0.0) {
104 lengthRequired = int(2.0 / meanConfidence + 0.5); 109 lengthRequired = int(2.0 / meanConfidence + 0.5);
105 } 110 }
106 // if (lengthRequired < 1) lengthRequired = 1; 111 //!!!
107 112 lengthRequired = lengthRequired / 2;
108 #ifdef DEBUG_NOTE_HYPOTHESIS 113 if (lengthRequired < 1) lengthRequired = 1;
109 std::cerr << "meanConfidence " << meanConfidence << ", lengthRequired " << lengthRequired << std::endl; 114
115 #ifdef DEBUG_NOTE_HYPOTHESIS
116 cerr << "meanConfidence " << meanConfidence << ", lengthRequired " << lengthRequired << endl;
110 #endif 117 #endif
111 118
112 return ((int)m_pending.size() > lengthRequired); 119 return ((int)m_pending.size() > lengthRequired);
120 }
121
122 static void printState(NoteHypothesis::State s)
123 {
124 switch (s) {
125 case NoteHypothesis::New: cerr << "New"; break;
126 case NoteHypothesis::Provisional: cerr << "Provisional"; break;
127 case NoteHypothesis::Rejected: cerr << "Rejected"; break;
128 case NoteHypothesis::Satisfied: cerr << "Satisfied"; break;
129 case NoteHypothesis::Expired: cerr << "Expired"; break;
130 }
113 } 131 }
114 132
115 bool 133 bool
116 NoteHypothesis::accept(Observation s) 134 NoteHypothesis::accept(Observation s)
117 { 135 {
118 bool accept = false; 136 bool accept = false;
119 137
120 #ifdef DEBUG_NOTE_HYPOTHESIS 138 #ifdef DEBUG_NOTE_HYPOTHESIS
121 std::cerr << "NoteHypothesis[" << this << "]::accept: state " << m_state << "..." << std::endl; 139 cerr << "NoteHypothesis[" << this << "]::accept (value " << s.value << ", time " << s.time << ", confidence " << s.confidence << "): state ";
140 printState(m_state);
141 cerr << "..." << endl;
122 #endif 142 #endif
123 143
124 static double negligibleConfidence = 0.0001; 144 static double negligibleConfidence = 0.0001;
125 145
126 if (s.confidence < negligibleConfidence) { 146 if (s.confidence < negligibleConfidence) {
162 case Expired: 182 case Expired:
163 break; 183 break;
164 } 184 }
165 185
166 if (accept) { 186 if (accept) {
187 #ifdef DEBUG_NOTE_HYPOTHESIS
188 cerr << "... accepting" << endl;
189 #endif
167 m_pending.insert(s); 190 m_pending.insert(s);
168 if (m_state == Provisional && isSatisfied()) { 191 if (m_state == Provisional && isSatisfied()) {
169 m_state = Satisfied; 192 m_state = Satisfied;
170 } 193 }
171 } 194 } else {
172 195 #ifdef DEBUG_NOTE_HYPOTHESIS
173 #ifdef DEBUG_NOTE_HYPOTHESIS 196 cerr << "... not accepting" << endl;
174 std::cerr << "... -> " << m_state << " (pending: " << m_pending.size() << ")" << std::endl; 197 #endif
198 }
199
200 #ifdef DEBUG_NOTE_HYPOTHESIS
201 cerr << "... -> ";
202 printState(m_state);
203 cerr << " (pending: " << m_pending.size() << ")" << endl;
175 #endif 204 #endif
176 205
177 return accept; 206 return accept;
178 } 207 }
179 208
192 return Observations(); 221 return Observations();
193 } 222 }
194 } 223 }
195 224
196 double 225 double
226 NoteHypothesis::getMedianFrequency() const
227 {
228 if (m_pending.empty()) return 0.0;
229 std::vector<double> freqs;
230 for (Observations::const_iterator i = m_pending.begin();
231 i != m_pending.end(); ++i) {
232 freqs.push_back(i->value);
233 }
234 std::sort(freqs.begin(), freqs.end());
235 return freqs[freqs.size()/2];
236 }
237
238 double
197 NoteHypothesis::getMeanFrequency() const 239 NoteHypothesis::getMeanFrequency() const
198 { 240 {
199 double acc = 0.0; 241 double acc = 0.0;
200 if (m_pending.empty()) return acc; 242 if (m_pending.empty()) return acc;
201 for (Observations::const_iterator i = m_pending.begin(); 243 for (Observations::const_iterator i = m_pending.begin();
204 } 246 }
205 acc /= m_pending.size(); 247 acc /= m_pending.size();
206 return acc; 248 return acc;
207 } 249 }
208 250
251 double
252 NoteHypothesis::getMedianConfidence() const
253 {
254 if (m_pending.empty()) return 0.0;
255 std::vector<double> confs;
256 for (Observations::const_iterator i = m_pending.begin();
257 i != m_pending.end(); ++i) {
258 confs.push_back(i->confidence);
259 }
260 std::sort(confs.begin(), confs.end());
261 return confs[confs.size()/2];
262 }
263
209 NoteHypothesis::Note 264 NoteHypothesis::Note
210 NoteHypothesis::getAveragedNote() const 265 NoteHypothesis::getAveragedNote() const
211 { 266 {
212 Note n; 267 Note n;
213 268
214 n.time = getStartTime(); 269 n.time = getStartTime();
215 n.duration = getDuration(); 270 n.duration = getDuration();
216 271 n.freq = getMedianFrequency();
217 // just mean frequency for now, but this isn't at all right perceptually 272 n.confidence = getMedianConfidence();
218 n.freq = getMeanFrequency();
219 273
220 return n; 274 return n;
221 } 275 }
222 276
223 RealTime 277 RealTime