berndporr / iir1

DSP IIR realtime filter library written in C++

Home Page:http://berndporr.github.io/iir1/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to deal with complex samples?

yarin177 opened this issue · comments

I have a vector of complex samples, my Frequency sample is 1.26MHz, I don't understand how to use the filters with it, because I get Nyquist error if I go beyond Fs/2, is there a way to filter complex samples?

right now I made 2 separate filters one for the real part and the other for the imaginary part, later I loop and do the filter() function for each part

vector<float> samples;
int Fs = 1260000;
int fcenter = 945000;
int BW = 12600;
Iir::Butterworth::BandPass<3> f_real;
Iir::Butterworth::BandPass<3> f_imag;
f_real.setup(Fs, fcenter, BW);
f_imag.setup(Fs, fcenter, BW);
for(int i = 0; i < 100; i++)
{
            float real_val = f_real.filter(samples[i].real());
            float imag_val = f_imag.filter(samples[i].imag());
            data.push_back({real_val,imag_val});
}

This would work fine if I didn't get that Nyquist error, if there is a way to fix that, please show me

There is no option as the filter internally converts the argument into double. You cannot split it up in real/imag and filter separately.
Also complex samples follow Mr Nyquist. No escape. There is no difference from that point of view.
So your max cutoff is 630kHz. That's life. There is no way around that with any filter.

I understand. but what is the problem with splitting the samples in real\part? it actually worked fine for me

Well it's a linear system and the coefficients are real valued so it should work isn't it? I was rather thinking of numerical inaccuracies which might be different between two real valued streams and the complex arithmetic but I guess that's negligible.

How is that my max cutoff is 630MHz?
If I plot FFT with my complex samples It will range from 0 to Fs without aliasing, unlike real samples which will range from 0 to Fs/2.
If I wanted to show a spectrum from 0 to Fs with real samples, I would need to sample at 2*Fs.

That's why I thought I am able to filter out parts beyond 630KHz

If you look at the frequencies of the FFT above > N/2 (Fs/2) they will go backwards to zero Hz so it's not going higher. These are the so called "negative frequencies". They carry indeed information if both time & frequency are allowed to be complex as done in OFDM (https://github.com/dchutchings/py_ofdm) but these are still frequencies below Nyquist. When you compare for example a frequency at X(k) with X(N-k) then you'll see that their complex angles are rotating in the other opposite direction. All explained here: https://youtube.com/playlist?list=PLvUvEbh7a8u_Wqtn7VpVhh_eZALqmLCQh

Until now I have used this simple FIR filter class by by Mike Perkins Which allowed me to apply maxoff of more than 630kHz, I did it by removing the Fs/2 division and leaving it to Fs, I thought the same method would work for this library too, but when I did it, some strange results came out.

Well, I close that now because everything has been said about it and I'm not going to look into the FIR class and then compare it with the IIR for beyond Nyquist. In 1st order that all sounds super dodgy to me as it cannot work. Of course feel free to prove that mathematically to me but not just telling me something works here. Just from a pure epistemological point of view the highest frequency which can be represented is: +1,-1,+1,-1. That's Fs/2. Sorry, case closed.