annotate dsp/chromagram/ChromaProcess.cpp @ 298:255e431ae3d4

* Key detector: when returning key strengths, use the peak value of the three underlying chromagram correlations (from 36-bin chromagram) corresponding to each key, instead of the mean. Rationale: This is the same method as used when returning the key value, and it's nice to have the same results in both returned value and plot. The peak performed better than the sum with a simple test set of triads, so it seems reasonable to change the plot to match the key output rather than the other way around. * FFT: kiss_fftr returns only the non-conjugate bins, synthesise the rest rather than leaving them (perhaps dangerously) undefined. Fixes an uninitialised data error in chromagram that could cause garbage results from key detector. * Constant Q: remove precalculated values again, I reckon they're not proving such a good tradeoff.
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 05 Jun 2009 15:12:39 +0000
parents a98dd8ec96f8
children
rev   line source
c@225 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@225 2
c@225 3 /*
c@225 4 QM DSP Library
c@225 5
c@225 6 Centre for Digital Music, Queen Mary, University of London.
c@225 7 This file copyright 2005-2006 Christian Landone.
c@225 8 All rights reserved.
c@225 9 */
c@225 10
c@225 11
c@225 12 #include "ChromaProcess.h"
c@241 13 #include "maths/Histogram.h"
c@225 14 #include <math.h>
c@225 15 //////////////////////////////////////////////////////////////////////
c@225 16 // Construction/Destruction
c@225 17 //////////////////////////////////////////////////////////////////////
c@225 18
c@225 19 ChromaProcess::ChromaProcess()
c@225 20 {
c@225 21
c@225 22 }
c@225 23
c@225 24 ChromaProcess::~ChromaProcess()
c@225 25 {
c@225 26
c@225 27 }
c@225 28
c@225 29 int ChromaProcess::findChromaBias( vector<double> chromaVector, unsigned int BPO, unsigned int frames )
c@225 30 {
c@225 31 vector<double> newChroma;
c@225 32 vector<int> peakIndex;
c@225 33 vector<int> modPeakIndex;
c@225 34
c@225 35 unsigned int chromaLength = chromaVector.size();
c@225 36
c@225 37 unsigned int newLength = chromaLength + (2*BPO);
c@225 38
c@225 39 newChroma.resize( newLength );
c@225 40 newChroma.clear();
c@225 41
c@225 42 modPeakIndex.resize( newLength );
c@225 43 modPeakIndex.clear();
c@225 44
c@225 45 //adds last row at the top and first row at the bottom to create
c@225 46 //circularity - effectively adds 2 to the bpo-length of the vectors:
c@225 47
c@225 48 for( unsigned int i = 0; i < BPO; i++ )
c@225 49 {
c@225 50 newChroma.push_back( chromaVector[ chromaLength - BPO + i ] );
c@225 51 }
c@225 52
c@225 53 for( unsigned i = 0; i < chromaLength; i++ )
c@225 54 {
c@225 55 newChroma.push_back( chromaVector[ i ] );
c@225 56 }
c@225 57
c@225 58 for( unsigned i = 0; i < BPO; i++ )
c@225 59 {
c@225 60 newChroma.push_back( chromaVector[ i ] );
c@225 61 }
c@225 62
c@225 63 // pick peaks in the chroma
c@225 64 peakIndex = getPeaks( newChroma, BPO );
c@225 65
c@225 66 // modularises to res = bpo/12 bins:
c@225 67 // corrects the mod value for bin 3
c@225 68 modPeakIndex = mod( peakIndex, 3 );
c@225 69
c@225 70 // finds the highest concentration of peaks on the bpo/12 bin resolution
c@225 71 THistogram<int> m_hist(3);
c@225 72
c@225 73 double ave, adev, sdev, var, skew, ccurt;
c@225 74
c@225 75 m_hist.compute(modPeakIndex);
c@225 76
c@225 77 m_hist.getMoments( modPeakIndex, ave, adev, sdev, var, skew, ccurt );
c@225 78
c@225 79 vector <double> histogram = m_hist.geTHistogramD();
c@225 80 //////////////////////////////////////////////////////////////////////////////
c@225 81
c@225 82 ///////////////////////////////////////////////////////////////////////////
c@225 83 // Find actual bias from histogram
c@225 84 int minIdx, maxIdx;
c@225 85 double min, max;
c@225 86
c@225 87 findHistMaxMin( histogram, &max, &maxIdx, &min, &minIdx );
c@225 88
c@225 89 /*
c@225 90 FILE* foutchroma = fopen("../testdata/newchroma.bin","wb");
c@225 91 FILE* foutpeaks = fopen("../testdata/peaks.bin","wb");
c@225 92
c@225 93
c@225 94 fwrite( &chromaVector[0], sizeof(double), chromaVector.size(), foutchroma );
c@225 95 fwrite( &histogram[0], sizeof(double), histogram.size(), foutpeaks );
c@225 96
c@225 97 fclose( foutchroma );
c@225 98 fclose( foutpeaks );
c@225 99 */
c@225 100 return maxIdx - 1;
c@225 101 }
c@225 102
c@225 103
c@225 104 vector <int> ChromaProcess::getPeaks(vector <double> chroma, unsigned int BPO)
c@225 105 {
c@225 106 vector <int> peaks;
c@225 107
c@225 108 double pre = 0;
c@225 109 double post = 0;
c@225 110 double current = 0;
c@225 111
c@225 112 unsigned int BPOCounter = 0;
c@225 113 unsigned int mult = 0;
c@225 114 unsigned int idx = 0;
c@225 115
c@225 116 for( unsigned int i = 0; i < chroma.size() - 0; i++ )
c@225 117 {
c@225 118 BPOCounter++;
c@225 119
c@225 120 pre = chroma[ i ];
c@225 121 current = chroma[ i + 1 ];
c@225 122 post = chroma[ i + 2 ];
c@225 123
c@225 124 if( (current > 0) && (current > pre) && (current > post) )
c@225 125 {
c@225 126 peaks.push_back( BPOCounter + 1);
c@225 127 }
c@225 128
c@225 129
c@225 130 if( BPOCounter == (BPO - 2 ) )
c@225 131 {
c@225 132 BPOCounter = 0;
c@225 133 i+=2;
c@225 134 }
c@225 135
c@225 136 }
c@225 137
c@225 138 /*
c@225 139 for( unsigned int i = 1; i < chroma.size() - 1; i++ )
c@225 140 {
c@225 141 BPOCounter++ ;
c@225 142
c@225 143 pre = chroma[ i - 1 ];
c@225 144 current = chroma[ i ];
c@225 145 post = chroma[ i + 1 ];
c@225 146
c@225 147 if( (current > 0) && (current > pre) && (current > post) )
c@225 148 {
c@225 149 peaks.push_back( BPOCounter + 1 );
c@225 150 }
c@225 151
c@225 152 if( BPOCounter == (PO - 1) )
c@225 153 {
c@225 154 BPOCounter = 1;
c@225 155 i+=2;
c@225 156 }
c@225 157 }
c@225 158 */
c@225 159 return peaks;
c@225 160 }
c@225 161
c@225 162 vector <int> ChromaProcess::mod(vector <int> input, int res)
c@225 163 {
c@225 164 vector <int> result;
c@225 165
c@225 166 for( unsigned int i = 0; i < input.size(); i++ )
c@225 167 {
c@225 168 int val = input[ i ];
c@225 169 int res = val - res * floor( (double)val / (double)res );
c@225 170
c@225 171 if( val != 0 )
c@225 172 {
c@225 173 if( res == 0 )
c@225 174 res = 3;
c@225 175
c@225 176 result.push_back( res );
c@225 177 }
c@225 178 else
c@225 179 {
c@225 180 result.push_back( val );
c@225 181 }
c@225 182 }
c@225 183 return result;
c@225 184 }
c@225 185
c@225 186 void ChromaProcess::findHistMaxMin( vector<double> hist, double* max, int* maxIdx, double* min, int* minIdx )
c@225 187 {
c@225 188 double temp = 0.0;
c@225 189 unsigned int vecLength = hist.size();
c@225 190
c@225 191 *minIdx = 0;
c@225 192 *maxIdx = 0;
c@225 193
c@225 194 *min = hist[0];
c@225 195 *max = *min;
c@225 196
c@225 197 for( unsigned int u = 0; u < vecLength; u++ )
c@225 198 {
c@225 199 temp = hist[ u ];
c@225 200
c@225 201 if( temp < *min )
c@225 202 {
c@225 203 *min = temp ;
c@225 204 *minIdx = u;
c@225 205 }
c@225 206 if( temp > *max )
c@225 207 {
c@225 208 *max = temp ;
c@225 209 *maxIdx = u;
c@225 210 }
c@225 211
c@225 212 }
c@225 213 }