Inverse fourier transform is not regenerating original signal amplitudes

26 views (last 30 days)
Hi,
I have a 50 Hz high-sampled signal with 3300 Hz noise and I'm trying to use a simple and manually designed low-pass filter to remove the noise and create the pure 50 Hz signal. When I plot the pure signal after using the ifft, the amplitudes are not correct, however the noise removal seems to work. Anybody who knows what I am missing? My code is shown below:
fs = 1/0.00001; % sample rate
fsdur = 0.00001; % sample duration
freqs = linspace(0, fs/2+1, fs/2);
data=Var1(1:fs) % 1 second of data
sigfourier=fft(data)/fs
ampsigfourier=sqrt(real(sigfourier).^2+imag(sigfourier).^2)*2 % check amplitudes
PSD=sigfourier.*conj(sigfourier)*fs
% simple filter
vec=zeros(round(fs),1);
positions=[10:60];
vec(positions)=1;
newfourier=sigfourier.*vec
signalfiltered=real(ifft(newfourier))
  1 Comment
Jonas
Jonas on 13 May 2021
Edited: Jonas on 13 May 2021
please remeber that the fft command gives you a two sided conjugate symmetric signal, so if you want to filter, then you have to edit values of the positive and negative frequency side. following that the input for ifft will be complex conjugate symmetric and the output will be already real if it is done correctly (see symmetry flag of ifft function for rounding issues)

Sign in to comment.

Accepted Answer

David Goodmanson
David Goodmanson on 14 May 2021
Hi Sebastian,
You appear to be treating fs in somewhat casual fashion. If fs = 1e5, then for a 1 sec pulse duration the number of samples N is also 1e5. But for any other pulse length that is not true. The code below uses sample length N, because fft and ifft make use of the sample length but know nothing about fs.
The 'signalfiltered' waveform differs from the data by a factor of 1e5 and another factor of 2.
[1] 1e5: fft and ifft are inverses of each other, so that ifft(fft(signal)) = signal. If you use sigfourier = fft(signal)/N as you did, then the ifft has to be multiplied by N to get back to the time waveform.
[2] sigfourier contains both positive and negative frequencies. The filtering process you used captured the positive frequencies but not the negative ones, which are up close to the top end of the frequency plot. Including both positve and negative frequencies in ifft gives a cosine waveform with the correct amplitude. From
cos(2*pi*f0*t) = (1/2)*(exp(2*pi*i*f0*t) + exp(-2*pi*i*f0*t))
you can see that neglecting the negative frequencies gives a complex wave of amplitude 1/2, and taking the real part gives (1/2)*cos(2*pi*f0*t).
I made some sample data but did not include any noise because the noise is not germane to the scaling. The code below shows the original code in fig(1) and the code with the rescaled variables in fig(2).
N = 1e5; fs = 1e5;
f0 = 50;
t = (1:N)/N;
data = 4.5*cos(2*pi*f0*t);
sigfourier = fft(data)/N;
% simple filter
vec = zeros(size(data));
positions = 10:60;
vec(positions) = 1;
newfourier = sigfourier.*vec;
signalfiltered = real(ifft(newfourier));
figure(1); grid on
subplot(2,1,1)
plot(data(1:6000))
subplot(2,1,2)
plot(signalfiltered(1:6000))
% version 2
vec = zeros(size(data));
positions2 = [10:60 N-60:N-10];
vec(positions2) = 1;
newfourier2 = sigfourier.*vec;
signalfiltered2 = N*real(ifft(newfourier2));
figure(2); grid on
subplot(2,1,1)
plot(data(1:6000))
subplot(2,1,2)
plot(signalfiltered2(1:6000))

More Answers (0)

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!