Mercurial > hg > tuning-difference
changeset 46:1623751c4549
Switch from 60bpo to 120 - seems to work better (?) with little performance downside. Also avoid recalculating second feature if not needed for fine tuning, and extend regression test
author | Chris Cannam |
---|---|
date | Tue, 09 Jul 2019 15:09:33 +0100 |
parents | 0fec1c76c92b |
children | f28b34e7ce8d |
files | src/TuningDifference.cpp src/TuningDifference.h test/expected.csv test/expected/input_vamp_tuning-difference_tuning-difference_cents.csv test/expected/input_vamp_tuning-difference_tuning-difference_rotfeature.csv test/expected/input_vamp_tuning-difference_tuning-difference_tuningfreq.csv test/regression.sh |
diffstat | 7 files changed, 63 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/src/TuningDifference.cpp Tue Jul 09 12:34:25 2019 +0100 +++ b/src/TuningDifference.cpp Tue Jul 09 15:09:33 2019 +0100 @@ -42,7 +42,7 @@ TuningDifference::TuningDifference(float inputSampleRate) : Plugin(inputSampleRate), - m_bpo(60), + m_bpo(120), m_refChroma(new Chromagram(paramsForTuningFrequency(440.))), m_blockSize(0), m_frameCount(0), @@ -86,7 +86,7 @@ { // Increment this each time you release a version that behaves // differently from the previous one - return 2; + return 3; } string @@ -159,7 +159,7 @@ desc.identifier = "finetuning"; desc.name = "Fine tuning"; - desc.description = "Use a fine tuning stage to increase nominal resolution from 20 cents to 1 cent."; + desc.description = "Use a fine tuning stage to increase nominal resolution from 10 cents to 1 cent."; desc.minValue = 0; desc.maxValue = 1; desc.defaultValue = (defaultFineTuning ? 1.f : 0.f); @@ -415,6 +415,16 @@ return FeatureSet(); } +void +TuningDifference::rotateFeature(TFeature &r, int rotation) const +{ + if (rotation < 0) { + rotate(r.begin(), r.begin() - rotation, r.end()); + } else { + rotate(r.begin(), r.end() - rotation, r.end()); + } +} + double TuningDifference::featureDistance(const TFeature &other, int rotation) const { @@ -426,11 +436,7 @@ // makes this chroma match an un-rotated reference, then this // chroma must have initially been lower than the reference. TFeature r(other); - if (rotation < 0) { - rotate(r.begin(), r.begin() - rotation, r.end()); - } else { - rotate(r.begin(), r.end() - rotation, r.end()); - } + rotateFeature(r, rotation); return distance(m_refFeature, r); } } @@ -455,12 +461,11 @@ } pair<int, double> -TuningDifference::findFineFrequency(int coarseCents, double coarseScore) +TuningDifference::findFineFrequency(int coarseCents) { int coarseResolution = 1200 / m_bpo; int searchDistance = coarseResolution/2 - 1; - double bestScore = coarseScore; int bestCents = coarseCents; double bestHz = frequencyForCentsAbove440(coarseCents); @@ -469,11 +474,20 @@ return pair<int, double>(bestCents, bestHz); } - cerr << "corresponding coarse Hz " << bestHz << " scores " << coarseScore << endl; + //!!! This is kind of absurd - all this brute force but all we're + //!!! really doing is aligning two very short signals at + //!!! sub-sample level - let's rewrite it someday + + cerr << "findFineFrequency: coarse frequency is " << bestHz << endl; cerr << "searchDistance = " << searchDistance << endl; + + double bestScore = 0; + bool firstScore = true; for (int sign = -1; sign <= 1; sign += 2) { - for (int offset = 1; offset <= searchDistance; ++offset) { + for (int offset = (sign < 0 ? 0 : 1); + offset <= searchDistance; + ++offset) { int fineCents = coarseCents + sign * offset; @@ -487,11 +501,12 @@ << ", Hz = " << fineHz << ", score " << fineScore << " (best score so far " << bestScore << ")" << endl; - if (fineScore < bestScore) { + if ((fineScore < bestScore) || firstScore) { cerr << "is good!" << endl; bestScore = fineScore; bestCents = fineCents; bestHz = fineHz; + firstScore = false; } else { break; } @@ -530,24 +545,17 @@ cerr << "rotation " << rotation << " -> cents " << coarseCents << endl; - double coarseHz = frequencyForCentsAbove440(coarseCents); - - TFeature coarseFeature; - if (rotation == 0) { - coarseFeature = otherFeature; - } else { - coarseFeature = computeFeatureFromSignal(m_other, coarseHz); + TFeature coarseFeature = otherFeature; + if (rotation != 0) { + rotateFeature(coarseFeature, rotation); } - double coarseScore = featureDistance(coarseFeature); - - cerr << "corresponding Hz " << coarseHz << " scores " << coarseScore << endl; //!!! This should be returning the fine chroma, not the coarse f.values.clear(); for (auto v: coarseFeature) f.values.push_back(float(v)); fs[m_outputs["rotfeature"]].push_back(f); - pair<int, double> fine = findFineFrequency(coarseCents, coarseScore); + pair<int, double> fine = findFineFrequency(coarseCents); int fineCents = fine.first; double fineHz = fine.second;
--- a/src/TuningDifference.h Tue Jul 09 12:34:25 2019 +0100 +++ b/src/TuningDifference.h Tue Jul 09 15:09:33 2019 +0100 @@ -77,9 +77,10 @@ Chromagram::Parameters paramsForTuningFrequency(double hz) const; TFeature computeFeatureFromTotals(const TFeature &totals) const; TFeature computeFeatureFromSignal(const Signal &signal, double hz) const; + void rotateFeature(TFeature &feature, int rotation) const; double featureDistance(const TFeature &other, int rotation = 0) const; int findBestRotation(const TFeature &other) const; - std::pair<int, double> findFineFrequency(int coarseCents, double coarseScore); + std::pair<int, double> findFineFrequency(int coarseCents); mutable std::map<string, int> m_outputs; };
--- a/test/expected.csv Tue Jul 09 12:34:25 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -0.000000000,-233
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/expected/input_vamp_tuning-difference_tuning-difference_cents.csv Tue Jul 09 15:09:33 2019 +0100 @@ -0,0 +1,1 @@ +0.000000000,-234
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/expected/input_vamp_tuning-difference_tuning-difference_rotfeature.csv Tue Jul 09 15:09:33 2019 +0100 @@ -0,0 +1,1 @@ +0.000000000,0.00854703,0.00931918,0.0106465,0.0122647,0.0138192,0.014525,0.0127565,0.00961516,0.00781605,0.00713913,0.0070496,0.00689058,0.00667673,0.0068509,0.00697572,0.00703986,0.00728556,0.00729718,0.00780589,0.00881012,0.00924105,0.00981542,0.0101795,0.0101861,0.0116841,0.0133551,0.0125837,0.0100393,0.00916784,0.00966024,0.00968428,0.00985668,0.010838,0.0113878,0.0130886,0.0154244,0.0147851,0.0124133,0.0108901,0.00978958,0.0085204,0.00787676,0.00806659,0.0081296,0.00795278,0.00725857,0.00640027,0.00608774,0.00564443,0.00578425,0.00616674,0.00679678,0.007764,0.00836082,0.00926527,0.0107817,0.010324,0.0083828,0.00728106,0.00676606,0.00674762,0.00674128,0.00633739,0.00626942,0.0063055,0.00667407,0.00670015,0.00663743,0.00677829,0.00728373,0.00811677,0.00894148,0.00974516,0.0115456,0.0143484,0.0156408,0.0138188,0.0104981,0.0084953,0.00746052,0.00668289,0.00641624,0.00640881,0.00641969,0.00688589,0.00793875,0.00798556,0.00685937,0.00603812,0.00571649,0.00562601,0.00541857,0.00519544,0.00539675,0.00576307,0.00631954,0.006413,0.00577577,0.00547572,0.00525969,0.00539033,0.00607725,0.00694533,0.00714786,0.00706424,0.00740421,0.00741943,0.00665752,0.00614163,0.00611627,0.00605784,0.00607328,0.0063531,0.007423,0.00861123,0.00968742,0.00927132,0.00812644,0.00785267,0.00828707
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/expected/input_vamp_tuning-difference_tuning-difference_tuningfreq.csv Tue Jul 09 15:09:33 2019 +0100 @@ -0,0 +1,1 @@ +0.000000000,384.372
--- a/test/regression.sh Tue Jul 09 12:34:25 2019 +0100 +++ b/test/regression.sh Tue Jul 09 15:09:33 2019 +0100 @@ -7,8 +7,6 @@ source_url=https://code.soundsoftware.ac.uk/attachments/download/1698/Zweieck-Duell.ogg testfile="$mydir/input.ogg" -outfile="$mydir/output.csv" -expfile="$mydir/expected.csv" if sonic-annotator -v >/dev/null ; then : @@ -45,26 +43,41 @@ rubberband -p -2.34 "$wavfile" "$lowfile" VAMP_PATH="$mydir/.." \ + time \ sonic-annotator \ - -d vamp:tuning-difference:tuning-difference \ + -d vamp:tuning-difference:tuning-difference:cents \ + -d vamp:tuning-difference:tuning-difference:tuningfreq \ + -d vamp:tuning-difference:tuning-difference:rotfeature \ -w csv \ --csv-omit-filename \ - --csv-one-file "$outfile" \ + --csv-basedir "$mydir/output" \ --csv-force \ --multiplex \ "$testfile" \ "$lowfile" -if cmp "$outfile" "$expfile" ; then - echo - echo PASS +failed="" + +for expected in "$mydir"/expected/*.csv ; do + outfile="$mydir"/output/$(basename $expected) + if cmp "$outfile" "$expected" ; then + echo "PASS: $outfile" + else + echo + echo "*** FAIL: Result does not match expected output. Diff follows:" + echo + sdiff -w 60 "$outfile" "$expected" + echo + failed="$failed $outfile" + fi +done + +if [ -n "$failed" ]; then + echo "Some tests failed: $failed" + exit 1 +else + echo "All tests passed" exit 0 -else - echo - echo "*** FAIL: Result does not match expected output. Diff follows:" - echo - sdiff -w 60 "$outfile" "$expfile" - exit 1 fi