How to know sampling frequency of a sin(x) function - matlab

Consider the following script that plots a sine wave.
t = 0:pi/100:2*pi;
y = sin(t);
plot(t,y)
grid on % Turn on grid lines for this plot
This gives me a plot of sine wave. I understand the sine wave that appears continuous, should actually be discrete (my PC cannot store infinite no. of samples of continuous signal), and the matlab plot function does some kind of interpolation to connect the dots.
So In fact I also used stem instead of plot to see the sampled values (on time axis) of sine.
Now my question is there must be some sampling frequency used here. How much is that?

The sampling interval is the time interval between two consecutive samples of your signal.
The sampling frequency means how much samples of your signal you have in a fixed time interval, and it is reciprocal to the sampling interval.
You declared:
t = 0:pi/100:2*pi;
So your sampling interval is π/100. This means that your sampling frequency is 100/π.
If you want exact units, you'll have to determine the time units for t. If t is in seconds, then your sampling frequency is 100/π Hz (1Hz = 1sec-1).
By the way, MATLAB's plot connects the sampling with straight lines, there is no additional interpolation involved.

Related

How can i use fft to find the maximum frequency of a periodic signal?

I'm trying to find the maximum frequency of a periodic signal in Matlab and as i know when you convert a periodic signal to the frequency spectrum you get only delta functions however i get a few curves between the produced delta functions. Here is the code :
t=[-0.02:10^-3:0.02];
s=5.*(1+cos(2*pi*10*t)).*cos(2*pi*100*t);
figure, subplot(211), plot(t,s);
y=fft(s);
subplot(212), plot(t,y);
Here is a code-snippet to help you understand how to get the frequency-spectrum using fft in matlab.
Things to remember are:
You need to decide on a sampling frequency, which should be high enough, as per the Nyquist Criterion (You need the number of samples, at least more than twice the highest frequency or else we will have aliasing). That means, fs in this example cannot be below 2 * 110. Better to have it even higher to see a have a better appearance of the signal.
For a real signal, what you want is the power-spectrum obtained as the square of the absolute of the output of the fft() function. The imaginary part, which contains the phase should contain nothing but noise. (I didn't plot the phase here, but you can do this to check for yourself.)
Finally, we need to use fftshift to shift the signal such that we get the mirrored spectrum around the zero-frequency.
The peaks would be at the correct frequencies. Now considering only the positive frequencies, as you can see, we have the largest peak at 100Hz and two further lobs around 100Hz +- 10Hz i.e. 90Hz and 110Hz.
Apparently, 110Hz is the highest frequency, in your example.
The code:
fs = 500; % sampling frequency - Should be high enough! Remember Nyquist!
t=[-.2:1/fs:.2];
s= 5.*(1+cos(2*pi*10*t)).*cos(2*pi*100*t);
figure, subplot(311), plot(t,s);
n = length(s);
y=fft(s);
f = (0:n-1)*(fs/n); % frequency range
power = abs(y).^2/n;
subplot(312), plot(f, power);
Y = fftshift(y);
fshift = (-n/2:n/2-1)*(fs/n); % zero-centered frequency range
powershift = abs(Y).^2/n;
subplot(313), plot(fshift, powershift);
The output plots:
The first plot is the signal in the time domain
The signal in the frequency domain
The shifted fft signal

How to plot FFT of sine wave? [duplicate]

I'm working on Matlab, I want to perform FFT on a wav file I previously recorded on Matlab as well.
fs = 44100; % Hz
t = 0:1/fs:1; % seconds
f = 600; % Hz
y = sin(2.*pi.*f.*t);
audiowrite('600freq.wav',y,fs)
This is the way I'm recording in the wav file.
Now to the reading and FFT part:
[y,Fs] = audioread('600freq.wav');
sound(y)
plot(fft(y))
This is the plot of the FFT I get:
Maybe I'm missing something about the FFT, but I expected two vertical lollipops.
Another thing I noticed that's wrong, is when I play the sound after reading it form the file it's longer and the pitch is significantly lower.
My guess is a sampling rate problem, but I really have no idea of what to do about it.
Thanks for any help in advance.
That's because you're not plotting the magnitude. What you are plotting are the coefficients, but these are complex valued. Because of that, the horizontal axis is the real component and the vertical axis is the imaginary component. Also, when you use sound by itself, the default sampling frequency is 8 kHz (8192 Hz to be exact) which explains why your sound is of a lower pitch. You need to use the sampling frequency as a second argument into sound, and that's given to you by the second output of audioread.
So, try placing abs after the fft call and also use Fs into sound:
[y,Fs] = audioread('600freq.wav');
sound(y, Fs);
plot(abs(fft(y)))
Also, the above code doesn't plot the horizontal axis properly. If you want to do that, make sure you fftshift your spectra after you take the Fourier transform, then label your axis properly. If you want to determine what each horizontal value is in terms of frequency, this awesome post by Paul R does the trick: How do I obtain the frequencies of each value in an FFT?
Basically, each horizontal value in your FFT is such that:
F = i * Fs / N
i is the bin number, Fs is the sampling frequency and N is the number of points you're using for the FFT. F is the interpreted frequency of the component you're looking at.
By default, fft assumes that N is the total number of points in your array. For the one-sided FFT, i goes from 0, 1, 2, up to floor((N-1)/2) due to the Nyquist sampling theorem.
Because what you're actually doing in the code you tried to write is displaying both sides of the spectrum, that's why it's nice to centre the spectrum so that the DC frequency is located in the middle and the left side is the negative spectra and the right side is the positive spectra.
We can incorporate that into your code here:
[y,Fs] = audioread('600freq.wav');
sound(y, Fs);
F = fftshift(abs(fft(y)));
f = linspace(-Fs/2, Fs/2, numel(y)+1);
f(end) = [];
plot(f, F);
The horizontal axis now reflects the correct frequency of each component as well as the vertical axis reflecting the magnitude of each component.
By running your audio generation code which generates a sine tone at 600 Hz, and then the above code to plot the spectra, I get this:
Note that I inserted a tool tip right at the positive side of the spectra... and it's about 600 Hz!

How to find the period of a periodic function using FFT?

Assume I have a smooth function (represented as a vector):
x=0:0.1:1000;
y=sin(2*x);
and I want to find its periodicity - pi (or even its frequency -2 ) .
I have tried the following:
nfft=1024;
Y=fft(y,nfft);
Y=abs(Y(1:nfft/2));
plot(Y);
but obviously it doesn't work (the plot does not give me a peak at "2" ).
Will you please help me find a way to find the value "2"?
Thanks in advance
You have several issues here:
You are computing the fft of x when your actual signal is y
x should be in radians
You need to define a sampling rate and use that to determine the frequency values along the x axis
So once we correct all of these things, we get:
samplingRate = 1000; % Samples per period
nPeriods = 10;
nSamples = samplingRate * nPeriods;
x = linspace(0, 2*pi*nPeriods, nSamples);
y = sin(2*x);
F = fft(y);
amplitude = abs(F / nSamples);
f = samplingRate / nSamples*[0:(nSamples/2-1),-nSamples/2:-1];
plot(f, amplitude)
In general, you can't use an FFT alone to find the period of a periodic signal. That's because an FFT does sinusoidal basis decomposition (or basis transform), and lots of non-sinusoidal waveforms (signals that look absolutely nothing like a sinewave or single sinusoidal basis vector) can be repeated to form a periodic function, waveform, or signal. Thus, it's quite possible for the frequency of a periodic function or waveform to not show up at all in an FFT result (it's called the missing fundamental problem).
Only in the case of a close or near sinusoidal signal will an FFT reliably report the reciprocal of the period of that periodic function.
There are lots of pitch detection/estimation algorithms. You can use an FFT as a sub-component of some composite methods, including cepstrums or cepstral analysis, and Harmonic Product Spectrum pitch detection methods.

FFT plot in Matlab

I have a small input signal of 60Hz sine wave from signal generator, which is corrupted with 50Hz mains supply frequency. I want to measure the amplitude of the 60Hz signal using FFT because it is very small to see in the oscilloscope.
The Matlab FFT code:
y = data;
Fs = 2048;
[r, L] = size(y);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
plot(f,2*abs(Y(1:NFFT/2+1)))
But the FFT plot doesn't give a sharp peak at 50 and 60Hz. The plot looks like this:
The consecutive points have high and low amplitude alternatively which gives a saw-tooth like plot. Why is it so? Is the amplitude of 60Hz affected by this?
Probably there are two effects
If one measures a time window of a signal, this leads unavoidable to a phase gap between the start and endpoint of the signal modes. The FFT of a gap or a rectangular signal causes high frequency oscillations. These oscillations caused by border effects can be damped due to a window function, which smooths out the signal to the borders.
There is a discrete frequency spectra in DFT. If one measures a signal which does not match to any of these discrete modes, a lot more frequencies are necessary to reconstruct the original signal.
Your 50 Hz signal may not be a pure perfect sine wave. Any differences from a perfect sine-wave (such as clipping or distortion) is equivalent to a modulation that will produce sidebands in the spectrum.
Windowing a signal whose period is not an exact sub-multiple of the FFT length will also convolve windowing artifacts with that signal.

Confusion in figuring out the relation between actual frequency values and FFT plot indexes in MATLAB

I know that there are a lot of similar questions to this, I am still unable to figure out the answer.
Let's say we have time signal in MATLAB:
t=0:1/44100:1
and a cosine signal with frequency 500Hz:
x=cos(2*pi*500*t);
Now, I am trying to plot the magnitude spectrum obtained using the fft command on signal x
FFT=abs(fft(x))
plot(FFT)
According to the theory, we should get two peaks in the plot, one at -500 Hz and the other at 500Hz.
What I don't understand is that I do get two peaks but I can't figure out at what frequencies these peaks are. I know there is a way to figure out the frequency using the FFT index, length of the input signal and the sampling frequency but I still can't calculate the frequency.
I know that there are methods to align the FFT plots so that the peaks lie at the index number of the frequency they represent by using the fftshift function, but what I want is to figure out the frequency using the the plot resulting from simply calling this function:
FFT=fft(x)
In this case, I already know that signal contains a cosine of 500Hz, but what if the signal that we want to get the FFT of is not known before time. How can we get the frequency values of the peaks in that sample using the output from the fft function?
You need to generate the frequency array yourself and plot your FFT result against it.
Like this:
function [Ycomp, fHz] = getFFT(data, Fs)
len = length(data);
NFFT = 2^nextpow2(len);
Ydouble = fft(data, NFFT)/len; % Double-sided FFT
Ycomp = Ydouble(1:NFFT/2+1); % Single-sided FFT, complex
fHz = Fs/2*linspace(0,1,NFFT/2+1); % Frequency array in Hertz.
semilogx(fHz, abs(Ycomp))
end
You will see peaks at 500 Hz and Fs - 500 Hz (i.e. 44100 - 500 = 43600 Hz in your particular case).
This is because the real-to-complex FFT output is complex conjugate symmetric - the top half of the spectrum is a "mirror image" of the bottom half when you are just looking at the magnitude and is therefore redundant.
Note that of plotting power spectra you can usually save yourself a lot of work by using MATLAB's periodogram function rather than dealing directly with all the details of FFT, window functions, plotting, etc.