# HG changeset patch # User Chris Cannam # Date 1559323531 -3600 # Node ID 1bea13b8f9515242353821b25398f35e0076e630 # Parent 3f649fbb11720bb0d0b41232383b3d149a6c0fb4 Style fixes in constant-Q: avoid unsigned, reuse our Window class, fix comments diff -r 3f649fbb1172 -r 1bea13b8f951 dsp/chromagram/Chromagram.cpp --- a/dsp/chromagram/Chromagram.cpp Fri May 31 18:15:59 2019 +0100 +++ b/dsp/chromagram/Chromagram.cpp Fri May 31 18:25:31 2019 +0100 @@ -57,8 +57,8 @@ m_uK = m_ConstantQ->getK(); // Initialise working arrays - m_frameSize = m_ConstantQ->getfftlength(); - m_hopSize = m_ConstantQ->gethop(); + m_frameSize = m_ConstantQ->getFFTLength(); + m_hopSize = m_ConstantQ->getHop(); // Initialise FFT object m_FFT = new FFTReal(m_frameSize); diff -r 3f649fbb1172 -r 1bea13b8f951 dsp/chromagram/ConstantQ.cpp --- a/dsp/chromagram/ConstantQ.cpp Fri May 31 18:15:59 2019 +0100 +++ b/dsp/chromagram/ConstantQ.cpp Fri May 31 18:25:31 2019 +0100 @@ -14,26 +14,16 @@ #include "ConstantQ.h" #include "dsp/transforms/FFT.h" +#include "base/Window.h" #include -//--------------------------------------------------------------------------- -// nextpow2 returns the smallest integer n such that 2^n >= x. -static double nextpow2(double x) { - double y = ceil(log(x)/log(2.0)); - return(y); -} - -static double squaredModule(const double & xx, const double & yy) { - return xx*xx + yy*yy; -} - //---------------------------------------------------------------------------- -ConstantQ::ConstantQ( CQConfig Config ) : +ConstantQ::ConstantQ( CQConfig config ) : m_sparseKernel(0) { - initialise( Config ); + initialise(config); } ConstantQ::~ConstantQ() @@ -41,100 +31,129 @@ deInitialise(); } -//---------------------------------------------------------------------------- +static double squaredModule(const double & xx, const double & yy) { + return xx*xx + yy*yy; +} + void ConstantQ::sparsekernel() { -// std::cerr << "ConstantQ: initialising sparse kernel, uK = " << m_uK << ", FFTLength = " << m_FFTLength << "..."; - SparseKernel *sk = new SparseKernel(); - //generates spectral kernel matrix (upside down?) - // initialise temporal kernel with zeros, twice length to deal w. complex numbers - - double* hammingWindowRe = new double [ m_FFTLength ]; - double* hammingWindowIm = new double [ m_FFTLength ]; - double* transfHammingWindowRe = new double [ m_FFTLength ]; - double* transfHammingWindowIm = new double [ m_FFTLength ]; - - for (unsigned u=0; u < m_FFTLength; u++) { - hammingWindowRe[u] = 0; - hammingWindowIm[u] = 0; - } - - // Here, fftleng*2 is a guess of the number of sparse cells in the matrix - // The matrix K x fftlength but the non-zero cells are an antialiased - // square root function. So mostly is a line, with some grey point. - sk->is.reserve( m_FFTLength*2 ); - sk->js.reserve( m_FFTLength*2 ); - sk->real.reserve( m_FFTLength*2 ); - sk->imag.reserve( m_FFTLength*2 ); + double* windowRe = new double [ m_FFTLength ]; + double* windowIm = new double [ m_FFTLength ]; + double* transfWindowRe = new double [ m_FFTLength ]; + double* transfWindowIm = new double [ m_FFTLength ]; - // for each bin value K, calculate temporal kernel, take its fft to - //calculate the spectral kernel then threshold it to make it sparse and - //add it to the sparse kernels matrix + // for each bin value K, calculate temporal kernel, take its fft + // to calculate the spectral kernel then threshold it to make it + // sparse and add it to the sparse kernels matrix + double squareThreshold = m_CQThresh * m_CQThresh; - FFT m_FFT(m_FFTLength); + FFT fft(m_FFTLength); - for (unsigned k = m_uK; k--; ) { - for (unsigned u=0; u < m_FFTLength; u++) { - hammingWindowRe[u] = 0; - hammingWindowIm[u] = 0; - } + for (int j = m_uK; j >= 0; --j) { - // Computing a hamming window - const unsigned hammingLength = (int) ceil( m_dQ * m_FS / ( m_FMin * pow(2,((double)(k))/(double)m_BPO))); - -// cerr << "k = " << k << ", q = " << m_dQ << ", m_FMin = " << m_FMin << ", hammingLength = " << hammingLength << " (rounded up from " << (m_dQ * m_FS / ( m_FMin * pow(2,((double)(k))/(double)m_BPO))) << ")" << endl; - - - unsigned origin = m_FFTLength/2 - hammingLength/2; - - for (unsigned i=0; i hamming(HammingWindow, windowLength); + hamming.cut(windowRe + origin); + hamming.cut(windowIm + origin); + + // Scale + for (int i = 0; i < windowLength; ++i) { + windowRe[origin + i] /= windowLength; + } + for (int i = 0; i < windowLength; ++i) { + windowIm[origin + i] /= windowLength; + } + + // Input is expected to have been fftshifted, so do the + // same to the input to the fft that contains the kernel + for (int i = 0; i < m_FFTLength/2; ++i) { + double temp = windowRe[i]; + windowRe[i] = windowRe[i + m_FFTLength/2]; + windowRe[i + m_FFTLength/2] = temp; + } + for (int i = 0; i < m_FFTLength/2; ++i) { + double temp = windowIm[i]; + windowIm[i] = windowIm[i + m_FFTLength/2]; + windowIm[i + m_FFTLength/2] = temp; } - //do fft of hammingWindow - m_FFT.process( 0, hammingWindowRe, hammingWindowIm, transfHammingWindowRe, transfHammingWindowIm ); - - for (unsigned j=0; j<( m_FFTLength ); j++) { + fft.process(false, windowRe, windowIm, transfWindowRe, transfWindowIm); + + // convert to sparse form + for (int i = 0; i < m_FFTLength; i++) { + // perform thresholding - const double squaredBin = squaredModule( transfHammingWindowRe[ j ], transfHammingWindowIm[ j ]); - if (squaredBin <= squareThreshold) continue; + double mag = squaredModule(transfWindowRe[i], transfWindowIm[i]); + if (mag <= squareThreshold) continue; // Insert non-zero position indexes - sk->is.push_back(j); - sk->js.push_back(k); + sk->is.push_back(i); + sk->js.push_back(j); - // take conjugate, normalise and add to array sparkernel - sk->real.push_back( transfHammingWindowRe[ j ]/m_FFTLength); - sk->imag.push_back(-transfHammingWindowIm[ j ]/m_FFTLength); + // take conjugate, normalise and add to array for sparse kernel + sk->real.push_back( transfWindowRe[i] / m_FFTLength); + sk->imag.push_back(-transfWindowIm[i] / m_FFTLength); } } - delete [] hammingWindowRe; - delete [] hammingWindowIm; - delete [] transfHammingWindowRe; - delete [] transfHammingWindowIm; + delete [] windowRe; + delete [] windowIm; + delete [] transfWindowRe; + delete [] transfWindowIm; -// std::cerr << "done\n -> is: " << sk->is.size() << ", js: " << sk->js.size() << ", reals: " << sk->real.size() << ", imags: " << sk->imag.size() << std::endl; - m_sparseKernel = sk; - return; +} + +void ConstantQ::initialise( CQConfig Config ) +{ + m_FS = Config.FS; // Sample rate + m_FMin = Config.min; // Minimum frequency + m_FMax = Config.max; // Maximum frequency + m_BPO = Config.BPO; // Bins per octave + m_CQThresh = Config.CQThresh; // Threshold for sparse kernel generation + + // Q value for filter bank + m_dQ = 1/(pow(2,(1/(double)m_BPO))-1); + + // No. of constant Q bins + m_uK = (int)ceil(m_BPO * log(m_FMax/m_FMin)/log(2.0)); + + // Length of fft required for this Constant Q filter bank + m_FFTLength = MathUtilities::nextPowerOfTwo(int(ceil(m_dQ * m_FS/m_FMin))); + + // Hop from one frame to next + m_hop = m_FFTLength / 8; + + // allocate memory for cqdata + m_CQdata = new double [2*m_uK]; +} + +void ConstantQ::deInitialise() +{ + delete [] m_CQdata; + delete m_sparseKernel; } //----------------------------------------------------------------------------- @@ -147,24 +166,24 @@ SparseKernel *sk = m_sparseKernel; - for (unsigned row=0; row<2*m_uK; row++) { + for (int row=0; row < 2 * m_uK; row++) { m_CQdata[ row ] = 0; m_CQdata[ row+1 ] = 0; } - const unsigned *fftbin = &(sk->is[0]); - const unsigned *cqbin = &(sk->js[0]); - const double *real = &(sk->real[0]); - const double *imag = &(sk->imag[0]); - const unsigned int sparseCells = sk->real.size(); + const int *fftbin = &(sk->is[0]); + const int *cqbin = &(sk->js[0]); + const double *real = &(sk->real[0]); + const double *imag = &(sk->imag[0]); + const int sparseCells = int(sk->real.size()); - for (unsigned i = 0; i fft length = " << m_FFTLength << ", hop = " << m_hop << std::endl; - - // allocate memory for cqdata - m_CQdata = new double [2*m_uK]; -} - -void ConstantQ::deInitialise() -{ - delete [] m_CQdata; - delete m_sparseKernel; -} - void ConstantQ::process(const double *FFTRe, const double* FFTIm, double *CQRe, double *CQIm) { @@ -214,25 +202,25 @@ SparseKernel *sk = m_sparseKernel; - for (unsigned row=0; rowis[0]); - const unsigned *cqbin = &(sk->js[0]); - const double *real = &(sk->real[0]); - const double *imag = &(sk->imag[0]); - const unsigned int sparseCells = sk->real.size(); + const int *fftbin = &(sk->is[0]); + const int *cqbin = &(sk->js[0]); + const double *real = &(sk->real[0]); + const double *imag = &(sk->imag[0]); + const int sparseCells = int(sk->real.size()); - for (unsigned i = 0; i is; - std::vector js; + std::vector is; + std::vector js; std::vector imag; std::vector real; }; diff -r 3f649fbb1172 -r 1bea13b8f951 dsp/segmentation/ClusterMeltSegmenter.cpp --- a/dsp/segmentation/ClusterMeltSegmenter.cpp Fri May 31 18:15:59 2019 +0100 +++ b/dsp/segmentation/ClusterMeltSegmenter.cpp Fri May 31 18:25:31 2019 +0100 @@ -82,7 +82,7 @@ ncoeff = constq->getK(); - fft = new FFTReal(constq->getfftlength()); + fft = new FFTReal(constq->getFFTLength()); } else if (featureType == FEATURE_TYPE_MFCC) { @@ -156,7 +156,7 @@ return; } - int fftsize = constq->getfftlength(); + int fftsize = constq->getFFTLength(); if (!window || window->getSize() != fftsize) { delete window;