PERFORMING FFT on EEG SIGNAL USING MATLAB - matlab

i have acquired a 5 minutes raw eeg from NEXUS 10 mark 2 equipment and it is giving me output in the matlab as 1 x 76800 row vector. as i understand , the sampling frequency choosen is 256 hz , hence it is giving me total 76800 sampling points. no wat i m perfoming N point FFT on this raw eeg signal. since N can only be power of 2 i am EXTRACTING 65536(2 ^16) SAMPLING POINTS FROM RAW EGG i.e. from 76800 points i have taken 65536. now i am not able to perform fft on the this vector (65536 sampling points)
please anybody can guide..as i am a beginner..
i have tried dis so far
x=raw(1,1:65536); %raw eeg contain 76800 points , 65536 points are taken
from this
N=length(x);
fs=256;
ts=1/fs;
tmax=(N-1)*ts;
t=0:ts:tmax;
plot(t,x); % plot time domain
f=-fs/2:fs/(N-1):fs/2;
fftval=fft(x);
plot(f,ffval); % plot freq domain
i do not know whether the steps followed are right or not.....m not able to understand from many post in stackoverflow i have gone through..please help..I DONT WANT TO USE EEGLAB AS GIVEN IN MANY POSTS.PLEASE HELP

I think the code could be like this:
load('eeg_4m.mat')
fs=2048;
x=val(1,:);
N=length(x);
ts=1/fs;
tmax=(N-1)*ts;
t=0:ts:tmax;
plot(t,x); % plot time domain
nfft = 2^( nextpow2(length(x)) );
df = fs/nfft;
f = 0:df:fs/2;
X = fft(x,nfft);
X = X(1:nfft/2+1);
figure; plot(f,abs(X)); axis([0,50,0,10e6]); % plot freq domain

768000 is a perfectly good FFT size. It factorizes over small primes: 2^11 * 3 * 5^3
On my laptop this takes about 15ms.
It is a somewhat common misconception that FFTs can only be powers of 2. This is not true of a mixed radix FFT.

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

Matlab: how to find fundamental frequency of a speech

I am new to Matlab and speech processing as well. I want to find the fundamental frequency of speech signal to determine the gender of the speaker. I removed the silence from the signal by analysing it within 10 msec periods.
After that I got the fft using this code :
abs(fft(input_signal_without_silences))
My plot of both the speech signal and the fft of it is below:
Now, I want to find the fundamental frequency but I could not understand which steps do I need to do this. Or do I misunderstand this concept?
As far as I have learnt, there are some methods like autocorrelation,
Since I am not familiar to both speech processing and matlab, any help and advice is very much appreciated.
The fft() help can solve most parts of your problem. I can give a brief overview of things based on the content of the help file.
At the moment what you are plotting is the two sided, unnormalized fft coefficients, which don't tell much. Use the following to get a more user informed spectral analysis of the voice signal. Using the single sided spectram you would be able to find the dominant frequency which might be the fundamental frequency of the speech signal.
y = []; %whatever your signal
T = 1e-2; % Sample time, 10 ms
Fs = 1/T; % Sampling frequency
L = length(y); % Length of signal
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)))
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
The problem is that you have a plot of Amplitude vs Sample Number instead of a plot of Amplitude vs Frequency.In order to calculate the fundamental frequency you need to find the frequency that corresponds to the highest frequency.
Matlab returns frequencies from -fs/2 to fs/2 so the frequency at index n is
f = n * (fs/N) - (fs/2)
where f = frequency, fs = sampling frequency, N = number of points in FFT.
So basically all you need to do is get the index where the plot is highest and substitute it in the equation above to get an estimate of the fundamental frequency.Make sure n > N/2 so that your fundamental frequency is positive.

FFT does not return the amplitudes in matlab?

I have generated the following time signal:
Now I want to perform a Discrete Fourier Transform by using the matlab command fft
Here is my code:
function [ xdft, omega ] = FastFourier( t, fs )
%% Inputs from other functions %%
[P_mean, x, u] = MyWay( t ) %From here comes my signal x(t)
%% FFT %%
xdft1 = fft(x); % Perform FFT
xdft2 = abs(xdft1); % Take the absolute value of the fft results
xdft = xdft2(1:length(x)/2+1); % FFT is symmetric, second half is not needed
freq = 0:fs/length(x):fs/2; % frequency axis
plot (freq(1:100),xdft(1:100));
end
And here is the plot that I get:
And what is puzzling to me is the y axis? Shouldn't the y axis represent the amplitudes of the frequency components? Is there a way to get the amplitudes of all the frequency components?
Thanks!
EDIT:
I have found that some people do the following:
n = size(x,2)/2; %The number of components and second half can be neglected again
xdft2 = abs(xdft1)/n;
This way I seem to get the amplitude spectrum, but why do I have to divide the absolute value by n?
FFT gives you a complex pair in each Frequency Bin. The first bin in the FFT is like the DC part of your signal (around 0 Hz), the second bin is Fs / N, where Fs is the sample rate and Nis the windowsize of the FFT, next bin is 2 * Fs / N and so on.
What you calc with the abs() of such a pair is the power contained in a bin.
you might also want to check this out: Understanding Matlab FFT example
Most (not all) FFT libraries preserve total energy (Parseval's theorem), which means that the magnitude has to get bigger for longer FFT windows (longer stationary waveform -> more energy). So you have to divide the result by N to get a more "natural" looking magnitude height of sinewaves in the spectrum.
If you want the amplitudes of the harmonics, then you need to plot real(xdft1) and imag(xdft1). Real(xdft1) gives you coefficients of all the cosine harmonics present in your signal, from -Fs/2 to +Fs/2, (we assume your Fs is large enough to cover all frequencies in the signal) and the imag(xdft) give the amplitudes of the sines.
What you are doing is giving you the magnitude of the signal, which is the RMS value of the total energy at a bin in both the real and imaginary frequency component.
Its often the item of most interest to people looking at a spectrum.
Basics of this: (https://www.youtube.com/watch?v=ZKNzMyS9Z6s&t=1629s)

basic FFT normalization questions

I'm using Matlab to take FFTs of signals, and I'm getting stuck on the normalization. Specifically, how to normalize the spectrum into units of dBm. I know that 0.316228 is the correct normalization factor, but my questions are related to how to normalize the bins correctly.
I created the following program to raise my questions. Just cut and paste it into Matlab and it'll run itself. See questions in-line.
In particular, I'm confused how to normalize the bins. For example, if the FFT has indices 1:end, where end is even, when I calculate the FFT magnitude spectrum, should I multiply by (2/N) for indices 2:(end/2)? Similarly, does the bin at the Nyquist frequency (located at index end/2+1) get normalized to (1/N)? I know there's a bunch of ways to normalize depending on one's interest. Let's say the signal I'm using (St below) are voltages captured from an ADC.
Any feedback is greatly appreciated. Thanks in advance!
%% 1. Create an Example Signal
N = 2^21 ; % N = number of points in time-domain signal (St)
St = 1 + rand(N,1,'single'); % St = example broadband signal (e.g. random noise)
% take FFT
Sf = fft(St, N);
Sf_mag = (2/N)*abs(Sf(1: N/2 + 1));
Sf_dBm = 20*log10(Sf_mag / 0.316228); % 0.316338 is peak voltage of 1 mW into 50 Ohms
% Q: Are Sf_mag and Sf_dBm normalized correctly? (assume 0.316338 is correct
% peak voltage to get 1mW in 50 Ohms)
% Q: Should Sf_mag(fftpoints/2 + 1) = (1/N)*abs(Sf(fftpoints/2 + 1) for correct normalization
% of Nyquist frequency? (since Nyquist frequency is not folded in frequency
% like the others are)
%% 2. Plot Result
% create FFT spectrum x-axis
samplerate = 20e9; % 20 Gsamples/sec
fft_xaxis = single(0 : 1 : N/2)';
fft_xaxis = fft_xaxis * single(samplerate/N);
semilogx(fft_xaxis, Sf_dBm, 'b-')
xlabel('Frequency (Hz)');
ylabel('FFT Magnitude (dBm)');
title('Spectrum of Signal (Blue) vs Frequency (Hz)');
xlim([1e4 1e10]);
grid on;
I am not totally clear about what you are trying to accomplish, but here are some tips that will let you debug your own program.
Do fft([1 1 1 1]). Do fft([1 1 1 1 1 1 1 1]). In particular, observe the output magnitude. Is it what you expect?
Then do fft([1 -1 1 -1]). Do fft([1 -1 1 -1 1 -1 1 -1]). Repeat for various signal lengths and frequencies. That should allow you to normalize your signals accordingly.
Also, do the same thing for ifft instead of fft. These are good sanity checks for various FFT implementations, because while most implementations may put the 1/N in front of the inverse transform, others may put 1/sqrt(N) in front of both forward and inverse transforms.
See this for an answer:
FFT normalization
Some software packages and references get sloppy on the normalization of the Fourier coefficients.
Assuming a real signal, then the normalization steps are:
1) The power in the frequency domain must equal the power in the time domain.
2) The magnitude of the Fourier coefficients are duplicated (x2) except for DC term and Nyquist term. DC and Nyquist terms appear only once. Depending on how your array indexing starts/stop, you need to be careful. Simply doubling the power to get a one sided spectrum is wrong.
3) To get power density (dBm/Hz) you need to normalize to the individual frequency bin size.

Frequency response using FFT in MATLAB

Here is the scenario: using a spectrum analyzer i have the input values and the output values. the number of samples is 32000 and the sampling rate is 2000 samples/sec, and the input is a sine wave of 50 hz, the input is current and the output is pressure in psi.
How do i calculate the frequency response from this data using MATLAB,
using the FFT function in MATLAB.
i was able to generate a sine wave, that gives out the the magnitude and phase angles, here is the code that i used:
%FFT Analysis to calculate the frequency response for the raw data
%The FFT allows you to efficiently estimate component frequencies in data from a discrete set of values sampled at a fixed rate
% Sampling frequency(Hz)
Fs = 2000;
% Time vector of 16 second
t = 0:1/Fs:16-1;
% Create a sine wave of 50 Hz.
x = sin(2*pi*t*50);
% Use next highest power of 2 greater than or equal to length(x) to calculate FFT.
nfft = pow2(nextpow2(length(x)))
% Take fft, padding with zeros so that length(fftx) is equal to nfft
fftx = fft(x,nfft);
% Calculate the number of unique points
NumUniquePts = ceil((nfft+1)/2);
% FFT is symmetric, throw away second half
fftx = fftx(1:NumUniquePts);
% Take the magnitude of fft of x and scale the fft so that it is not a function of the length of x
mx = abs(fftx)/length(x);
% Take the square of the magnitude of fft of x.
mx = mx.^2;
% Since we dropped half the FFT, we multiply mx by 2 to keep the same energy.
% The DC component and Nyquist component, if it exists, are unique and should not be multiplied by 2.
if rem(nfft, 2) % odd nfft excludes Nyquist point
mx(2:end) = mx(2:end)*2;
else
mx(2:end -1) = mx(2:end -1)*2;
end
% This is an evenly spaced frequency vector with NumUniquePts points.
f = (0:NumUniquePts-1)*Fs/nfft;
% Generate the plot, title and labels.
subplot(211),plot(f,mx);
title('Power Spectrum of a 50Hz Sine Wave');
xlabel('Frequency (Hz)');
ylabel('Power');
% returns the phase angles, in radians, for each element of complex array fftx
phase = unwrap(angle(fftx));
PHA = phase*180/pi;
subplot(212),plot(f,PHA),title('frequency response');
xlabel('Frequency (Hz)')
ylabel('Phase (Degrees)')
grid on
i took the frequency response from the phase plot at 90 degree phase angle, is this the right way to calculate the frequency response?
how do i compare this response to the values that is obtained from the analyzer? this is a cross check to see if the analyzer logic makes sense or not.
Looks OK at first glance, but a couple of things you're missing:
you should apply a window function to the time domain data before the FFT, see e.g. http://en.wikipedia.org/wiki/Window_function for windowing in general and http://en.wikipedia.org/wiki/Hann_window for the most commonly used window function (Hann aka Hanning).
you probably want to plot log magnitude in dB rather than just raw magnitude
You should consider looking at the cpsd() function for calculating the Frequency response. The scaling and normalisation for various window functions is handled for you.
the Frequency reponse would then be
G = cpsd (output,input) / cpsd (input,input)
then take the angle() to obtain the phase difference between the input and the output.
Your code snippet does not mention what the input and output data sets are.