changeset 104:1e433aaa44ad

Merge mepd_new_params branch
author Chris Cannam
date Mon, 02 Sep 2013 09:26:46 +0100
parents 37449f085a4c (current diff) 941b28572da2 (diff)
children c32a2446f7fe
files dsp/tempotracking/TempoTrackV2.cpp
diffstat 3 files changed, 92 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/build/osx/Makefile.osx	Thu Jun 13 10:23:09 2013 +0100
+++ b/build/osx/Makefile.osx	Mon Sep 02 09:26:46 2013 +0100
@@ -1,5 +1,5 @@
 
-CFLAGS := -arch i386 -arch ppc -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -I/Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/ -DUSE_PTHREADS
+CFLAGS := -arch i386 -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.6.sdk -I/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/Headers/ -DUSE_PTHREADS
 
 CXXFLAGS  := $(CFLAGS)
 
--- a/dsp/tempotracking/TempoTrackV2.cpp	Thu Jun 13 10:23:09 2013 +0100
+++ b/dsp/tempotracking/TempoTrackV2.cpp	Mon Sep 02 09:26:46 2013 +0100
@@ -41,7 +41,7 @@
     b[0] = 0.2066;
     b[1] = 0.4131;
     b[2] = 0.2066;
-    
+
     double inp1 = 0.;
     double inp2 = 0.;
     double out1 = 0.;
@@ -67,7 +67,7 @@
 
     for (unsigned int i = 0;i < df.size();i++)
     {
-        lp_df[i] = 0.;    
+        lp_df[i] = 0.;
     }
 
     inp1 = 0.; inp2 = 0.;
@@ -91,10 +91,17 @@
 }
 
 
+// MEPD 28/11/12
+// This function now allows for a user to specify an inputtempo (in BPM)
+// and a flag "constraintempo" which replaces the general rayleigh weighting for periodicities
+// with a gaussian which is centered around the input tempo
+// Note, if inputtempo = 120 and constraintempo = false, then functionality is
+// as it was before
 void
 TempoTrackV2::calculateBeatPeriod(const vector<double> &df,
                                   vector<double> &beat_period,
-                                  vector<double> &tempi)
+                                  vector<double> &tempi,
+                                  double inputtempo, bool constraintempo)
 {
     // to follow matlab.. split into 512 sample frames with a 128 hop size
     // calculate the acf,
@@ -103,13 +110,42 @@
     // and get best path
 
     unsigned int wv_len = 128;
-    double rayparam = 43.;
+
+    // MEPD 28/11/12
+    // the default value of inputtempo in the beat tracking plugin is 120
+    // so if the user specifies a different inputtempo, the rayparam will be updated
+    // accordingly.
+    // note: 60*44100/512 is a magic number
+    // this might (will?) break if a user specifies a different frame rate for the onset detection function
+    double rayparam = (60*44100/512)/inputtempo;
+
+    // these debug statements can be removed.
+    std::cout << "inputtempo" << inputtempo << std::endl;
+    std::cout << "rayparam" << rayparam << std::endl;
+    std::cout << "constraintempo" << constraintempo << std::endl;
 
     // make rayleigh weighting curve
     d_vec_t wv(wv_len);
-    for (unsigned int i=0; i<wv.size(); i++)
+
+    // check whether or not to use rayleigh weighting (if constraintempo is false)
+    // or use gaussian weighting it (constraintempo is true)
+    if (constraintempo)
     {
-        wv[i] = (static_cast<double> (i) / pow(rayparam,2.)) * exp((-1.*pow(-static_cast<double> (i),2.)) / (2.*pow(rayparam,2.)));
+        for (unsigned int i=0; i<wv.size(); i++)
+        {
+            // MEPD 28/11/12
+            // do a gaussian weighting instead of rayleigh
+            wv[i] = exp( (-1.*pow((static_cast<double> (i)-rayparam),2.)) / (2.*pow(rayparam/4.,2.)) );
+        }
+    }
+    else
+    {
+        for (unsigned int i=0; i<wv.size(); i++)
+        {
+            // MEPD 28/11/12
+            // standard rayleigh weighting over periodicities
+            wv[i] = (static_cast<double> (i) / pow(rayparam,2.)) * exp((-1.*pow(-static_cast<double> (i),2.)) / (2.*pow(rayparam,2.)));
+        }
     }
 
     // beat tracking frame size (roughly 6 seconds) and hop (1.5 seconds)
@@ -130,9 +166,9 @@
             dfframe[k] = df[i+k];
         }
         // get rcf vector for current frame
-        d_vec_t rcf(wv_len);    
+        d_vec_t rcf(wv_len);
         get_rcf(dfframe,wv,rcf);
-  
+
         rcfmat.push_back( d_vec_t() ); // adds a new column
         col_counter++;
         for (unsigned int j=0; j<rcf.size(); j++)
@@ -140,7 +176,7 @@
             rcfmat[col_counter].push_back( rcf[j] );
         }
     }
-  
+
     // now call viterbi decoding function
     viterbi_decode(rcfmat,wv,beat_period,tempi);
 }
@@ -161,7 +197,7 @@
 
     d_vec_t acf(dfframe.size());
 
-    
+
     for (unsigned int lag=0; lag<dfframe.size(); lag++)
     {
         double sum = 0.;
@@ -169,7 +205,7 @@
 
         for (unsigned int n=0; n<(dfframe.size()-lag); n++)
         {
-            tmp = dfframe[n] * dfframe[n+lag];    
+            tmp = dfframe[n] * dfframe[n+lag];
             sum += tmp;
         }
         acf[lag] = static_cast<double> (sum/ (dfframe.size()-lag));
@@ -177,7 +213,7 @@
 
     // now apply comb filtering
     int numelem = 4;
-	
+
     for (unsigned int i = 2;i < rcf.size();i++) // max beat period
     {
         for (int a = 1;a <= numelem;a++) // number of comb elements
@@ -188,10 +224,10 @@
             }
         }
     }
-  
+
     // apply adaptive threshold to rcf
     MathUtilities::adaptiveThreshold(rcf);
-  
+
     double rcfsum =0.;
     for (unsigned int i=0; i<rcf.size(); i++)
     {
@@ -218,11 +254,11 @@
     {
         tmat.push_back ( d_vec_t() ); // adds a new column
         for (unsigned int j=0; j<wv.size(); j++)
-        {	
+        {
             tmat[i].push_back(0.); // fill with zeros initially
         }
     }
-    
+
     // variance of Gaussians in transition matrix
     // formed of Gaussians on diagonal - implies slow tempo change
     double sigma = 8.;
@@ -230,7 +266,7 @@
     for (unsigned int i=20;i <wv.size()-20; i++)
     {
         for (unsigned int j=20; j<wv.size()-20; j++)
-        {	
+        {
             double mu = static_cast<double>(i);
             tmat[i][j] = exp( (-1.*pow((j-mu),2.)) / (2.*pow(sigma,2.)) );
         }
@@ -246,7 +282,7 @@
         delta.push_back( d_vec_t());
         psi.push_back( i_vec_t());
         for (unsigned int j=0; j<rcfmat[i].size(); j++)
-        {	
+        {
             delta[i].push_back(0.); // fill with zeros initially
             psi[i].push_back(0); // fill with zeros initially
         }
@@ -265,16 +301,16 @@
         delta[0][j] = wv[j] * rcfmat[0][j];
         psi[0][j] = 0;
     }
-    
+
     double deltasum = 0.;
     for (unsigned int i=0; i<Q; i++)
     {
         deltasum += delta[0][i];
-    }      
+    }
     for (unsigned int i=0; i<Q; i++)
     {
         delta[0][i] /= (deltasum + EPS);
-    }      
+    }
 
 
     for (unsigned int t=1; t<T; t++)
@@ -286,12 +322,12 @@
             for (unsigned int i=0; i<Q; i++)
             {
                 tmp_vec[i] = delta[t-1][i] * tmat[j][i];
-            }      
-   
-            delta[t][j] = get_max_val(tmp_vec);    
+            }
+
+            delta[t][j] = get_max_val(tmp_vec);
 
             psi[t][j] = get_max_ind(tmp_vec);
- 
+
             delta[t][j] *= rcfmat[t][j];
         }
 
@@ -300,23 +336,23 @@
         for (unsigned int i=0; i<Q; i++)
         {
             deltasum += delta[t][i];
-        }      
+        }
         for (unsigned int i=0; i<Q; i++)
         {
             delta[t][i] /= (deltasum + EPS);
-        }      
+        }
     }
 
     i_vec_t bestpath(T);
     d_vec_t tmp_vec(Q);
     for (unsigned int i=0; i<Q; i++)
-    {  
+    {
         tmp_vec[i] = delta[T-1][i];
     }
 
     // find starting point - best beat period for "last" frame
     bestpath[T-1] = get_max_ind(tmp_vec);
- 
+
     // backtrace through index of maximum values in psi
     for (unsigned int t=T-2; t>0 ;t--)
     {
@@ -328,7 +364,7 @@
 
     unsigned int lastind = 0;
     for (unsigned int i=0; i<T; i++)
-    {  
+    {
         unsigned int step = 128;
         for (unsigned int j=0; j<step; j++)
         {
@@ -361,7 +397,7 @@
             maxval = df[i];
         }
     }
-    
+
     return maxval;
 }
 
@@ -378,7 +414,7 @@
             ind = i;
         }
     }
-    
+
     return ind;
 }
 
@@ -390,17 +426,21 @@
     {
         sum += df[i];
     }
-    
+
     for (unsigned int i=0; i<df.size(); i++)
     {
         df[i]/= (sum + EPS);
     }
 }
 
+// MEPD 28/11/12
+// this function has been updated to allow the "alpha" and "tightness" parameters
+// of the dynamic program to be set by the user
+// the default value of alpha = 0.9 and tightness = 4
 void
 TempoTrackV2::calculateBeats(const vector<double> &df,
                              const vector<double> &beat_period,
-                             vector<double> &beats)
+                             vector<double> &beats, double alpha, double tightness)
 {
     if (df.empty() || beat_period.empty()) return;
 
@@ -414,8 +454,12 @@
         backlink[i] = -1;
     }
 
-    double tightness = 4.;
-    double alpha = 0.9;
+    //double tightness = 4.;
+    //double alpha = 0.9;
+    // MEPD 28/11/12
+    // debug statements that can be removed.
+    std::cout << "alpha" << alpha << std::endl;
+    std::cout << "tightness" << tightness << std::endl;
 
     // main loop
     for (unsigned int i=0; i<localscore.size(); i++)
@@ -436,7 +480,7 @@
             // ELSE LEAVE AT DEFAULT VALUE FROM INITIALISATION:  D_VEC_T SCORECANDS (TXWT.SIZE());
 
             int cscore_ind = i+prange_min+j;
-            if (cscore_ind >= 0)   
+            if (cscore_ind >= 0)
             {
                 scorecands[j] = txwt[j] * cumscore[cscore_ind];
             }
@@ -457,7 +501,7 @@
     for (unsigned int i=cumscore.size() - beat_period[beat_period.size()-1] ; i<cumscore.size(); i++)
     {
         tmp_vec.push_back(cumscore[i]);
-    }  
+    }
 
     int startpoint = get_max_ind(tmp_vec) + cumscore.size() - beat_period[beat_period.size()-1] ;
 
@@ -476,10 +520,10 @@
         if (backlink[b] == b) break; // shouldn't happen... haha
         ibeats.push_back(backlink[b]);
     }
-  
+
     // REVERSE SEQUENCE OF IBEATS AND STORE AS BEATS
     for (unsigned int i=0; i<ibeats.size(); i++)
-    { 
+    {
         beats.push_back( static_cast<double>(ibeats[ibeats.size()-i-1]) );
     }
 }
--- a/dsp/tempotracking/TempoTrackV2.h	Thu Jun 13 10:23:09 2013 +0100
+++ b/dsp/tempotracking/TempoTrackV2.h	Mon Sep 02 09:26:46 2013 +0100
@@ -18,16 +18,14 @@
 #define TEMPOTRACKV2_H
 
 #include <vector>
-#include <cstddef>
-
-using std::vector;
+using namespace std;
 
 //!!! Question: how far is this actually sample rate dependent?  I
 // think it does produce plausible results for e.g. 48000 as well as
 // 44100, but surely the fixed window sizes and comb filtering will
 // make it prefer double or half time when run at e.g. 96000?
 
-class TempoTrackV2  
+class TempoTrackV2
 {
 public:
     /**
@@ -41,15 +39,17 @@
     TempoTrackV2(float sampleRate, size_t dfIncrement);
     ~TempoTrackV2();
 
-    // Returned beat periods are given in df increment units; tempi in bpm
+    // Returned beat periods are given in df increment units; inputtempo and tempi in bpm
+    // MEPD 28/11/12 Expose inputtempo and constraintempo parameters
     void calculateBeatPeriod(const vector<double> &df,
                              vector<double> &beatPeriod,
-                             vector<double> &tempi);
+                             vector<double> &tempi, double inputtempo, bool constraintempo);
 
     // Returned beat positions are given in df increment units
+    // MEPD 28/11/12 Expose alpha and tightness parameters
     void calculateBeats(const vector<double> &df,
                         const vector<double> &beatPeriod,
-                        vector<double> &beats);
+                        vector<double> &beats, double alpha, double tightness);
 
 private:
     typedef vector<int> i_vec_t;