60 #include <Eigen/SparseCore>
64 #include <unsupported/Eigen/FFT>
70 using namespace RTPROCESSINGLIB;
71 using namespace Eigen;
72 using namespace UTILSLIB;
80 FilterParameter(QString(
"Tschebyscheff"), QString(
"A tschebyscheff filter"))
105 , m_sFilterName(
"Unknown")
106 , m_sFilterShortDescription(
"")
122 , m_dCenterFreq(dCenterfreq)
123 , m_dBandwidth(dBandwidth)
124 , m_dParksWidth(dParkswidth)
125 , m_iFilterOrder(iOrder)
126 , m_iDesignMethod(iDesignMethod)
127 , m_iFilterType(iFilterType)
128 , m_sFilterName(sFilterName)
129 , m_sFilterShortDescription()
132 qWarning() <<
"[FilterKernel::FilterKernel] Less than 9 taps were provided. Setting number of taps to 9.";
144 iFftLength = iDataSize + m_vecCoeff.cols();
145 exp = ceil(MNEMath::log2(iFftLength));
146 iFftLength = pow(2, exp);
149 if(m_vecCoeff.cols() != (iFftLength/2+1)) {
150 fftTransformCoeffs(iFftLength);
157 bool bKeepOverhead)
const
160 RowVectorXd vecDataZeroPad = RowVectorXd::Zero(2*m_vecCoeff.cols() + vecData.cols());
161 RowVectorXd vecFilteredTime = RowVectorXd::Zero(2*m_vecCoeff.cols() + vecData.cols());
163 vecDataZeroPad.segment(m_vecCoeff.cols(), vecData.cols()) = vecData;
166 for(
int i = m_vecCoeff.cols(); i < vecFilteredTime.cols(); i++) {
167 vecFilteredTime(i-m_vecCoeff.cols()) = vecDataZeroPad.segment(i-m_vecCoeff.cols(),m_vecCoeff.cols()) * m_vecCoeff.transpose();
172 return vecFilteredTime.segment(m_vecCoeff.cols()/2, vecData.cols());
175 return vecFilteredTime.head(vecData.cols()+m_vecCoeff.cols());
183 #ifdef EIGEN_FFTW_DEFAULT
184 fftw_make_planner_thread_safe();
188 int iFftLength = vecData.cols() + m_vecCoeff.cols();
189 int exp = ceil(MNEMath::log2(iFftLength));
190 iFftLength = pow(2, exp);
193 if(m_vecFftCoeff.cols() != (iFftLength/2+1)) {
194 fftTransformCoeffs(iFftLength);
198 Eigen::FFT<double> fft;
199 fft.SetFlag(fft.HalfSpectrum);
202 int iOriginalSize = vecData.cols();
203 if (vecData.cols() < iFftLength) {
204 int iResidual = iFftLength - vecData.cols();
205 vecData.conservativeResize(iFftLength);
206 vecData.tail(iResidual).setZero();
210 RowVectorXcd vecFreqData;
211 fft.fwd(vecFreqData, vecData, iFftLength);
214 vecFreqData = m_vecFftCoeff.array() * vecFreqData.array();
217 fft.inv(vecData, vecFreqData);
221 vecData = vecData.segment(m_vecCoeff.cols()/2, iOriginalSize).eval();
223 vecData = vecData.head(iOriginalSize + m_vecCoeff.cols()).eval();
229 QString FilterKernel::getName()
const
231 return m_sFilterName;
236 void FilterKernel::setName(
const QString& sFilterName)
238 m_sFilterName = sFilterName;
243 double FilterKernel::getSamplingFrequency()
const
250 void FilterKernel::setSamplingFrequency(
double dSFreq)
257 int FilterKernel::getFilterOrder()
const
259 return m_iFilterOrder;
264 void FilterKernel::setFilterOrder(
int iOrder)
266 m_iFilterOrder = iOrder;
271 double FilterKernel::getCenterFrequency()
const
273 return m_dCenterFreq;
278 void FilterKernel::setCenterFrequency(
double dCenterFreq)
280 m_dCenterFreq = dCenterFreq;
285 double FilterKernel::getBandwidth()
const
292 void FilterKernel::setBandwidth(
double dBandwidth)
294 m_dBandwidth = dBandwidth;
299 double FilterKernel::getParksWidth()
const
301 return m_dParksWidth;
306 void FilterKernel::setParksWidth(
double dParksWidth)
308 m_dParksWidth = dParksWidth;
313 double FilterKernel::getHighpassFreq()
const
315 return m_dHighpassFreq;
320 void FilterKernel::setHighpassFreq(
double dHighpassFreq)
322 m_dHighpassFreq = dHighpassFreq;
327 double FilterKernel::getLowpassFreq()
const
329 return m_dLowpassFreq;
334 void FilterKernel::setLowpassFreq(
double dLowpassFreq)
336 m_dLowpassFreq = dLowpassFreq;
341 Eigen::RowVectorXd FilterKernel::getCoefficients()
const
348 void FilterKernel::setCoefficients(
const Eigen::RowVectorXd& vecCoeff)
350 m_vecCoeff = vecCoeff;
355 Eigen::RowVectorXcd FilterKernel::getFftCoefficients()
const
357 return m_vecFftCoeff;
362 void FilterKernel::setFftCoefficients(
const Eigen::RowVectorXcd& vecFftCoeff)
364 m_vecFftCoeff = vecFftCoeff;
369 bool FilterKernel::fftTransformCoeffs(
int iFftLength)
371 #ifdef EIGEN_FFTW_DEFAULT
372 fftw_make_planner_thread_safe();
375 if(m_vecCoeff.cols() > iFftLength) {
376 std::cout <<
"[FilterKernel::fftTransformCoeffs] The number of filter taps is bigger than the FFT length."<< std::endl;
381 Eigen::FFT<double> fft;
382 fft.SetFlag(fft.HalfSpectrum);
385 RowVectorXd vecInputFft;
386 if (m_vecCoeff.cols() < iFftLength) {
387 vecInputFft.setZero(iFftLength);
388 vecInputFft.block(0,0,1,m_vecCoeff.cols()) = m_vecCoeff;
390 vecInputFft = m_vecCoeff;
394 RowVectorXcd vecFreqData;
395 fft.fwd(vecFreqData, vecInputFft, iFftLength);
396 m_vecFftCoeff = vecFreqData;;
403 void FilterKernel::designFilter()
406 int iFftLength = m_iFilterOrder;
407 int exp = ceil(MNEMath::log2(iFftLength));
408 iFftLength = pow(2, exp);
410 switch(m_iDesignMethod) {
416 static_cast<ParksMcClellan::TPassType
>(m_iFilterType));
417 m_vecCoeff = filter.FirCoeff;
420 fftTransformCoeffs(iFftLength);
428 switch(m_iFilterType) {
431 (m_dCenterFreq)*(m_sFreq/2.),
432 m_dParksWidth*(m_sFreq/2),
433 (m_dCenterFreq)*(m_sFreq/2),
434 m_dParksWidth*(m_sFreq/2),
436 static_cast<CosineFilter::TPassType
>(m_iFilterType));
442 (m_dCenterFreq)*(m_sFreq/2),
443 m_dParksWidth*(m_sFreq/2),
444 (m_dCenterFreq)*(m_sFreq/2),
445 m_dParksWidth*(m_sFreq/2),
447 static_cast<CosineFilter::TPassType
>(m_iFilterType));
453 (m_dCenterFreq + m_dBandwidth/2)*(m_sFreq/2),
454 m_dParksWidth*(m_sFreq/2),
455 (m_dCenterFreq - m_dBandwidth/2)*(m_sFreq/2),
456 m_dParksWidth*(m_sFreq/2),
458 static_cast<CosineFilter::TPassType
>(m_iFilterType));
464 m_vecCoeff.resize(m_iFilterOrder);
466 m_vecCoeff.head(m_iFilterOrder/2) = filtercos.
m_vecCoeff.tail(m_iFilterOrder/2);
467 m_vecCoeff.tail(m_iFilterOrder/2) = filtercos.
m_vecCoeff.head(m_iFilterOrder/2);
470 fftTransformCoeffs(iFftLength);
476 switch(m_iFilterType) {
479 m_dHighpassFreq = m_dCenterFreq*(m_sFreq/2);
483 m_dLowpassFreq = m_dCenterFreq*(m_sFreq/2);
488 m_dLowpassFreq = (m_dCenterFreq + m_dBandwidth/2)*(m_sFreq/2);
489 m_dHighpassFreq = (m_dCenterFreq - m_dBandwidth/2)*(m_sFreq/2);
492 getShortDescription();
497 QString FilterKernel::getShortDescription()
const
499 QString description(
m_designMethods.at(m_iDesignMethod).getName() +
" - " + \
500 QString::number(m_dHighpassFreq,
'g',4) +
"Hz to " + QString::number(m_dLowpassFreq,
'g',4) +
"Hz - " \
501 "Ord: " + QString::number(m_iFilterOrder));
509 if(m_iDesignMethod < 0){
519 if(m_iFilterType < 0){
527 void FilterKernel::setDesignMethod(
int iDesignMethod)
529 if(iDesignMethod < 0){
532 m_iDesignMethod = iDesignMethod;
538 void FilterKernel::setFilterType(
int iFilterType)
543 m_iFilterType = iFilterType;
564 QString sDescription)
566 , m_sDescription(sDescription)