Different plot shape for fft depending on time sample spacing

26 views (last 30 days)
jefazo jefazo on 20 Nov 2019
Edited: Daniel M on 21 Nov 2019
Hi everyone, I am having the following issue. I am trying to analyse the input and output signal of my filter using fft. However, I am not sure if my fft is correct. My input signal is the product of a sawtooth and sine waveforms both with frequencies 6kHz and 32kHz, respectively. Both individual signals have an amplitude of 1 before being multiplied.
Depending on my time values I get different result for my fft plots. If I use values of time spaced out by the period of my sampling frequency, I get a "nice" looking graph with clear peaks as you would expect in a Fourier Transform (see Fig.1). However, if I use values of time spaced out by the period of the signal being sampled, the graph has more frequency components (see Fig. 2). I really don't know which graph is correctly displays my FFT. Also I have the problem that I used an online tutorial to achieve my FFT but I do not understand why the guy did what he did in his code which I do not understand. However, if I plot the absolute values of FFT, I get graphs with similar shapes but the amplitudes jump up to 30 or 40 more (see Fig. 3 and 4). Also for Fig.2 why is there a small wiggle at the start of the filtered signal (time domain) vs time ? Please your help in performing FFT accurately would be of great help. Thanks.
%Time values using sampling frequency period.
fsampling = 80000;
tsampling = 0:1/fsampling:5000000*Tsampling;
%Time values using sawtooth frequency period.
fsampling = 80000;
fsawtooth = 6000;
Tsawtooth = (1/fsawtooth);
tsawtooth = 0:1/fssampling:20*Tsawtooth;
%Piece of code to use FFT that I don't understand.
L0 = length(product);
NFFT0 = 2^nextpow2(L0);
Y0 = fft(product,NFFT0)/L0;
FreqDom0 = fs/2*linspace(0,1,NFFT0/2+1);
plot(FreqDom0, 2*abs(Y0(1:NFFT0/2+1)));
%Performing FFT using just abs.
IPFFT = abs(fft(product));
plot(t, IPFFT);

Daniel M on 20 Nov 2019
Edited: Daniel M on 20 Nov 2019
Your code is incomplete so I can barely comment on it. If you have trouble understanding it, you should look up the examples from The MathWorks on Fourier transforms. https://www.mathworks.com/help/matlab/examples.html?category=fourier-analysis-and-filtering
As for your general question, it has to do with a concept called resolution. There is temporal resolution (time domain) and spectral resolution (frequency domain). Resolution can be thought of as the step size from one point to the next. The fft() function transforms your time series into a number of bins each representing a certain bandwidth of frequencies. Essentially, the more samples you have in the time domain, the better your resolution in the frequency domain (more bins therefore smaller bandwidth of each bin). Read more here. https://dsp.stackexchange.com/questions/10236/fft-frequency-resolution
This is why Fig1 looks more ideal than Fig2. You can verify this by comparing to the analytical Fourier series of your problem. http://mathworld.wolfram.com/FourierSeries.html
Fig2 is not incorrect, it just has a lower resolution than the results of Fig1.
I disagree that the "amplitudes jump" in Figs 3 and 4. I think you are misreading the y-axis, because they have different scales. You can use the function linkaxes to easily synchronize the axes between plots. https://www.mathworks.com/help/matlab/ref/linkaxes.html
As for the "wiggle", that is likely due to the way you filtered your signal. You probably used filter() instead of filtfilt(), and introduced a phase distortion into your signal.
Daniel M on 21 Nov 2019
Again, you're not showing your full code so I have no way to verify that the signals should have peaks at 6 and 32 kHz. I cannot explain the concepts as clearly as they are explained in the documentation for the fft function, so start by studying and reproducing their examples.
Using the second input to fft (NFFT0) isn't necessary. It can improve performance, but I find it tends to just skew the results and lead to a loss in precision. Dividing by L0 and multiplying Y0 by 2 are also not necessary if you're just looking at the frequency. They only normalize the results so that the magnitudes are dealt with properly. (E.g. since you're only looking at the one-sided spectrum, you need to multiply by 2 to get the correct power for the bins).
There are also useful examples in the documentation for fftshift.