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.
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 identities cos(atan(A))=(1+A^2)^(-1/2)
, and sin(atan(A))=A*(1+A^2)^(-1/2)
, and so
re = mag .* real(F)./sqrt(real(F).^2+imag(F).^2);
im = mag .* imag(F)./sqrt(real(F).^2+imag(F).^2);
EDIT: I think that if you want to change the phase angle by S
, this will do the trick:
re = mag .* (real(F)*cos(S)-imag(F)*sin(S))./sqrt(real(F).^2+imag(F).^2);
im = mag .* (real(F)*sin(S)+imag(F)*cos(S))./sqrt(real(F).^2+imag(F).^2);
EDIT2: You will still sometimes get bad results with non-zero imaginary part (e.g. if S=pi
), and you will need to plot either stem(real(x_i))
or stem(1:length(x_i),x_i)
as Luis suggested.
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 of x_i
correctly reproduces x
, whereas the imaginary part of x_i
is very small. You can check with stem(real(x_i))
and stem(imag(x_i))
Now stem(x_i)
with complex x_i
plots the imaginary part versus the real part. On the othe hand, stem(1:length(x_i),x_i)
(or of course stem(real(x_i))
) plots the real part of x_i
. Note that this is consistent with plot
's behaviour (see also the answer to this question)
So just plot the real imaginary parts of x_i
separately with stem
. You'll see that the real part reproduces x
as expected, and the imaginary part is negligible (of the order of eps
).