Mercurial > hg > silvet
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 |