changeset 150:729cc1da9b8d memory

Use fixed-lag HMM in note tracking as well (when fixed-lag mode is selected)
author Chris Cannam
date Wed, 17 May 2017 16:29:43 +0100
parents b83e6fbe22cc
children 4f3001031231
files MonoNote.cpp MonoNote.h PYinVamp.cpp test/TestMonoNote.cpp
diffstat 4 files changed, 30 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/MonoNote.cpp	Wed May 17 15:55:37 2017 +0100
+++ b/MonoNote.cpp	Wed May 17 16:29:43 2017 +0100
@@ -21,8 +21,9 @@
 using std::vector;
 using std::pair;
 
-MonoNote::MonoNote() :
-    hmm(0)
+MonoNote::MonoNote(bool fixedLag) :
+    m_fixedLag(fixedLag),
+    hmm(m_fixedLag ? 1000 : 0)
 {
 }
 
@@ -49,6 +50,7 @@
     // time.
 
     vector<int> path;
+    path.reserve(pitchProb.size());
     
     if (!pitchProb.empty()) {
 
@@ -56,13 +58,21 @@
         
         for (size_t iFrame = 1; iFrame < pitchProb.size(); ++iFrame)
         {
+            if (m_fixedLag && (int(iFrame) >= hmm.m_fixedLag)) 
+            {
+                vector<int> rawPath = hmm.track();
+                path.push_back(rawPath[0]);
+            }
+
             hmm.process(hmm.calculateObsProb(pitchProb[iFrame]));
         }
 
-        path = hmm.track();
+        vector<int> rawPath = hmm.track();
+        path.insert(path.end(), rawPath.begin(), rawPath.end());
     }
     
-    vector<MonoNote::FrameOutput> out; 
+    vector<MonoNote::FrameOutput> out;
+    out.reserve(path.size());
 
     for (size_t iFrame = 0; iFrame < path.size(); ++iFrame)
     {
--- a/MonoNote.h	Wed May 17 15:55:37 2017 +0100
+++ b/MonoNote.h	Wed May 17 16:29:43 2017 +0100
@@ -26,7 +26,7 @@
 
 class MonoNote {
 public:
-    MonoNote();
+    MonoNote(bool fixedLag);
     virtual ~MonoNote();
     
     struct FrameOutput {
@@ -39,7 +39,9 @@
     };
     // pitchProb is a frame-wise vector carrying a vector of pitch-probability pairs
     const vector<FrameOutput> process(const vector<vector<pair<double, double> > > pitchProb);
+
 private:
+    bool m_fixedLag;
     MonoNoteHMM hmm;
 };
 
--- a/PYinVamp.cpp	Wed May 17 15:55:37 2017 +0100
+++ b/PYinVamp.cpp	Wed May 17 16:29:43 2017 +0100
@@ -431,7 +431,7 @@
     m_yin.setFrameSize(m_blockSize);
     m_yin.setFast(!m_preciseTime);
 
-    if (m_fixedLag == 1.f) m_pitchHmm = MonoPitchHMM(100);
+    if (m_fixedLag > 0.5f) m_pitchHmm = MonoPitchHMM(100);
     else                   m_pitchHmm = MonoPitchHMM(0);
     
     m_pitchProb.clear();
@@ -494,7 +494,7 @@
 
     int lag = m_pitchHmm.m_fixedLag;
 
-    if (m_fixedLag == 1.f) // do fixed-lag smoothing instead of full Viterbi
+    if (m_fixedLag > 0.5f) // do fixed-lag smoothing instead of full Viterbi
     {
         if (int(m_timestamp.size()) == lag + 1)
         {
@@ -623,7 +623,16 @@
         smoothedPitch.push_back(temp);
     }
 
-    MonoNote mn;
+    // In fixed-lag mode, we use fixed-lag processing for the note
+    // transitions here as well as for the pitch transitions in
+    // process. The main reason we provide the fixed-lag option is so
+    // that we can get pitch results incrementally from process; we
+    // don't get that outcome here, but we do benefit from its bounded
+    // memory usage, which can be quite a big deal. So if the caller
+    // asked for it there, we use it here too. (It is a bit slower,
+    // but not much.)
+    
+    MonoNote mn(m_fixedLag > 0.5f);
     vector<MonoNote::FrameOutput> mnOut = mn.process(smoothedPitch);
 
     std::cerr << "mnOut size: " << mnOut.size() << std::endl;
--- a/test/TestMonoNote.cpp	Wed May 17 15:55:37 2017 +0100
+++ b/test/TestMonoNote.cpp	Wed May 17 16:29:43 2017 +0100
@@ -14,7 +14,7 @@
 
 BOOST_AUTO_TEST_CASE(instantiate)
 {
-    MonoNote mn;
+    MonoNote mn(false);
     vector<vector<pair<double, double> > > pitchProb;
     size_t n = 8;