Mercurial > hg > match-vamp
comparison src/Matcher.cpp @ 75:e1a5f3095ba6 cheap_diagonals
Merge from branch refactors
author | Chris Cannam |
---|---|
date | Wed, 19 Nov 2014 12:13:28 +0000 |
parents | fb6e4829c1af b9aa663a607b |
children |
comparison
equal
deleted
inserted
replaced
68:7aa1ab3db7c9 | 75:e1a5f3095ba6 |
---|---|
19 #include <iostream> | 19 #include <iostream> |
20 | 20 |
21 #include <cstdlib> | 21 #include <cstdlib> |
22 #include <cassert> | 22 #include <cassert> |
23 | 23 |
24 using namespace std; | |
25 | |
24 //#define DEBUG_MATCHER 1 | 26 //#define DEBUG_MATCHER 1 |
25 | |
26 Matcher::Matcher(Parameters parameters, | |
27 FeatureExtractor::Parameters feParams, | |
28 Matcher *p) : | |
29 m_params(parameters), | |
30 m_featureExtractor(feParams), | |
31 m_metric(parameters.distanceNorm) | |
32 { | |
33 #ifdef DEBUG_MATCHER | |
34 cerr << "Matcher::Matcher(" << m_params.sampleRate << ", " << p << ")" << endl; | |
35 #endif | |
36 | |
37 m_otherMatcher = p; // the first matcher will need this to be set later | |
38 m_firstPM = (!p); | |
39 m_frameCount = 0; | |
40 m_runCount = 0; | |
41 m_featureSize = m_featureExtractor.getFeatureSize(); | |
42 m_blockSize = 0; | |
43 | |
44 m_blockSize = lrint(m_params.blockTime / m_params.hopTime); | |
45 #ifdef DEBUG_MATCHER | |
46 cerr << "Matcher: m_blockSize = " << m_blockSize << endl; | |
47 #endif | |
48 | |
49 m_initialised = false; | |
50 } | |
51 | 27 |
52 Matcher::Matcher(Parameters parameters, Matcher *p, int m_featureSize_) : | 28 Matcher::Matcher(Parameters parameters, Matcher *p, int m_featureSize_) : |
53 m_params(parameters), | 29 m_params(parameters), |
54 m_featureSize(m_featureSize_), | 30 m_featureSize(m_featureSize_), |
55 m_featureExtractor(FeatureExtractor::Parameters(m_params.sampleRate, m_params.fftSize)), // unused default config | |
56 m_metric(parameters.distanceNorm) | 31 m_metric(parameters.distanceNorm) |
57 { | 32 { |
58 #ifdef DEBUG_MATCHER | 33 #ifdef DEBUG_MATCHER |
59 cerr << "Matcher::Matcher(" << m_params.sampleRate << ", " << p << ", " << m_featureSize << ")" << endl; | 34 cerr << "Matcher::Matcher(" << m_params.sampleRate << ", " << p << ", " << m_featureSize << ")" << endl; |
60 #endif | 35 #endif |
84 Matcher::init() | 59 Matcher::init() |
85 { | 60 { |
86 if (m_initialised) return; | 61 if (m_initialised) return; |
87 | 62 |
88 m_frames = vector<vector<double> > | 63 m_frames = vector<vector<double> > |
89 (m_blockSize, vector<double>(m_featureSize, 0)); | 64 (m_blockSize, vector<double>(m_featureSize, -1.0)); |
90 | 65 |
91 m_distXSize = m_blockSize * 2; | 66 m_distXSize = m_blockSize * 2; |
92 | 67 |
93 size(); | 68 size(); |
94 | 69 |
100 | 75 |
101 void | 76 void |
102 Matcher::size() | 77 Matcher::size() |
103 { | 78 { |
104 int distSize = (m_params.maxRunCount + 1) * m_blockSize; | 79 int distSize = (m_params.maxRunCount + 1) * m_blockSize; |
105 m_bestPathCost.resize(m_distXSize, vector<double>(distSize, 0)); | 80 m_bestPathCost.resize(m_distXSize, vector<double>(distSize, -1)); |
106 m_distance.resize(m_distXSize, vector<float>(distSize, 0)); | 81 m_distance.resize(m_distXSize, vector<float>(distSize, -1)); |
107 m_advance.resize(m_distXSize, vector<Advance>(distSize, AdvanceNone)); | 82 m_advance.resize(m_distXSize, vector<Advance>(distSize, AdvanceNone)); |
108 m_distYSizes.resize(m_distXSize, distSize); | |
109 m_first.resize(m_distXSize, 0); | 83 m_first.resize(m_distXSize, 0); |
110 m_last.resize(m_distXSize, 0); | 84 m_last.resize(m_distXSize, 0); |
111 } | 85 } |
112 | 86 |
113 vector<double> | 87 void |
114 Matcher::consumeFrame(double *reBuffer, double *imBuffer) | 88 Matcher::consumeFeatureVector(vector<double> feature) |
115 { | |
116 if (!m_initialised) init(); | |
117 | |
118 vector<double> real(reBuffer, reBuffer + m_params.fftSize/2 + 1); | |
119 vector<double> imag(imBuffer, imBuffer + m_params.fftSize/2 + 1); | |
120 vector<double> feature = m_featureExtractor.process(real, imag); | |
121 int frameIndex = m_frameCount % m_blockSize; | |
122 m_frames[frameIndex] = feature; | |
123 calcAdvance(); | |
124 | |
125 return feature; | |
126 } | |
127 | |
128 void | |
129 Matcher::consumeFeatureVector(std::vector<double> feature) | |
130 { | 89 { |
131 if (!m_initialised) init(); | 90 if (!m_initialised) init(); |
132 int frameIndex = m_frameCount % m_blockSize; | 91 int frameIndex = m_frameCount % m_blockSize; |
133 m_frames[frameIndex] = feature; | 92 m_frames[frameIndex] = feature; |
134 calcAdvance(); | 93 calcAdvance(); |
151 | 110 |
152 // We need to copy distance[m_frameCount-m_blockSize] to | 111 // We need to copy distance[m_frameCount-m_blockSize] to |
153 // distance[m_frameCount], and then truncate | 112 // distance[m_frameCount], and then truncate |
154 // distance[m_frameCount-m_blockSize] to its first len elements. | 113 // distance[m_frameCount-m_blockSize] to its first len elements. |
155 // Same for bestPathCost. | 114 // Same for bestPathCost. |
156 /* | 115 |
157 std::cerr << "Matcher(" << this << "): moving " << distYSizes[m_frameCount - m_blockSize] << " from " << m_frameCount - m_blockSize << " to " | 116 vector<float> dOld = m_distance[m_frameCount - m_blockSize]; |
158 << m_frameCount << ", allocating " << len << " for " | 117 vector<float> dNew(len, -1.f); |
159 << m_frameCount - m_blockSize << std::endl; | 118 |
160 */ | 119 vector<double> bpcOld = m_bestPathCost[m_frameCount - m_blockSize]; |
161 m_distance[m_frameCount] = m_distance[m_frameCount - m_blockSize]; | 120 vector<double> bpcNew(len, -1.0); |
162 m_distance[m_frameCount - m_blockSize].resize(len, 0); | 121 |
163 | 122 vector<Advance> adOld = m_advance[m_frameCount - m_blockSize]; |
164 m_bestPathCost[m_frameCount] = m_bestPathCost[m_frameCount - m_blockSize]; | 123 vector<Advance> adNew(len, AdvanceNone); |
165 m_bestPathCost[m_frameCount - m_blockSize].resize(len, 0); | 124 |
166 | 125 for (int i = 0; i < len; ++i) { |
167 m_advance[m_frameCount] = m_advance[m_frameCount - m_blockSize]; | 126 dNew[i] = dOld[i]; |
168 m_advance[m_frameCount - m_blockSize].resize(len, AdvanceNone); | 127 bpcNew[i] = bpcOld[i]; |
128 adNew[i] = adOld[i]; | |
129 } | |
169 | 130 |
170 m_distYSizes[m_frameCount] = m_distYSizes[m_frameCount - m_blockSize]; | 131 m_distance[m_frameCount] = dOld; |
171 m_distYSizes[m_frameCount - m_blockSize] = len; | 132 m_distance[m_frameCount - m_blockSize] = dNew; |
133 | |
134 m_bestPathCost[m_frameCount] = bpcOld; | |
135 m_bestPathCost[m_frameCount - m_blockSize] = bpcNew; | |
136 | |
137 m_advance[m_frameCount] = adOld; | |
138 m_advance[m_frameCount - m_blockSize] = adNew; | |
172 } | 139 } |
173 | 140 |
174 int stop = m_otherMatcher->m_frameCount; | 141 int stop = m_otherMatcher->m_frameCount; |
175 int index = stop - m_blockSize; | 142 int index = stop - m_blockSize; |
176 if (index < 0) | 143 if (index < 0) |
192 mx = dMN; | 159 mx = dMN; |
193 else if (dMN < mn) | 160 else if (dMN < mn) |
194 mn = dMN; | 161 mn = dMN; |
195 | 162 |
196 if ((m_frameCount == 0) && (index == 0)) // first element | 163 if ((m_frameCount == 0) && (index == 0)) // first element |
197 setValue(0, 0, AdvanceNone, 0, dMN); | 164 updateValue(0, 0, AdvanceNone, 0, dMN); |
198 else if (m_frameCount == 0) // first row | 165 else if (m_frameCount == 0) // first row |
199 setValue(0, index, AdvanceOther, | 166 updateValue(0, index, AdvanceOther, |
200 getValue(0, index-1, true), dMN); | 167 getPathCost(0, index-1), dMN); |
201 else if (index == 0) // first column | 168 else if (index == 0) // first column |
202 setValue(m_frameCount, index, AdvanceThis, | 169 updateValue(m_frameCount, index, AdvanceThis, |
203 getValue(m_frameCount - 1, 0, true), dMN); | 170 getPathCost(m_frameCount - 1, 0), dMN); |
204 else if (index == m_otherMatcher->m_frameCount - m_blockSize) { | 171 else if (index == m_otherMatcher->m_frameCount - m_blockSize) { |
205 // missing value(s) due to cutoff | 172 // missing value(s) due to cutoff |
206 // - no previous value in current row (resp. column) | 173 // - no previous value in current row (resp. column) |
207 // - no diagonal value if prev. dir. == curr. dirn | 174 // - no diagonal value if prev. dir. == curr. dirn |
208 double min2 = getValue(m_frameCount - 1, index, true); | 175 double min2 = getPathCost(m_frameCount - 1, index); |
209 // if ((m_firstPM && (first[m_frameCount - 1] == index)) || | 176 // if ((m_firstPM && (first[m_frameCount - 1] == index)) || |
210 // (!m_firstPM && (m_last[index-1] < m_frameCount))) | 177 // (!m_firstPM && (m_last[index-1] < m_frameCount))) |
211 if (m_first[m_frameCount - 1] == index) | 178 if (m_first[m_frameCount - 1] == index) |
212 setValue(m_frameCount, index, AdvanceThis, min2, dMN); | 179 updateValue(m_frameCount, index, AdvanceThis, min2, dMN); |
213 else { | 180 else { |
214 double min1 = getValue(m_frameCount - 1, index - 1, true); | 181 double min1 = getPathCost(m_frameCount - 1, index - 1); |
215 if (min1 + dMN <= min2) | 182 if (min1 + dMN <= min2) |
216 setValue(m_frameCount, index, AdvanceBoth, min1,dMN); | 183 updateValue(m_frameCount, index, AdvanceBoth, min1,dMN); |
217 else | 184 else |
218 setValue(m_frameCount, index, AdvanceThis, min2,dMN); | 185 updateValue(m_frameCount, index, AdvanceThis, min2,dMN); |
219 } | 186 } |
220 } else { | 187 } else { |
221 double min1 = getValue(m_frameCount, index-1, true); | 188 double min1 = getPathCost(m_frameCount, index-1); |
222 double min2 = getValue(m_frameCount - 1, index, true); | 189 double min2 = getPathCost(m_frameCount - 1, index); |
223 double min3 = getValue(m_frameCount - 1, index-1, true); | 190 double min3 = getPathCost(m_frameCount - 1, index-1); |
224 if (min1 <= min2) { | 191 if (min1 <= min2) { |
225 if (min3 + dMN <= min1) | 192 if (min3 + dMN <= min1) |
226 setValue(m_frameCount, index, AdvanceBoth, min3,dMN); | 193 updateValue(m_frameCount, index, AdvanceBoth, min3,dMN); |
227 else | 194 else |
228 setValue(m_frameCount, index, AdvanceOther,min1,dMN); | 195 updateValue(m_frameCount, index, AdvanceOther,min1,dMN); |
229 } else { | 196 } else { |
230 if (min3 + dMN <= min2) | 197 if (min3 + dMN <= min2) |
231 setValue(m_frameCount, index, AdvanceBoth, min3,dMN); | 198 updateValue(m_frameCount, index, AdvanceBoth, min3,dMN); |
232 else | 199 else |
233 setValue(m_frameCount, index, AdvanceThis, min2,dMN); | 200 updateValue(m_frameCount, index, AdvanceThis, min2,dMN); |
234 } | 201 } |
235 } | 202 } |
236 m_otherMatcher->m_last[index]++; | 203 m_otherMatcher->m_last[index]++; |
237 } // loop for row (resp. column) | 204 } // loop for row (resp. column) |
238 | 205 |
240 m_runCount++; | 207 m_runCount++; |
241 | 208 |
242 m_otherMatcher->m_runCount = 0; | 209 m_otherMatcher->m_runCount = 0; |
243 } | 210 } |
244 | 211 |
212 bool | |
213 Matcher::isInRange(int i, int j) | |
214 { | |
215 if (m_firstPM) { | |
216 return ((i >= 0) && | |
217 (i < int(m_first.size())) && | |
218 (j >= m_first[i]) && | |
219 (j < int(m_first[i] + m_bestPathCost[i].size()))); | |
220 } else { | |
221 return m_otherMatcher->isInRange(j, i); | |
222 } | |
223 } | |
224 | |
225 bool | |
226 Matcher::isAvailable(int i, int j) | |
227 { | |
228 if (m_firstPM) { | |
229 if (isInRange(i, j)) { | |
230 return (m_bestPathCost[i][j - m_first[i]] >= 0); | |
231 } else { | |
232 return false; | |
233 } | |
234 } else { | |
235 return m_otherMatcher->isAvailable(j, i); | |
236 } | |
237 } | |
238 | |
239 pair<int, int> | |
240 Matcher::getColRange(int i) | |
241 { | |
242 if (i < 0 || i >= int(m_first.size())) { | |
243 cerr << "ERROR: Matcher::getColRange(" << i << "): Index out of range" | |
244 << endl; | |
245 throw "Index out of range"; | |
246 } else { | |
247 return pair<int, int>(m_first[i], m_last[i]); | |
248 } | |
249 } | |
250 | |
251 pair<int, int> | |
252 Matcher::getRowRange(int i) | |
253 { | |
254 return m_otherMatcher->getColRange(i); | |
255 } | |
256 | |
257 float | |
258 Matcher::getDistance(int i, int j) | |
259 { | |
260 if (m_firstPM) { | |
261 if (!isInRange(i, j)) { | |
262 cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): " | |
263 << "Location is not in range" << endl; | |
264 throw "Distance not available"; | |
265 } | |
266 float dist = m_distance[i][j - m_first[i]]; | |
267 if (dist < 0) { | |
268 cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): " | |
269 << "Location is in range, but distance (" | |
270 << dist << ") is invalid or has not been set" << endl; | |
271 throw "Distance not available"; | |
272 } | |
273 return dist; | |
274 } else { | |
275 return m_otherMatcher->getDistance(j, i); | |
276 } | |
277 } | |
278 | |
279 void | |
280 Matcher::setDistance(int i, int j, float distance) | |
281 { | |
282 if (m_firstPM) { | |
283 if (!isInRange(i, j)) { | |
284 cerr << "ERROR: Matcher::setDistance(" << i << ", " << j << ", " | |
285 << distance << "): Location is out of range" << endl; | |
286 throw "Indices out of range"; | |
287 } | |
288 m_distance[i][j - m_first[i]] = distance; | |
289 } else { | |
290 m_otherMatcher->setDistance(j, i, distance); | |
291 } | |
292 } | |
293 | |
245 double | 294 double |
246 Matcher::getValue(int i, int j, bool firstAttempt) | 295 Matcher::getPathCost(int i, int j) |
247 { | 296 { |
248 if (m_firstPM) | 297 if (m_firstPM) { |
298 if (!isAvailable(i, j)) { | |
299 if (!isInRange(i, j)) { | |
300 cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): " | |
301 << "Location is not in range" << endl; | |
302 } else { | |
303 cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): " | |
304 << "Location is in range, but pathCost (" | |
305 << m_bestPathCost[i][j - m_first[i]] | |
306 << ") is invalid or has not been set" << endl; | |
307 } | |
308 throw "Path cost not available"; | |
309 } | |
249 return m_bestPathCost[i][j - m_first[i]]; | 310 return m_bestPathCost[i][j - m_first[i]]; |
250 else | 311 } else { |
251 return m_otherMatcher->m_bestPathCost[j][i - m_otherMatcher->m_first[j]]; | 312 return m_otherMatcher->getPathCost(j, i); |
252 } // getValue() | 313 } |
253 | 314 } |
254 void | 315 |
255 Matcher::setValue(int i, int j, Advance dir, double value, float dMN) | 316 void |
256 { | 317 Matcher::setPathCost(int i, int j, Advance dir, double pathCost) |
257 float diagonalWeight = sqrtf(2.f); | 318 { |
258 | 319 if (m_firstPM) { |
259 if (dir == AdvanceBoth) { | 320 if (!isInRange(i, j)) { |
260 dMN *= diagonalWeight; | 321 cerr << "ERROR: Matcher::setPathCost(" << i << ", " << j << ", " |
261 } | 322 << dir << ", " << pathCost |
262 | 323 << "): Location is out of range" << endl; |
263 if (m_firstPM) { | 324 throw "Indices out of range"; |
264 | 325 } |
265 int jdx = j - m_first[i]; | 326 m_advance[i][j - m_first[i]] = dir; |
266 m_distance[i][jdx] = dMN; | 327 m_bestPathCost[i][j - m_first[i]] = pathCost; |
267 m_advance[i][jdx] = dir; | 328 } else { |
268 m_bestPathCost[i][jdx] = value + dMN; | |
269 | |
270 } else { | |
271 | |
272 if (dir == AdvanceThis) { | 329 if (dir == AdvanceThis) { |
273 dir = AdvanceOther; | 330 dir = AdvanceOther; |
274 } else if (dir == AdvanceOther) { | 331 } else if (dir == AdvanceOther) { |
275 dir = AdvanceThis; | 332 dir = AdvanceThis; |
276 } | 333 } |
334 m_otherMatcher->setPathCost(j, i, dir, pathCost); | |
335 } | |
336 | |
337 } | |
338 | |
339 void | |
340 Matcher::updateValue(int i, int j, Advance dir, double value, float dMN) | |
341 { | |
342 float diagonalWeight = sqrtf(2.f); | |
343 | |
344 float weight = 1.f; | |
345 if (dir == AdvanceBoth) { | |
346 weight *= diagonalWeight; | |
347 } | |
348 | |
349 if (m_firstPM) { | |
350 | |
351 m_distance[i][j - m_first[i]] = dMN; | |
352 setPathCost(i, j, dir, value + weight * dMN); | |
353 | |
354 } else { | |
277 | 355 |
278 int idx = i - m_otherMatcher->m_first[j]; | 356 int idx = i - m_otherMatcher->m_first[j]; |
279 | 357 |
280 if (idx == (int)m_otherMatcher->m_distYSizes[j]) { | 358 if (idx == (int)m_otherMatcher->m_distance[j].size()) { |
281 // This should never happen, but if we allow arbitrary | 359 // This should never happen, but if we allow arbitrary |
282 // pauses in either direction, and arbitrary lengths at | 360 // pauses in either direction, and arbitrary lengths at |
283 // end, it is better than a segmentation fault. | 361 // end, it is better than a segmentation fault. |
284 std::cerr << "Emergency resize: " << idx << " -> " << idx * 2 << std::endl; | 362 cerr << "Emergency resize: " << idx << " -> " << idx * 2 << endl; |
285 m_otherMatcher->m_distYSizes[j] = idx * 2; | 363 m_otherMatcher->m_bestPathCost[j].resize(idx * 2, -1); |
286 m_otherMatcher->m_bestPathCost[j].resize(idx * 2, 0); | 364 m_otherMatcher->m_distance[j].resize(idx * 2, -1); |
287 m_otherMatcher->m_distance[j].resize(idx * 2, 0); | |
288 m_otherMatcher->m_advance[j].resize(idx * 2, AdvanceNone); | 365 m_otherMatcher->m_advance[j].resize(idx * 2, AdvanceNone); |
289 } | 366 } |
290 | 367 |
291 m_otherMatcher->m_distance[j][idx] = dMN; | 368 m_otherMatcher->m_distance[j][idx] = dMN; |
292 m_otherMatcher->m_advance[j][idx] = dir; | 369 m_otherMatcher->setPathCost(j, i, dir, value + weight * dMN); |
293 m_otherMatcher->m_bestPathCost[j][idx] = value + dMN; | 370 } |
294 } | 371 } |
295 } // setValue() | 372 |
296 | 373 Matcher::Advance |
374 Matcher::getAdvance(int i, int j) | |
375 { | |
376 if (m_firstPM) { | |
377 if (!isInRange(i, j)) { | |
378 cerr << "ERROR: Matcher::getAdvance(" << i << ", " << j << "): " | |
379 << "Location is not in range" << endl; | |
380 throw "Advance not available"; | |
381 } | |
382 return m_advance[i][j - m_first[i]]; | |
383 } else { | |
384 return m_otherMatcher->getAdvance(j, i); | |
385 } | |
386 } |