Mercurial > hg > qm-dsp
diff dsp/chromagram/ConstantQ.cpp @ 51:114e833c07ac
* Do not calculate CQ sparse kernel when chromagram is constructed: only
when it's actually used
* Pre-calculate CQ sparse kernels in the sizes required for the default
configurations of some of our transforms
author | cannam |
---|---|
date | Thu, 04 Dec 2008 11:59:29 +0000 |
parents | 3dff6e3e2121 |
children | 6cb2b3cd5356 |
line wrap: on
line diff
--- a/dsp/chromagram/ConstantQ.cpp Tue Nov 25 16:00:05 2008 +0000 +++ b/dsp/chromagram/ConstantQ.cpp Thu Dec 04 11:59:29 2008 +0000 @@ -12,6 +12,33 @@ #include <iostream> +#include "CQprecalc.cpp" + +static bool push_precalculated(int uk, int fftlength, + std::vector<unsigned> &is, + std::vector<unsigned> &js, + std::vector<double> &real, + std::vector<double> &imag) +{ + if (uk == 76 && fftlength == 16384) { + push_76_16384(is, js, real, imag); + return true; + } + if (uk == 144 && fftlength == 4096) { + push_144_4096(is, js, real, imag); + return true; + } + if (uk == 65 && fftlength == 2048) { + push_65_2048(is, js, real, imag); + return true; + } + if (uk == 84 && fftlength == 65536) { + push_84_65536(is, js, real, imag); + return true; + } + return false; +} + //--------------------------------------------------------------------------- // nextpow2 returns the smallest integer n such that 2^n >= x. static double nextpow2(double x) { @@ -25,7 +52,8 @@ //---------------------------------------------------------------------------- -ConstantQ::ConstantQ( CQConfig Config ) +ConstantQ::ConstantQ( CQConfig Config ) : + m_sparseKernel(0) { initialise( Config ); } @@ -38,6 +66,16 @@ //---------------------------------------------------------------------------- void ConstantQ::sparsekernel() { +// std::cerr << "ConstantQ: initialising sparse kernel, uK = " << m_uK << ", FFTLength = " << m_FFTLength << "..."; + + SparseKernel *sk = new SparseKernel(); + + if (push_precalculated(m_uK, m_FFTLength, + sk->is, sk->js, sk->real, sk->imag)) { + m_sparseKernel = sk; + return; + } + //generates spectral kernel matrix (upside down?) // initialise temporal kernel with zeros, twice length to deal w. complex numbers @@ -52,14 +90,13 @@ 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. - m_sparseKernelIs.reserve( m_FFTLength*2 ); - m_sparseKernelJs.reserve( m_FFTLength*2 ); - m_sparseKernelRealValues.reserve( m_FFTLength*2 ); - m_sparseKernelImagValues.reserve( m_FFTLength*2 ); + sk->is.reserve( m_FFTLength*2 ); + sk->js.reserve( m_FFTLength*2 ); + sk->real.reserve( m_FFTLength*2 ); + sk->imag.reserve( m_FFTLength*2 ); // for each bin value K, calculate temporal kernel, take its fft to //calculate the spectral kernel then threshold it to make it sparse and @@ -111,12 +148,12 @@ if (squaredBin <= squareThreshold) continue; // Insert non-zero position indexes, doubled because they are floats - m_sparseKernelIs.push_back(j); - m_sparseKernelJs.push_back(k); + sk->is.push_back(j); + sk->js.push_back(k); // take conjugate, normalise and add to array sparkernel - m_sparseKernelRealValues.push_back( transfHammingWindowRe[ j ]/m_FFTLength); - m_sparseKernelImagValues.push_back(-transfHammingWindowIm[ j ]/m_FFTLength); + sk->real.push_back( transfHammingWindowRe[ j ]/m_FFTLength); + sk->imag.push_back(-transfHammingWindowIm[ j ]/m_FFTLength); } } @@ -126,21 +163,97 @@ delete [] transfHammingWindowRe; delete [] transfHammingWindowIm; +/* + using std::cout; + using std::endl; + + cout.precision(28); + + int n = sk->is.size(); + int w = 8; + cout << "static unsigned int sk_i_" << m_uK << "_" << m_FFTLength << "[" << n << "] = {" << endl; + for (int i = 0; i < n; ++i) { + if (i % w == 0) cout << " "; + cout << sk->is[i]; + if (i + 1 < n) cout << ", "; + if (i % w == w-1) cout << endl; + }; + if (n % w != 0) cout << endl; + cout << "};" << endl; + + n = sk->js.size(); + cout << "static unsigned int sk_j_" << m_uK << "_" << m_FFTLength << "[" << n << "] = {" << endl; + for (int i = 0; i < n; ++i) { + if (i % w == 0) cout << " "; + cout << sk->js[i]; + if (i + 1 < n) cout << ", "; + if (i % w == w-1) cout << endl; + }; + if (n % w != 0) cout << endl; + cout << "};" << endl; + + w = 2; + n = sk->real.size(); + cout << "static double sk_real_" << m_uK << "_" << m_FFTLength << "[" << n << "] = {" << endl; + for (int i = 0; i < n; ++i) { + if (i % w == 0) cout << " "; + cout << sk->real[i]; + if (i + 1 < n) cout << ", "; + if (i % w == w-1) cout << endl; + }; + if (n % w != 0) cout << endl; + cout << "};" << endl; + + n = sk->imag.size(); + cout << "static double sk_imag_" << m_uK << "_" << m_FFTLength << "[" << n << "] = {" << endl; + for (int i = 0; i < n; ++i) { + if (i % w == 0) cout << " "; + cout << sk->imag[i]; + if (i + 1 < n) cout << ", "; + if (i % w == w-1) cout << endl; + }; + if (n % w != 0) cout << endl; + cout << "};" << endl; + + cout << "static void push_" << m_uK << "_" << m_FFTLength << "(vector<unsigned int> &is, vector<unsigned int> &js, vector<double> &real, vector<double> &imag)" << endl; + cout << "{\n is.reserve(" << n << ");\n"; + cout << " js.reserve(" << n << ");\n"; + cout << " real.reserve(" << n << ");\n"; + cout << " imag.reserve(" << n << ");\n"; + cout << " for (int i = 0; i < " << n << "; ++i) {" << endl; + cout << " is.push_back(sk_i_" << m_uK << "_" << m_FFTLength << "[i]);" << endl; + cout << " js.push_back(sk_j_" << m_uK << "_" << m_FFTLength << "[i]);" << endl; + cout << " real.push_back(sk_real_" << m_uK << "_" << m_FFTLength << "[i]);" << endl; + cout << " imag.push_back(sk_imag_" << m_uK << "_" << m_FFTLength << "[i]);" << endl; + cout << " }" << endl; + cout << "}" << endl; +*/ +// 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; } //----------------------------------------------------------------------------- double* ConstantQ::process( const double* fftdata ) { + if (!m_sparseKernel) { + std::cerr << "ERROR: ConstantQ::process: Sparse kernel has not been initialised" << std::endl; + return m_CQdata; + } + + SparseKernel *sk = m_sparseKernel; + for (unsigned row=0; row<2*m_uK; row++) { m_CQdata[ row ] = 0; m_CQdata[ row+1 ] = 0; } - const unsigned *fftbin = &(m_sparseKernelIs[0]); - const unsigned *cqbin = &(m_sparseKernelJs[0]); - const double *real = &(m_sparseKernelRealValues[0]); - const double *imag = &(m_sparseKernelImagValues[0]); - const unsigned int sparseCells = m_sparseKernelRealValues.size(); + 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(); for (unsigned i = 0; i<sparseCells; i++) { @@ -186,22 +299,30 @@ void ConstantQ::deInitialise() { delete [] m_CQdata; + delete m_sparseKernel; } void ConstantQ::process(const double *FFTRe, const double* FFTIm, double *CQRe, double *CQIm) { + if (!m_sparseKernel) { + std::cerr << "ERROR: ConstantQ::process: Sparse kernel has not been initialised" << std::endl; + return; + } + + SparseKernel *sk = m_sparseKernel; + for (unsigned row=0; row<m_uK; row++) { CQRe[ row ] = 0; CQIm[ row ] = 0; } - const unsigned *fftbin = &(m_sparseKernelIs[0]); - const unsigned *cqbin = &(m_sparseKernelJs[0]); - const double *real = &(m_sparseKernelRealValues[0]); - const double *imag = &(m_sparseKernelImagValues[0]); - const unsigned int sparseCells = m_sparseKernelRealValues.size(); + 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(); for (unsigned i = 0; i<sparseCells; i++) {