changeset 170:2114b2545c27 finetune

Refactor to avoid allocating 300 EM objects at a time!
author Chris Cannam
date Wed, 21 May 2014 11:53:31 +0100
parents 192c4ba3de45
children 7c0ce480a7a4 9c6edc191f78
files src/Silvet.cpp src/Silvet.h
diffstat 2 files changed, 65 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/Silvet.cpp	Wed May 21 11:15:53 2014 +0100
+++ b/src/Silvet.cpp	Wed May 21 11:53:31 2014 +0100
@@ -33,6 +33,8 @@
 
 static int processingSampleRate = 44100;
 static int processingBPO = 60;
+
+//!!! todo: replace these two with values from instrument pack
 static int processingHeight = 545;
 static int processingNotes = 88;
 
@@ -382,52 +384,83 @@
     FeatureSet fs;
 
     if (filtered.empty()) return fs;
+    
+    const InstrumentPack &pack = m_instruments[m_instrument];
 
     int width = filtered.size();
 
     int iterations = m_hqMode ? 20 : 10;
 
-    vector<EM *> em(width, (EM *)0);
-    vector<double> sums(width, 0.0);
+    //!!! pitches or notes? [terminology]
+    Grid localPitches(width, vector<double>(processingNotes, 0.0));
+
+    bool wantShifts = m_hqMode && m_fineTuning;
+    int shiftCount = 1;
+    if (wantShifts) {
+        shiftCount = pack.templateMaxShift * 2 + 1;
+    }
+
+    vector<vector<int> > localBestShifts;
+    if (wantShifts) {
+        localBestShifts = 
+            vector<vector<int> >(width, vector<int>(processingNotes, 0));
+    }
+
+    vector<bool> present(width, false);
 
 #pragma omp parallel for
     for (int i = 0; i < width; ++i) {
 
+        double sum = 0.0;
         for (int j = 0; j < processingHeight; ++j) {
-            sums[i] += filtered.at(i).at(j);
+            sum += filtered.at(i).at(j);
+        }
+        if (sum < 1e-5) continue;
+
+        present[i] = true;
+
+        EM em(&pack, m_hqMode);
+
+        for (int j = 0; j < iterations; ++j) {
+            em.iterate(filtered.at(i).data());
         }
 
-        if (sums[i] < 1e-5) continue;
+        const float *pitchDist = em.getPitchDistribution();
+        const float *const *shiftDist = em.getShifts();
 
-        em[i] = new EM(&m_instruments[m_instrument], m_hqMode);
+        for (int j = 0; j < processingNotes; ++j) {
 
-        for (int j = 0; j < iterations; ++j) {
-            em[i]->iterate(filtered.at(i).data());
+            localPitches[i][j] = pitchDist[j] * sum;
+
+            int bestShift = 0;
+            int bestShiftValue = 0.0;
+            if (wantShifts) {
+                for (int k = 0; k < shiftCount; ++k) {
+                    if (k == 0 || shiftDist[k][j] > bestShiftValue) {
+                        bestShiftValue = shiftDist[k][j];
+                        bestShift = k;
+                    }
+                }
+                localBestShifts[i][j] = bestShift;
+            }                
         }
     }
-
-    int shiftCount = 1;
-
-    if (m_hqMode && m_fineTuning) {
-        shiftCount = m_instruments[m_instrument].templateMaxShift * 2 + 1;
-    }
         
     for (int i = 0; i < width; ++i) {
 
-        if (!em[i]) {
+        if (!present[i]) {
+            // silent column
+            for (int j = 0; j < processingNotes; ++j) {
+                m_postFilter[j]->push(0.0);
+            }
             m_pianoRoll.push_back(map<int, double>());
-            if (shiftCount > 1) {
+            if (wantShifts) {
                 m_pianoRollShifts.push_back(map<int, int>());
             }
             continue;
         }
 
-        postProcess(em[i]->getPitchDistribution(),
-                    em[i]->getShifts(),
-                    shiftCount,
-                    sums[i]);
-        
-        delete em[i];
+        postProcess(localPitches[i], localBestShifts[i], wantShifts);
         
         FeatureList noteFeatures = noteTrack(shiftCount);
 
@@ -508,15 +541,14 @@
 }
     
 void
-Silvet::postProcess(const float *pitches,
-                    const float *const *shifts,
-                    int shiftCount,
-                    double gain)
+Silvet::postProcess(const vector<double> &pitches,
+                    const vector<int> &bestShifts,
+                    bool wantShifts)
 {
     vector<double> filtered;
 
     for (int j = 0; j < processingNotes; ++j) {
-        m_postFilter[j]->push(pitches[j] * gain);
+        m_postFilter[j]->push(pitches[j]);
         filtered.push_back(m_postFilter[j]->get());
     }
 
@@ -533,10 +565,8 @@
     ValueIndexMap strengths;
 
     for (int j = 0; j < processingNotes; ++j) {
-
         double strength = filtered[j];
         if (strength < threshold) continue;
-
         strengths.insert(ValueIndexMap::value_type(strength, j));
     }
 
@@ -554,24 +584,14 @@
 
         active[j] = strength;
 
-        if (shiftCount > 1) {
-
-            // find preferred shift f for note j
-            int bestShift = 0;
-            float bestShiftValue = 0.f;
-            for (int f = 0; f < shiftCount; ++f) {
-                if (f == 0 || shifts[f][j] > bestShiftValue) {
-                    bestShiftValue = shifts[f][j];
-                    bestShift = f;
-                }
-            }
-
-            activeShifts[j] = bestShift;
+        if (wantShifts) {
+            activeShifts[j] = bestShifts[j];
         }
     }
 
     m_pianoRoll.push_back(active);
-    if (shiftCount > 1) {
+
+    if (wantShifts) {
         m_pianoRollShifts.push_back(activeShifts);
     }
 }
--- a/src/Silvet.h	Wed May 21 11:15:53 2014 +0100
+++ b/src/Silvet.h	Wed May 21 11:53:31 2014 +0100
@@ -89,10 +89,9 @@
 
     Grid preProcess(const Grid &);
 
-    void postProcess(const float *pitches,
-                     const float *const *shifts,
-                     int shiftCount,
-                     double gain); // -> piano roll column
+    void postProcess(const vector<double> &pitches,
+                     const vector<int> &bestShifts,
+                     bool wantShifts); // -> piano roll column
 
     FeatureList noteTrack(int shiftCount);