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 }