comparison dsp/keydetection/GetKeyMode.cpp @ 461:9414df58fd0e

Fix an issue is a mutithreading context The global profile buffers where used concurrently by different threads leading to wrong detection results. This is fixed by using a local copy of the buffers. In addition, this commit also includes some minor performance improvements.
author Daniel Schürmann <daschuer@mixxx.org>
date Fri, 24 May 2019 21:40:47 +0200
parents 02cb97d2dee8
children 0076c66d2932
comparison
equal deleted inserted replaced
460:02cb97d2dee8 461:9414df58fd0e
59 { 59 {
60 m_DecimationFactor = 8; 60 m_DecimationFactor = 8;
61 61
62 // Chromagram configuration parameters 62 // Chromagram configuration parameters
63 m_ChromaConfig.normalise = MathUtilities::NormaliseUnitMax; 63 m_ChromaConfig.normalise = MathUtilities::NormaliseUnitMax;
64 m_ChromaConfig.FS = lrint(sampleRate/(double)m_DecimationFactor); 64 m_ChromaConfig.FS = sampleRate/(double)m_DecimationFactor;
65 if (m_ChromaConfig.FS < 1) { 65 if (m_ChromaConfig.FS < 1) {
66 m_ChromaConfig.FS = 1; 66 m_ChromaConfig.FS = 1;
67 } 67 }
68 68
69 // Set C (= MIDI #12) as our base : 69 // Set C3 (= MIDI #48) as our base:
70 // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc. 70 // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc.
71 m_ChromaConfig.min = Pitch::getFrequencyForPitch( 48, 0, tuningFrequency ); 71 m_ChromaConfig.min = Pitch::getFrequencyForPitch( 48, 0, tuningFrequency );
72 m_ChromaConfig.max = Pitch::getFrequencyForPitch( 96, 0, tuningFrequency ); 72 m_ChromaConfig.max = Pitch::getFrequencyForPitch( 96, 0, tuningFrequency );
73 73
74 m_ChromaConfig.BPO = kBinsPerOctave; 74 m_ChromaConfig.BPO = kBinsPerOctave;
102 m_MeanHPCP = new double[kBinsPerOctave]; 102 m_MeanHPCP = new double[kBinsPerOctave];
103 103
104 m_MajCorr = new double[kBinsPerOctave]; 104 m_MajCorr = new double[kBinsPerOctave];
105 m_MinCorr = new double[kBinsPerOctave]; 105 m_MinCorr = new double[kBinsPerOctave];
106 106
107 m_MajProfileNorm = new double[kBinsPerOctave];
108 m_MinProfileNorm = new double[kBinsPerOctave];
109
110 double mMaj = MathUtilities::mean( MajProfile, kBinsPerOctave );
111 double mMin = MathUtilities::mean( MinProfile, kBinsPerOctave );
112
113 for( unsigned int i = 0; i < kBinsPerOctave; i++ ) {
114 m_MajProfileNorm[i] = MajProfile[i] - mMaj;
115 m_MinProfileNorm[i] = MinProfile[i] - mMin;
116 }
117
107 m_MedianFilterBuffer = new int[ m_MedianWinsize ]; 118 m_MedianFilterBuffer = new int[ m_MedianWinsize ];
108 memset( m_MedianFilterBuffer, 0, sizeof(int)*m_MedianWinsize); 119 memset( m_MedianFilterBuffer, 0, sizeof(int)*m_MedianWinsize);
109 120
110 m_SortedBuffer = new int[ m_MedianWinsize ]; 121 m_SortedBuffer = new int[ m_MedianWinsize ];
111 memset( m_SortedBuffer, 0, sizeof(int)*m_MedianWinsize); 122 memset( m_SortedBuffer, 0, sizeof(int)*m_MedianWinsize);
123 delete [] m_DecimatedBuffer; 134 delete [] m_DecimatedBuffer;
124 delete [] m_ChromaBuffer; 135 delete [] m_ChromaBuffer;
125 delete [] m_MeanHPCP; 136 delete [] m_MeanHPCP;
126 delete [] m_MajCorr; 137 delete [] m_MajCorr;
127 delete [] m_MinCorr; 138 delete [] m_MinCorr;
139 delete [] m_MajProfileNorm;
140 delete [] m_MinProfileNorm;
128 delete [] m_MedianFilterBuffer; 141 delete [] m_MedianFilterBuffer;
129 delete [] m_SortedBuffer; 142 delete [] m_SortedBuffer;
130 delete [] m_keyStrengths; 143 delete [] m_keyStrengths;
131 } 144 }
132 145
133 double GetKeyMode::krumCorr(double *pData1, double *pData2, unsigned int length) 146 double GetKeyMode::krumCorr( const double *pDataNorm, const double *pProfileNorm,
147 int shiftProfile, unsigned int length)
134 { 148 {
135 double retVal= 0.0; 149 double retVal= 0.0;
136 150
137 double num = 0; 151 double num = 0;
138 double den = 0; 152 double den = 0;
139 double mX = MathUtilities::mean( pData1, length );
140 double mY = MathUtilities::mean( pData2, length );
141
142 double sum1 = 0; 153 double sum1 = 0;
143 double sum2 = 0; 154 double sum2 = 0;
144 155
145 for( unsigned int i = 0; i <length; i++ ) { 156 for( unsigned int i = 0; i <length; i++ )
146 num += ( pData1[i] - mX ) * ( pData2[i] - mY ); 157 {
147 158 int k = (i - shiftProfile + length) % length;
148 sum1 += ( (pData1[i]-mX) * (pData1[i]-mX) ); 159
149 sum2 += ( (pData2[i]-mY) * (pData2[i]-mY) ); 160 num += pDataNorm[i] * pProfileNorm[k];
150 } 161
151 162 sum1 += ( pDataNorm[i] * pDataNorm[i] );
163 sum2 += ( pProfileNorm[k] * pProfileNorm[k] );
164 }
165
152 den = sqrt(sum1 * sum2); 166 den = sqrt(sum1 * sum2);
153 167
154 if( den>0 ) { 168 if( den>0 ) {
155 retVal = num/den; 169 retVal = num/den;
156 } else { 170 } else {
168 ////////////////////////////////////////////// 182 //////////////////////////////////////////////
169 m_Decimator->process( PCMData, m_DecimatedBuffer); 183 m_Decimator->process( PCMData, m_DecimatedBuffer);
170 184
171 m_ChrPointer = m_Chroma->process( m_DecimatedBuffer ); 185 m_ChrPointer = m_Chroma->process( m_DecimatedBuffer );
172 186
173 // The Cromagram has the center of C at bin 0, while the major
174 // and minor profiles have the center of C at 1. We want to have
175 // the correlation for C result also at 1.
176 // To achieve this we have to shift two times:
177 MathUtilities::circShift( m_ChrPointer, kBinsPerOctave, 2);
178 /* 187 /*
179 std::cout << "raw chroma: "; 188 std::cout << "raw chroma: ";
180 for (int ii = 0; ii < kBinsPerOctave; ++ii) { 189 for (int ii = 0; ii < kBinsPerOctave; ++ii) {
181 if (ii % (kBinsPerOctave/12) == 0) std::cout << "\n"; 190 if (ii % (kBinsPerOctave/12) == 0) std::cout << "\n";
182 std::cout << m_ChrPointer[ii] << " "; 191 std::cout << m_ChrPointer[ii] << " ";
208 } 217 }
209 218
210 m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling; 219 m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling;
211 } 220 }
212 221
213 222 // Normalize for zero average
214 for( k = 0; k < kBinsPerOctave; k++ ) { 223 double mHPCP = MathUtilities::mean( m_MeanHPCP, kBinsPerOctave );
215 m_MajCorr[k] = krumCorr( m_MeanHPCP, MajProfile, kBinsPerOctave ); 224 for( k = 0; k < kBinsPerOctave; k++ )
216 m_MinCorr[k] = krumCorr( m_MeanHPCP, MinProfile, kBinsPerOctave ); 225 {
217 226 m_MeanHPCP[k] -= mHPCP;
218 MathUtilities::circShift( MajProfile, kBinsPerOctave, 1 ); 227 }
219 MathUtilities::circShift( MinProfile, kBinsPerOctave, 1 ); 228
229
230 for( k = 0; k < kBinsPerOctave; k++ )
231 {
232 // The Cromagram has the center of C at bin 0, while the major
233 // and minor profiles have the center of C at 1. We want to have
234 // the correlation for C result also at 1.
235 // To achieve this we have to shift two times:
236 m_MajCorr[k] = krumCorr( m_MeanHPCP, m_MajProfileNorm, (int)k - 2, kBinsPerOctave );
237 m_MinCorr[k] = krumCorr( m_MeanHPCP, m_MinProfileNorm, (int)k - 2, kBinsPerOctave );
220 } 238 }
221 239
222 /* 240 /*
223 std::cout << "raw keys: "; 241 std::cout << "raw keys: ";
224 for (int ii = 0; ii < kBinsPerOctave; ++ii) { 242 for (int ii = 0; ii < kBinsPerOctave; ++ii) {