changeset 82:e8ceb7d3bd4f matthiasm-plugin

merge
author Matthias Mauch <mail@matthiasmauch.net>
date Mon, 15 Nov 2010 11:01:56 +0900
parents 4270f3039ab0 (diff) f50f701df33e (current diff)
children 3277f6cef3fe fc28c50caace
files NNLSChroma.cpp
diffstat 7 files changed, 624 insertions(+), 601 deletions(-) [+]
line wrap: on
line diff
--- a/Chordino.cpp	Mon Nov 15 09:23:49 2010 +0900
+++ b/Chordino.cpp	Mon Nov 15 11:01:56 2010 +0900
@@ -246,12 +246,16 @@
          calculate tuning from (using the angle of the complex number defined by the 
          cumulative mean real and imag values)
     **/
-    float meanTuningImag = sinvalue * m_meanTuning1 - sinvalue * m_meanTuning2;
-    float meanTuningReal = m_meanTuning0 + cosvalue * m_meanTuning1 + cosvalue * m_meanTuning2;
+    float meanTuningImag = 0;
+    float meanTuningReal = 0;
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        meanTuningReal += m_meanTunings[iBPS] * cosvalues[iBPS];
+        meanTuningImag += m_meanTunings[iBPS] * sinvalues[iBPS];
+    }
     float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI));
     float normalisedtuning = atan2(meanTuningImag, meanTuningReal)/(2*M_PI);
     int intShift = floor(normalisedtuning * 3);
-    float intFactor = normalisedtuning * 3 - intShift; // intFactor is a really bad name for this
+    float floatShift = normalisedtuning * 3 - intShift; // floatShift is a really bad name for this
 		    
     char buffer0 [50];
 		
@@ -285,13 +289,13 @@
 		
         if (m_tuneLocal) {
             intShift = floor(m_localTuning[count] * 3);
-            intFactor = m_localTuning[count] * 3 - intShift; // intFactor is a really bad name for this
+            floatShift = m_localTuning[count] * 3 - intShift; // floatShift is a really bad name for this
         }
 		        
-        // cerr << intShift << " " << intFactor << endl;
+        // cerr << intShift << " " << floatShift << endl;
 		        
         for (unsigned k = 2; k < currentLogSpectum.values.size() - 3; ++k) { // interpolate all inner bins
-            tempValue = currentLogSpectum.values[k + intShift] * (1-intFactor) + currentLogSpectum.values[k+intShift+1] * intFactor;
+            tempValue = currentLogSpectum.values[k + intShift] * (1-floatShift) + currentLogSpectum.values[k+intShift+1] * floatShift;
             currentTunedSpec.values.push_back(tempValue);
         }
 		        
@@ -370,11 +374,11 @@
 			
         if (some_b_greater_zero) {
             if (m_useNNLS == 0) {
-                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
+                for (unsigned iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
                     currval = 0;
-                    currval += b[iNote + 1 + -1] * 0.5;
-                    currval += b[iNote + 1 +  0] * 1.0; 
-                    currval += b[iNote + 1 +  1] * 0.5; 
+                    for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) {
+                        currval += b[iNote + iBPS] * (1-abs(iBPS*1.0/(nBPS/2+1)));						
+                    }
                     chroma[iSemitone % 12] += currval * treblewindow[iSemitone];
                     basschroma[iSemitone % 12] += currval * basswindow[iSemitone];
                     iSemitone++;
@@ -386,11 +390,11 @@
                 vector<int> signifIndex;
                 int index=0;
                 sumb /= 84.0;
-                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
+                for (unsigned iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
                     float currval = 0;
-                    currval += b[iNote + 1 + -1];						
-                    currval += b[iNote + 1 +  0];						
-                    currval += b[iNote + 1 +  1];
+                    for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) {
+                        currval += b[iNote + iBPS]; 
+                    }
                     if (currval > 0) signifIndex.push_back(index);
                     index++;
                 }
@@ -400,6 +404,7 @@
                 int indx[84+1000];
                 int mode;
                 int dictsize = nNote*signifIndex.size();
+                // cerr << "dictsize is " << dictsize << "and values size" << f3.values.size()<< endl;
                 float *curr_dict = new float[dictsize];
                 for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
                     for (unsigned iBin = 0; iBin < nNote; iBin++) {
--- a/NNLSBase.cpp	Mon Nov 15 09:23:49 2010 +0900
+++ b/NNLSBase.cpp	Mon Nov 15 11:01:56 2010 +0900
@@ -34,12 +34,8 @@
     m_blockSize(0),
     m_stepSize(0),
     m_lengthOfNoteIndex(0),
-    m_meanTuning0(0),
-    m_meanTuning1(0),
-    m_meanTuning2(0),
-    m_localTuning0(0),
-    m_localTuning1(0),
-    m_localTuning2(0),
+    m_meanTunings(0),
+    m_localTunings(0),
     m_whitening(1.0),
     m_preset(0.0),
     m_localTuning(0),
@@ -54,7 +50,9 @@
     m_rollon(0),
 	m_s(0.7),
 	m_useNNLS(1),
-	m_useHMM(1)
+	m_useHMM(1),
+	sinvalues(0),
+	cosvalues(0)
 {
     if (debug_on) cerr << "--> NNLSBase" << endl;
 
@@ -352,6 +350,14 @@
         cerr << "--> initialise";
     }
 	
+	// make things for tuning estimation
+	for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        sinvalues.push_back(sin(2*M_PI*(iBPS*1.0/nBPS)));
+        cosvalues.push_back(cos(2*M_PI*(iBPS*1.0/nBPS)));
+    }
+    
+	
+	// make hamming window of length 1/2 octave
 	int hamwinlength = nBPS * 6 + 1;
     float hamwinsum = 0;
     for (int i = 0; i < hamwinlength; ++i) { 
@@ -359,6 +365,13 @@
         hamwinsum += 0.54 - 0.46 * cos((2*M_PI*i)/(hamwinlength-1));
     }
     for (int i = 0; i < hamwinlength; ++i) hw[i] = hw[i] / hamwinsum;
+    
+    
+    // initialise the tuning
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        m_meanTunings.push_back(0);
+        m_localTunings.push_back(0);
+    }
 	
     if (channels < getMinChannelCount() ||
 	channels > getMaxChannelCount()) return false;
@@ -411,12 +424,10 @@
     m_frameCount = 0;
     // m_dictID = 0;
     m_logSpectrum.clear();
-    m_meanTuning0 = 0;
-    m_meanTuning1 = 0;
-    m_meanTuning2 = 0;
-    m_localTuning0 = 0;
-    m_localTuning1 = 0;
-    m_localTuning2 = 0;
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        m_meanTunings[iBPS] = 0;
+        m_localTunings[iBPS] = 0;
+    }
     m_localTuning.clear();
 }
 
@@ -473,24 +484,28 @@
 	
     float one_over_N = 1.0/m_frameCount;
     // update means of complex tuning variables
-    m_meanTuning0 *= float(m_frameCount-1)*one_over_N;
-    m_meanTuning1 *= float(m_frameCount-1)*one_over_N;
-    m_meanTuning2 *= float(m_frameCount-1)*one_over_N;
-	
-    for (int iTone = 0; iTone < 160; iTone = iTone + 3) {
-        m_meanTuning0 += nm[iTone + 0]*one_over_N;
-    	m_meanTuning1 += nm[iTone + 1]*one_over_N;
-    	m_meanTuning2 += nm[iTone + 2]*one_over_N;
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) m_meanTunings[iBPS] *= float(m_frameCount-1)*one_over_N;
+    
+    for (int iTone = 0; iTone < round(nNote*0.62/nBPS)*nBPS+1; iTone = iTone + nBPS) {
+        for (int iBPS = 0; iBPS < nBPS; ++iBPS) m_meanTunings[iBPS] += nm[iTone + iBPS]*one_over_N;
         float ratioOld = 0.997;
-        m_localTuning0 *= ratioOld; m_localTuning0 += nm[iTone + 0] * (1 - ratioOld);
-        m_localTuning1 *= ratioOld; m_localTuning1 += nm[iTone + 1] * (1 - ratioOld);
-        m_localTuning2 *= ratioOld; m_localTuning2 += nm[iTone + 2] * (1 - ratioOld);
+        for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+            m_localTunings[iBPS] *= ratioOld; 
+            m_localTunings[iBPS] += nm[iTone + iBPS] * (1 - ratioOld);
+        }
     }
-	
     // if (m_tuneLocal) {
     // local tuning
-    float localTuningImag = sinvalue * m_localTuning1 - sinvalue * m_localTuning2;
-    float localTuningReal = m_localTuning0 + cosvalue * m_localTuning1 + cosvalue * m_localTuning2;
+    // float localTuningImag = sinvalue * m_localTunings[1] - sinvalue * m_localTunings[2];
+    // float localTuningReal = m_localTunings[0] + cosvalue * m_localTunings[1] + cosvalue * m_localTunings[2];
+    
+    float localTuningImag = 0;
+    float localTuningReal = 0;
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        localTuningReal += m_localTunings[iBPS] * cosvalues[iBPS];
+        localTuningImag += m_localTunings[iBPS] * sinvalues[iBPS];
+    }
+    
     float normalisedtuning = atan2(localTuningImag, localTuningReal)/(2*M_PI);
     m_localTuning.push_back(normalisedtuning);
     
@@ -514,526 +529,526 @@
 NNLSBase::FeatureSet
 NNLSBase::getRemainingFeatures()
 {
-    if (debug_on) cerr << "--> getRemainingFeatures" << endl;
-    FeatureSet fsOut;
-    if (m_logSpectrum.size() == 0) return fsOut;
-    int nChord = m_chordnames.size();
+    // if (debug_on) cerr << "--> getRemainingFeatures" << endl;
+       FeatureSet fsOut;
+    //    if (m_logSpectrum.size() == 0) return fsOut;
+    //    int nChord = m_chordnames.size();
+    //    // 
+    //    /**  Calculate Tuning
+    //         calculate tuning from (using the angle of the complex number defined by the 
+    //         cumulative mean real and imag values)
+    //    **/
+    //    float meanTuningImag = sinvalue * m_meanTunings[1] - sinvalue * m_meanTunings[2];
+    //    float meanTuningReal = m_meanTunings[0] + cosvalue * m_meanTunings[1] + cosvalue * m_meanTunings[2];
+    //    float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI));
+    //    float normalisedtuning = atan2(meanTuningImag, meanTuningReal)/(2*M_PI);
+    //    int intShift = floor(normalisedtuning * 3);
+    //    float floatShift = normalisedtuning * 3 - intShift; // floatShift is a really bad name for this
+    //          
+    //    char buffer0 [50];
+    //      
+    //    sprintf(buffer0, "estimated tuning: %0.1f Hz", cumulativetuning);
+    //          
+    //    // cerr << "normalisedtuning: " << normalisedtuning << '\n';
+    //          
+    //    // push tuning to FeatureSet fsOut
+    //    Feature f0; // tuning
+    //    f0.hasTimestamp = true;
+    //    f0.timestamp = Vamp::RealTime::frame2RealTime(0, lrintf(m_inputSampleRate));;
+    //    f0.label = buffer0;
+    //    fsOut[0].push_back(f0);  
+    //          
+    //    /** Tune Log-Frequency Spectrogram
+    //        calculate a tuned log-frequency spectrogram (f2): use the tuning estimated above (kinda f0) to 
+    //        perform linear interpolation on the existing log-frequency spectrogram (kinda f1).
+    //    **/
+    //    cerr << endl << "[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... ";
+    //                  
+    //    float tempValue = 0;
+    //    float dbThreshold = 0; // relative to the background spectrum
+    //    float thresh = pow(10,dbThreshold/20);
+    //    // cerr << "tune local ? " << m_tuneLocal << endl;
+    //    int count = 0;
+    //      
+    //    for (FeatureList::iterator i = m_logSpectrum.begin(); i != m_logSpectrum.end(); ++i) {
+    //        Feature f1 = *i;
+    //        Feature f2; // tuned log-frequency spectrum
+    //        f2.hasTimestamp = true;
+    //        f2.timestamp = f1.timestamp;
+    //        f2.values.push_back(0.0); f2.values.push_back(0.0); // set lower edge to zero
+    //      
+    //        if (m_tuneLocal == 1.0) {
+    //            intShift = floor(m_localTuning[count] * 3);
+    //            floatShift = m_localTuning[count] * 3 - intShift; // floatShift is a really bad name for this
+    //        }
+    //              
+    //        // cerr << intShift << " " << floatShift << endl;
+    //              
+    //        for (unsigned k = 2; k < f1.values.size() - 3; ++k) { // interpolate all inner bins
+    //            tempValue = f1.values[k + intShift] * (1-floatShift) + f1.values[k+intShift+1] * floatShift;
+    //            f2.values.push_back(tempValue);
+    //        }
+    //              
+    //        f2.values.push_back(0.0); f2.values.push_back(0.0); f2.values.push_back(0.0); // upper edge
+    //        vector<float> runningmean = SpecialConvolution(f2.values,hw);
+    //        vector<float> runningstd;
+    //        for (int i = 0; i < nNote; i++) { // first step: squared values into vector (variance)
+    //            runningstd.push_back((f2.values[i] - runningmean[i]) * (f2.values[i] - runningmean[i]));
+    //        }
+    //        runningstd = SpecialConvolution(runningstd,hw); // second step convolve
+    //        for (int i = 0; i < nNote; i++) { 
+    //            runningstd[i] = sqrt(runningstd[i]); // square root to finally have running std
+    //            if (runningstd[i] > 0) {
+    //                // f2.values[i] = (f2.values[i] / runningmean[i]) > thresh ? 
+    //                //                            (f2.values[i] - runningmean[i]) / pow(runningstd[i],m_whitening) : 0;
+    //                f2.values[i] = (f2.values[i] - runningmean[i]) > 0 ?
+    //                    (f2.values[i] - runningmean[i]) / pow(runningstd[i],m_whitening) : 0;
+    //            }
+    //            if (f2.values[i] < 0) {
+    //                cerr << "ERROR: negative value in logfreq spectrum" << endl;
+    //            }
+    //        }
+    //        fsOut[2].push_back(f2);
+    //        count++;
+    //    }
+    //    cerr << "done." << endl;
+    //      
+    //    /** Semitone spectrum and chromagrams
+    //        Semitone-spaced log-frequency spectrum derived from the tuned log-freq spectrum above. the spectrum
+    //        is inferred using a non-negative least squares algorithm.
+    //        Three different kinds of chromagram are calculated, "treble", "bass", and "both" (which means 
+    //        bass and treble stacked onto each other).
+    //    **/
+    //    if (m_useNNLS == 0) {
+    //        cerr << "[NNLS Chroma Plugin] Mapping to semitone spectrum and chroma ... ";
+    //    } else {
+    //        cerr << "[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... ";
+    //    }
     // 
-    /**  Calculate Tuning
-         calculate tuning from (using the angle of the complex number defined by the 
-         cumulative mean real and imag values)
-    **/
-    float meanTuningImag = sinvalue * m_meanTuning1 - sinvalue * m_meanTuning2;
-    float meanTuningReal = m_meanTuning0 + cosvalue * m_meanTuning1 + cosvalue * m_meanTuning2;
-    float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI));
-    float normalisedtuning = atan2(meanTuningImag, meanTuningReal)/(2*M_PI);
-    int intShift = floor(normalisedtuning * 3);
-    float intFactor = normalisedtuning * 3 - intShift; // intFactor is a really bad name for this
-		    
-    char buffer0 [50];
-		
-    sprintf(buffer0, "estimated tuning: %0.1f Hz", cumulativetuning);
-		    
-    // cerr << "normalisedtuning: " << normalisedtuning << '\n';
-		    
-    // push tuning to FeatureSet fsOut
-    Feature f0; // tuning
-    f0.hasTimestamp = true;
-    f0.timestamp = Vamp::RealTime::frame2RealTime(0, lrintf(m_inputSampleRate));;
-    f0.label = buffer0;
-    fsOut[0].push_back(f0);  
-		    
-    /** Tune Log-Frequency Spectrogram
-        calculate a tuned log-frequency spectrogram (f2): use the tuning estimated above (kinda f0) to 
-        perform linear interpolation on the existing log-frequency spectrogram (kinda f1).
-    **/
-    cerr << endl << "[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... ";
-					
-    float tempValue = 0;
-    float dbThreshold = 0; // relative to the background spectrum
-    float thresh = pow(10,dbThreshold/20);
-    // cerr << "tune local ? " << m_tuneLocal << endl;
-    int count = 0;
-		
-    for (FeatureList::iterator i = m_logSpectrum.begin(); i != m_logSpectrum.end(); ++i) {
-        Feature f1 = *i;
-        Feature f2; // tuned log-frequency spectrum
-        f2.hasTimestamp = true;
-        f2.timestamp = f1.timestamp;
-        f2.values.push_back(0.0); f2.values.push_back(0.0); // set lower edge to zero
-		
-        if (m_tuneLocal == 1.0) {
-            intShift = floor(m_localTuning[count] * 3);
-            intFactor = m_localTuning[count] * 3 - intShift; // intFactor is a really bad name for this
-        }
-		        
-        // cerr << intShift << " " << intFactor << endl;
-		        
-        for (unsigned k = 2; k < f1.values.size() - 3; ++k) { // interpolate all inner bins
-            tempValue = f1.values[k + intShift] * (1-intFactor) + f1.values[k+intShift+1] * intFactor;
-            f2.values.push_back(tempValue);
-        }
-		        
-        f2.values.push_back(0.0); f2.values.push_back(0.0); f2.values.push_back(0.0); // upper edge
-        vector<float> runningmean = SpecialConvolution(f2.values,hw);
-        vector<float> runningstd;
-        for (int i = 0; i < nNote; i++) { // first step: squared values into vector (variance)
-            runningstd.push_back((f2.values[i] - runningmean[i]) * (f2.values[i] - runningmean[i]));
-        }
-        runningstd = SpecialConvolution(runningstd,hw); // second step convolve
-        for (int i = 0; i < nNote; i++) { 
-            runningstd[i] = sqrt(runningstd[i]); // square root to finally have running std
-            if (runningstd[i] > 0) {
-                // f2.values[i] = (f2.values[i] / runningmean[i]) > thresh ? 
-                // 		                    (f2.values[i] - runningmean[i]) / pow(runningstd[i],m_whitening) : 0;
-                f2.values[i] = (f2.values[i] - runningmean[i]) > 0 ?
-                    (f2.values[i] - runningmean[i]) / pow(runningstd[i],m_whitening) : 0;
-            }
-            if (f2.values[i] < 0) {
-                cerr << "ERROR: negative value in logfreq spectrum" << endl;
-            }
-        }
-        fsOut[2].push_back(f2);
-        count++;
-    }
-    cerr << "done." << endl;
-	    
-    /** Semitone spectrum and chromagrams
-        Semitone-spaced log-frequency spectrum derived from the tuned log-freq spectrum above. the spectrum
-        is inferred using a non-negative least squares algorithm.
-        Three different kinds of chromagram are calculated, "treble", "bass", and "both" (which means 
-        bass and treble stacked onto each other).
-    **/
-    if (m_useNNLS == 0) {
-        cerr << "[NNLS Chroma Plugin] Mapping to semitone spectrum and chroma ... ";
-    } else {
-        cerr << "[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... ";
-    }
-
-	    
-    vector<vector<float> > chordogram;
-    vector<vector<int> > scoreChordogram;
-    vector<float> chordchange = vector<float>(fsOut[2].size(),0);
-    vector<float> oldchroma = vector<float>(12,0);
-    vector<float> oldbasschroma = vector<float>(12,0);
-    count = 0;
-
-    for (FeatureList::iterator it = fsOut[2].begin(); it != fsOut[2].end(); ++it) {
-        Feature f2 = *it; // logfreq spectrum
-        Feature f3; // semitone spectrum
-        Feature f4; // treble chromagram
-        Feature f5; // bass chromagram
-        Feature f6; // treble and bass chromagram
-	
-        f3.hasTimestamp = true;
-        f3.timestamp = f2.timestamp;
-	        
-        f4.hasTimestamp = true;
-        f4.timestamp = f2.timestamp;
-	        
-        f5.hasTimestamp = true;
-        f5.timestamp = f2.timestamp;
-	        
-        f6.hasTimestamp = true;
-        f6.timestamp = f2.timestamp;
-	        
-			float b[nNote];
-	
-        bool some_b_greater_zero = false;
-        float sumb = 0;
-        for (int i = 0; i < nNote; i++) {
-            // b[i] = m_dict[(nNote * count + i) % (nNote * 84)];
-            b[i] = f2.values[i];
-            sumb += b[i];
-            if (b[i] > 0) {
-                some_b_greater_zero = true;
-            }            
-        }
-	    
-        // here's where the non-negative least squares algorithm calculates the note activation x
-	
-        vector<float> chroma = vector<float>(12, 0);
-        vector<float> basschroma = vector<float>(12, 0);
-        float currval;
-        unsigned iSemitone = 0;
-			
-        if (some_b_greater_zero) {
-            if (m_useNNLS == 0) {
-                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
-                    currval = 0;
-                    currval += b[iNote + 1 + -1] * 0.5;						
-                    currval += b[iNote + 1 +  0] * 1.0;						
-                    currval += b[iNote + 1 +  1] * 0.5;						
-                    f3.values.push_back(currval);
-                    chroma[iSemitone % 12] += currval * treblewindow[iSemitone];
-                    basschroma[iSemitone % 12] += currval * basswindow[iSemitone];
-                    iSemitone++;
-                }
-		        
-            } else {
-					float x[84+1000];
-                for (int i = 1; i < 1084; ++i) x[i] = 1.0;
-                vector<int> signifIndex;
-                int index=0;
-                sumb /= 84.0;
-                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
-                    float currval = 0;
-                    currval += b[iNote + 1 + -1];						
-                    currval += b[iNote + 1 +  0];						
-                    currval += b[iNote + 1 +  1];
-                    if (currval > 0) signifIndex.push_back(index);
-                    f3.values.push_back(0); // fill the values, change later
-                    index++;
-                }
-				    float rnorm;
-				    float w[84+1000];
-				    float zz[84+1000];
-                int indx[84+1000];
-                int mode;
-                int dictsize = nNote*signifIndex.size();
-                // cerr << "dictsize is " << dictsize << "and values size" << f3.values.size()<< endl;
-					float *curr_dict = new float[dictsize];
-                for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
-                    for (unsigned iBin = 0; iBin < nNote; iBin++) {
-                        curr_dict[iNote * nNote + iBin] = 1.0 * m_dict[signifIndex[iNote] * nNote + iBin];
-                    }
-                }
-					nnls(curr_dict, nNote, nNote, signifIndex.size(), b, x, &rnorm, w, zz, indx, &mode);
-                delete [] curr_dict;
-                for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
-                    f3.values[signifIndex[iNote]] = x[iNote];
-                    // cerr << mode << endl;
-                    chroma[signifIndex[iNote] % 12] += x[iNote] * treblewindow[signifIndex[iNote]];
-                    basschroma[signifIndex[iNote] % 12] += x[iNote] * basswindow[signifIndex[iNote]];
-                }
-            }	
-        }
-			
-            
-	        
-			
-        f4.values = chroma; 
-        f5.values = basschroma;
-        chroma.insert(chroma.begin(), basschroma.begin(), basschroma.end()); // just stack the both chromas 
-        f6.values = chroma; 
-	        
-        if (m_doNormalizeChroma > 0) {
-            vector<float> chromanorm = vector<float>(3,0);			
-            switch (int(m_doNormalizeChroma)) {
-            case 0: // should never end up here
-                break;
-            case 1:
-                chromanorm[0] = *max_element(f4.values.begin(), f4.values.end());
-                chromanorm[1] = *max_element(f5.values.begin(), f5.values.end());
-                chromanorm[2] = max(chromanorm[0], chromanorm[1]);
-                break;
-            case 2:
-                for (vector<float>::iterator it = f4.values.begin(); it != f4.values.end(); ++it) {
-                    chromanorm[0] += *it; 						
-                }
-                for (vector<float>::iterator it = f5.values.begin(); it != f5.values.end(); ++it) {
-                    chromanorm[1] += *it; 						
-                }
-                for (vector<float>::iterator it = f6.values.begin(); it != f6.values.end(); ++it) {
-                    chromanorm[2] += *it; 						
-                }
-                break;
-            case 3:
-                for (vector<float>::iterator it = f4.values.begin(); it != f4.values.end(); ++it) {
-                    chromanorm[0] += pow(*it,2); 						
-                }
-                chromanorm[0] = sqrt(chromanorm[0]);
-                for (vector<float>::iterator it = f5.values.begin(); it != f5.values.end(); ++it) {
-                    chromanorm[1] += pow(*it,2); 						
-                }
-                chromanorm[1] = sqrt(chromanorm[1]);
-                for (vector<float>::iterator it = f6.values.begin(); it != f6.values.end(); ++it) {
-                    chromanorm[2] += pow(*it,2); 						
-                }
-                chromanorm[2] = sqrt(chromanorm[2]);
-                break;
-            }
-            if (chromanorm[0] > 0) {
-                for (int i = 0; i < f4.values.size(); i++) {
-                    f4.values[i] /= chromanorm[0];
-                }
-            }
-            if (chromanorm[1] > 0) {
-                for (int i = 0; i < f5.values.size(); i++) {
-                    f5.values[i] /= chromanorm[1];
-                }
-            }
-            if (chromanorm[2] > 0) {
-                for (int i = 0; i < f6.values.size(); i++) {
-                    f6.values[i] /= chromanorm[2];
-                }
-            }
-				
-        }
-	
-        // local chord estimation
-        vector<float> currentChordSalience;
-        float tempchordvalue = 0;
-        float sumchordvalue = 0;
-	        
-        for (int iChord = 0; iChord < nChord; iChord++) {
-            tempchordvalue = 0;
-            for (int iBin = 0; iBin < 12; iBin++) {
-                tempchordvalue += m_chorddict[24 * iChord + iBin] * chroma[iBin];
-            }
-            for (int iBin = 12; iBin < 24; iBin++) {
-                tempchordvalue += m_chorddict[24 * iChord + iBin] * chroma[iBin];
-            }
-            sumchordvalue+=tempchordvalue;
-            currentChordSalience.push_back(tempchordvalue);
-        }
-        if (sumchordvalue > 0) {
-            for (int iChord = 0; iChord < nChord; iChord++) {
-                currentChordSalience[iChord] /= sumchordvalue;
-            }
-        } else {
-            currentChordSalience[nChord-1] = 1.0;
-        }
-        chordogram.push_back(currentChordSalience);
-	        
-        fsOut[3].push_back(f3);
-        fsOut[4].push_back(f4);
-        fsOut[5].push_back(f5);
-        fsOut[6].push_back(f6);
-        count++;
-    }
-    cerr << "done." << endl;
-		
-
-    /* Simple chord estimation
-       I just take the local chord estimates ("currentChordSalience") and average them over time, then
-       take the maximum. Very simple, don't do this at home...
-    */
-    cerr << "[NNLS Chroma Plugin] Chord Estimation ... ";
-    count = 0; 
-    int halfwindowlength = m_inputSampleRate / m_stepSize;
-    vector<int> chordSequence;
-    for (FeatureList::iterator it = fsOut[6].begin(); it != fsOut[6].end(); ++it) { // initialise the score chordogram
-        vector<int> temp = vector<int>(nChord,0);
-        scoreChordogram.push_back(temp);
-    }
-    for (FeatureList::iterator it = fsOut[6].begin(); it < fsOut[6].end()-2*halfwindowlength-1; ++it) {		
-        int startIndex = count + 1;
-        int endIndex = count + 2 * halfwindowlength;
-			
-        float chordThreshold = 2.5/nChord;//*(2*halfwindowlength+1);
-            
-        vector<int> chordCandidates;
-        for (unsigned iChord = 0; iChord < nChord-1; iChord++) {
-            // float currsum = 0;
-            // for (unsigned iFrame = startIndex; iFrame < endIndex; ++iFrame) {
-            //  currsum += chordogram[iFrame][iChord];
-            // }
-            //                 if (currsum > chordThreshold) chordCandidates.push_back(iChord);
-            for (unsigned iFrame = startIndex; iFrame < endIndex; ++iFrame) {
-                if (chordogram[iFrame][iChord] > chordThreshold) {
-                    chordCandidates.push_back(iChord);
-                    break;
-                }                    
-            }
-        }
-        chordCandidates.push_back(nChord-1);
-        // cerr << chordCandidates.size() << endl;          
-	        
-        float maxval = 0; // will be the value of the most salient *chord change* in this frame
-        float maxindex = 0; //... and the index thereof
-        unsigned bestchordL = nChord-1; // index of the best "left" chord
-        unsigned bestchordR = nChord-1; // index of the best "right" chord
- 	 		
-        for (int iWF = 1; iWF < 2*halfwindowlength; ++iWF) {
-            // now find the max values on both sides of iWF
-            // left side:
-            float maxL = 0;
-            unsigned maxindL = nChord-1;
-            for (unsigned kChord = 0; kChord < chordCandidates.size(); kChord++) {
-                unsigned iChord = chordCandidates[kChord];
-                float currsum = 0;
-                for (unsigned iFrame = 0; iFrame < iWF-1; ++iFrame) {
-                    currsum += chordogram[count+iFrame][iChord];
-                }
-                if (iChord == nChord-1) currsum *= 0.8;
-                if (currsum > maxL) {
-                    maxL = currsum;
-                    maxindL = iChord;
-                }
-            }				
-            // right side:
-            float maxR = 0;
-            unsigned maxindR = nChord-1;
-            for (unsigned kChord = 0; kChord < chordCandidates.size(); kChord++) {
-                unsigned iChord = chordCandidates[kChord];
-                float currsum = 0;
-                for (unsigned iFrame = iWF-1; iFrame < 2*halfwindowlength; ++iFrame) {
-                    currsum += chordogram[count+iFrame][iChord];
-                }
-                if (iChord == nChord-1) currsum *= 0.8;
-                if (currsum > maxR) {
-                    maxR = currsum;
-                    maxindR = iChord;
-                }
-            }
-            if (maxL+maxR > maxval) {					
-                maxval = maxL+maxR;
-                maxindex = iWF;
-                bestchordL = maxindL;
-                bestchordR = maxindR;
-            }
-				
-        }
-        // cerr << "maxindex: " << maxindex << ", bestchordR is " << bestchordR << ", of frame " << count << endl;
-        // add a score to every chord-frame-point that was part of a maximum 
-        for (unsigned iFrame = 0; iFrame < maxindex-1; ++iFrame) {
-            scoreChordogram[iFrame+count][bestchordL]++;
-        }
-        for (unsigned iFrame = maxindex-1; iFrame < 2*halfwindowlength; ++iFrame) {
-            scoreChordogram[iFrame+count][bestchordR]++;
-        }
-        if (bestchordL != bestchordR) chordchange[maxindex+count] += (halfwindowlength - abs(maxindex-halfwindowlength)) * 2.0 / halfwindowlength;
-        count++;	
-    }
-    // cerr << "*******  agent finished   *******" << endl;
-    count = 0;
-    for (FeatureList::iterator it = fsOut[6].begin(); it != fsOut[6].end(); ++it) { 
-        float maxval = 0; // will be the value of the most salient chord in this frame
-        float maxindex = 0; //... and the index thereof
-        for (unsigned iChord = 0; iChord < nChord; iChord++) {
-            if (scoreChordogram[count][iChord] > maxval) {
-                maxval = scoreChordogram[count][iChord];
-                maxindex = iChord;
-                // cerr << iChord << endl;
-            }
-        }
-        chordSequence.push_back(maxindex);
-        // cerr << "before modefilter, maxindex: " << maxindex << endl;
-        count++;
-    }
-    // cerr << "*******  mode filter done *******" << endl;
-
-	
-    // mode filter on chordSequence
-    count = 0;
-    string oldChord = "";
-    for (FeatureList::iterator it = fsOut[6].begin(); it != fsOut[6].end(); ++it) {
-        Feature f6 = *it;
-        Feature f7; // chord estimate
-        f7.hasTimestamp = true;
-        f7.timestamp = f6.timestamp;
-        Feature f8; // chord estimate
-        f8.hasTimestamp = true;
-        f8.timestamp = f6.timestamp;
-			
-        vector<int> chordCount = vector<int>(nChord,0);
-        int maxChordCount = 0;
-        int maxChordIndex = nChord-1;
-        string maxChord;
-        int startIndex = max(count - halfwindowlength/2,0);
-        int endIndex = min(int(chordogram.size()), count + halfwindowlength/2);
-        for (int i = startIndex; i < endIndex; i++) {				
-            chordCount[chordSequence[i]]++;
-            if (chordCount[chordSequence[i]] > maxChordCount) {
-                // cerr << "start index " << startIndex << endl;
-                maxChordCount++;
-                maxChordIndex = chordSequence[i];
-                maxChord = m_chordnames[maxChordIndex];
-            }
-        }
-        // chordSequence[count] = maxChordIndex;
-        // cerr << maxChordIndex << endl;
-        f8.values.push_back(chordchange[count]/(halfwindowlength*2));
-        // cerr << chordchange[count] << endl;
-        fsOut[9].push_back(f8);
-        if (oldChord != maxChord) {
-            oldChord = maxChord;
-	
-            // char buffer1 [50];
-            // if (maxChordIndex < nChord - 1) {
-            //     sprintf(buffer1, "%s%s", notenames[maxChordIndex % 12 + 12], chordtypes[maxChordIndex]);
-            // } else {
-            //     sprintf(buffer1, "N");
-            // }
-            // f7.label = buffer1;
-            f7.label = m_chordnames[maxChordIndex];
-            fsOut[7].push_back(f7);
-        }
-        count++;
-    }
-    Feature f7; // last chord estimate
-    f7.hasTimestamp = true;
-    f7.timestamp = fsOut[6][fsOut[6].size()-1].timestamp;
-    f7.label = "N";
-    fsOut[7].push_back(f7);
-    cerr << "done." << endl;
-    //     // musicity
-    //     count = 0;
-    //     int oldlabeltype = 0; // start value is 0, music is 1, speech is 2
-    //     vector<float> musicityValue; 
-    //     for (FeatureList::iterator it = fsOut[4].begin(); it != fsOut[4].end(); ++it) {
-    //         Feature f4 = *it;
-    //         
-    //         int startIndex = max(count - musicitykernelwidth/2,0);
-    //         int endIndex = min(int(chordogram.size()), startIndex + musicitykernelwidth - 1);
-    //         float chromasum = 0;
-    //         float diffsum = 0;
-    //         for (int k = 0; k < 12; k++) {
-    //             for (int i = startIndex + 1; i < endIndex; i++) {
-    //                 chromasum += pow(fsOut[4][i].values[k],2);
-    //                 diffsum += abs(fsOut[4][i-1].values[k] - fsOut[4][i].values[k]);
-    //             }
-    //         }
-    //         diffsum /= chromasum;
-    //         musicityValue.push_back(diffsum);        
-    //         count++;
-    //     }
-    //     
-    //     float musicityThreshold = 0.44;
-    //     if (m_stepSize == 4096) {
-    //         musicityThreshold = 0.74;
-    //     }
-    //     if (m_stepSize == 4410) {
-    //         musicityThreshold = 0.77;
-    //     }
-    //     
-    //     count = 0;
-    //     for (FeatureList::iterator it = fsOut[4].begin(); it != fsOut[4].end(); ++it) {
-    //         Feature f4 = *it;
-    //         Feature f8; // musicity
-    //         Feature f9; // musicity segmenter
-    //         
-    //         f8.hasTimestamp = true;
-    //         f8.timestamp = f4.timestamp;
-    //         f9.hasTimestamp = true;
-    //         f9.timestamp = f4.timestamp;    
-    //         
-    //         int startIndex = max(count - musicitykernelwidth/2,0);
-    //         int endIndex = min(int(chordogram.size()), startIndex + musicitykernelwidth - 1);
-    //         int musicityCount = 0;
-    //         for (int i = startIndex; i <= endIndex; i++) {
-    //             if (musicityValue[i] > musicityThreshold) musicityCount++;
-    //         }
-    //         bool isSpeech = (2 * musicityCount > endIndex - startIndex + 1); 
-    //         
-    //         if (isSpeech) {
-    //             if (oldlabeltype != 2) {
-    //                 f9.label = "Speech";
-    //                 fsOut[9].push_back(f9);
-    //                 oldlabeltype = 2;
-    //             }
-    //         } else {
-    //             if (oldlabeltype != 1) {
-    //                 f9.label = "Music";
-    //                 fsOut[9].push_back(f9);
-    //                 oldlabeltype = 1;
-    //             }
-    //         }
-    //         f8.values.push_back(musicityValue[count]);
-    //         fsOut[8].push_back(f8);
-    //         count++;
-    //      }
+    //      
+    //    vector<vector<float> > chordogram;
+    //    vector<vector<int> > scoreChordogram;
+    //    vector<float> chordchange = vector<float>(fsOut[2].size(),0);
+    //    vector<float> oldchroma = vector<float>(12,0);
+    //    vector<float> oldbasschroma = vector<float>(12,0);
+    //    count = 0;
+    // 
+    //    for (FeatureList::iterator it = fsOut[2].begin(); it != fsOut[2].end(); ++it) {
+    //        Feature f2 = *it; // logfreq spectrum
+    //        Feature f3; // semitone spectrum
+    //        Feature f4; // treble chromagram
+    //        Feature f5; // bass chromagram
+    //        Feature f6; // treble and bass chromagram
+    //  
+    //        f3.hasTimestamp = true;
+    //        f3.timestamp = f2.timestamp;
+    //          
+    //        f4.hasTimestamp = true;
+    //        f4.timestamp = f2.timestamp;
+    //          
+    //        f5.hasTimestamp = true;
+    //        f5.timestamp = f2.timestamp;
+    //          
+    //        f6.hasTimestamp = true;
+    //        f6.timestamp = f2.timestamp;
+    //          
+    //          float b[nNote];
+    //  
+    //        bool some_b_greater_zero = false;
+    //        float sumb = 0;
+    //        for (int i = 0; i < nNote; i++) {
+    //            // b[i] = m_dict[(nNote * count + i) % (nNote * 84)];
+    //            b[i] = f2.values[i];
+    //            sumb += b[i];
+    //            if (b[i] > 0) {
+    //                some_b_greater_zero = true;
+    //            }            
+    //        }
+    //      
+    //        // here's where the non-negative least squares algorithm calculates the note activation x
+    //  
+    //        vector<float> chroma = vector<float>(12, 0);
+    //        vector<float> basschroma = vector<float>(12, 0);
+    //        float currval;
+    //        unsigned iSemitone = 0;
+    //          
+    //        if (some_b_greater_zero) {
+    //            if (m_useNNLS == 0) {
+    //                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
+    //                    currval = 0;
+    //                    currval += b[iNote + 1 + -1] * 0.5;                       
+    //                    currval += b[iNote + 1 +  0] * 1.0;                       
+    //                    currval += b[iNote + 1 +  1] * 0.5;                       
+    //                    f3.values.push_back(currval);
+    //                    chroma[iSemitone % 12] += currval * treblewindow[iSemitone];
+    //                    basschroma[iSemitone % 12] += currval * basswindow[iSemitone];
+    //                    iSemitone++;
+    //                }
+    //              
+    //            } else {
+    //                  float x[84+1000];
+    //                for (int i = 1; i < 1084; ++i) x[i] = 1.0;
+    //                vector<int> signifIndex;
+    //                int index=0;
+    //                sumb /= 84.0;
+    //                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
+    //                    float currval = 0;
+    //                    currval += b[iNote + 1 + -1];                     
+    //                    currval += b[iNote + 1 +  0];                     
+    //                    currval += b[iNote + 1 +  1];
+    //                    if (currval > 0) signifIndex.push_back(index);
+    //                    f3.values.push_back(0); // fill the values, change later
+    //                    index++;
+    //                }
+    //                  float rnorm;
+    //                  float w[84+1000];
+    //                  float zz[84+1000];
+    //                int indx[84+1000];
+    //                int mode;
+    //                int dictsize = nNote*signifIndex.size();
+    //                // cerr << "dictsize is " << dictsize << "and values size" << f3.values.size()<< endl;
+    //                  float *curr_dict = new float[dictsize];
+    //                for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
+    //                    for (unsigned iBin = 0; iBin < nNote; iBin++) {
+    //                        curr_dict[iNote * nNote + iBin] = 1.0 * m_dict[signifIndex[iNote] * nNote + iBin];
+    //                    }
+    //                }
+    //                  nnls(curr_dict, nNote, nNote, signifIndex.size(), b, x, &rnorm, w, zz, indx, &mode);
+    //                delete [] curr_dict;
+    //                for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
+    //                    f3.values[signifIndex[iNote]] = x[iNote];
+    //                    // cerr << mode << endl;
+    //                    chroma[signifIndex[iNote] % 12] += x[iNote] * treblewindow[signifIndex[iNote]];
+    //                    basschroma[signifIndex[iNote] % 12] += x[iNote] * basswindow[signifIndex[iNote]];
+    //                }
+    //            } 
+    //        }
+    //          
+    //            
+    //          
+    //          
+    //        f4.values = chroma; 
+    //        f5.values = basschroma;
+    //        chroma.insert(chroma.begin(), basschroma.begin(), basschroma.end()); // just stack the both chromas 
+    //        f6.values = chroma; 
+    //          
+    //        if (m_doNormalizeChroma > 0) {
+    //            vector<float> chromanorm = vector<float>(3,0);            
+    //            switch (int(m_doNormalizeChroma)) {
+    //            case 0: // should never end up here
+    //                break;
+    //            case 1:
+    //                chromanorm[0] = *max_element(f4.values.begin(), f4.values.end());
+    //                chromanorm[1] = *max_element(f5.values.begin(), f5.values.end());
+    //                chromanorm[2] = max(chromanorm[0], chromanorm[1]);
+    //                break;
+    //            case 2:
+    //                for (vector<float>::iterator it = f4.values.begin(); it != f4.values.end(); ++it) {
+    //                    chromanorm[0] += *it;                         
+    //                }
+    //                for (vector<float>::iterator it = f5.values.begin(); it != f5.values.end(); ++it) {
+    //                    chromanorm[1] += *it;                         
+    //                }
+    //                for (vector<float>::iterator it = f6.values.begin(); it != f6.values.end(); ++it) {
+    //                    chromanorm[2] += *it;                         
+    //                }
+    //                break;
+    //            case 3:
+    //                for (vector<float>::iterator it = f4.values.begin(); it != f4.values.end(); ++it) {
+    //                    chromanorm[0] += pow(*it,2);                      
+    //                }
+    //                chromanorm[0] = sqrt(chromanorm[0]);
+    //                for (vector<float>::iterator it = f5.values.begin(); it != f5.values.end(); ++it) {
+    //                    chromanorm[1] += pow(*it,2);                      
+    //                }
+    //                chromanorm[1] = sqrt(chromanorm[1]);
+    //                for (vector<float>::iterator it = f6.values.begin(); it != f6.values.end(); ++it) {
+    //                    chromanorm[2] += pow(*it,2);                      
+    //                }
+    //                chromanorm[2] = sqrt(chromanorm[2]);
+    //                break;
+    //            }
+    //            if (chromanorm[0] > 0) {
+    //                for (int i = 0; i < f4.values.size(); i++) {
+    //                    f4.values[i] /= chromanorm[0];
+    //                }
+    //            }
+    //            if (chromanorm[1] > 0) {
+    //                for (int i = 0; i < f5.values.size(); i++) {
+    //                    f5.values[i] /= chromanorm[1];
+    //                }
+    //            }
+    //            if (chromanorm[2] > 0) {
+    //                for (int i = 0; i < f6.values.size(); i++) {
+    //                    f6.values[i] /= chromanorm[2];
+    //                }
+    //            }
+    //              
+    //        }
+    //  
+    //        // local chord estimation
+    //        vector<float> currentChordSalience;
+    //        float tempchordvalue = 0;
+    //        float sumchordvalue = 0;
+    //          
+    //        for (int iChord = 0; iChord < nChord; iChord++) {
+    //            tempchordvalue = 0;
+    //            for (int iBin = 0; iBin < 12; iBin++) {
+    //                tempchordvalue += m_chorddict[24 * iChord + iBin] * chroma[iBin];
+    //            }
+    //            for (int iBin = 12; iBin < 24; iBin++) {
+    //                tempchordvalue += m_chorddict[24 * iChord + iBin] * chroma[iBin];
+    //            }
+    //            sumchordvalue+=tempchordvalue;
+    //            currentChordSalience.push_back(tempchordvalue);
+    //        }
+    //        if (sumchordvalue > 0) {
+    //            for (int iChord = 0; iChord < nChord; iChord++) {
+    //                currentChordSalience[iChord] /= sumchordvalue;
+    //            }
+    //        } else {
+    //            currentChordSalience[nChord-1] = 1.0;
+    //        }
+    //        chordogram.push_back(currentChordSalience);
+    //          
+    //        fsOut[3].push_back(f3);
+    //        fsOut[4].push_back(f4);
+    //        fsOut[5].push_back(f5);
+    //        fsOut[6].push_back(f6);
+    //        count++;
+    //    }
+    //    cerr << "done." << endl;
+    //      
+    // 
+    //    /* Simple chord estimation
+    //       I just take the local chord estimates ("currentChordSalience") and average them over time, then
+    //       take the maximum. Very simple, don't do this at home...
+    //    */
+    //    cerr << "[NNLS Chroma Plugin] Chord Estimation ... ";
+    //    count = 0; 
+    //    int halfwindowlength = m_inputSampleRate / m_stepSize;
+    //    vector<int> chordSequence;
+    //    for (FeatureList::iterator it = fsOut[6].begin(); it != fsOut[6].end(); ++it) { // initialise the score chordogram
+    //        vector<int> temp = vector<int>(nChord,0);
+    //        scoreChordogram.push_back(temp);
+    //    }
+    //    for (FeatureList::iterator it = fsOut[6].begin(); it < fsOut[6].end()-2*halfwindowlength-1; ++it) {       
+    //        int startIndex = count + 1;
+    //        int endIndex = count + 2 * halfwindowlength;
+    //          
+    //        float chordThreshold = 2.5/nChord;//*(2*halfwindowlength+1);
+    //            
+    //        vector<int> chordCandidates;
+    //        for (unsigned iChord = 0; iChord < nChord-1; iChord++) {
+    //            // float currsum = 0;
+    //            // for (unsigned iFrame = startIndex; iFrame < endIndex; ++iFrame) {
+    //            //  currsum += chordogram[iFrame][iChord];
+    //            // }
+    //            //                 if (currsum > chordThreshold) chordCandidates.push_back(iChord);
+    //            for (unsigned iFrame = startIndex; iFrame < endIndex; ++iFrame) {
+    //                if (chordogram[iFrame][iChord] > chordThreshold) {
+    //                    chordCandidates.push_back(iChord);
+    //                    break;
+    //                }                    
+    //            }
+    //        }
+    //        chordCandidates.push_back(nChord-1);
+    //        // cerr << chordCandidates.size() << endl;          
+    //          
+    //        float maxval = 0; // will be the value of the most salient *chord change* in this frame
+    //        float maxindex = 0; //... and the index thereof
+    //        unsigned bestchordL = nChord-1; // index of the best "left" chord
+    //        unsigned bestchordR = nChord-1; // index of the best "right" chord
+    //          
+    //        for (int iWF = 1; iWF < 2*halfwindowlength; ++iWF) {
+    //            // now find the max values on both sides of iWF
+    //            // left side:
+    //            float maxL = 0;
+    //            unsigned maxindL = nChord-1;
+    //            for (unsigned kChord = 0; kChord < chordCandidates.size(); kChord++) {
+    //                unsigned iChord = chordCandidates[kChord];
+    //                float currsum = 0;
+    //                for (unsigned iFrame = 0; iFrame < iWF-1; ++iFrame) {
+    //                    currsum += chordogram[count+iFrame][iChord];
+    //                }
+    //                if (iChord == nChord-1) currsum *= 0.8;
+    //                if (currsum > maxL) {
+    //                    maxL = currsum;
+    //                    maxindL = iChord;
+    //                }
+    //            }             
+    //            // right side:
+    //            float maxR = 0;
+    //            unsigned maxindR = nChord-1;
+    //            for (unsigned kChord = 0; kChord < chordCandidates.size(); kChord++) {
+    //                unsigned iChord = chordCandidates[kChord];
+    //                float currsum = 0;
+    //                for (unsigned iFrame = iWF-1; iFrame < 2*halfwindowlength; ++iFrame) {
+    //                    currsum += chordogram[count+iFrame][iChord];
+    //                }
+    //                if (iChord == nChord-1) currsum *= 0.8;
+    //                if (currsum > maxR) {
+    //                    maxR = currsum;
+    //                    maxindR = iChord;
+    //                }
+    //            }
+    //            if (maxL+maxR > maxval) {                 
+    //                maxval = maxL+maxR;
+    //                maxindex = iWF;
+    //                bestchordL = maxindL;
+    //                bestchordR = maxindR;
+    //            }
+    //              
+    //        }
+    //        // cerr << "maxindex: " << maxindex << ", bestchordR is " << bestchordR << ", of frame " << count << endl;
+    //        // add a score to every chord-frame-point that was part of a maximum 
+    //        for (unsigned iFrame = 0; iFrame < maxindex-1; ++iFrame) {
+    //            scoreChordogram[iFrame+count][bestchordL]++;
+    //        }
+    //        for (unsigned iFrame = maxindex-1; iFrame < 2*halfwindowlength; ++iFrame) {
+    //            scoreChordogram[iFrame+count][bestchordR]++;
+    //        }
+    //        if (bestchordL != bestchordR) chordchange[maxindex+count] += (halfwindowlength - abs(maxindex-halfwindowlength)) * 2.0 / halfwindowlength;
+    //        count++;  
+    //    }
+    //    // cerr << "*******  agent finished   *******" << endl;
+    //    count = 0;
+    //    for (FeatureList::iterator it = fsOut[6].begin(); it != fsOut[6].end(); ++it) { 
+    //        float maxval = 0; // will be the value of the most salient chord in this frame
+    //        float maxindex = 0; //... and the index thereof
+    //        for (unsigned iChord = 0; iChord < nChord; iChord++) {
+    //            if (scoreChordogram[count][iChord] > maxval) {
+    //                maxval = scoreChordogram[count][iChord];
+    //                maxindex = iChord;
+    //                // cerr << iChord << endl;
+    //            }
+    //        }
+    //        chordSequence.push_back(maxindex);
+    //        // cerr << "before modefilter, maxindex: " << maxindex << endl;
+    //        count++;
+    //    }
+    //    // cerr << "*******  mode filter done *******" << endl;
+    // 
+    //  
+    //    // mode filter on chordSequence
+    //    count = 0;
+    //    string oldChord = "";
+    //    for (FeatureList::iterator it = fsOut[6].begin(); it != fsOut[6].end(); ++it) {
+    //        Feature f6 = *it;
+    //        Feature f7; // chord estimate
+    //        f7.hasTimestamp = true;
+    //        f7.timestamp = f6.timestamp;
+    //        Feature f8; // chord estimate
+    //        f8.hasTimestamp = true;
+    //        f8.timestamp = f6.timestamp;
+    //          
+    //        vector<int> chordCount = vector<int>(nChord,0);
+    //        int maxChordCount = 0;
+    //        int maxChordIndex = nChord-1;
+    //        string maxChord;
+    //        int startIndex = max(count - halfwindowlength/2,0);
+    //        int endIndex = min(int(chordogram.size()), count + halfwindowlength/2);
+    //        for (int i = startIndex; i < endIndex; i++) {             
+    //            chordCount[chordSequence[i]]++;
+    //            if (chordCount[chordSequence[i]] > maxChordCount) {
+    //                // cerr << "start index " << startIndex << endl;
+    //                maxChordCount++;
+    //                maxChordIndex = chordSequence[i];
+    //                maxChord = m_chordnames[maxChordIndex];
+    //            }
+    //        }
+    //        // chordSequence[count] = maxChordIndex;
+    //        // cerr << maxChordIndex << endl;
+    //        f8.values.push_back(chordchange[count]/(halfwindowlength*2));
+    //        // cerr << chordchange[count] << endl;
+    //        fsOut[9].push_back(f8);
+    //        if (oldChord != maxChord) {
+    //            oldChord = maxChord;
+    //  
+    //            // char buffer1 [50];
+    //            // if (maxChordIndex < nChord - 1) {
+    //            //     sprintf(buffer1, "%s%s", notenames[maxChordIndex % 12 + 12], chordtypes[maxChordIndex]);
+    //            // } else {
+    //            //     sprintf(buffer1, "N");
+    //            // }
+    //            // f7.label = buffer1;
+    //            f7.label = m_chordnames[maxChordIndex];
+    //            fsOut[7].push_back(f7);
+    //        }
+    //        count++;
+    //    }
+    //    Feature f7; // last chord estimate
+    //    f7.hasTimestamp = true;
+    //    f7.timestamp = fsOut[6][fsOut[6].size()-1].timestamp;
+    //    f7.label = "N";
+    //    fsOut[7].push_back(f7);
+    //    cerr << "done." << endl;
+    //    //     // musicity
+    //    //     count = 0;
+    //    //     int oldlabeltype = 0; // start value is 0, music is 1, speech is 2
+    //    //     vector<float> musicityValue; 
+    //    //     for (FeatureList::iterator it = fsOut[4].begin(); it != fsOut[4].end(); ++it) {
+    //    //         Feature f4 = *it;
+    //    //         
+    //    //         int startIndex = max(count - musicitykernelwidth/2,0);
+    //    //         int endIndex = min(int(chordogram.size()), startIndex + musicitykernelwidth - 1);
+    //    //         float chromasum = 0;
+    //    //         float diffsum = 0;
+    //    //         for (int k = 0; k < 12; k++) {
+    //    //             for (int i = startIndex + 1; i < endIndex; i++) {
+    //    //                 chromasum += pow(fsOut[4][i].values[k],2);
+    //    //                 diffsum += abs(fsOut[4][i-1].values[k] - fsOut[4][i].values[k]);
+    //    //             }
+    //    //         }
+    //    //         diffsum /= chromasum;
+    //    //         musicityValue.push_back(diffsum);        
+    //    //         count++;
+    //    //     }
+    //    //     
+    //    //     float musicityThreshold = 0.44;
+    //    //     if (m_stepSize == 4096) {
+    //    //         musicityThreshold = 0.74;
+    //    //     }
+    //    //     if (m_stepSize == 4410) {
+    //    //         musicityThreshold = 0.77;
+    //    //     }
+    //    //     
+    //    //     count = 0;
+    //    //     for (FeatureList::iterator it = fsOut[4].begin(); it != fsOut[4].end(); ++it) {
+    //    //         Feature f4 = *it;
+    //    //         Feature f8; // musicity
+    //    //         Feature f9; // musicity segmenter
+    //    //         
+    //    //         f8.hasTimestamp = true;
+    //    //         f8.timestamp = f4.timestamp;
+    //    //         f9.hasTimestamp = true;
+    //    //         f9.timestamp = f4.timestamp;    
+    //    //         
+    //    //         int startIndex = max(count - musicitykernelwidth/2,0);
+    //    //         int endIndex = min(int(chordogram.size()), startIndex + musicitykernelwidth - 1);
+    //    //         int musicityCount = 0;
+    //    //         for (int i = startIndex; i <= endIndex; i++) {
+    //    //             if (musicityValue[i] > musicityThreshold) musicityCount++;
+    //    //         }
+    //    //         bool isSpeech = (2 * musicityCount > endIndex - startIndex + 1); 
+    //    //         
+    //    //         if (isSpeech) {
+    //    //             if (oldlabeltype != 2) {
+    //    //                 f9.label = "Speech";
+    //    //                 fsOut[9].push_back(f9);
+    //    //                 oldlabeltype = 2;
+    //    //             }
+    //    //         } else {
+    //    //             if (oldlabeltype != 1) {
+    //    //                 f9.label = "Music";
+    //    //                 fsOut[9].push_back(f9);
+    //    //                 oldlabeltype = 1;
+    //    //             }
+    //    //         }
+    //    //         f8.values.push_back(musicityValue[count]);
+    //    //         fsOut[8].push_back(f8);
+    //    //         count++;
+    //    //      }
     return fsOut;     
 
 }
--- a/NNLSBase.h	Mon Nov 15 09:23:49 2010 +0900
+++ b/NNLSBase.h	Mon Nov 15 11:01:56 2010 +0900
@@ -60,12 +60,8 @@
     size_t m_blockSize;
     size_t m_stepSize;
     int m_lengthOfNoteIndex;
-    float m_meanTuning0;
-    float m_meanTuning1;
-    float m_meanTuning2;
-    float m_localTuning0;
-    float m_localTuning1;
-    float m_localTuning2;
+    vector<float> m_meanTunings;
+    vector<float> m_localTunings;
     float m_whitening;
     float m_preset;
 	float m_s;
@@ -82,6 +78,8 @@
     float m_doNormalizeChroma;
     float m_rollon;
     vector<float> hw;
+    vector<float> sinvalues;
+    vector<float> cosvalues;
 };
 
 
--- a/NNLSChroma.cpp	Mon Nov 15 09:23:49 2010 +0900
+++ b/NNLSChroma.cpp	Mon Nov 15 11:01:56 2010 +0900
@@ -219,12 +219,16 @@
          calculate tuning from (using the angle of the complex number defined by the 
          cumulative mean real and imag values)
     **/
-    float meanTuningImag = sinvalue * m_meanTuning1 - sinvalue * m_meanTuning2;
-    float meanTuningReal = m_meanTuning0 + cosvalue * m_meanTuning1 + cosvalue * m_meanTuning2;
+    float meanTuningImag = 0;
+    float meanTuningReal = 0;
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        meanTuningReal += m_meanTunings[iBPS] * cosvalues[iBPS];
+        meanTuningImag += m_meanTunings[iBPS] * sinvalues[iBPS];
+    }
     float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI));
     float normalisedtuning = atan2(meanTuningImag, meanTuningReal)/(2*M_PI);
     int intShift = floor(normalisedtuning * 3);
-    float intFactor = normalisedtuning * 3 - intShift; // intFactor is a really bad name for this
+    float floatShift = normalisedtuning * 3 - intShift; // floatShift is a really bad name for this
 		    
     char buffer0 [50];
 		
@@ -244,8 +248,6 @@
     // cerr << "tune local ? " << m_tuneLocal << endl;
     int count = 0;
 
-    cerr << nNote;
-    cerr << endl << "-------------------------------------"<< endl;
 		
     for (FeatureList::iterator i = m_logSpectrum.begin(); i != m_logSpectrum.end(); ++i) {
         Feature f1 = *i;
@@ -256,13 +258,13 @@
 		
         if (m_tuneLocal) {
             intShift = floor(m_localTuning[count] * 3);
-            intFactor = m_localTuning[count] * 3 - intShift; // intFactor is a really bad name for this
+            floatShift = m_localTuning[count] * 3 - intShift; // floatShift is a really bad name for this
         }
 		        
-        // cerr << intShift << " " << intFactor << endl;
+        // cerr << intShift << " " << floatShift << endl;
 		        
         for (unsigned k = 2; k < f1.values.size() - 3; ++k) { // interpolate all inner bins
-            tempValue = f1.values[k + intShift] * (1-intFactor) + f1.values[k+intShift+1] * intFactor;
+            tempValue = f1.values[k + intShift] * (1-floatShift) + f1.values[k+intShift+1] * floatShift;
             f2.values.push_back(tempValue);
         }
 		        
@@ -349,11 +351,11 @@
 			
         if (some_b_greater_zero) {
             if (m_useNNLS == 0) {
-                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
+                for (unsigned iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
                     currval = 0;
-                    currval += b[iNote + 1 + -1] * 0.5;						
-                    currval += b[iNote + 1 +  0] * 1.0;						
-                    currval += b[iNote + 1 +  1] * 0.5;						
+                    for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) {
+                        currval += b[iNote + iBPS] * (1-abs(iBPS*1.0/(nBPS/2+1)));						
+                    }
                     f3.values.push_back(currval);
                     chroma[iSemitone % 12] += currval * treblewindow[iSemitone];
                     basschroma[iSemitone % 12] += currval * basswindow[iSemitone];
@@ -366,11 +368,11 @@
                 vector<int> signifIndex;
                 int index=0;
                 sumb /= 84.0;
-                for (unsigned iNote = 2; iNote < nNote - 2; iNote += 3) {
+                for (unsigned iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
                     float currval = 0;
-                    currval += b[iNote + 1 + -1]; 
-                    currval += b[iNote + 1 +  0]; 
-                    currval += b[iNote + 1 +  1];
+                    for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) {
+                        currval += b[iNote + iBPS]; 
+                    }
                     if (currval > 0) signifIndex.push_back(index);
                     f3.values.push_back(0); // fill the values, change later
                     index++;
--- a/Tuning.cpp	Mon Nov 15 09:23:49 2010 +0900
+++ b/Tuning.cpp	Mon Nov 15 11:01:56 2010 +0900
@@ -187,8 +187,15 @@
          calculate tuning from (using the angle of the complex number defined by the 
          cumulative mean real and imag values)
     **/
-    float meanTuningImag = sinvalue * m_meanTuning1 - sinvalue * m_meanTuning2;
-    float meanTuningReal = m_meanTuning0 + cosvalue * m_meanTuning1 + cosvalue * m_meanTuning2;
+    
+    float meanTuningImag = 0;
+    float meanTuningReal = 0;
+    for (int iBPS = 0; iBPS < nBPS; ++iBPS) {
+        meanTuningReal += m_meanTunings[iBPS] * cosvalues[iBPS];
+        meanTuningImag += m_meanTunings[iBPS] * sinvalues[iBPS];
+    }
+    
+
     float cumulativetuning = 440 * pow(2,atan2(meanTuningImag, meanTuningReal)/(24*M_PI));
 		    
     char buffer0 [50];
--- a/chromamethods.cpp	Mon Nov 15 09:23:49 2010 +0900
+++ b/chromamethods.cpp	Mon Nov 15 11:01:56 2010 +0900
@@ -105,7 +105,7 @@
 
 bool logFreqMatrix(int fs, int blocksize, float *outmatrix) {
 	
-    int binspersemitone = 3; // this must be 3
+    int binspersemitone = nBPS; 
     int minoctave = 0; // this must be 0
     int maxoctave = 7; // this must be 7
     int oversampling = 80;
@@ -128,14 +128,14 @@
     int maxMIDI = 21 + maxoctave * 12; // this includes one additional semitone!
     vector<float> cq_f;
     float oob = 1.0/binspersemitone; // one over binspersemitone
-    cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-69))); // 0.083333 is approx 1/12
-    cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI+oob-69)));
-    for (int i = minMIDI + 1; i < maxMIDI; ++i) {
-        for (int k = -1; k < 2; ++k)	 {
+    // cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-69))); // 0.083333 is approx 1/12
+    // cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI+oob-69)));
+    for (int i = minMIDI; i < maxMIDI; ++i) {
+        for (int k = 0; k < binspersemitone; ++k)	 {
             cq_f.push_back(440 * pow(2.0,0.083333333333 * (i+oob*k-69)));
         }
     }
-    cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-oob-69)));
+    // cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-oob-69)));
     cq_f.push_back(440 * pow(2.0,0.083333 * (maxMIDI-69)));
 
     int nFFT = fft_f.size();
@@ -171,7 +171,7 @@
 }
 
 void dictionaryMatrix(float* dm, float s_param) {
-    int binspersemitone = 3; // this must be 3
+    int binspersemitone = nBPS;
     int minoctave = 0; // this must be 0
     int maxoctave = 7; // this must be 7
     // float s_param = 0.7;
@@ -181,14 +181,14 @@
     int maxMIDI = 21 + maxoctave * 12; // this includes one additional semitone!
     vector<float> cq_f;
     float oob = 1.0/binspersemitone; // one over binspersemitone
-    cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-69))); // 0.083333 is approx 1/12
-    cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI+oob-69)));
-    for (int i = minMIDI + 1; i < maxMIDI; ++i) {
-        for (int k = -1; k < 2; ++k)	 {
+    // cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-69))); // 0.083333 is approx 1/12
+    // cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI+oob-69)));
+    for (int i = minMIDI; i < maxMIDI; ++i) {
+        for (int k = 0; k < binspersemitone; ++k)	 {
             cq_f.push_back(440 * pow(2.0,0.083333333333 * (i+oob*k-69)));
         }
     }
-    cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-oob-69)));
+    // cq_f.push_back(440 * pow(2.0,0.083333 * (minMIDI-oob-69)));
     cq_f.push_back(440 * pow(2.0,0.083333 * (maxMIDI-69)));
 
     float curr_f;
--- a/chromamethods.h	Mon Nov 15 09:23:49 2010 +0900
+++ b/chromamethods.h	Mon Nov 15 11:01:56 2010 +0900
@@ -22,7 +22,7 @@
 #include <vector>
 #include <string>
 
-const int nBPS = 3; // bins per semitone
+const int nBPS = 5; // bins per semitone
 const int nOctave = 7;
 const int nNote = nOctave * 12 * nBPS + 2 * (nBPS/2+1); // a core over all octaves, plus some overlap at top and bottom
 
@@ -53,10 +53,6 @@
 static const float basswindow[] = {0.001769, 0.015848, 0.043608, 0.084265, 0.136670, 0.199341, 0.270509, 0.348162, 0.430105, 0.514023, 0.597545, 0.678311, 0.754038, 0.822586, 0.882019, 0.930656, 0.967124, 0.990393, 0.999803, 0.995091, 0.976388, 0.944223, 0.899505, 0.843498, 0.777785, 0.704222, 0.624888, 0.542025, 0.457975, 0.375112, 0.295778, 0.222215, 0.156502, 0.100495, 0.055777, 0.023612, 0.004909, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000};
 static const float treblewindow[] = {0.000350, 0.003144, 0.008717, 0.017037, 0.028058, 0.041719, 0.057942, 0.076638, 0.097701, 0.121014, 0.146447, 0.173856, 0.203090, 0.233984, 0.266366, 0.300054, 0.334860, 0.370590, 0.407044, 0.444018, 0.481304, 0.518696, 0.555982, 0.592956, 0.629410, 0.665140, 0.699946, 0.733634, 0.766016, 0.796910, 0.826144, 0.853553, 0.878986, 0.902299, 0.923362, 0.942058, 0.958281, 0.971942, 0.982963, 0.991283, 0.996856, 0.999650, 0.999650, 0.996856, 0.991283, 0.982963, 0.971942, 0.958281, 0.942058, 0.923362, 0.902299, 0.878986, 0.853553, 0.826144, 0.796910, 0.766016, 0.733634, 0.699946, 0.665140, 0.629410, 0.592956, 0.555982, 0.518696, 0.481304, 0.444018, 0.407044, 0.370590, 0.334860, 0.300054, 0.266366, 0.233984, 0.203090, 0.173856, 0.146447, 0.121014, 0.097701, 0.076638, 0.057942, 0.041719, 0.028058, 0.017037, 0.008717, 0.003144, 0.000350};
 
-static const float sinvalue = 0.866025404;
-static const float cosvalue = -0.5;
-
-
 
 #include "nnls.h"