Mercurial > hg > qm-dsp
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) { |