Mercurial > hg > qm-dsp
changeset 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 | bfd7d7633e1d |
files | dsp/keydetection/GetKeyMode.cpp dsp/keydetection/GetKeyMode.h |
diffstat | 2 files changed, 43 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/dsp/keydetection/GetKeyMode.cpp Fri May 24 21:06:47 2019 +0200 +++ b/dsp/keydetection/GetKeyMode.cpp Fri May 24 21:40:47 2019 +0200 @@ -61,12 +61,12 @@ // Chromagram configuration parameters m_ChromaConfig.normalise = MathUtilities::NormaliseUnitMax; - m_ChromaConfig.FS = lrint(sampleRate/(double)m_DecimationFactor); + m_ChromaConfig.FS = sampleRate/(double)m_DecimationFactor; if (m_ChromaConfig.FS < 1) { m_ChromaConfig.FS = 1; } - // Set C (= MIDI #12) as our base : + // Set C3 (= MIDI #48) as our base: // This implies that key = 1 => Cmaj, key = 12 => Bmaj, key = 13 => Cmin, etc. m_ChromaConfig.min = Pitch::getFrequencyForPitch( 48, 0, tuningFrequency ); m_ChromaConfig.max = Pitch::getFrequencyForPitch( 96, 0, tuningFrequency ); @@ -104,6 +104,17 @@ m_MajCorr = new double[kBinsPerOctave]; m_MinCorr = new double[kBinsPerOctave]; + m_MajProfileNorm = new double[kBinsPerOctave]; + m_MinProfileNorm = new double[kBinsPerOctave]; + + double mMaj = MathUtilities::mean( MajProfile, kBinsPerOctave ); + double mMin = MathUtilities::mean( MinProfile, kBinsPerOctave ); + + for( unsigned int i = 0; i < kBinsPerOctave; i++ ) { + m_MajProfileNorm[i] = MajProfile[i] - mMaj; + m_MinProfileNorm[i] = MinProfile[i] - mMin; + } + m_MedianFilterBuffer = new int[ m_MedianWinsize ]; memset( m_MedianFilterBuffer, 0, sizeof(int)*m_MedianWinsize); @@ -125,30 +136,33 @@ delete [] m_MeanHPCP; delete [] m_MajCorr; delete [] m_MinCorr; + delete [] m_MajProfileNorm; + delete [] m_MinProfileNorm; delete [] m_MedianFilterBuffer; delete [] m_SortedBuffer; delete [] m_keyStrengths; } -double GetKeyMode::krumCorr(double *pData1, double *pData2, unsigned int length) +double GetKeyMode::krumCorr( const double *pDataNorm, const double *pProfileNorm, + int shiftProfile, unsigned int length) { double retVal= 0.0; double num = 0; double den = 0; - double mX = MathUtilities::mean( pData1, length ); - double mY = MathUtilities::mean( pData2, length ); - double sum1 = 0; double sum2 = 0; - for( unsigned int i = 0; i <length; i++ ) { - num += ( pData1[i] - mX ) * ( pData2[i] - mY ); + for( unsigned int i = 0; i <length; i++ ) + { + int k = (i - shiftProfile + length) % length; - sum1 += ( (pData1[i]-mX) * (pData1[i]-mX) ); - sum2 += ( (pData2[i]-mY) * (pData2[i]-mY) ); + num += pDataNorm[i] * pProfileNorm[k]; + + sum1 += ( pDataNorm[i] * pDataNorm[i] ); + sum2 += ( pProfileNorm[k] * pProfileNorm[k] ); } - + den = sqrt(sum1 * sum2); if( den>0 ) { @@ -170,11 +184,6 @@ m_ChrPointer = m_Chroma->process( m_DecimatedBuffer ); - // The Cromagram has the center of C at bin 0, while the major - // and minor profiles have the center of C at 1. We want to have - // the correlation for C result also at 1. - // To achieve this we have to shift two times: - MathUtilities::circShift( m_ChrPointer, kBinsPerOctave, 2); /* std::cout << "raw chroma: "; for (int ii = 0; ii < kBinsPerOctave; ++ii) { @@ -210,13 +219,22 @@ m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling; } + // Normalize for zero average + double mHPCP = MathUtilities::mean( m_MeanHPCP, kBinsPerOctave ); + for( k = 0; k < kBinsPerOctave; k++ ) + { + m_MeanHPCP[k] -= mHPCP; + } - for( k = 0; k < kBinsPerOctave; k++ ) { - m_MajCorr[k] = krumCorr( m_MeanHPCP, MajProfile, kBinsPerOctave ); - m_MinCorr[k] = krumCorr( m_MeanHPCP, MinProfile, kBinsPerOctave ); - MathUtilities::circShift( MajProfile, kBinsPerOctave, 1 ); - MathUtilities::circShift( MinProfile, kBinsPerOctave, 1 ); + for( k = 0; k < kBinsPerOctave; k++ ) + { + // The Cromagram has the center of C at bin 0, while the major + // and minor profiles have the center of C at 1. We want to have + // the correlation for C result also at 1. + // To achieve this we have to shift two times: + m_MajCorr[k] = krumCorr( m_MeanHPCP, m_MajProfileNorm, (int)k - 2, kBinsPerOctave ); + m_MinCorr[k] = krumCorr( m_MeanHPCP, m_MinProfileNorm, (int)k - 2, kBinsPerOctave ); } /*
--- a/dsp/keydetection/GetKeyMode.h Fri May 24 21:06:47 2019 +0200 +++ b/dsp/keydetection/GetKeyMode.h Fri May 24 21:40:47 2019 +0200 @@ -27,7 +27,8 @@ int process( double* PCMData ); - double krumCorr( double* pData1, double* pData2, unsigned int length ); + double krumCorr( const double *pDataNorm, const double *pProfileNorm, + int shiftProfile, unsigned int length ); unsigned int getBlockSize() { return m_ChromaFrameSize*m_DecimationFactor; } unsigned int getHopSize() { return m_ChromaHopSize*m_DecimationFactor; } @@ -77,6 +78,8 @@ double* m_ChromaBuffer; double* m_MeanHPCP; + double* m_MajProfileNorm; + double* m_MinProfileNorm; double* m_MajCorr; double* m_MinCorr; int* m_MedianFilterBuffer;