64 m_iNumOfBlocks = m_iDataLength;
65 m_iBlockSize =
static_cast<int>(matData.cols());
66 m_iSensors =
static_cast<int>(matData.rows());
67 m_matCircBuf.resize(m_iSensors,
static_cast<Eigen::Index
>(m_iNumOfBlocks) * m_iBlockSize);
69 m_bFirstBlock =
false;
73 m_matCircBuf.block(0, m_iBlockIndex * m_iBlockSize, m_iSensors, m_iBlockSize) = matData;
76 if (m_iBlockIndex < m_iNumOfBlocks) {
83 const int iTotalSamples = m_iNumOfBlocks * m_iBlockSize;
84 const int iHalfSpec = m_iFftLength / 2 + 1;
85 const int nb = std::max(1, iTotalSamples / m_iFftLength);
88 for (
int k = 0; k < m_iFftLength; ++k) {
89 winPow +=
static_cast<double>(m_fWin[k]) * m_fWin[k];
92 MatrixXd sum_psdx = MatrixXd::Zero(m_iSensors, iHalfSpec);
93 RowVectorXd vecDataZeroPad = RowVectorXd::Zero(m_iFftLength);
94 RowVectorXcd vecFreqData(iHalfSpec);
95 Eigen::FFT<double> fft;
96 fft.SetFlag(fft.HalfSpectrum);
98 for (
int n = 0; n < nb; ++n) {
99 const int iOffset = n * m_iFftLength;
101 for (
int i = 0; i < m_iSensors; ++i) {
102 vecDataZeroPad.setZero();
103 const int iCopyLen = std::min(m_iFftLength, iTotalSamples - iOffset);
104 vecDataZeroPad.head(iCopyLen) = m_matCircBuf.block(i, iOffset, 1, iCopyLen);
105 for (
int k = 0; k < m_iFftLength; ++k) {
106 vecDataZeroPad[k] *= m_fWin[k];
108 fft.fwd(vecFreqData, vecDataZeroPad);
111 for (
int j = 0; j < iHalfSpec; ++j) {
112 double spower = std::norm(vecFreqData(j)) / (m_dFs * winPow);
113 if (j > 0 && !(m_iFftLength % 2 == 0 && j == m_iFftLength / 2)) {
116 sum_psdx(i, j) += spower;
122 MatrixXd matResult(m_iSensors, iHalfSpec);
123 for (
int i = 0; i < m_iSensors; ++i) {
124 for (
int j = 0; j < iHalfSpec; ++j) {
125 matResult(i, j) = 10.0 * std::log10(sum_psdx(i, j) / nb);
180 qRegisterMetaType<Eigen::MatrixXd>(
"Eigen::MatrixXd");
182 auto* worker =
new RtNoiseWorker(iFftLength, pFiffInfo, iDataLength);
183 worker->moveToThread(&m_workerThread);
185 connect(&m_workerThread, &QThread::finished,
186 worker, &QObject::deleteLater);