Beispiel #1
0
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());
}
Beispiel #2
0
Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample, bool frequency, int type, bool window) {
	int numData = int(GetCount());
    VectorXd timebuf(numData);
    int num = 0;
    for (int i = 0; i < numData; ++i) {
        double data = Membercall(getdata)(i);
        if (!IsNull(data)) {
			timebuf[i] = Membercall(getdata)(i);
			num++;
        }
    }
    Vector<Pointf> res;	
    if (num < 3)
        return res;
    timebuf.resize(num);
    
    double windowSum = 0;
    if (window) {
	    for (int i = 0; i < numData; ++i) {
	        double windowDat = 0.54 - 0.46*cos(2*M_PI*i/numData);
	        windowSum += windowDat;
	    	timebuf[i] *= windowDat;	// Hamming window
	    }
	} else
		windowSum = numData;
	
    VectorXcd freqbuf;
    try {
	    Eigen::FFT<double> fft;
	    fft.SetFlag(fft.HalfSpectrum);
	    fft.fwd(freqbuf, timebuf);
    } catch(...) {
        return res;
    }
    if (frequency) {
    	for (int i = 0; i < int(freqbuf.size()); ++i) {    
    		double xdata = i/(tSample*numData);
		
			switch (type) {
			case T_PHASE:	res << Pointf(xdata, std::arg(freqbuf[i]));				break;
			case T_FFT:		res << Pointf(xdata, 2*std::abs(freqbuf[i])/windowSum);	break;
			case T_PSD:		res << Pointf(xdata, 2*sqr(std::abs(freqbuf[i]))/(windowSum/tSample));
			}
    	}
    } else {
        for (int i = int(freqbuf.size()) - 1; i > 0; --i) {    
    		double xdata = (tSample*numData)/i;
		
			switch (type) {
			case T_PHASE:	res << Pointf(xdata, std::arg(freqbuf[i]));				break;
			case T_FFT:		res << Pointf(xdata, 2*std::abs(freqbuf[i])/windowSum);	break;
			case T_PSD:		res << Pointf(xdata, 2*sqr(std::abs(freqbuf[i]))/(windowSum/tSample));
			}
    	}
    }
    return res;
}
Beispiel #3
0
void FilterData::fftTransformCoeffs()
{
    #ifdef EIGEN_FFTW_DEFAULT
        fftw_make_planner_thread_safe();
    #endif

    //zero-pad m_dCoeffA to m_iFFTlength
    RowVectorXd t_coeffAzeroPad = RowVectorXd::Zero(m_iFFTlength);
    t_coeffAzeroPad.head(m_dCoeffA.cols()) = m_dCoeffA;

    //generate fft object
    Eigen::FFT<double> fft;
    fft.SetFlag(fft.HalfSpectrum);

    //fft-transform filter coeffs
    m_dFFTCoeffA = RowVectorXcd::Zero(m_iFFTlength);
    fft.fwd(m_dFFTCoeffA,t_coeffAzeroPad);
}
Beispiel #4
0
CosineFilter::CosineFilter(int fftLength, float lowpass, float lowpass_width, float highpass, float highpass_width, double sFreq, TPassType type)
{
    m_iFilterOrder = fftLength;

    int highpasss,lowpasss;
    int highpass_widths,lowpass_widths;
    int k,s,w;
    int resp_size = fftLength/2+1; //Take half because we are not interested in the conjugate complex part of the spectrum

    double pi4 = M_PI/4.0;
    float mult,add,c;

    RowVectorXcd filterFreqResp = RowVectorXcd::Ones(resp_size);

    //Transform frequencies into samples
    highpasss = ((resp_size-1)*highpass)/(0.5*sFreq);
    lowpasss = ((resp_size-1)*lowpass)/(0.5*sFreq);

    lowpass_widths = ((resp_size-1)*lowpass_width)/(0.5*sFreq);
    lowpass_widths = (lowpass_widths+1)/2;

    if (highpass_width > 0.0) {
        highpass_widths = ((resp_size-1)*highpass_width)/(0.5*sFreq);
        highpass_widths  = (highpass_widths+1)/2;
    }
    else
        highpass_widths = 3;

    //Calculate filter freq response - use cosine
    //Build high pass filter
    if(type != LPF) {
        if (highpasss > highpass_widths + 1) {
            w    = highpass_widths;
            mult = 1.0/w;
            add  = 3.0;

            for (k = 0; k < highpasss-w+1; k++)
                filterFreqResp(k) = 0.0;

            for (k = -w+1, s = highpasss-w+1; k < w; k++, s++) {
                if (s >= 0 && s < resp_size) {
                    c = cos(pi4*(k*mult+add));
                    filterFreqResp(s) = filterFreqResp(s).real()*c*c;
                }
            }
        }
    }

    //Build low pass filter
    if(type != HPF) {
        if (lowpass_widths > 0) {
            w    = lowpass_widths;
            mult = 1.0/w;
            add  = 1.0;

            for (k = -w+1, s = lowpasss-w+1; k < w; k++, s++) {
                if (s >= 0 && s < resp_size) {
                    c = cos(pi4*(k*mult+add));
                    filterFreqResp(s) = filterFreqResp(s).real()*c*c;
                }
            }

            for (k = s; k < resp_size; k++)
                filterFreqResp(k) = 0.0;
        }
        else {
            for (k = lowpasss; k < resp_size; k++)
                filterFreqResp(k) = 0.0;
        }
    }

    m_dFFTCoeffA = filterFreqResp;

    //Generate windowed impulse response - invert fft coeeficients to time domain
    Eigen::FFT<double> fft;
    fft.SetFlag(fft.HalfSpectrum);

    //invert to time domain and
    fft.inv(m_dCoeffA, filterFreqResp);/*
    m_dCoeffA = m_dCoeffA.segment(0,1024).eval();

    //window/zero-pad m_dCoeffA to m_iFFTlength
    RowVectorXd t_coeffAzeroPad = RowVectorXd::Zero(fftLength);
    t_coeffAzeroPad.head(m_dCoeffA.cols()) = m_dCoeffA;

    //fft-transform filter coeffs
    m_dFFTCoeffA = RowVectorXcd::Zero(fftLength);
    fft.fwd(m_dFFTCoeffA,t_coeffAzeroPad);*/
}