annotate src/Finder.cpp @ 46:b0ebc3e2c016 refactors

Some fixes: int -> float
author Chris Cannam
date Thu, 13 Nov 2014 15:09:04 +0000
parents a1b7df871496
children 8cbc15519d2c
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 Vamp feature extraction plugin using the MATCH audio alignment
cannam@0 5 algorithm.
cannam@0 6
cannam@0 7 Centre for Digital Music, Queen Mary, University of London.
cannam@0 8 This file copyright 2007 Simon Dixon, Chris Cannam and QMUL.
cannam@0 9
cannam@0 10 This program is free software; you can redistribute it and/or
cannam@0 11 modify it under the terms of the GNU General Public License as
cannam@0 12 published by the Free Software Foundation; either version 2 of the
cannam@0 13 License, or (at your option) any later version. See the file
cannam@0 14 COPYING included with this distribution for more information.
cannam@0 15 */
cannam@0 16
cannam@0 17 #include "Finder.h"
cannam@0 18
Chris@30 19 #include "Path.h"
Chris@30 20
Chris@30 21 #include <algorithm>
Chris@30 22
cannam@0 23
cannam@0 24 Finder::Finder(Matcher *p1, Matcher *p2)
cannam@0 25 {
Chris@43 26 if (!p1->m_firstPM)
cannam@0 27 std::cerr << "Warning: wrong args in Finder()" << std::endl;
cannam@0 28 pm1 = p1;
cannam@0 29 pm2 = p2;
cannam@0 30 index1 = 0;
cannam@0 31 index2 = 0;
cannam@0 32 rowRange = new int[2];
cannam@0 33 colRange = new int[2];
cannam@0 34 } // constructor
cannam@0 35
cannam@0 36 Finder::~Finder()
cannam@0 37 {
cannam@0 38 delete[] rowRange;
cannam@0 39 delete[] colRange;
cannam@0 40 }
cannam@0 41
cannam@0 42 bool
cannam@0 43 Finder::find(int i1, int i2)
cannam@0 44 {
cannam@0 45 if (i1 >= 0) {
cannam@0 46 index1 = i1;
Chris@43 47 index2 = i2 - pm1->m_first[i1];
cannam@0 48 }
Chris@43 49 return (i1 >= 0) && (i2 >= pm1->m_first[i1]) && (i2 < pm1->m_last[i1]);
cannam@0 50 } // find()
cannam@0 51
cannam@0 52 void
cannam@0 53 Finder::getColRange(int row, int *range)
cannam@0 54 {
Chris@43 55 range[0] = pm1->m_first[row];
Chris@43 56 range[1] = pm1->m_last[row];
cannam@0 57 } // getColRange()
cannam@0 58
cannam@0 59 void
cannam@0 60 Finder::getRowRange(int col, int *range)
cannam@0 61 {
Chris@43 62 range[0] = pm2->m_first[col];
Chris@43 63 range[1] = pm2->m_last[col];
cannam@0 64 } // getRowRange()
cannam@0 65
Chris@45 66 Matcher::Advance
cannam@0 67 Finder::getExpandDirection(int row, int col)
cannam@0 68 {
cannam@0 69 return getExpandDirection(row, col, false);
cannam@0 70 } // getExpandDirection()
cannam@0 71
Chris@45 72 Matcher::Advance
cannam@0 73 Finder::getExpandDirection(int row, int col, bool check)
cannam@0 74 {
cannam@0 75 int min = getPathCost(row, col);
cannam@0 76 bestRow = row;
cannam@0 77 bestCol = col;
cannam@0 78 getRowRange(col, rowRange);
cannam@0 79 if (rowRange[1] > row+1)
cannam@0 80 rowRange[1] = row+1; // don't cheat by looking at future :)
cannam@0 81 for (int index = rowRange[0]; index < rowRange[1]; index++) {
cannam@0 82 int tmp = getPathCost(index, col);
cannam@0 83 if (tmp < min) {
cannam@0 84 min = tmp;
cannam@0 85 bestRow = index;
cannam@0 86 }
cannam@0 87 }
cannam@0 88 getColRange(row, colRange);
cannam@0 89 if (colRange[1] > col+1)
cannam@0 90 colRange[1] = col+1; // don't cheat by looking at future :)
cannam@0 91 for (int index = colRange[0]; index < colRange[1]; index++) {
cannam@0 92 int tmp = getPathCost(row, index);
cannam@0 93 if (tmp < min) {
cannam@0 94 min = tmp;
cannam@0 95 bestCol = index;
cannam@0 96 bestRow = row;
cannam@0 97 }
cannam@0 98 }
cannam@0 99 // System.err.print(" BEST: " + bestRow + " " + bestCol + " " + check);
cannam@0 100 // System.err.println(" " + pm1->frameCount + " " + pm2->frameCount);
cannam@0 101 if (check) {
cannam@0 102 // System.err.println(find(row+1, col) + " " + find(row, col+1));
Chris@45 103 if (!find(row, col+1)) {
Chris@45 104 return Matcher::AdvanceThis;
Chris@45 105 } else if (!find(row+1, col)) {
Chris@45 106 return Matcher::AdvanceOther;
Chris@45 107 }
cannam@0 108 }
Chris@45 109
Chris@45 110 if (bestRow == row) {
Chris@45 111 if (bestCol == col) {
Chris@45 112 return Matcher::AdvanceBoth;
Chris@45 113 } else {
Chris@45 114 return Matcher::AdvanceThis;
Chris@45 115 }
Chris@45 116 } else if (bestCol == col) {
Chris@45 117 return Matcher::AdvanceOther;
Chris@45 118 } else {
Chris@46 119 return Matcher::AdvanceNone;
Chris@45 120 }
cannam@0 121
cannam@0 122 } // getExpandDirection()
cannam@0 123
Chris@45 124 float
cannam@0 125 Finder::getDistance(int row, int col)
cannam@0 126 {
cannam@0 127 if (find(row, col)) {
Chris@43 128 return pm1->m_distance[row][col - pm1->m_first[row]];
cannam@0 129 }
cannam@0 130 std::cerr << "getDistance(" << row << "," << col << "): out of bounds" << std::endl;
cannam@0 131 throw "getDistance index out of bounds";
cannam@0 132 } // getDistance()/2
cannam@0 133
cannam@0 134 void
Chris@45 135 Finder::setDistance(int row, int col, float b)
cannam@0 136 {
cannam@0 137 if (find(row, col)) {
Chris@43 138 pm1->m_distance[row][col - pm1->m_first[row]] = b;
cannam@0 139 return;
cannam@0 140 }
cannam@0 141 std::cerr << "setDistance(" << row << "," << col << "," << b << "): out of bounds" << std::endl;
cannam@0 142 throw "setDistance index out of bounds";
cannam@0 143 } // setDistance()
cannam@0 144
Chris@45 145 float
cannam@0 146 Finder::getPathCost(int row, int col)
cannam@0 147 {
cannam@0 148 if (find(row, col)) // "1" avoids div by 0 below
Chris@45 149 return pm1->m_bestPathCost[row][col - pm1->m_first[row]] / float(1+row+col);
cannam@0 150 std::cerr << "getPathCost(" << row << "," << col << "): out of bounds" << std::endl;
cannam@0 151 throw "getPathCost index out of bounds";
cannam@0 152 } // getPathCost()
cannam@0 153
Chris@45 154 float
cannam@0 155 Finder::getRawPathCost(int row, int col)
cannam@0 156 {
cannam@0 157 if (find(row, col))
Chris@43 158 return pm1->m_bestPathCost[row][col - pm1->m_first[row]];
cannam@0 159 std::cerr << "getRawPathCost(" << row << "," << col << "): out of bounds" << std::endl;
cannam@0 160 throw "getRawPathCost index out of bounds";
cannam@0 161 } // getRawPathCost()
cannam@0 162
cannam@0 163 void
Chris@45 164 Finder::setPathCost(int row, int col, float cost)
cannam@0 165 {
cannam@0 166 if (find(row, col)) {
Chris@45 167 pm1->m_bestPathCost[row][col - pm1->m_first[row]] = cost;
cannam@0 168 return;
cannam@0 169 }
Chris@45 170 std::cerr << "setPathCost(" << row << "," << col << "," << cost << "): out of bounds" << std::endl;
cannam@0 171 throw "setPathCost index out of bounds";
cannam@0 172 } // setPathCost()
cannam@0 173
Chris@45 174 Matcher::Advance
Chris@45 175 Finder::getAdvance()
Chris@45 176 {
Chris@45 177 return pm1->m_advance[index1][index2];
Chris@45 178 }
Chris@45 179
Chris@45 180 void
Chris@45 181 Finder::setAdvance(Matcher::Advance a)
Chris@45 182 {
Chris@45 183 pm1->m_advance[index1][index2] = a;
Chris@45 184 }
Chris@45 185
Chris@45 186 float
cannam@0 187 Finder::getDistance()
cannam@0 188 {
Chris@43 189 return pm1->m_distance[index1][index2];
cannam@0 190 } // getDistance()/0
cannam@0 191
cannam@0 192 void
Chris@45 193 Finder::setDistance(float b)
cannam@0 194 {
Chris@45 195 pm1->m_distance[index1][index2] = b;
cannam@0 196 } // setDistance()
cannam@0 197
Chris@45 198 float
cannam@0 199 Finder::getPathCost()
cannam@0 200 {
Chris@43 201 return pm1->m_bestPathCost[index1][index2];
cannam@0 202 } // getPathCost()
cannam@0 203
cannam@0 204 void
Chris@45 205 Finder::setPathCost(float cost)
cannam@0 206 {
Chris@45 207 pm1->m_bestPathCost[index1][index2] = cost;
cannam@0 208 } // setPathCost()
cannam@0 209
cannam@0 210 void
cannam@0 211 Finder::recalculatePathCostMatrix(int r1, int c1, int r2, int c2)
cannam@0 212 {
cannam@0 213 if (!find(r1,c1)) {
cannam@0 214 std::cerr << "recalculatePathCostMatrix(" << r1 << "," << c1 << "): out of bounds" << std::endl;
cannam@0 215 throw "recalculatePathCostMatrix index out of bounds";
cannam@0 216 }
cannam@0 217 int thisRowStart, c;
cannam@0 218 int prevRowStart = 0, prevRowStop = 0;
cannam@0 219 for (int r = r1; r <= r2; r++) {
Chris@43 220 thisRowStart = pm1->m_first[r];
cannam@0 221 if (thisRowStart < c1)
cannam@0 222 thisRowStart = c1;
cannam@0 223 for (c = thisRowStart; c <= c2; c++) {
cannam@0 224 if (find(r,c)) {
cannam@0 225 int i2 = index2;
Chris@43 226 int newCost = pm1->m_distance[r][i2];
Chris@45 227 Matcher::Advance dir = Matcher::AdvanceNone;
cannam@0 228 if (r > r1) { // not first row
cannam@0 229 int min = -1;
cannam@0 230 if ((c > prevRowStart) && (c <= prevRowStop)) {
cannam@0 231 // diagonal from (r-1,c-1)
Chris@43 232 min = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]-1] +
cannam@0 233 newCost * 2;
Chris@45 234 dir = Matcher::AdvanceBoth;
cannam@0 235 }
cannam@0 236 if ((c >= prevRowStart) && (c < prevRowStop)) {
cannam@0 237 // vertical from (r-1,c)
Chris@43 238 int cost = pm1->m_bestPathCost[r-1][c-pm1->m_first[r-1]] +
cannam@0 239 newCost;
cannam@0 240 if ((min == -1) || (cost < min)) {
cannam@0 241 min = cost;
Chris@45 242 dir = Matcher::AdvanceThis;
cannam@0 243 }
cannam@0 244 }
cannam@0 245 if (c > thisRowStart) {
cannam@0 246 // horizontal from (r,c-1)
Chris@43 247 int cost =pm1->m_bestPathCost[r][i2-1]+newCost;
cannam@0 248 if ((min == -1) || (cost < min)) {
cannam@0 249 min = cost;
Chris@45 250 dir = Matcher::AdvanceOther;
cannam@0 251 }
cannam@0 252 }
Chris@43 253 pm1->m_bestPathCost[r][i2] = min;
cannam@0 254 } else if (c > thisRowStart) { // first row
cannam@0 255 // horizontal from (r,c-1)
Chris@43 256 pm1->m_bestPathCost[r][i2] = pm1->m_bestPathCost[r][i2-1] +
cannam@0 257 newCost;
Chris@45 258 dir = Matcher::AdvanceOther;
cannam@0 259 }
Chris@45 260 pm1->m_advance[r][i2] = dir;
cannam@0 261 } else
cannam@0 262 break; // end of row
cannam@0 263 }
cannam@0 264 prevRowStart = thisRowStart;
cannam@0 265 prevRowStop = c;
cannam@0 266 }
cannam@0 267 } // recalculatePathCostMatrix()
Chris@30 268
Chris@30 269 int
Chris@31 270 Finder::retrievePath(bool smooth, vector<int> &pathx, vector<int> &pathy)
Chris@30 271 {
Chris@30 272 int x = pm2->getFrameCount() - 1;
Chris@30 273 int y = pm1->getFrameCount() - 1;
Chris@30 274
Chris@30 275 pathx.clear();
Chris@30 276 pathy.clear();
Chris@30 277
Chris@30 278 while (find(y, x) && ((x > 0) || (y > 0))) {
Chris@30 279
Chris@33 280 // cerr << "x = " << x << ", y = " << y;
Chris@33 281
Chris@30 282 pathx.push_back(x);
Chris@30 283 pathy.push_back(y);
Chris@30 284
Chris@45 285 switch (getAdvance()) {
Chris@45 286 case Matcher::AdvanceThis:
Chris@33 287 // cerr << ", going down (dist = " << (int)getDistance() << ")" << endl;
Chris@33 288 y--;
Chris@33 289 break;
Chris@45 290 case Matcher::AdvanceOther:
Chris@33 291 // cerr << ", going left (dist = " << (int)getDistance() << ")" << endl;
Chris@33 292 x--;
Chris@33 293 break;
Chris@45 294 case Matcher::AdvanceBoth:
Chris@33 295 // cerr << ", going diag (dist = " << (int)getDistance() << ")" << endl;
Chris@33 296 x--;
Chris@33 297 y--;
Chris@33 298 break;
Chris@45 299 case Matcher::AdvanceNone: // this would indicate a bug, but we wouldn't want to hang
Chris@33 300 // cerr << "WARNING: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << endl;
Chris@33 301 if (x > y) {
Chris@33 302 x--;
Chris@33 303 } else {
Chris@33 304 y--;
Chris@33 305 }
Chris@33 306 break;
Chris@30 307 }
Chris@30 308 }
Chris@30 309
Chris@30 310 std::reverse(pathx.begin(), pathx.end());
Chris@30 311 std::reverse(pathy.begin(), pathy.end());
Chris@30 312
Chris@31 313 if (smooth) {
Chris@31 314 int smoothedLen = Path().smooth(pathx, pathy, pathx.size());
Chris@31 315 return smoothedLen;
Chris@31 316 } else {
Chris@31 317 return pathx.size();
Chris@31 318 }
Chris@30 319 }
Chris@30 320
Chris@30 321