Mercurial > hg > qm-dsp
comparison dsp/keydetection/GetKeyMode.cpp @ 458:e7e36ecd7ad2
make m_BPO const and rename to kBinsPerOctave
author | Daniel Schürmann <daschuer@mixxx.org> |
---|---|
date | Fri, 24 May 2019 20:31:32 +0200 |
parents | 8a8cf7296e58 |
children | b7e10277a84c |
comparison
equal
deleted
inserted
replaced
457:8a8cf7296e58 | 458:e7e36ecd7ad2 |
---|---|
20 #include <iostream> | 20 #include <iostream> |
21 | 21 |
22 #include <cstring> | 22 #include <cstring> |
23 #include <cstdlib> | 23 #include <cstdlib> |
24 | 24 |
25 static const int kBinsPerOctave = 36; | |
26 | |
25 // Chords profile | 27 // Chords profile |
26 static double MajProfile[36] = { | 28 static double MajProfile[kBinsPerOctave] = { |
27 0.0384, 0.0629, 0.0258, 0.0121, 0.0146, 0.0106, 0.0364, 0.0610, 0.0267, | 29 0.0384, 0.0629, 0.0258, 0.0121, 0.0146, 0.0106, 0.0364, 0.0610, 0.0267, |
28 0.0126, 0.0121, 0.0086, 0.0364, 0.0623, 0.0279, 0.0275, 0.0414, 0.0186, | 30 0.0126, 0.0121, 0.0086, 0.0364, 0.0623, 0.0279, 0.0275, 0.0414, 0.0186, |
29 0.0173, 0.0248, 0.0145, 0.0364, 0.0631, 0.0262, 0.0129, 0.0150, 0.0098, | 31 0.0173, 0.0248, 0.0145, 0.0364, 0.0631, 0.0262, 0.0129, 0.0150, 0.0098, |
30 0.0312, 0.0521, 0.0235, 0.0129, 0.0142, 0.0095, 0.0289, 0.0478, 0.0239}; | 32 0.0312, 0.0521, 0.0235, 0.0129, 0.0142, 0.0095, 0.0289, 0.0478, 0.0239}; |
31 | 33 |
32 static double MinProfile[36] = { | 34 static double MinProfile[kBinsPerOctave] = { |
33 0.0375, 0.0682, 0.0299, 0.0119, 0.0138, 0.0093, 0.0296, 0.0543, 0.0257, | 35 0.0375, 0.0682, 0.0299, 0.0119, 0.0138, 0.0093, 0.0296, 0.0543, 0.0257, |
34 0.0292, 0.0519, 0.0246, 0.0159, 0.0234, 0.0135, 0.0291, 0.0544, 0.0248, | 36 0.0292, 0.0519, 0.0246, 0.0159, 0.0234, 0.0135, 0.0291, 0.0544, 0.0248, |
35 0.0137, 0.0176, 0.0104, 0.0352, 0.0670, 0.0302, 0.0222, 0.0349, 0.0164, | 37 0.0137, 0.0176, 0.0104, 0.0352, 0.0670, 0.0302, 0.0222, 0.0349, 0.0164, |
36 0.0174, 0.0297, 0.0166, 0.0222, 0.0401, 0.0202, 0.0175, 0.0270, 0.0146}; | 38 0.0174, 0.0297, 0.0166, 0.0222, 0.0401, 0.0202, 0.0175, 0.0270, 0.0146}; |
37 // | 39 // |
68 // Set C (= MIDI #12) as our base : | 70 // Set C (= MIDI #12) as our base : |
69 // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc. | 71 // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc. |
70 m_ChromaConfig.min = Pitch::getFrequencyForPitch( 48, 0, tuningFrequency ); | 72 m_ChromaConfig.min = Pitch::getFrequencyForPitch( 48, 0, tuningFrequency ); |
71 m_ChromaConfig.max = Pitch::getFrequencyForPitch( 96, 0, tuningFrequency ); | 73 m_ChromaConfig.max = Pitch::getFrequencyForPitch( 96, 0, tuningFrequency ); |
72 | 74 |
73 m_ChromaConfig.BPO = 36; | 75 m_ChromaConfig.BPO = kBinsPerOctave; |
74 m_ChromaConfig.CQThresh = 0.0054; | 76 m_ChromaConfig.CQThresh = 0.0054; |
75 | 77 |
76 // Chromagram inst. | 78 // Chromagram inst. |
77 m_Chroma = new Chromagram( m_ChromaConfig ); | 79 m_Chroma = new Chromagram( m_ChromaConfig ); |
78 | 80 |
79 // Get calculated parameters from chroma object | 81 // Get calculated parameters from chroma object |
80 m_ChromaFrameSize = m_Chroma->getFrameSize(); | 82 m_ChromaFrameSize = m_Chroma->getFrameSize(); |
81 // override hopsize for this application | 83 // override hopsize for this application |
82 m_ChromaHopSize = m_ChromaFrameSize; | 84 m_ChromaHopSize = m_ChromaFrameSize; |
83 m_BPO = m_ChromaConfig.BPO; | |
84 | 85 |
85 // std::cerr << "chroma frame size = " << m_ChromaFrameSize << ", decimation factor = " << m_DecimationFactor << " therefore block size = " << getBlockSize() << std::endl; | 86 // std::cerr << "chroma frame size = " << m_ChromaFrameSize << ", decimation factor = " << m_DecimationFactor << " therefore block size = " << getBlockSize() << std::endl; |
86 | 87 |
87 // Chromagram average and estimated key median filter lengths | 88 // Chromagram average and estimated key median filter lengths |
88 m_ChromaBuffersize = (int)ceil( m_hpcpAverage * m_ChromaConfig.FS/m_ChromaFrameSize ); | 89 m_ChromaBuffersize = (int)ceil( m_hpcpAverage * m_ChromaConfig.FS/m_ChromaFrameSize ); |
94 m_MedianBufferFilling = 0; | 95 m_MedianBufferFilling = 0; |
95 | 96 |
96 // Spawn objectc/arrays | 97 // Spawn objectc/arrays |
97 m_DecimatedBuffer = new double[m_ChromaFrameSize]; | 98 m_DecimatedBuffer = new double[m_ChromaFrameSize]; |
98 | 99 |
99 m_ChromaBuffer = new double[m_BPO * m_ChromaBuffersize]; | 100 m_ChromaBuffer = new double[kBinsPerOctave * m_ChromaBuffersize]; |
100 memset( m_ChromaBuffer, 0, sizeof(double) * m_BPO * m_ChromaBuffersize); | 101 memset( m_ChromaBuffer, 0, sizeof(double) * kBinsPerOctave * m_ChromaBuffersize); |
101 | 102 |
102 m_MeanHPCP = new double[m_BPO]; | 103 m_MeanHPCP = new double[kBinsPerOctave]; |
103 | 104 |
104 m_MajCorr = new double[m_BPO]; | 105 m_MajCorr = new double[kBinsPerOctave]; |
105 m_MinCorr = new double[m_BPO]; | 106 m_MinCorr = new double[kBinsPerOctave]; |
106 m_Keys = new double[2*m_BPO]; | 107 m_Keys = new double[2*kBinsPerOctave]; |
107 | 108 |
108 m_MedianFilterBuffer = new int[ m_MedianWinsize ]; | 109 m_MedianFilterBuffer = new int[ m_MedianWinsize ]; |
109 memset( m_MedianFilterBuffer, 0, sizeof(int)*m_MedianWinsize); | 110 memset( m_MedianFilterBuffer, 0, sizeof(int)*m_MedianWinsize); |
110 | 111 |
111 m_SortedBuffer = new int[ m_MedianWinsize ]; | 112 m_SortedBuffer = new int[ m_MedianWinsize ]; |
175 | 176 |
176 // The Cromagram has the center of C at bin 0, while the major | 177 // The Cromagram has the center of C at bin 0, while the major |
177 // and minor profiles have the center of C at 1. We want to have | 178 // and minor profiles have the center of C at 1. We want to have |
178 // the correlation for C result also at 1. | 179 // the correlation for C result also at 1. |
179 // To achieve this we have to shift two times: | 180 // To achieve this we have to shift two times: |
180 MathUtilities::circShift( m_ChrPointer, m_BPO, 2); | 181 MathUtilities::circShift( m_ChrPointer, kBinsPerOctave, 2); |
181 /* | 182 /* |
182 std::cout << "raw chroma: "; | 183 std::cout << "raw chroma: "; |
183 for (int ii = 0; ii < m_BPO; ++ii) { | 184 for (int ii = 0; ii < kBinsPerOctave; ++ii) { |
184 if (ii % (m_BPO/12) == 0) std::cout << "\n"; | 185 if (ii % (kBinsPerOctave/12) == 0) std::cout << "\n"; |
185 std::cout << m_ChrPointer[ii] << " "; | 186 std::cout << m_ChrPointer[ii] << " "; |
186 } | 187 } |
187 std::cout << std::endl; | 188 std::cout << std::endl; |
188 */ | 189 */ |
189 // populate hpcp values; | 190 // populate hpcp values; |
190 int cbidx; | 191 int cbidx; |
191 for( j = 0; j < m_BPO; j++ ) { | 192 for( j = 0; j < kBinsPerOctave; j++ ) { |
192 cbidx = (m_bufferindex * m_BPO) + j; | 193 cbidx = (m_bufferindex * kBinsPerOctave) + j; |
193 m_ChromaBuffer[ cbidx ] = m_ChrPointer[j]; | 194 m_ChromaBuffer[ cbidx ] = m_ChrPointer[j]; |
194 } | 195 } |
195 | 196 |
196 //keep track of input buffers; | 197 //keep track of input buffers; |
197 if( m_bufferindex++ >= m_ChromaBuffersize - 1) { | 198 if( m_bufferindex++ >= m_ChromaBuffersize - 1) { |
202 if( m_ChromaBufferFilling++ >= m_ChromaBuffersize) { | 203 if( m_ChromaBufferFilling++ >= m_ChromaBuffersize) { |
203 m_ChromaBufferFilling = m_ChromaBuffersize; | 204 m_ChromaBufferFilling = m_ChromaBuffersize; |
204 } | 205 } |
205 | 206 |
206 //calculate mean | 207 //calculate mean |
207 for( k = 0; k < m_BPO; k++ ) { | 208 for( k = 0; k < kBinsPerOctave; k++ ) { |
208 double mnVal = 0.0; | 209 double mnVal = 0.0; |
209 for( j = 0; j < m_ChromaBufferFilling; j++ ) { | 210 for( j = 0; j < m_ChromaBufferFilling; j++ ) { |
210 mnVal += m_ChromaBuffer[ k + (j*m_BPO) ]; | 211 mnVal += m_ChromaBuffer[ k + (j*kBinsPerOctave) ]; |
211 } | 212 } |
212 | 213 |
213 m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling; | 214 m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling; |
214 } | 215 } |
215 | 216 |
216 | 217 |
217 for( k = 0; k < m_BPO; k++ ) { | 218 for( k = 0; k < kBinsPerOctave; k++ ) { |
218 m_MajCorr[k] = krumCorr( m_MeanHPCP, MajProfile, m_BPO ); | 219 m_MajCorr[k] = krumCorr( m_MeanHPCP, MajProfile, kBinsPerOctave ); |
219 m_MinCorr[k] = krumCorr( m_MeanHPCP, MinProfile, m_BPO ); | 220 m_MinCorr[k] = krumCorr( m_MeanHPCP, MinProfile, kBinsPerOctave ); |
220 | 221 |
221 MathUtilities::circShift( MajProfile, m_BPO, 1 ); | 222 MathUtilities::circShift( MajProfile, kBinsPerOctave, 1 ); |
222 MathUtilities::circShift( MinProfile, m_BPO, 1 ); | 223 MathUtilities::circShift( MinProfile, kBinsPerOctave, 1 ); |
223 } | 224 } |
224 | 225 |
225 for( k = 0; k < m_BPO; k++ ) { | 226 for( k = 0; k < kBinsPerOctave; k++ ) { |
226 m_Keys[k] = m_MajCorr[k]; | 227 m_Keys[k] = m_MajCorr[k]; |
227 m_Keys[k+m_BPO] = m_MinCorr[k]; | 228 m_Keys[k+kBinsPerOctave] = m_MinCorr[k]; |
228 } | 229 } |
229 | 230 |
230 for (k = 0; k < 24; ++k) { | 231 for (k = 0; k < 24; ++k) { |
231 m_keyStrengths[k] = 0; | 232 m_keyStrengths[k] = 0; |
232 } | 233 } |
233 | 234 |
234 for( k = 0; k < m_BPO*2; k++ ) { | 235 for( k = 0; k < kBinsPerOctave*2; k++ ) { |
235 int idx = k / (m_BPO/12); | 236 int idx = k / (kBinsPerOctave/12); |
236 int rem = k % (m_BPO/12); | 237 int rem = k % (kBinsPerOctave/12); |
237 if (rem == 0 || m_Keys[k] > m_keyStrengths[idx]) { | 238 if (rem == 0 || m_Keys[k] > m_keyStrengths[idx]) { |
238 m_keyStrengths[idx] = m_Keys[k]; | 239 m_keyStrengths[idx] = m_Keys[k]; |
239 } | 240 } |
240 | 241 |
241 // m_keyStrengths[k/(m_BPO/12)] += m_Keys[k]; | 242 // m_keyStrengths[k/(kBinsPerOctave/12)] += m_Keys[k]; |
242 } | 243 } |
243 | 244 |
244 /* | 245 /* |
245 std::cout << "raw keys: "; | 246 std::cout << "raw keys: "; |
246 for (int ii = 0; ii < 2*m_BPO; ++ii) { | 247 for (int ii = 0; ii < 2*kBinsPerOctave; ++ii) { |
247 if (ii % (m_BPO/12) == 0) std::cout << "\n"; | 248 if (ii % (kBinsPerOctave/12) == 0) std::cout << "\n"; |
248 std::cout << m_Keys[ii] << " "; | 249 std::cout << m_Keys[ii] << " "; |
249 } | 250 } |
250 std::cout << std::endl; | 251 std::cout << std::endl; |
251 | 252 |
252 std::cout << "key strengths: "; | 253 std::cout << "key strengths: "; |
258 */ | 259 */ |
259 double dummy; | 260 double dummy; |
260 // m_Keys[1] is C center 1 / 3 + 1 = 1 | 261 // m_Keys[1] is C center 1 / 3 + 1 = 1 |
261 // m_Keys[4] is D center 4 / 3 + 1 = 2 | 262 // m_Keys[4] is D center 4 / 3 + 1 = 2 |
262 // '+ 1' because we number keys 1-24, not 0-23. | 263 // '+ 1' because we number keys 1-24, not 0-23. |
263 key = MathUtilities::getMax( m_Keys, 2* m_BPO, &dummy ) / 3 + 1; | 264 key = MathUtilities::getMax( m_Keys, 2* kBinsPerOctave, &dummy ) / 3 + 1; |
264 | 265 |
265 // std::cout << "key pre-sorting: " << key << std::endl; | 266 // std::cout << "key pre-sorting: " << key << std::endl; |
266 | 267 |
267 | 268 |
268 //Median filtering | 269 //Median filtering |
316 | 317 |
317 bool GetKeyMode::isModeMinor( int key ) | 318 bool GetKeyMode::isModeMinor( int key ) |
318 { | 319 { |
319 return (key > 12); | 320 return (key > 12); |
320 } | 321 } |
322 | |
323 unsigned int getChromaSize() | |
324 { | |
325 return kBinsPerOctave; | |
326 } |