changeset 99:daee3c60c4f9 matthiasm-plugin

merge
author Matthias Mauch <mail@matthiasmauch.net>
date Fri, 03 Dec 2010 19:10:09 +0900
parents 69c56e1fdfc3 (current diff) 0b2d7524f248 (diff)
children d1398182a072
files chromamethods.cpp
diffstat 9 files changed, 132 insertions(+), 617 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Dec 03 19:02:42 2010 +0900
+++ b/.hgtags	Fri Dec 03 19:10:09 2010 +0900
@@ -1,2 +1,3 @@
 12fd1d3ccd6e0072fc4be295e7a1e383e84912a1 0.1
 12fd1d3ccd6e0072fc4be295e7a1e383e84912a1 0.1
+dab7e7bfeba17478fa6c5af050c6270026ad635b 0.2
--- a/Chordino.cpp	Fri Dec 03 19:02:42 2010 +0900
+++ b/Chordino.cpp	Fri Dec 03 19:10:09 2010 +0900
@@ -103,7 +103,7 @@
     d0.unit = "%";
     d0.minValue = 0;
     d0.maxValue = 5;
-    d0.defaultValue = 0;
+    d0.defaultValue = 0.0;
     d0.isQuantized = true;
 	d0.quantizeStep = 0.5;
     list.push_back(d0);
@@ -115,7 +115,7 @@
     d1.unit = "";
     d1.minValue = 0;
     d1.maxValue = 1;
-    d1.defaultValue = 0;
+    d1.defaultValue = 0.0;
     d1.isQuantized = true;
     d1.valueNames.push_back("global tuning");
     d1.valueNames.push_back("local tuning");
@@ -148,11 +148,11 @@
     ParameterDescriptor boostn;
     boostn.identifier = "boostn";
     boostn.name = "boost N";
-    boostn.description = "Relative weight of the N label.";
+    boostn.description = "Boost likelihood of the N (no chord) label.";
     boostn.unit = "";
-    boostn.minValue = 1.0;
-    boostn.maxValue = 2.0;
-    boostn.defaultValue = 1.0;
+    boostn.minValue = 0.0;
+    boostn.maxValue = 1.0;
+    boostn.defaultValue = 0.1;
     boostn.isQuantized = false;
     list.push_back(boostn);
 
@@ -282,7 +282,7 @@
 		    
     /** Tune Log-Frequency Spectrogram
         calculate a tuned log-frequency spectrogram (currentTunedSpec): use the tuning estimated above (kinda f0) to 
-        perform linear interpolation on the existing log-frequency spectrogram (kinda currentLogSpectum).
+        perform linear interpolation on the existing log-frequency spectrogram (kinda currentLogSpectrum).
     **/
     cerr << endl << "[Chordino Plugin] Tuning Log-Frequency Spectrogram ... ";
 					
@@ -298,11 +298,11 @@
     vector<Vamp::RealTime> timestamps;
 
     for (FeatureList::iterator i = m_logSpectrum.begin(); i != m_logSpectrum.end(); ++i) {
-        Feature currentLogSpectum = *i;
+        Feature currentLogSpectrum = *i;
         Feature currentTunedSpec; // tuned log-frequency spectrum
         currentTunedSpec.hasTimestamp = true;
-        currentTunedSpec.timestamp = currentLogSpectum.timestamp;
-        timestamps.push_back(currentLogSpectum.timestamp);
+        currentTunedSpec.timestamp = currentLogSpectrum.timestamp;
+        timestamps.push_back(currentLogSpectrum.timestamp);
         currentTunedSpec.values.push_back(0.0); currentTunedSpec.values.push_back(0.0); // set lower edge to zero
 		
         if (m_tuneLocal) {
@@ -312,8 +312,8 @@
 		        
         // cerr << intShift << " " << floatShift << endl;
 		        
-        for (unsigned k = 2; k < currentLogSpectum.values.size() - 3; ++k) { // interpolate all inner bins
-            tempValue = currentLogSpectum.values[k + intShift] * (1-floatShift) + currentLogSpectum.values[k+intShift+1] * floatShift;
+        for (int k = 2; k < (int)currentLogSpectrum.values.size() - 3; ++k) { // interpolate all inner bins
+            tempValue = currentLogSpectrum.values[k + intShift] * (1-floatShift) + currentLogSpectrum.values[k+intShift+1] * floatShift;
             currentTunedSpec.values.push_back(tempValue);
         }
 		        
@@ -388,11 +388,11 @@
         vector<float> chroma = vector<float>(12, 0);
         vector<float> basschroma = vector<float>(12, 0);
         float currval;
-        unsigned iSemitone = 0;
+        int iSemitone = 0;
 			
         if (some_b_greater_zero) {
             if (m_useNNLS == 0) {
-                for (unsigned iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
+                for (int iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
                     currval = 0;
                     for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) {
                         currval += b[iNote + iBPS] * (1-abs(iBPS*1.0/(nBPS/2+1)));						
@@ -408,7 +408,7 @@
                 vector<int> signifIndex;
                 int index=0;
                 sumb /= 84.0;
-                for (unsigned iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
+                for (int iNote = nBPS/2 + 2; iNote < nNote - nBPS/2; iNote += nBPS) {
                     float currval = 0;
                     for (int iBPS = -nBPS/2; iBPS < nBPS/2+1; ++iBPS) {
                         currval += b[iNote + iBPS]; 
@@ -424,14 +424,14 @@
                 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++) {
+                for (int iNote = 0; iNote < (int)signifIndex.size(); ++iNote) {
+                    for (int 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) {
+                for (int iNote = 0; iNote < (int)signifIndex.size(); ++iNote) {
                     // cerr << mode << endl;
                     chroma[signifIndex[iNote] % 12] += x[iNote] * treblewindow[signifIndex[iNote]];
                     basschroma[signifIndex[iNote] % 12] += x[iNote] * basswindow[signifIndex[iNote]];
@@ -466,7 +466,7 @@
                 break;
             }
             if (chromanorm[2] > 0) {
-                for (int i = 0; i < chroma.size(); i++) {
+                for (int i = 0; i < (int)chroma.size(); i++) {
                     currentChromas.values[i] /= chromanorm[2];
                 }
             }
@@ -536,7 +536,7 @@
         fsOut[m_outputChords].push_back(chord_feature);
         
         chordchange[0] = 0;
-        for (int iFrame = 1; iFrame < chordpath.size(); ++iFrame) {
+        for (int iFrame = 1; iFrame < (int)chordpath.size(); ++iFrame) {
             // cerr << chordpath[iFrame] << endl;
             if (chordpath[iFrame] != oldchord ) {
                 // chord
@@ -547,12 +547,12 @@
                 fsOut[m_outputChords].push_back(chord_feature);
                 oldchord = chordpath[iFrame];         
                 // chord notes
-                for (int iNote = 0; iNote < oldnotes.size(); ++iNote) { // finish duration of old chord
+                for (int iNote = 0; iNote < (int)oldnotes.size(); ++iNote) { // finish duration of old chord
                     oldnotes[iNote].duration = oldnotes[iNote].duration + timestamps[iFrame];
                     fsOut[m_outputChordnotes].push_back(oldnotes[iNote]);
                 }
                 oldnotes.clear();
-                for (int iNote = 0; iNote < m_chordnotes[chordpath[iFrame]].size(); ++iNote) { // prepare notes of current chord
+                for (int iNote = 0; iNote < (int)m_chordnotes[chordpath[iFrame]].size(); ++iNote) { // prepare notes of current chord
                     Feature chordnote_feature;
                     chordnote_feature.hasTimestamp = true;
                     chordnote_feature.timestamp = timestamps[iFrame];
@@ -589,13 +589,13 @@
             float chordThreshold = 2.5/nChord;//*(2*halfwindowlength+1);
 
             vector<int> chordCandidates;
-            for (unsigned iChord = 0; iChord < nChord-1; iChord++) {
+            for (int iChord = 0; iChord+1 < nChord; iChord++) {
                 // float currsum = 0;
-                // for (unsigned iFrame = startIndex; iFrame < endIndex; ++iFrame) {
+                // for (int iFrame = startIndex; iFrame < endIndex; ++iFrame) {
                 //  currsum += chordogram[iFrame][iChord];
                 // }
                 //                 if (currsum > chordThreshold) chordCandidates.push_back(iChord);
-                for (unsigned iFrame = startIndex; iFrame < endIndex; ++iFrame) {
+                for (int iFrame = startIndex; iFrame < endIndex; ++iFrame) {
                     if (chordogram[iFrame][iChord] > chordThreshold) {
                         chordCandidates.push_back(iChord);
                         break;
@@ -607,18 +607,18 @@
 
             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
+            int bestchordL = nChord-1; // index of the best "left" chord
+            int 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];
+                int maxindL = nChord-1;
+                for (int kChord = 0; kChord < (int)chordCandidates.size(); kChord++) {
+                    int iChord = chordCandidates[kChord];
                     float currsum = 0;
-                    for (unsigned iFrame = 0; iFrame < iWF-1; ++iFrame) {
+                    for (int iFrame = 0; iFrame < iWF-1; ++iFrame) {
                         currsum += chordogram[count+iFrame][iChord];
                     }
                     if (iChord == nChord-1) currsum *= 0.8;
@@ -629,11 +629,11 @@
                 }				
                 // right side:
                 float maxR = 0;
-                unsigned maxindR = nChord-1;
-                for (unsigned kChord = 0; kChord < chordCandidates.size(); kChord++) {
-                    unsigned iChord = chordCandidates[kChord];
+                int maxindR = nChord-1;
+                for (int kChord = 0; kChord < (int)chordCandidates.size(); kChord++) {
+                    int iChord = chordCandidates[kChord];
                     float currsum = 0;
-                    for (unsigned iFrame = iWF-1; iFrame < 2*halfwindowlength; ++iFrame) {
+                    for (int iFrame = iWF-1; iFrame < 2*halfwindowlength; ++iFrame) {
                         currsum += chordogram[count+iFrame][iChord];
                     }
                     if (iChord == nChord-1) currsum *= 0.8;
@@ -652,10 +652,10 @@
             }
             // 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) {
+            for (int iFrame = 0; iFrame < maxindex-1; ++iFrame) {
                 scoreChordogram[iFrame+count][bestchordL]++;
             }
-            for (unsigned iFrame = maxindex-1; iFrame < 2*halfwindowlength; ++iFrame) {
+            for (int iFrame = maxindex-1; iFrame < 2*halfwindowlength; ++iFrame) {
                 scoreChordogram[iFrame+count][bestchordR]++;
             }
             if (bestchordL != bestchordR) {
@@ -668,7 +668,7 @@
         for (vector<Vamp::RealTime>::iterator it = timestamps.begin(); it != timestamps.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++) {
+            for (int iChord = 0; iChord < nChord; iChord++) {
                 if (scoreChordogram[count][iChord] > maxval) {
                     maxval = scoreChordogram[count][iChord];
                     maxindex = iChord;
@@ -713,12 +713,12 @@
                 oldChord = maxChord;
                 chord_feature.label = m_chordnames[maxChordIndex];
                 fsOut[m_outputChords].push_back(chord_feature);
-                for (int iNote = 0; iNote < oldnotes.size(); ++iNote) { // finish duration of old chord
+                for (int iNote = 0; iNote < (int)oldnotes.size(); ++iNote) { // finish duration of old chord
                     oldnotes[iNote].duration = oldnotes[iNote].duration + chord_feature.timestamp;
                     fsOut[m_outputChordnotes].push_back(oldnotes[iNote]);
                 }
                 oldnotes.clear();
-                for (int iNote = 0; iNote < m_chordnotes[maxChordIndex].size(); ++iNote) { // prepare notes of current chord
+                for (int iNote = 0; iNote < (int)m_chordnotes[maxChordIndex].size(); ++iNote) { // prepare notes of current chord
                     Feature chordnote_feature;
                     chordnote_feature.hasTimestamp = true;
                     chordnote_feature.timestamp = chord_feature.timestamp;
@@ -737,7 +737,7 @@
     chord_feature.label = "N";
     fsOut[m_outputChords].push_back(chord_feature);
     
-    for (int iNote = 0; iNote < oldnotes.size(); ++iNote) { // finish duration of old chord
+    for (int iNote = 0; iNote < (int)oldnotes.size(); ++iNote) { // finish duration of old chord
         oldnotes[iNote].duration = oldnotes[iNote].duration + timestamps[timestamps.size()-1];
         fsOut[m_outputChordnotes].push_back(oldnotes[iNote]);
     }
--- a/NNLSBase.cpp	Fri Dec 03 19:02:42 2010 +0900
+++ b/NNLSBase.cpp	Fri Dec 03 19:10:09 2010 +0900
@@ -39,23 +39,22 @@
     m_localTunings(0),
     m_whitening(1.0),
     m_preset(0.0),
-    m_useNNLS(1),
-	m_useHMM(1),
-    m_localTuning(0),
+    m_useNNLS(1.0),
+	m_useHMM(1.0),
+    m_localTuning(0.0),
     m_kernelValue(0),
     m_kernelFftIndex(0),
     m_kernelNoteIndex(0),
     m_dict(0),
-    m_tuneLocal(0),
+    m_tuneLocal(0.0),
     m_doNormalizeChroma(0),
-    m_rollon(0),
-    m_boostN(1.1),
+    m_rollon(0.0),
+    m_boostN(0.1),
 	m_s(0.7),
 	sinvalues(0),
 	cosvalues(0)
 {
     if (debug_on) cerr << "--> NNLSBase" << endl;
-
     // make the *note* dictionary matrix
     m_dict = new float[nNote * 84];
     for (unsigned i = 0; i < nNote * 84; ++i) m_dict[i] = 0.0;
@@ -83,7 +82,7 @@
     if (debug_on) cerr << "--> getPluginVersion" << endl;
     // Increment this each time you release a version that behaves
     // differently from the previous one
-    return 1;
+    return 2;
 }
 
 string
@@ -394,8 +393,8 @@
     m_kernelFftIndex.clear();
     m_kernelNoteIndex.clear();
     int countNonzero = 0;
-    for (unsigned iNote = 0; iNote < nNote; ++iNote) { // I don't know if this is wise: manually making a sparse matrix
-        for (unsigned iFFT = 0; iFFT < blockSize/2; ++iFFT) {
+    for (int iNote = 0; iNote < nNote; ++iNote) { // I don't know if this is wise: manually making a sparse matrix
+        for (int iFFT = 0; iFFT < blockSize/2; ++iFFT) {
             if (tempkernel[iFFT + blockSize/2 * iNote] > 0) {
                 m_kernelValue.push_back(tempkernel[iFFT + blockSize/2 * iNote]);
                 if (tempkernel[iFFT + blockSize/2 * iNote] > 0) {
@@ -448,7 +447,8 @@
     float maxmag = -10000;
     for (size_t iBin = 0; iBin < m_blockSize/2; iBin++) {
         magnitude[iBin] = sqrt(fbuf[2 * iBin] * fbuf[2 * iBin] + 
-                               fbuf[2 * iBin + 1] * fbuf[2 * iBin + 1]);		
+                               fbuf[2 * iBin + 1] * fbuf[2 * iBin + 1]);
+        if (magnitude[iBin]>m_blockSize*1.0) magnitude[iBin] = m_blockSize; // a valid audio signal (between -1 and 1) should not be limited here.
         if (maxmag < magnitude[iBin]) maxmag = magnitude[iBin];
         if (m_rollon > 0) {
             energysum += pow(magnitude[iBin],2);
@@ -473,7 +473,7 @@
 		
     // note magnitude mapping using pre-calculated matrix
     float *nm  = new float[nNote]; // note magnitude
-    for (size_t iNote = 0; iNote < nNote; iNote++) {
+    for (int iNote = 0; iNote < nNote; iNote++) {
         nm[iNote] = 0; // initialise as 0
     }
     int binCount = 0;
@@ -517,7 +517,7 @@
     Feature f1; // logfreqspec
     f1.hasTimestamp = true;
     f1.timestamp = timestamp;
-    for (size_t iNote = 0; iNote < nNote; iNote++) {
+    for (int iNote = 0; iNote < nNote; iNote++) {
         f1.values.push_back(nm[iNote]);
     }
 
@@ -528,534 +528,3 @@
     m_logSpectrum.push_back(f1); // remember note magnitude
 }
 
-
-#ifdef NOT_DEFINED
-
-NNLSBase::FeatureSet
-NNLSBase::getRemainingFeatures()
-{
-    // 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 ... ";
-    //    }
-    // 
-    //      
-    //    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;     
-
-}
-
-#endif
--- a/NNLSChroma.cpp	Fri Dec 03 19:02:42 2010 +0900
+++ b/NNLSChroma.cpp	Fri Dec 03 19:10:09 2010 +0900
@@ -408,14 +408,14 @@
                 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++) {
+                for (int iNote = 0; iNote < (int)signifIndex.size(); ++iNote) {
+                    for (int 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) {
+                for (int iNote = 0; iNote < (int)signifIndex.size(); ++iNote) {
                     f3.values[signifIndex[iNote]] = x[iNote];
                     // cerr << mode << endl;
                     chroma[signifIndex[iNote] % 12] += x[iNote] * treblewindow[signifIndex[iNote]];
@@ -481,17 +481,17 @@
                 break;
             }
             if (chromanorm[0] > 0) {
-                for (int i = 0; i < f4.values.size(); i++) {
+                for (size_t 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++) {
+                for (size_t 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++) {
+                for (size_t i = 0; i < f6.values.size(); i++) {
                     f6.values[i] /= chromanorm[2];
                 }
             }
--- a/README	Fri Dec 03 19:02:42 2010 +0900
+++ b/README	Fri Dec 03 19:10:09 2010 +0900
@@ -30,6 +30,7 @@
 * Bass Chromagram: a 12-dimensional chromagram, restricted to the bass range. At each frame the Semitone Spectrum is multiplied by a bass pattern and then mapped to the 12 chroma bins. 
 * Chromagram: a 12-dimensional chromagram, restricted with mid-range emphasis. At each frame the Semitone Spectrum is multiplied by a mid-range pattern and then mapped to the 12 chroma bins.
 * Chromagram and Bass Chromagram: a 24-dimensional chromagram, consisting of the both Bass Chromgram and Chromagram, see above. When normalisation is used, this representation will however be scaled differently, and hence be different from the individual chromagrams.
+* Consonance estimate: A simple consonance value based on the convolution of a consonance profile with the Semitone Spectrum. Experimental status. Compare two pieces of audio in terms of consonance if the instrumentation is similar. Instruments with fluctuating pitches (also: voice) will decrease the consonance value.
 
 ### Chordino ###
 
@@ -49,11 +50,13 @@
 * spectral whitening (0.0 -- 1.0; default: 1.0): determines how much the log-frequency spectrum is whitened. A value of 0.0 means no whitening. For values other than 0.0 the log-freq spectral bins are divided by  [standard deviation of their neighbours]^[spectral whitening], where "^" means "to the power of".
 * spectral shape (0.5 -- 0.9; default: 0.7): the shape of the notes in the NNLS dictionary. Their harmonic amplitude follows a geometrically decreasing pattern, in which the i-th harmonic has an amplitude of [spectral shape]^[i-1], where "^" means "to the power of".
 * chroma normalisation (none, maximum norm, L1 norm, L2 norm; default: none): determines whether or how the chromagrams are normalised. If the setting is not 'none', then each chroma frame separately is divided by the chosen vector norm. Note that normalisation implies that the joint 24-dim. "Chroma and Bass Chromagram" output will be different from the individual 12-dim. "Chromagram" and "Bass Chromagram" outputs.
+* boost likelihood of the N (no chord) label (0.0 -- 1.0; default: 0.1): leads to greater values in the profile of the "no chord" chord, hence non-harmonic parts of audio files are more likely to be recogised as such. Warning: for values above the default, it quickly leads to many chords being misclassified as N.
 
 #### Outputs ####
 
 * Chord Estimate: estimated chord times and labels.
 * Harmonic Change Value: an indication of the likelihood of harmonic change. Depends on the chord dictionary. Calculation is different depending on whether the Viterbi algorithm is used for chord estimation, or the simple chord estimate.
+* Note Representation of Chord Estimate: a simple MIDI-like represenation of the estimated chord with bass note (if applicable) and chord notes. Can be used, for example, to export MIDI chords from Sonic Visuliser.
 
 ### Tuning ###
 
--- a/chromamethods.cpp	Fri Dec 03 19:02:42 2010 +0900
+++ b/chromamethods.cpp	Fri Dec 03 19:10:09 2010 +0900
@@ -119,7 +119,7 @@
 	
     // linear oversampled frequency vector
     vector<float> oversampled_f;
-    for (unsigned int i = 0; i < oversampling * blocksize/2; ++i) {
+    for (int i = 0; i < oversampling * blocksize/2; ++i) {
         oversampled_f.push_back(i * ((fs * 1.0 / blocksize) / oversampling));
     }
 	
@@ -195,16 +195,16 @@
     float floatbin;
     float curr_amp;
     // now for every combination calculate the matrix element
-    for (unsigned iOut = 0; iOut < 12 * (maxoctave - minoctave); ++iOut) {
+    for (int iOut = 0; iOut < 12 * (maxoctave - minoctave); ++iOut) {
         // cerr << iOut << endl;
-        for (unsigned iHarm = 1; iHarm <= 20; ++iHarm) {
+        for (int iHarm = 1; iHarm <= 20; ++iHarm) {
             curr_f = 440 * pow(2,(minMIDI-69+iOut)*1.0/12) * iHarm;
             // if (curr_f > cq_f[nNote-1])  break;
             floatbin = ((iOut + 1) * binspersemitone + 1) + binspersemitone * 12 * log2(iHarm);
             // cerr << floatbin << endl;
             curr_amp = pow(s_param,float(iHarm-1));
             // cerr << "curramp" << curr_amp << endl;
-            for (unsigned iNote = 0; iNote < nNote; ++iNote) {
+            for (int iNote = 0; iNote < nNote; ++iNote) {
                 if (abs(iNote+1.0-floatbin)<2) {
                     dm[iNote  + nNote * iOut] += cospuls(iNote+1.0, floatbin, binspersemitone + 0.0) * curr_amp;
                     // dm[iNote + nNote * iOut] += 1 * curr_amp;
@@ -342,7 +342,7 @@
     
     bool hasExternalDictinoary = true;
     
-    for (int i = 0; i < ppath.size(); ++i) {
+    for (size_t i = 0; i < ppath.size(); ++i) {
     	chordDictFilename = ppath[i] + "/" + chordDictBase;
     	cerr << "Looking for chord.dict in " << chordDictFilename << "..." ;
     	fstream fin;
@@ -353,7 +353,7 @@
     	    cerr << " success." << endl;
     	    break;
         } else {
-            if (i < ppath.size()-1) cerr << " (not found yet) ..." << endl;
+            if (i+1 < ppath.size()) cerr << " (not found yet) ..." << endl;
             else {
                 cerr << "* WARNING: failed to find chord dictionary, using default chord dictionary." << endl;
                 hasExternalDictinoary = false;                
@@ -366,8 +366,8 @@
     // int iElement = 0;
     int nChord = 0;
 	
-	vector<string> tempChordNames = staticChordnames();
-	vector<float> tempChordDict = staticChordvalues();
+    vector<string> tempChordNames = staticChordnames();
+    vector<float> tempChordDict = staticChordvalues();
     vector<string> loadedChordNames;
     vector<float> loadedChordDict;
     if (hasExternalDictinoary && chordDictFile.is_open()) {
@@ -400,21 +400,20 @@
         }
     }
     
-    
         
-    for (int iType = 0; iType < tempChordNames.size(); ++iType) {
+    for (int iType = 0; iType < (int)tempChordNames.size(); ++iType) {
         // now make all 12 chords of every type
-        for (unsigned iSemitone = 0; iSemitone < 12; iSemitone++) {	
+        for (int iSemitone = 0; iSemitone < 12; iSemitone++) {	
             vector<int> tempchordnotes;			
             // add bass slash notation
             string slashNotation = "";
-            for (unsigned kSemitone = 1; kSemitone < 12; kSemitone++) {
+            for (int kSemitone = 1; kSemitone < 12; kSemitone++) {
                 if (tempChordDict[24*iType+(kSemitone) % 12] > 0.99) {
                     slashNotation = bassnames[iSemitone][kSemitone];
                 }
             }
             if (slashNotation=="") tempchordnotes.push_back(MIDI_basenote + (iSemitone+12) % 12);
-            for (unsigned kSemitone = 0; kSemitone < 12; kSemitone++) { // bass pitch classes
+            for (int kSemitone = 0; kSemitone < 12; kSemitone++) { // bass pitch classes
                 // cerr << ((kSemitone - iSemitone + 12) % 12) << endl;
                 float bassValue = 0;
                 if (tempChordDict[24*iType+(kSemitone - iSemitone + 12) % 12]==1) {
@@ -425,7 +424,7 @@
                 }
                 loadedChordDict.push_back(bassValue);                        
             }
-            for (unsigned kSemitone = 0; kSemitone < 12; kSemitone++) { // chord pitch classes
+            for (int kSemitone = 0; kSemitone < 12; kSemitone++) { // chord pitch classes
                 loadedChordDict.push_back(tempChordDict[24*iType+((kSemitone - iSemitone + 12) % 12) + 12]);
                 if (tempChordDict[24*iType+((kSemitone - iSemitone + 12) % 12) + 12] > 0) tempchordnotes.push_back(MIDI_basenote + (kSemitone+12+6) % 12 - 6 + 24);
             }
@@ -456,7 +455,7 @@
     float exponent = 2.0;
     // float m_boostN = 1.1;
     // cerr << " N BOOST : " << boostN << endl << endl;
-    for (int iChord = 0; iChord < loadedChordDict.size()/24; iChord++) {
+    for (int iChord = 0; iChord < (int)loadedChordDict.size()/24; iChord++) {
         float sum = 0;
         float stand = 0;
         for (int iST = 0; iST < 24; ++iST) {
@@ -466,10 +465,10 @@
             // loadedChordDict[24 * iChord + iST] -= sum/24;
             stand += pow(abs(loadedChordDict[24 * iChord + iST]),exponent)/24;
         }
-        if (iChord < loadedChordDict.size()/24 - 1) {
-            stand = pow(stand,(float)1.0/exponent);
+        if (iChord < (int)loadedChordDict.size()/24 - 1) {
+            stand = powf(stand,1.0f/exponent);
         } else {
-            stand = pow(stand,(float)1.0/exponent) / boostN;
+            stand = powf(stand,1.0f/exponent) / (1+boostN);
         }
         for (int iST = 0; iST < 24; ++iST) {
             loadedChordDict[24 * iChord + iST] /= stand;            
@@ -480,7 +479,7 @@
 
 
     nChord = 0;
-    for (int i = 0; i < loadedChordNames.size(); i++) {
+    for (int i = 0; i < (int)loadedChordNames.size(); i++) {
         nChord++;
     }
     chordDictFile.close();
@@ -495,4 +494,4 @@
     return loadedChordNames;
 }
 
-    
\ No newline at end of file
+    
--- a/nnls-chroma.n3	Fri Dec 03 19:02:42 2010 +0900
+++ b/nnls-chroma.n3	Fri Dec 03 19:10:09 2010 +0900
@@ -42,6 +42,7 @@
     vamp:parameter   plugbase:chordino_param_tuningmode ;
     vamp:parameter   plugbase:chordino_param_whitening ;
     vamp:parameter   plugbase:chordino_param_s ;
+    vamp:parameter   plugbase:chordino_param_boostn ;
 
     vamp:output      plugbase:chordino_output_simplechord ;
     vamp:output      plugbase:chordino_output_chordnotes ;
@@ -110,6 +111,16 @@
     vamp:unit           ""  ;
     vamp:default_value   0.7 ;
     vamp:value_names     ();
+
+plugbase:chordino_param_boostn a  vamp:Parameter ;
+    vamp:identifier     "boostn" ;
+    dc:title            "Boost likelihood of the N (no chord) label." ;
+    dc:format           "" ;
+    vamp:min_value       0 ;
+    vamp:max_value       1 ;
+    vamp:unit           ""  ;
+    vamp:default_value   0.1 ;
+    vamp:value_names     ();
     .
 plugbase:chordino_output_simplechord a  vamp:SparseOutput ;
     vamp:identifier       "simplechord" ;
@@ -177,6 +188,7 @@
     vamp:output      plugbase:nnls-chroma_output_chroma ;
     vamp:output      plugbase:nnls-chroma_output_basschroma ;
     vamp:output      plugbase:nnls-chroma_output_bothchroma ;
+    vamp:output      plugbase:nnls-chroma_output_consonance ;
     .
 plugbase:nnls-chroma_param_useNNLS a  vamp:QuantizedParameter ;
     vamp:identifier     "useNNLS" ;
@@ -299,6 +311,17 @@
     vamp:bin_names        ( "A  (bass)" "Bb (bass)" "B  (bass)" "C  (bass)" "C# (bass)" "D  (bass)" "Eb (bass)" "E  (bass)" "F  (bass)" "F# (bass)" "G  (bass)" "Ab (bass)" "A" "Bb" "B" "C" "C#" "D" "Eb" "E" "F" "F#" "G" "Ab");
     vamp:computes_signal_type  af:Chromagram ;
     .
+
+plugbase:nnls-chroma_output_consonance a  vamp:DenseOutput ;
+    vamp:identifier       "consonance" ;
+    dc:title              "Consonance estimate." ;
+    dc:description        """A simple consonance value based on the convolution of a consonance profile with the semitone spectrum."""  ;
+    vamp:fixed_bin_count  "true" ;
+    vamp:unit             "" ;
+    vamp:bin_count        1 ; 
+    vamp:computes_signal_type  af:TonalChangeDetectionFunction;
+    .
+
 plugbase:tuning a   vamp:Plugin ;
     dc:title              "Tuning" ;
     vamp:name             "Tuning" ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/releasenotes-0.2.txt	Fri Dec 03 19:10:09 2010 +0900
@@ -0,0 +1,25 @@
+NNLS Chroma 0.2 -- Release Notes
+
+General Description:
+
+A Vamp plugin library for harmony and chord extraction with some features aimed at amateur musicians, and some at music information retrieval researchers.
+It contains the Chordino, NNLS Chroma and Tuning plugins.
+For more information see README or http://isophonics.net/nnls-chroma
+
+New features: 
+
+Chordino:
+* The new MIDI note output of the estimated chords allows, for example, instant playback of chord notes in Sonic Visualiser.
+* new parameter "boost N": allows better recognition of the "no chord" label N (default setting is 0.1, previous Chordino version had no boost, i.e. 0.0).
+
+NNLS Chroma:
+* new output "Consonance Estimate". Experimental attempt to capture the tonal consonance in at a given time. Based on the convolution of a simple consonance profile with the semitone spectrum.
+
+Bug fixes:
+
+* Default chord dictionary loads when no chord.dict file found in Vamp path.
+* Corrected parameter range for spectral rollon parameter (Chordino).
+* Semitone Spectrum has values at zero energy frames (NNLS Chroma).
+* Crash with non-standard input resolved (now amplitude-limited).
+* minor internal fixes.
+
--- a/viterbi.cpp	Fri Dec 03 19:02:42 2010 +0900
+++ b/viterbi.cpp	Fri Dec 03 19:10:09 2010 +0900
@@ -12,11 +12,6 @@
     if (trans[0].size() != nState || trans.size() != nState || obs[0].size() != nState) {
         cerr << "ERROR: matrix sizes inconsistent." << endl;
     }
-    
-    for (int iState = 0; iState < nState; ++iState) delta[iState] = init[iState];
-    for (int iFrame = 1; iFrame < nFrame; ++iFrame) {
-        for (int iState = 0; iState < nState; ++iState) delta[iFrame*nState + iState];
-    }
         
     // vector<vector<double> > delta; // "matrix" of conditional probabilities    
     vector<vector<int> > psi; //  "matrix" of remembered indices of the best transitions
@@ -28,7 +23,7 @@
     /* initialise first frame */
     // delta.push_back(init);    
     for (int iState = 0; iState < nState; ++iState) {
-        delta[iState] *= obs[0][iState];
+        delta[iState] = init[iState] * obs[0][iState];
         deltasum += delta[iState];
     }
     for (int iState = 0; iState < nState; ++iState) delta[iState] /= deltasum; // normalise (scale)