51 #include <unsupported/Eigen/FFT>
58 #include <QtConcurrent>
65 using namespace UTILSLIB;
66 using namespace Eigen;
73 const MatrixXd &matTaper,
78 fft.SetFlag(fft.HalfSpectrum);
81 if (vecData.cols() != matTaper.cols() || iNfft < vecData.cols()) {
86 RowVectorXd vecInputFFT;
87 RowVectorXcd vecTmpFreq;
88 MatrixXcd matTapSpectrum(matTaper.rows(),
int(floor(iNfft / 2.0)) + 1);
89 for (
int i=0; i < matTaper.rows(); i++) {
90 vecInputFFT = vecData.cwiseProduct(matTaper.row(i));
91 fft.fwd(vecTmpFreq, vecInputFFT, iNfft);
92 matTapSpectrum.row(i) = vecTmpFreq;
95 return matTapSpectrum;
101 const MatrixXd &matTaper,
105 #ifdef EIGEN_FFTW_DEFAULT
106 fftw_make_planner_thread_safe();
109 QVector<MatrixXcd> finalResult;
119 fft.SetFlag(fft.HalfSpectrum);
121 RowVectorXd vecInputFFT, rowData;
122 RowVectorXcd vecTmpFreq;
124 MatrixXcd matTapSpectrum(matTaper.rows(),
int(floor(iNfft / 2.0)) + 1);
126 for (
int i = 0; i < matData.rows(); ++i) {
127 rowData = matData.row(i);
130 for (j = 0; j < matTaper.rows(); j++) {
131 vecInputFFT = rowData.cwiseProduct(matTaper.row(j));
132 fft.fwd(vecTmpFreq, vecInputFFT, iNfft);
133 matTapSpectrum.row(j) = vecTmpFreq;
136 finalResult.append(matTapSpectrum);
147 QList<TaperedSpectraInputData> lData;
149 dataTemp.matTaper = matTaper;
150 dataTemp.iNfft = iNfft;
152 for (
int i = 0; i < matData.rows(); ++i) {
153 dataTemp.vecData = matData.row(i);
155 lData.append(dataTemp);
158 QFuture<QVector<MatrixXcd> > result = QtConcurrent::mappedReduced(lData,
161 QtConcurrent::OrderedReduce);
162 result.waitForFinished();
163 finalResult = result.result();
174 return computeTaperedSpectraRow(inputData.vecData,
182 const MatrixXcd& resultData)
185 finalData.append(resultData);
199 const Eigen::VectorXd &vecTapWeights,
204 if (matTapSpectrum.rows() != vecTapWeights.rows()) {
205 return Eigen::RowVectorXd();
211 double denom = vecTapWeights.cwiseAbs2().sum() * dSampFreq;
212 Eigen::RowVectorXd vecPsd = 2.0 * (vecTapWeights.asDiagonal() * matTapSpectrum).cwiseAbs2().colwise().sum() / denom;
216 vecPsd.tail(1) /= 2.0;
225 const Eigen::MatrixXcd &vecTapSpectrumTarget,
226 const Eigen::VectorXd &vecTapWeightsSeed,
227 const Eigen::VectorXd &vecTapWeightsTarget,
236 if (vecTapSpectrumSeed.rows() != vecTapSpectrumTarget.rows()) {
237 return Eigen::MatrixXcd();
239 if (vecTapSpectrumSeed.cols() != vecTapSpectrumTarget.cols()) {
240 return Eigen::MatrixXcd();
242 if (vecTapSpectrumSeed.rows() != vecTapWeightsSeed.rows()) {
243 return Eigen::MatrixXcd();
245 if (vecTapSpectrumTarget.rows() != vecTapWeightsTarget.rows()) {
246 return Eigen::MatrixXcd();
256 double denom = sqrt(vecTapWeightsSeed.cwiseAbs2().sum()) * sqrt(vecTapWeightsTarget.cwiseAbs2().sum()) * dSampFreq;
257 Eigen::RowVectorXcd vecCsd = 2.0 * (vecTapWeightsSeed.asDiagonal() * vecTapSpectrumSeed).cwiseProduct((vecTapWeightsTarget.asDiagonal() * vecTapSpectrumTarget).conjugate()).colwise().sum() / denom;
266 vecCsd.tail(1) /= 2.0;
281 RowVectorXd vecFFTFreqs;
283 vecFFTFreqs = (dSampFreq / iNfft) * RowVectorXd::LinSpaced(iNfft / 2.0 + 1, 0.0, iNfft / 2.0);
285 vecFFTFreqs = (dSampFreq / iNfft) * RowVectorXd::LinSpaced((iNfft - 1) / 2.0 + 1, 0.0, (iNfft - 1) / 2.0);
294 QPair<MatrixXd, VectorXd> pairOut;
295 if (sWindowType ==
"hanning") {
296 pairOut.first = hanningWindow(iSignalLength);
297 pairOut.second = VectorXd::Ones(1);
298 }
else if (sWindowType ==
"ones") {
299 pairOut.first = MatrixXd::Ones(1, iSignalLength) / double(iSignalLength);
300 pairOut.second = VectorXd::Ones(1);
302 pairOut.first = hanningWindow(iSignalLength);
303 pairOut.second = VectorXd::Ones(1);
312 std::pair<MatrixXd, VectorXd> pairOut;
313 if (sWindowType ==
"hanning") {
314 pairOut.first = hanningWindow(iSignalLength);
315 pairOut.second = VectorXd::Ones(1);
316 }
else if (sWindowType ==
"ones") {
317 pairOut.first = MatrixXd::Ones(1, iSignalLength) / double(iSignalLength);
318 pairOut.second = VectorXd::Ones(1);
320 pairOut.first = hanningWindow(iSignalLength);
321 pairOut.second = VectorXd::Ones(1);
328 MatrixXd Spectral::hanningWindow(
int iSignalLength)
330 MatrixXd matHann = MatrixXd::Zero(1, iSignalLength);
333 for (
int n = 0; n < iSignalLength; n++) {
334 matHann(0, n) = 0.5 - 0.5 * cos(2.0 * M_PI * n / (iSignalLength - 1.0));
336 matHann.array() /= matHann.row(0).norm();