Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread save key detect #2113

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 69 additions & 44 deletions lib/qm-dsp/dsp/keydetection/GetKeyMode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
#include <cstdlib>

// Chords profile
static double MajProfile[36] =
static const double MajProfile[36] =
{ 0.0384, 0.0629, 0.0258, 0.0121, 0.0146, 0.0106, 0.0364, 0.0610, 0.0267,
0.0126, 0.0121, 0.0086, 0.0364, 0.0623, 0.0279, 0.0275, 0.0414, 0.0186,
0.0173, 0.0248, 0.0145, 0.0364, 0.0631, 0.0262, 0.0129, 0.0150, 0.0098,
0.0312, 0.0521, 0.0235, 0.0129, 0.0142, 0.0095, 0.0289, 0.0478, 0.0239};

static double MinProfile[36] =
static const double MinProfile[36] =
{ 0.0375, 0.0682, 0.0299, 0.0119, 0.0138, 0.0093, 0.0296, 0.0543, 0.0257,
0.0292, 0.0519, 0.0246, 0.0159, 0.0234, 0.0135, 0.0291, 0.0544, 0.0248,
0.0137, 0.0176, 0.0104, 0.0352, 0.0670, 0.0302, 0.0222, 0.0349, 0.0164,
Expand All @@ -51,7 +51,6 @@ GetKeyMode::GetKeyMode( int sampleRate, float tuningFrequency,
m_MeanHPCP(0),
m_MajCorr(0),
m_MinCorr(0),
m_Keys(0),
m_MedianFilterBuffer(0),
m_SortedBuffer(0),
m_keyStrengths(0)
Expand All @@ -70,7 +69,8 @@ GetKeyMode::GetKeyMode( int sampleRate, float tuningFrequency,
m_ChromaConfig.max = Pitch::getFrequencyForPitch
(96, 0, tuningFrequency);

m_ChromaConfig.BPO = 36;
m_BPO = sizeof(MajProfile) / sizeof(MajProfile[0]);
m_ChromaConfig.BPO = m_BPO;
m_ChromaConfig.CQThresh = 0.0054;

// Chromagram inst.
Expand All @@ -80,7 +80,6 @@ GetKeyMode::GetKeyMode( int sampleRate, float tuningFrequency,
m_ChromaFrameSize = m_Chroma->getFrameSize();
// override hopsize for this application
m_ChromaHopSize = m_ChromaFrameSize;
m_BPO = m_ChromaConfig.BPO;

// std::cerr << "chroma frame size = " << m_ChromaFrameSize << ", decimation factor = " << m_DecimationFactor << " therefore block size = " << getBlockSize() << std::endl;

Expand All @@ -103,8 +102,19 @@ GetKeyMode::GetKeyMode( int sampleRate, float tuningFrequency,

m_MajCorr = new double[m_BPO];
m_MinCorr = new double[m_BPO];
m_Keys = new double[2*m_BPO];

m_MajProfileNorm = new double[m_BPO];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_BPO is just the constant 36. Static allocation would work for all those arrays as well as a single dynamic allocation with partitioning/slicing.

m_MinProfileNorm = new double[m_BPO];

double mMaj = MathUtilities::mean( MajProfile, m_BPO );
double mMin = MathUtilities::mean( MinProfile, m_BPO );

for( unsigned int i = 0; i < m_BPO; 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);

Expand All @@ -128,31 +138,32 @@ GetKeyMode::~GetKeyMode()
delete [] m_MeanHPCP;
delete [] m_MajCorr;
delete [] m_MinCorr;
delete [] m_Keys;
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 );
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);
Expand All @@ -177,11 +188,6 @@ int GetKeyMode::process(double *PCMData)

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, m_BPO, 2);
/*
std::cout << "raw chroma: ";
for (unsigned int ii = 0; ii < m_BPO; ++ii) {
Expand Down Expand Up @@ -218,36 +224,24 @@ int GetKeyMode::process(double *PCMData)
m_MeanHPCP[k] = mnVal/(double)m_ChromaBufferFilling;
}


// Normalize for zero average
double mHPCP = MathUtilities::mean( m_MeanHPCP, m_BPO );
for( k = 0; k < m_BPO; k++ )
{
m_MajCorr[k] = krumCorr( m_MeanHPCP, MajProfile, m_BPO );
m_MinCorr[k] = krumCorr( m_MeanHPCP, MinProfile, m_BPO );

MathUtilities::circShift( MajProfile, m_BPO, 1 );
MathUtilities::circShift( MinProfile, m_BPO, 1 );
}

for( k = 0; k < m_BPO; k++ )
{
m_Keys[k] = m_MajCorr[k];
m_Keys[k+m_BPO] = m_MinCorr[k];
m_MeanHPCP[k] -= mHPCP;
}

for (k = 0; k < 24; ++k) {
m_keyStrengths[k] = 0;
}

for( k = 0; k < m_BPO*2; k++ )
for( k = 0; k < m_BPO; k++ )
{
int idx = k / (m_BPO/12);
int rem = k % (m_BPO/12);
if (rem == 0 || m_Keys[k] > m_keyStrengths[idx]) {
m_keyStrengths[idx] = m_Keys[k];
}

// m_keyStrengths[k/(m_BPO/12)] += m_Keys[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, m_BPO );
m_MinCorr[k] = krumCorr( m_MeanHPCP, m_MinProfileNorm, (int)k - 2, m_BPO );
}


/*
std::cout << "raw keys: ";
Expand All @@ -264,11 +258,14 @@ int GetKeyMode::process(double *PCMData)
}
std::cout << std::endl;
*/
double dummy;
// m_Keys[1] is C center 1 / 3 + 1 = 1
// m_Keys[4] is D center 4 / 3 + 1 = 2
// '+ 1' because we number keys 1-24, not 0-23.
int maxBin = MathUtilities::getMax( m_Keys, 2* m_BPO, &dummy );
double maxMaj;
int maxMajBin = MathUtilities::getMax( m_MajCorr, m_BPO, &maxMaj );
double maxMin;
int maxMinBin = MathUtilities::getMax( m_MinCorr, m_BPO, &maxMin );
int maxBin = (maxMaj > maxMin) ? maxMajBin : (maxMinBin + m_BPO);
key = maxBin / 3 + 1;

// std::cout << "fractional key pre-sorting: " << (maxBin + 2) / 3.0 << std::endl;
Expand Down Expand Up @@ -328,3 +325,31 @@ bool GetKeyMode::isModeMinor( int key )
{
return (key > 12);
}

double* GetKeyMode::getKeyStrengths() {
unsigned int k;

for (k = 0; k < 24; ++k) {
m_keyStrengths[k] = 0;
}

for( k = 0; k < m_BPO; k++ )
{
int idx = k / (m_BPO/12);
int rem = k % (m_BPO/12);
if (rem == 0 || m_MajCorr[k] > m_keyStrengths[idx]) {
m_keyStrengths[idx] = m_MajCorr[k];
}
}

for( k = 0; k < m_BPO; k++ )
{
int idx = (k + m_BPO) / (m_BPO/12);
int rem = k % (m_BPO/12);
if (rem == 0 || m_MinCorr[k] > m_keyStrengths[idx]) {
m_keyStrengths[idx] = m_MinCorr[k];
}
}

return m_keyStrengths;
}
8 changes: 5 additions & 3 deletions lib/qm-dsp/dsp/keydetection/GetKeyMode.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class GetKeyMode

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; }
Expand All @@ -37,7 +38,7 @@ class GetKeyMode

double* getMeanHPCP() { return m_MeanHPCP; }

double *getKeyStrengths() { return m_keyStrengths; }
double* getKeyStrengths();

bool isModeMinor( int key );

Expand Down Expand Up @@ -79,9 +80,10 @@ class GetKeyMode
double* m_ChromaBuffer;
double* m_MeanHPCP;

double* m_MajProfileNorm;
double* m_MinProfileNorm;
double* m_MajCorr;
double* m_MinCorr;
double* m_Keys;
int* m_MedianFilterBuffer;
int* m_SortedBuffer;

Expand Down