Mercurial > hg > match-vamp
changeset 83:10e76188c846 refactors
Expose diagonal weight as a parameter
author | Chris Cannam |
---|---|
date | Thu, 27 Nov 2014 10:49:11 +0000 |
parents | 3616d541d69e |
children | de7034e93dd0 |
files | Makefile.linux src/Finder.cpp src/MatchVampPlugin.cpp src/Matcher.cpp src/Matcher.h |
diffstat | 5 files changed, 69 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.linux Thu Nov 27 10:14:07 2014 +0000 +++ b/Makefile.linux Thu Nov 27 10:49:11 2014 +0000 @@ -1,6 +1,6 @@ -CXXFLAGS += -fPIC -ffast-math -O3 -Wall -Werror -Wfloat-conversion -#CXXFLAGS += -fPIC -g -Wall -Werror +#CXXFLAGS += -fPIC -ffast-math -O3 -Wall -Werror -Wfloat-conversion +CXXFLAGS += -fPIC -g -Wall -Werror -DPERFORM_ERROR_CHECKS=1 LDFLAGS += -shared -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -Wl,-Bsymbolic -Wl,-z,defs -lpthread -Wl,--version-script=vamp-plugin.map
--- a/src/Finder.cpp Thu Nov 27 10:14:07 2014 +0000 +++ b/src/Finder.cpp Thu Nov 27 10:49:11 2014 +0000 @@ -92,6 +92,8 @@ { int prevRowStart = 0, prevRowStop = 0; + float diagonalWeight = m_m->getDiagonalWeight(); + for (int r = r1; r <= r2; r++) { pair<int, int> colRange = m_m->getColRange(r); @@ -108,7 +110,7 @@ double min = -1; if ((c > prevRowStart) && (c <= prevRowStop)) { // diagonal from (r-1,c-1) - min = m_m->getPathCost(r-1, c-1) + newCost * 2; + min = m_m->getPathCost(r-1, c-1) + newCost * diagonalWeight; dir = Matcher::AdvanceBoth; } if ((c >= prevRowStart) && (c < prevRowStop)) { @@ -161,6 +163,8 @@ int prevRowStart = 0, prevRowStop = 0; + float diagonalWeight = m_m->getDiagonalWeight(); + for (int r = r1; r <= r2; r++) { pair<int, int> colRange = m_m->getColRange(r); @@ -178,9 +182,9 @@ double min = -1; if ((c > prevRowStart) && (c <= prevRowStop)) { // diagonal from (r-1,c-1) - min = m_m->getPathCost(r-1, c-1) + newCost * 2; + min = m_m->getPathCost(r-1, c-1) + newCost * diagonalWeight; err.prevCost = m_m->getPathCost(r-1, c-1); - err.distance = newCost * 2; + err.distance = newCost * diagonalWeight; dir = Matcher::AdvanceBoth; } if ((c >= prevRowStart) && (c < prevRowStop)) { @@ -210,8 +214,10 @@ if (c > rowStart) { // horizontal from (r,c-1) + updateTo = m_m->getPathCost(r, c-1) + newCost; + err.prevCost = m_m->getPathCost(r, c-1); + err.distance = newCost; dir = Matcher::AdvanceOther; - updateTo = m_m->getPathCost(r, c-1) + newCost; } } @@ -262,10 +268,13 @@ cerr << "\nWARNING: Checking path-cost matrix returned mismatch:" << endl; cerr << "Type: " << err.type << endl; cerr << "At row " << err.r << ", column " << err.c << " advancing " - << err.advance << "\nPrev cost " << err.prevCost + << Matcher::advanceToString(err.advance) + << "\nPrev cost " << err.prevCost << " plus distance " << err.distance << " gives " << err.costShouldBe << ", but matrix contains " << err.costWas - << "\n" << endl; + << endl; + cerr << "Note: diagonal weight = " << m_m->getDiagonalWeight() << endl; + cerr << endl; } #endif
--- a/src/MatchVampPlugin.cpp Thu Nov 27 10:14:07 2014 +0000 +++ b/src/MatchVampPlugin.cpp Thu Nov 27 10:49:11 2014 +0000 @@ -233,6 +233,16 @@ desc.unit = "s"; list.push_back(desc); + desc.identifier = "diagonalweight"; + desc.name = "Diagonal Weight"; + desc.description = "Weight applied to cost of diagonal step relative to horizontal or vertical step. The default of 2.0 is good for gross tracking of quite different performances; closer to 1.0 produces a smoother path for performances more similar in tempo"; + desc.minValue = 1.0; + desc.maxValue = 3.0; + desc.defaultValue = 2.0; + desc.isQuantized = false; + desc.unit = ""; + list.push_back(desc); + desc.identifier = "smooth"; desc.name = "Smooth Path"; desc.description = "Smooth the path by replacing steps with diagonals"; @@ -262,6 +272,8 @@ return m_feParams.useChromaFrequencyMap ? 1.0 : 0.0; } else if (name == "gradientlimit") { return m_params.maxRunCount; + } else if (name == "diagonalweight") { + return m_params.diagonalWeight; } else if (name == "zonewidth") { return (float)m_params.blockTime; } else if (name == "smooth") { @@ -286,6 +298,8 @@ m_feParams.useChromaFrequencyMap = (value > 0.5); } else if (name == "gradientlimit") { m_params.maxRunCount = int(value + 0.1); + } else if (name == "diagonalweight") { + m_params.diagonalWeight = value; } else if (name == "zonewidth") { m_params.blockTime = value; } else if (name == "smooth") {
--- a/src/Matcher.cpp Thu Nov 27 10:14:07 2014 +0000 +++ b/src/Matcher.cpp Thu Nov 27 10:49:11 2014 +0000 @@ -339,10 +339,16 @@ void Matcher::updateValue(int i, int j, Advance dir, double value, float dMN) { + float weighted = dMN; + if (dir == AdvanceBoth) { + weighted *= m_params.diagonalWeight; + } + if (m_firstPM) { m_distance[i][j - m_first[i]] = dMN; - setPathCost(i, j, dir, value + (dir == AdvanceBoth ? dMN*2: dMN)); + + setPathCost(i, j, dir, value + weighted); } else { @@ -359,7 +365,7 @@ } m_otherMatcher->m_distance[j][idx] = dMN; - m_otherMatcher->setPathCost(j, i, dir, value + (dir == AdvanceBoth ? dMN*2: dMN)); + m_otherMatcher->setPathCost(j, i, dir, value + weighted); } }
--- a/src/Matcher.h Thu Nov 27 10:14:07 2014 +0000 +++ b/src/Matcher.h Thu Nov 27 10:49:11 2014 +0000 @@ -42,6 +42,15 @@ AdvanceThis, AdvanceOther }; + static string advanceToString(Advance a) { + switch (a) { + case AdvanceNone: return "AdvanceNone"; + case AdvanceBoth: return "AdvanceBoth"; + case AdvanceThis: return "AdvanceThis"; + case AdvanceOther: return "AdvanceOther"; + } + return "(unknown)"; + } struct Parameters { @@ -51,7 +60,8 @@ hopTime(hopTime_), fftSize(fftSize_), blockTime(10.0), - maxRunCount(3) + maxRunCount(3), + diagonalWeight(2.0) {} /** Sample rate of audio */ @@ -62,13 +72,15 @@ /** Spacing of audio frames (determines the amount of overlap or * skip between frames). This value is expressed in - * seconds. */ + * seconds. + */ double hopTime; /** Size of an FFT frame in samples. Note that the data passed * in to Matcher is already in the frequency domain, so this * expresses the size of the frame that the caller will be - * providing. */ + * providing. + */ int fftSize; /** The width of the search band (error margin) around the current @@ -83,6 +95,17 @@ * processed. */ int maxRunCount; + + /** Weight applied to cost of diagonal step relative to + * horizontal or vertical step. The default of 2.0 means that + * a diagonal is not favoured over horizontal+vertical + * combined, which is good when maintaining gross tracking of + * performances that may have wildly differing speeds but + * which also leads to quite jaggy paths. A more typical + * normal DTW approach for performances with similar speeds + * might use 1.0 or something close to it. + */ + float diagonalWeight; }; /** Constructor for Matcher. @@ -131,6 +154,10 @@ return m_otherMatcher->getFrameCount(); } + float getDiagonalWeight() { + return m_params.diagonalWeight; + } + /** Processes a feature vector frame, presumably calculated from * audio data by some external code such as a FeatureExtractor. * Calculates the distance to all frames stored in the