2
votes

I'm trying to filter a (real) signal in Matlab using the FFT and the inverse FFT (IFFT). I have an IIR filter (coefficients 'b' and 'a'). I'm expecting (approximately?) the same result as if I had simply done this:

filteredSignal = filter(b,a,signal);

So this is what I did:

NFFT = length(signal);
FFTsignal = fft(signal, NFFT);
FilterFreqResponse = freqz(b,a,NFFT);
FFTfilteredSignal = FFTsignal .* FilterFreqResponse;
filteredSignal = ifft(FFTfilteredSignal, NFFT);

And the problem here is that the resulting signal (filteredSignal) is complex. And I'd like a real signal (as my input signal). The filter function also returns a real signal. So... what am I doing wrong? Is it impossible to use FFT-based filtering with an IIR filter? I mean: the frequency response of my filter is not symmetric with respect to the origin, so the spectrum of my filtered signal will not be symmetric neither... so the filtered signal in the time domain cannot be real...?

PS: there a "symmetric" option in the ifft function:

filteredSignal = ifft(FFTfilteredSignal, NFFT, 'symmetric');

If I do this, the filteredSignal is now real... but is clearly different (in amplitude and phase) from the one I get using the "filter" function directly. And this "symmetric" option apparently discards the imaginary part, or something like that, so it's probably not a good idea to use it i guess....

Thanks a lot in advance! (and sorry for my English)

4

4 Answers

1
votes

Your FilterFreqResponse is evaluated at NFFT points equally spaced around only the upper half of the unit circle. Did you try FilterFreqResponse = freqz(b,a,NFFT,'whole') ?

3
votes

It is incorrect to just use the real part of the result,

the reason that your answer is complex is that the point wise multiplication has not been performed symmetrically: i.e. for the answer to make sense the vector FilterResponse has to be symmetric about its centre element. You should build the Filter response only up to Fs/2 (i.e. a smaller vector) and then write some logic to apply it conjugate-symmetrically to the mirror frequencies. Alternatively Matlab can do this for you automatically via: FilterFreqResponse = freqz(b,a,NFFT,'whole')

Only then should the 'symmetric' option be used with ifft, since its purpose is to prevent the small numerical error that might exist between the symmetry you created.

1
votes

Use the real part of inverse FFT:

filteredSignal = real(ifft(FFTfilteredSignal, NFFT));
0
votes

Multiplication in the frequency domain is circular convolution in the time domain. To get rid of circular convolution artifacts, you would need to zero pad your signal by the length of your filter response before the FFT, mirror your frequency response filter so that it is complex conjugate symmetric before multiplying (perhaps making both vectors length 2N in your case), then after the IFFT, throw away the added padding, or keep it for additional overlap add/save processing.