ConstantQTransform.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <iostream>
00023 #include "ConstantQTransform.hxx"
00024 #include "FourierTransform.hxx"
00025 #include <cmath>
00026
00027 namespace Simac
00028 {
00029
00030
00031 static double nextpow2(double x)
00032 {
00033 return ceil(std::log(x)/std::log(2.0));
00034 }
00035
00036 static double squaredModule(const double & xx, const double & yy)
00037 {
00038 return xx*xx + yy*yy;
00039 }
00040
00041
00042 ConstantQTransform::ConstantQTransform(unsigned iFS, double ifmin, double ifmax, unsigned binsPerOctave)
00043 : _binsPerOctave(binsPerOctave)
00044 {
00045 FS = iFS;
00046 fmin = ifmin;
00047 fmax = ifmax;
00048
00049 Q = 1/(std::pow(2.,(1/(double)_binsPerOctave))-1);
00050 K = (int) ceil(_binsPerOctave * std::log(fmax/fmin)/std::log(2.0));
00051
00052
00053 mSpectrumSize = (int) std::pow(2., nextpow2(ceil(Q*FS/fmin)));
00054
00055
00056 cqdata.resize(2*K);
00057 }
00058
00059 ConstantQTransform::~ConstantQTransform()
00060 {
00061 }
00062
00063 void ConstantQTransform::sparsekernel(double thresh)
00064 {
00065
00066
00067 double* hammingWindow = new double [2*mSpectrumSize];
00068 for (unsigned mm=0; mm<2*mSpectrumSize; mm++) {
00069 hammingWindow[mm] = 0;
00070 }
00071
00072
00073
00074 mSparseKernelIs.reserve(mSpectrumSize*2);
00075 mSparseKernelJs.reserve(mSpectrumSize*2);
00076 mSparseKernelRealValues.reserve(mSpectrumSize*2);
00077 mSparseKernelImagValues.reserve(mSpectrumSize*2);
00078
00079
00080
00081
00082 double squareThreshold = thresh * thresh;
00083 FourierTransform fft(mSpectrumSize, 1, true);
00084 for (unsigned k=K; k--; ) {
00085
00086 const unsigned hammingLength = (int) ceil(Q * FS / (fmin * std::pow(2.,((double)(k))/(double)_binsPerOctave)));
00087 for (unsigned i=0; i<hammingLength; i++) {
00088 const double angle = 2*M_PI*Q*i/hammingLength;
00089 const double real = cos(angle);
00090 const double imag = sin(angle);
00091 const double absol = Hamming(hammingLength, i)/hammingLength;
00092 hammingWindow[2*i ] = absol*real;
00093 hammingWindow[2*i+1] = absol*imag;
00094 }
00095
00096
00097 fft.doIt(hammingWindow);
00098 const double * transformedHamming = &fft.spectrum()[0];
00099
00100 for (unsigned j=0; j<(2*mSpectrumSize); j+=2) {
00101
00102 const double squaredBin = squaredModule(transformedHamming[j], transformedHamming[j+1]);
00103 if (squaredBin <= squareThreshold) continue;
00104
00105 mSparseKernelIs.push_back(j);
00106 mSparseKernelJs.push_back(k*2);
00107
00108 mSparseKernelRealValues.push_back( transformedHamming[j ]/mSpectrumSize);
00109 mSparseKernelImagValues.push_back(-transformedHamming[j+1]/mSpectrumSize);
00110 }
00111 }
00112 delete [] hammingWindow;
00113 }
00114
00115
00116 void ConstantQTransform::doIt(const std::vector<double> & fftdata)
00117 {
00118
00119
00120
00121
00122 double * constantQSpectrum = &cqdata[0];
00123 const double * fftSpectrum = &fftdata[0];
00124 for (unsigned row=0; row<2*K; row+=2) {
00125 constantQSpectrum[row ] = 0;
00126 constantQSpectrum[row+1] = 0;
00127 }
00128 const unsigned *fftbin = &(mSparseKernelIs[0]);
00129 const unsigned *cqbin = &(mSparseKernelJs[0]);
00130 const double *real = &(mSparseKernelRealValues[0]);
00131 const double *imag = &(mSparseKernelImagValues[0]);
00132 const unsigned int nSparseCells = mSparseKernelRealValues.size();
00133 for (unsigned i = 0; i<nSparseCells; i++)
00134 {
00135 const unsigned row = cqbin[i];
00136 const unsigned col = fftbin[i];
00137 const double & r1 = real[i];
00138 const double & i1 = imag[i];
00139 const double & r2 = fftSpectrum[col];
00140 const double & i2 = fftSpectrum[col+1];
00141
00142 constantQSpectrum[row ] += r1*r2 - i1*i2;
00143 constantQSpectrum[row+1] += r1*i2 + i1*r2;
00144 }
00145 }
00146
00147 }
00148
00149