Hi guy's I'm working on simple signals and I want to calculate the Fourier transform of a signal, get the magnitude and phases, then reconstruct the original signal from that.
I'm basing my code on this thread.
Code:
>> n=0:99;
>> N=length(n);
>> x = sin((2*pi/N).*n).*cos((pi/N).*n);
>> F = fft(x);
>> mag = sqrt(real(F).^2 + imag(F).^2);
>> phase = atan2(imag(F),real(F));
>> re = mag .* cos(phase);
>> im = mag .* sin(phase);
>> F_i = re + 1i*im;
>> x_i = ifft(F_i);
>> figure;stem(x);figure;stem(x_i);
I completely get different graphs.
EDIT: I'm actually doing this to test what would happen to a signal if the phase changes. So with this I will need the phase angle to construct the signal again.
I'm still new to both Fourier + Matlab so I apologize if I'm making some random stupid mistake. I'll appreciate it if you guys can point me in the right direction. Thank you.
There is no such numerical instability in the FFT. The problem is that roundoff errors give a very small imaginary part in the recovered signal
x_i
. That's normal. The real part ofx_i
correctly reproducesx
, whereas the imaginary part ofx_i
is very small. You can check withstem(real(x_i))
andstem(imag(x_i))
Now
stem(x_i)
with complexx_i
plots the imaginary part versus the real part. On the othe hand,stem(1:length(x_i),x_i)
(or of coursestem(real(x_i))
) plots the real part ofx_i
. Note that this is consistent withplot
's behaviour (see also the answer to this question)So just plot the real imaginary parts of
x_i
separately withstem
. You'll see that the real part reproducesx
as expected, and the imaginary part is negligible (of the order ofeps
).The problem is caused by round-off errors in
phase
, so don't use them when calulating the sine and consine of the phase angles. Instead, use trig identitiescos(atan(A))=(1+A^2)^(-1/2)
, andsin(atan(A))=A*(1+A^2)^(-1/2)
, and soEDIT: I think that if you want to change the phase angle by
S
, this will do the trick:EDIT2: You will still sometimes get bad results with non-zero imaginary part (e.g. if
S=pi
), and you will need to plot eitherstem(real(x_i))
orstem(1:length(x_i),x_i)
as Luis suggested.