annotate dsp/chromagram/ChromaProcess.cpp @ 73:dcb555b90924

* 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 cannam
date Fri, 05 Jun 2009 15:12:39 +0000
parents 2e3f5d2d62c1
children
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 QM DSP Library
cannam@0 5
cannam@0 6 Centre for Digital Music, Queen Mary, University of London.
cannam@0 7 This file copyright 2005-2006 Christian Landone.
cannam@0 8 All rights reserved.
cannam@0 9 */
cannam@0 10
cannam@0 11
cannam@0 12 #include "ChromaProcess.h"
cannam@16 13 #include "maths/Histogram.h"
cannam@0 14 #include <math.h>
cannam@0 15 //////////////////////////////////////////////////////////////////////
cannam@0 16 // Construction/Destruction
cannam@0 17 //////////////////////////////////////////////////////////////////////
cannam@0 18
cannam@0 19 ChromaProcess::ChromaProcess()
cannam@0 20 {
cannam@0 21
cannam@0 22 }
cannam@0 23
cannam@0 24 ChromaProcess::~ChromaProcess()
cannam@0 25 {
cannam@0 26
cannam@0 27 }
cannam@0 28
cannam@0 29 int ChromaProcess::findChromaBias( vector<double> chromaVector, unsigned int BPO, unsigned int frames )
cannam@0 30 {
cannam@0 31 vector<double> newChroma;
cannam@0 32 vector<int> peakIndex;
cannam@0 33 vector<int> modPeakIndex;
cannam@0 34
cannam@0 35 unsigned int chromaLength = chromaVector.size();
cannam@0 36
cannam@0 37 unsigned int newLength = chromaLength + (2*BPO);
cannam@0 38
cannam@0 39 newChroma.resize( newLength );
cannam@0 40 newChroma.clear();
cannam@0 41
cannam@0 42 modPeakIndex.resize( newLength );
cannam@0 43 modPeakIndex.clear();
cannam@0 44
cannam@0 45 //adds last row at the top and first row at the bottom to create
cannam@0 46 //circularity - effectively adds 2 to the bpo-length of the vectors:
cannam@0 47
cannam@0 48 for( unsigned int i = 0; i < BPO; i++ )
cannam@0 49 {
cannam@0 50 newChroma.push_back( chromaVector[ chromaLength - BPO + i ] );
cannam@0 51 }
cannam@0 52
cannam@0 53 for( unsigned i = 0; i < chromaLength; i++ )
cannam@0 54 {
cannam@0 55 newChroma.push_back( chromaVector[ i ] );
cannam@0 56 }
cannam@0 57
cannam@0 58 for( unsigned i = 0; i < BPO; i++ )
cannam@0 59 {
cannam@0 60 newChroma.push_back( chromaVector[ i ] );
cannam@0 61 }
cannam@0 62
cannam@0 63 // pick peaks in the chroma
cannam@0 64 peakIndex = getPeaks( newChroma, BPO );
cannam@0 65
cannam@0 66 // modularises to res = bpo/12 bins:
cannam@0 67 // corrects the mod value for bin 3
cannam@0 68 modPeakIndex = mod( peakIndex, 3 );
cannam@0 69
cannam@0 70 // finds the highest concentration of peaks on the bpo/12 bin resolution
cannam@0 71 THistogram<int> m_hist(3);
cannam@0 72
cannam@0 73 double ave, adev, sdev, var, skew, ccurt;
cannam@0 74
cannam@0 75 m_hist.compute(modPeakIndex);
cannam@0 76
cannam@0 77 m_hist.getMoments( modPeakIndex, ave, adev, sdev, var, skew, ccurt );
cannam@0 78
cannam@0 79 vector <double> histogram = m_hist.geTHistogramD();
cannam@0 80 //////////////////////////////////////////////////////////////////////////////
cannam@0 81
cannam@0 82 ///////////////////////////////////////////////////////////////////////////
cannam@0 83 // Find actual bias from histogram
cannam@0 84 int minIdx, maxIdx;
cannam@0 85 double min, max;
cannam@0 86
cannam@0 87 findHistMaxMin( histogram, &max, &maxIdx, &min, &minIdx );
cannam@0 88
cannam@0 89 /*
cannam@0 90 FILE* foutchroma = fopen("../testdata/newchroma.bin","wb");
cannam@0 91 FILE* foutpeaks = fopen("../testdata/peaks.bin","wb");
cannam@0 92
cannam@0 93
cannam@0 94 fwrite( &chromaVector[0], sizeof(double), chromaVector.size(), foutchroma );
cannam@0 95 fwrite( &histogram[0], sizeof(double), histogram.size(), foutpeaks );
cannam@0 96
cannam@0 97 fclose( foutchroma );
cannam@0 98 fclose( foutpeaks );
cannam@0 99 */
cannam@0 100 return maxIdx - 1;
cannam@0 101 }
cannam@0 102
cannam@0 103
cannam@0 104 vector <int> ChromaProcess::getPeaks(vector <double> chroma, unsigned int BPO)
cannam@0 105 {
cannam@0 106 vector <int> peaks;
cannam@0 107
cannam@0 108 double pre = 0;
cannam@0 109 double post = 0;
cannam@0 110 double current = 0;
cannam@0 111
cannam@0 112 unsigned int BPOCounter = 0;
cannam@0 113 unsigned int mult = 0;
cannam@0 114 unsigned int idx = 0;
cannam@0 115
cannam@0 116 for( unsigned int i = 0; i < chroma.size() - 0; i++ )
cannam@0 117 {
cannam@0 118 BPOCounter++;
cannam@0 119
cannam@0 120 pre = chroma[ i ];
cannam@0 121 current = chroma[ i + 1 ];
cannam@0 122 post = chroma[ i + 2 ];
cannam@0 123
cannam@0 124 if( (current > 0) && (current > pre) && (current > post) )
cannam@0 125 {
cannam@0 126 peaks.push_back( BPOCounter + 1);
cannam@0 127 }
cannam@0 128
cannam@0 129
cannam@0 130 if( BPOCounter == (BPO - 2 ) )
cannam@0 131 {
cannam@0 132 BPOCounter = 0;
cannam@0 133 i+=2;
cannam@0 134 }
cannam@0 135
cannam@0 136 }
cannam@0 137
cannam@0 138 /*
cannam@0 139 for( unsigned int i = 1; i < chroma.size() - 1; i++ )
cannam@0 140 {
cannam@0 141 BPOCounter++ ;
cannam@0 142
cannam@0 143 pre = chroma[ i - 1 ];
cannam@0 144 current = chroma[ i ];
cannam@0 145 post = chroma[ i + 1 ];
cannam@0 146
cannam@0 147 if( (current > 0) && (current > pre) && (current > post) )
cannam@0 148 {
cannam@0 149 peaks.push_back( BPOCounter + 1 );
cannam@0 150 }
cannam@0 151
cannam@0 152 if( BPOCounter == (PO - 1) )
cannam@0 153 {
cannam@0 154 BPOCounter = 1;
cannam@0 155 i+=2;
cannam@0 156 }
cannam@0 157 }
cannam@0 158 */
cannam@0 159 return peaks;
cannam@0 160 }
cannam@0 161
cannam@0 162 vector <int> ChromaProcess::mod(vector <int> input, int res)
cannam@0 163 {
cannam@0 164 vector <int> result;
cannam@0 165
cannam@0 166 for( unsigned int i = 0; i < input.size(); i++ )
cannam@0 167 {
cannam@0 168 int val = input[ i ];
cannam@0 169 int res = val - res * floor( (double)val / (double)res );
cannam@0 170
cannam@0 171 if( val != 0 )
cannam@0 172 {
cannam@0 173 if( res == 0 )
cannam@0 174 res = 3;
cannam@0 175
cannam@0 176 result.push_back( res );
cannam@0 177 }
cannam@0 178 else
cannam@0 179 {
cannam@0 180 result.push_back( val );
cannam@0 181 }
cannam@0 182 }
cannam@0 183 return result;
cannam@0 184 }
cannam@0 185
cannam@0 186 void ChromaProcess::findHistMaxMin( vector<double> hist, double* max, int* maxIdx, double* min, int* minIdx )
cannam@0 187 {
cannam@0 188 double temp = 0.0;
cannam@0 189 unsigned int vecLength = hist.size();
cannam@0 190
cannam@0 191 *minIdx = 0;
cannam@0 192 *maxIdx = 0;
cannam@0 193
cannam@0 194 *min = hist[0];
cannam@0 195 *max = *min;
cannam@0 196
cannam@0 197 for( unsigned int u = 0; u < vecLength; u++ )
cannam@0 198 {
cannam@0 199 temp = hist[ u ];
cannam@0 200
cannam@0 201 if( temp < *min )
cannam@0 202 {
cannam@0 203 *min = temp ;
cannam@0 204 *minIdx = u;
cannam@0 205 }
cannam@0 206 if( temp > *max )
cannam@0 207 {
cannam@0 208 *max = temp ;
cannam@0 209 *maxIdx = u;
cannam@0 210 }
cannam@0 211
cannam@0 212 }
cannam@0 213 }