>> fft([1 4 66])
ans =
71.0000 -34.0000 +53.6936i -34.0000 -53.6936i
Can someone explain according the result above?
EDIT Well that's embarassing. I left out a factor of 2. Updated answer follows...
The Discrete Fourier Transform, which an FFT algorithm computes quickly, assumes the input data of length N is one period of a periodic signal. The period is 2*pi rad. The frequency of the output points is given by 2*n*pi/N rad/sec, where n is the index from 0 to N-1.
For your example, then, 71 is the value at 0 rad/sec, commonly called DC, -34+53.7i is the value at 2*pi/3 rad/sec, and its conjugate is the value at 4*pi/3 rad/sec. Note that by periodicity, 2*pi/3 rad/sec = -2*pi/3 rad/sec = 4*pi/3 rad/sec. So the second half of the spectrum can be regarded as the frequencies from -pi..0 or pi..2*pi.
If the data represents sampled data at a constant sampling rate, and you know that sampling rate, you can convert rad/sec to Hz. Let the sampling rate be deltaT. Its reciprocal is the sampling frequency Fs. Then the period is T = N*deltaT sec = 2*pi rad. 1/T gives the frequency resolution deltaF = Fs/N Hz. Therefore the frequency of the output points is n*Fs/N Hz.
This is a vector of complex numbers representing your signal in frequency domain.
Related
I am new to Matlab and performing signal processing. I am trying to understand what this code is doing? How and why are we determining the indexNyquist and spectrum?
spectrum = fft(Signal,k); %generate spetrum of signal with FFT to k points
indexNyquist = round(k/2+1); %vicinity of nyquist frequency
spectrum = spectrum(1:indexNyquist); %truncate spectrum to Nyquist frequency
spectrum = spectrum/(length(Signal)); %scale spectrum by number of points
spectrum(2:end) = 2 * spectrum3(2:end); %compensate for truncating negative frequencies, but not DC component
For a purely real input signal the corresponding FFT will be complex conjugate symmetric about the Nyquist frequency, so there is no useful additional information in the top N/2 bins. We can therefore just take the bottom N/2 bins and multiply their magnitude by 2 to get a (complex) spectrum with no redundancy. This spectrum represents frequencies from 0 to Nyquist (and their aliased equivalent frequencies).
Note that bin 0 (0 Hz aka DC) is purely real and does not need to be doubled, hence the comment in your Matlab code.
This code takes FFT of a signal and plots it on a new frequency axis.
f=600;
Fs=6000;
t=0:1/Fs:0.3;
n=0:1:length(t);
x=cos(2*pi*(400/Fs)*n)+2*sin(2*pi*(1100/Fs)*n);
y=fft(x,512);
freqaxis=Fs*(linspace(-0.5,0.5, length(y)));
subplot(211)
plot(freqaxis,fftshift(abs(y)));
I understand why we used fftshift because we wanted to see the signal centered at the 0 Hz (DC) value and it is better for observation.
However I seem to be confused about how the frequency axis is defined. Specifically, why did we especially multiply the range of [-0.5 0.5] with Fs and we obtain the [-3000 3000] range? It could be [-0.25 0.25].
The reason why the range is between [-Fs/2,Fs/2] is because Fs/2 is the Nyquist frequency. This is the largest possible frequency that has the ability of being visualized and what is ultimately present in your frequency decomposition. I also disagree with your comment where the range "could be between [-0.25,0.25]". This is contrary to the definition of the Nyquist frequency.
From signal processing theory, we know that we must sample by at least twice the bandwidth of the signal in order to properly reconstruct the signal. The bandwidth is defined as the largest possible frequency component that can be seen in your signal, which is also called the Nyquist Frequency. In other words:
Fs = 2*BW
The upper limit of where we can visualize the spectrum and ultimately the bandwidth / Nyquist frequency is defined as:
BW = Fs / 2;
Therefore because your sampling frequency is 6000 Hz, this means the Nyquist frequency is 3000 Hz, so the range of visualization is [-3000,3000] Hz which is correct in your magnitude graph.
BTW, your bin centres for each of the frequencies is incorrect. You specified the total number of bins in the FFT to be 512, yet the way you are specifying the bins is with respect to the total length of the signal. I'm surprised why you don't get a syntax error because the output of the fft function should give you 512 points yet your frequency axis variable will be an array that is larger than 512. In any case, that is not correct. The frequency at each bin i is supposed to be:
f = i * Fs / N, for i = 0, 1, 2, ..., N-1
N is the total number of points you have in your FFT, which is 512. You originally had it as length(y) and that is not correct... so this is probably why you have a source of confusion when examining the frequency axis. You can read up about why this is the case by referencing user Paul R's wonderful post here: How do I obtain the frequencies of each value in an FFT?
Note that we only specify bins from 0 up to N - 1. To account for this when you specify the bin centres of each frequency, you usually specify an additional point in your linspace command and remove the last point:
freqaxis=Fs*(linspace(-0.5,0.5, 513); %// Change
freqaxis(end) = []; %// Change
BTW, the way you've declared freqaxis is a bit obfuscated to me. This to me is more readable:
freqaxis = linspace(-Fs/2, Fs/2, 513);
freqaxis(end) = [];
I personally hate using length and I favour numel more.
In any case, when I run the corrected code to specify the bin centres, I now get this plot. Take note that I inserted multiple data cursors where the peaks of the spectrum are, which correspond to the frequencies for each of the cosines that you have declared (400 Hz and 1100 Hz):
You see that there are some slight inaccuracies, primarily due to the number of bins you have specified (i.e. 512). If you increased the total number of bins, you will see that the frequencies at each of the peaks will get more accurate.
I have a audio signal sample at the rate of 10Khz, I need to find fourier coefficients of my signal. I saw one example in mathwork's website where they are using following code to do the fft decomposition of a signal y:
NFFT = 2^nextpow2(L);
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
where L is the length of the signal, I don't really understand why its defining the variable NFFT the way shown in the code above? Can't I just chose any value for NFFT? Also why are we taking Fs/2 in third line of the code above?
NFFT can be any positive value, but FFT computations are typically much more efficient when the number of samples can be factored into small primes. Quoting from Matlab documentation:
The execution time for fft depends on the length of the transform. It is fastest for powers of two. It is almost as fast for lengths that have only small prime factors. It is typically several times slower for lengths that are prime or which have large prime factors.
It is thus common to compute the FFT for the power of 2 which is greater or equal to the number of samples of the signal y. This is what NFFT = 2^nextpow2(L) does (in the Example from Matlab documentation y is constructed to have a length L).
When NFFT > L the signal is zero padded to the NFFT length.
As far as fs/2 goes, it is simply because the frequency spectrum of a real-valued signal has Hermitian symmetry (which means that the values spectrum above fs/2 can be obtained from the complex-conjugate of the values below fs/2), and as such is completely specifies from the first NFFT/2+1 values (with the index NFFT/2+1 corresponding to fs/2). So, instead of showing the redundant information above fs/2, the example chose to illustrate only the spectrum up to fs/2.
Output of FFT is complex for real valued input. That means for a signal sampled at Fs Hz, The fourier transform of this signal will have frequency components from -Fs/2 to Fs/2 and is symmetric at zero Hz. (Nyquist criterion states that if you have a signal with maxium frequency component at f Hz, you need to sample it with atleast 2f Hz .
You may wonder what does negative frequency mean here. If you are a mathematician you may care about the negative frequency but if you are an engineer, you may choose to ignore the notion of negative frequency and focus only on frequencies from 0 to Fs/2. (Max freq component for a signal sampled at Fs Hz is Fs/2)
Using FFT to learn more about frequency components present in your signal is cumbsrsome. You can use the function pwelch function in MATLAB to learn more frequencies present in your signal and also the power of these signals. MATLAB will automatically compute the NFFT required and return the frequencies present in your signal along with the power at each frequency. Use this syntax:
[p,f] = pwelch(x,[],[],[],Fs)
Look at the documentation of pwelch for more information.
I was expecting the frequency component to be 1700 i.e. a spike at 1700 but the output shows multiple frequency:
fs = 44100;
t = 0:1/fs:0.001;
s = sin(2 * pi * 1700 * t);
subplot(211), stem(abs(fft(s))), title('abs(fft(s))')
subplot(212), stem(s), title('s')
Similarly when I tried the below code I did not got what I expected:
Fs = 8000;
dt = 1/Fs;
StopTime = 0.25;
t = (0:dt:StopTime-dt)';
Fc = 60;
x = cos(2*pi*Fc*t);
subplot(211), stem(abs(fft(x))), title('abs(fft(x))')
subplot(212), stem(x), title('x')
Why my frequency component are being displayed as multiples values as there should be exactly one frequency present in a signal in one steady sine / cos wave.
It's a single frequency, but it appears twice: positive and negative frequencies. You'll see this better with fftshift, which arranges the frequency samples so that they run from -fs/2 to fs/2:
subplot(211)
freq_axis = -fs/2+fs/numel(t):fs/numel(t):fs/2;
stem(freq_axis, abs(fftshift(fft(s))))
title('abs(fft(s))')
For example, in your first example this produces the following figure.
Note the two spikes around +1700 and -1700 Hz. Their location is not exact for two reasons:
Your time signal is of finite duration, which produces convolution with a sinc in the frequency domain. That is, the frequency spike is made wider.
The FFT gives frequency samples, and none of those samples falls exactly at +/-1700 Hz.
In your second example the time signal is longer (it contains more cycles), which reduces the width of the frequency spikes. This can be appreciated in your second figure (again the fftshift correction is needed to make the two spikes appear in symmetric frequency locations).
Since your signal is not an integer number of cycles there is a discontinuity (remember that the Fourier Transform assumes periodicity), which results in spectral leakage, which is visible as a "smearing" of the spectrum. To avoid this we usually apply a suitable window function (e.g. von Hann aka Hanning window)prior to the FFT - think of this as smoothing out the discontinuity. This reduces the smearing and makes peaks more distinct.
As noted in another answer, you also see a second peak because you're plotting the entire spectrum, and every component in the time domain has a positive and a negative frequency component in the frequency domain. For a real-valued signal the FFT is complex-conjugate symmetric in the frequency domain and so half of the spectrum is redundant. You would normally only plot N/2 values.
I am doing FFT with matlab.the time period i am doing the fft on it is 1 second and it consist of 50000 equlay spaces samples. I want to test the FFT results. so I have given an input as below (wave) which is a complex of sinosuidal waves (and I have samples it by sampling frequency of 50 KHZ)and I expect to have the frequency magnitude results as I have given in the input. the results are ok for low frequency ranges but for the higher frequency (5752 Hz and 7993 Hz) results are 5.87 and 6.7 respectively (instead of 6 and ). what Is the origin of this big mistake ? how can I improve my results ?!
Here is the code:
t = 0:1/50000:1;
wave = 100*sin(2*pi*50*t)+1*sin (2*pi*123*t)+2*sin (2*pi*203*t)+3*sin(2*pi*223*t)+4*sin(2*pi*331*t)+5*sin(2*pi*2812*t)+6*sin(2*pi*5752*t)+7*sin(2*pi*7993*t);
SPEC = fft(wave);
L = size(SPEC,2);
x= (0:L/2-1);
Half_SPEC = abs(SPEC(1:L/2))/(L/2); %% removing the mirror side and ranging the domain
plot(x,Half_SPEC);
As Oli Charlesworth has pointed out, you are taking the FFT of 50001 points, which means that the frequency spacing is 1/50001.
Typically the FFT will give you the exact magnitude of your sinusoid only if its frequency is an exact multiple of the frequency spacing. Otherwise, the energy will be spread over multiple FFT bins in a process called spectral leakage.
You may confirm this by changing the number of samples such that the frequency of your sinusoids are a multiple of the frequency spacing:
t = 0:1/50000:1-1/50000;
Windowing the input signal can also help control the amount of leakage.