cannam@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@0: /* cannam@0: QM DSP Library cannam@0: cannam@0: Centre for Digital Music, Queen Mary, University of London. cannam@0: This file copyright 2005-2006 Christian Landone. cannam@0: All rights reserved. cannam@0: */ cannam@0: cannam@0: #include "ConstantQ.h" cannam@0: #include "dsp/transforms/FFT.h" cannam@0: cannam@20: #include cannam@20: cannam@0: //--------------------------------------------------------------------------- cannam@0: // nextpow2 returns the smallest integer n such that 2^n >= x. cannam@0: static double nextpow2(double x) { cannam@0: double y = ceil(log(x)/log(2.0)); cannam@0: return(y); cannam@0: } cannam@0: cannam@0: static double squaredModule(const double & xx, const double & yy) { cannam@0: return xx*xx + yy*yy; cannam@0: } cannam@0: cannam@0: //---------------------------------------------------------------------------- cannam@0: cannam@0: ConstantQ::ConstantQ( CQConfig Config ) cannam@0: { cannam@0: initialise( Config ); cannam@0: } cannam@0: cannam@0: ConstantQ::~ConstantQ() cannam@0: { cannam@0: deInitialise(); cannam@0: } cannam@0: cannam@0: //---------------------------------------------------------------------------- cannam@0: void ConstantQ::sparsekernel() cannam@0: { cannam@0: //generates spectral kernel matrix (upside down?) cannam@0: // initialise temporal kernel with zeros, twice length to deal w. complex numbers cannam@0: cannam@0: double* hammingWindowRe = new double [ m_FFTLength ]; cannam@0: double* hammingWindowIm = new double [ m_FFTLength ]; cannam@0: double* transfHammingWindowRe = new double [ m_FFTLength ]; cannam@0: double* transfHammingWindowIm = new double [ m_FFTLength ]; cannam@0: cannam@0: for (unsigned u=0; u < m_FFTLength; u++) cannam@0: { cannam@0: hammingWindowRe[u] = 0; cannam@0: hammingWindowIm[u] = 0; cannam@0: } cannam@0: cannam@0: cannam@0: // Here, fftleng*2 is a guess of the number of sparse cells in the matrix cannam@0: // The matrix K x fftlength but the non-zero cells are an antialiased cannam@0: // square root function. So mostly is a line, with some grey point. cannam@0: m_sparseKernelIs.reserve( m_FFTLength*2 ); cannam@0: m_sparseKernelJs.reserve( m_FFTLength*2 ); cannam@0: m_sparseKernelRealValues.reserve( m_FFTLength*2 ); cannam@0: m_sparseKernelImagValues.reserve( m_FFTLength*2 ); cannam@0: cannam@0: // for each bin value K, calculate temporal kernel, take its fft to cannam@0: //calculate the spectral kernel then threshold it to make it sparse and cannam@0: //add it to the sparse kernels matrix cannam@0: double squareThreshold = m_CQThresh * m_CQThresh; cannam@0: cannam@0: FFT m_FFT; cannam@0: cannam@0: for (unsigned k = m_uK; k--; ) cannam@0: { cannam@3: for (unsigned u=0; u < m_FFTLength; u++) cannam@3: { cannam@3: hammingWindowRe[u] = 0; cannam@3: hammingWindowIm[u] = 0; cannam@3: } cannam@3: cannam@0: // Computing a hamming window cannam@0: const unsigned hammingLength = (int) ceil( m_dQ * m_FS / ( m_FMin * pow(2,((double)(k))/(double)m_BPO))); cannam@3: cannam@3: unsigned origin = m_FFTLength/2 - hammingLength/2; cannam@3: cannam@0: for (unsigned i=0; i fft length = " << m_FFTLength << ", hop = " << m_hop << std::endl; cannam@20: cannam@0: // allocate memory for cqdata cannam@0: m_CQdata = new double [2*m_uK]; cannam@0: } cannam@0: cannam@0: void ConstantQ::deInitialise() cannam@0: { cannam@0: delete [] m_CQdata; cannam@0: } cannam@0: cannam@32: void ConstantQ::process(const double *FFTRe, const double* FFTIm, cannam@32: double *CQRe, double *CQIm) cannam@0: { cannam@0: for (unsigned row=0; row