RowVectorXd FilterData::applyFFTFilter(const RowVectorXd& data, bool keepOverhead, CompensateEdgeEffects compensateEdgeEffects) const { #ifdef EIGEN_FFTW_DEFAULT fftw_make_planner_thread_safe(); #endif if(data.cols()<m_dCoeffA.cols() && compensateEdgeEffects==MirrorData) { qDebug()<<QString("Error in FilterData: Number of filter taps(%1) bigger then data size(%2). Not enough data to perform mirroring!").arg(m_dCoeffA.cols()).arg(data.cols()); return data; } // std::cout<<"m_iFFTlength: "<<m_iFFTlength<<std::endl; // std::cout<<"2*m_dCoeffA.cols() + data.cols(): "<<2*m_dCoeffA.cols() + data.cols()<<std::endl; if(2*m_dCoeffA.cols() + data.cols()>m_iFFTlength) { qDebug()<<"Error in FilterData: Number of mirroring/zeropadding size plus data size is bigger then fft length!"; return data; } //Do zero padding or mirroring depending on user input RowVectorXd t_dataZeroPad = RowVectorXd::Zero(m_iFFTlength); switch(compensateEdgeEffects) { case MirrorData: t_dataZeroPad.head(m_dCoeffA.cols()) = data.head(m_dCoeffA.cols()).reverse(); //front t_dataZeroPad.segment(m_dCoeffA.cols(), data.cols()) = data; //middle t_dataZeroPad.tail(m_dCoeffA.cols()) = data.tail(m_dCoeffA.cols()).reverse(); //back break; case ZeroPad: t_dataZeroPad.head(data.cols()) = data; break; default: t_dataZeroPad.head(data.cols()) = data; break; } //generate fft object Eigen::FFT<double> fft; fft.SetFlag(fft.HalfSpectrum); //fft-transform data sequence RowVectorXcd t_freqData; fft.fwd(t_freqData,t_dataZeroPad); //perform frequency-domain filtering RowVectorXcd t_filteredFreq = m_dFFTCoeffA.array()*t_freqData.array(); //inverse-FFT RowVectorXd t_filteredTime; fft.inv(t_filteredTime,t_filteredFreq); //Return filtered data if(!keepOverhead) return t_filteredTime.segment(m_dCoeffA.cols()/2, data.cols()); return t_filteredTime.head(data.cols()+m_dCoeffA.cols()); }
RowVectorXd FilterData::applyConvFilter(const RowVectorXd& data, bool keepOverhead, CompensateEdgeEffects compensateEdgeEffects) const { if(data.cols()<m_dCoeffA.cols() && compensateEdgeEffects==MirrorData){ qDebug()<<QString("Error in FilterData: Number of filter taps(%1) bigger then data size(%2). Not enough data to perform mirroring!").arg(m_dCoeffA.cols()).arg(data.cols()); return data; } //Do zero padding or mirroring depending on user input RowVectorXd t_dataZeroPad = RowVectorXd::Zero(2*m_dCoeffA.cols() + data.cols()); RowVectorXd t_filteredTime = RowVectorXd::Zero(2*m_dCoeffA.cols() + data.cols()); switch(compensateEdgeEffects) { case MirrorData: t_dataZeroPad.head(m_dCoeffA.cols()) = data.head(m_dCoeffA.cols()).reverse(); //front t_dataZeroPad.segment(m_dCoeffA.cols(), data.cols()) = data; //middle t_dataZeroPad.tail(m_dCoeffA.cols()) = data.tail(m_dCoeffA.cols()).reverse(); //back break; case ZeroPad: t_dataZeroPad.segment(m_dCoeffA.cols(), data.cols()) = data; break; default: t_dataZeroPad.segment(m_dCoeffA.cols(), data.cols()) = data; break; } //Do the convolution for(int i=m_dCoeffA.cols(); i<t_filteredTime.cols(); i++) t_filteredTime(i-m_dCoeffA.cols()) = t_dataZeroPad.segment(i-m_dCoeffA.cols(),m_dCoeffA.cols()) * m_dCoeffA.transpose(); //Return filtered data if(!keepOverhead) return t_filteredTime.segment(m_dCoeffA.cols()/2, data.cols()); return t_filteredTime.head(data.cols()+m_dCoeffA.cols()); }