Adjusting the frequency and the magnitude axis of MATLAB fft [duplicate] - matlab

This question already has an answer here:
Audioread in matlab of wav file and FFT
(1 answer)
Closed 7 years ago.
I wrote a small script to get the fft of a sinus signal :
N = 1000; % number of samples
n = (0:N-1)'; % generate a vector n for x[n]
Fs_normal = 36621.09375;
%generate a signal in pass-band, N samples and simulate filter
f0 = 1000; % set 1000 Hz
x= sin(2*pi*f0*n/Fs_normal); % input signal
figure(3);
stem(x),title('sinus wave with 1000 Hz (n)'),grid;
figure(4);
plot(abs(fft(x))),grid,title('FFT of sin wave with 1000 Hz frequency');
here is the fft result that I get :
as you can see the axis doesn't make any sense ( at least to me), is there a way to get this the right way ?

The FFT gives you 1000 bins
freqvals = [0:N-1]/N * Fs_normal;
plot(freqvals, abs(fft(x))),grid,title('FFT of sin wave with 1000 Hz frequency');
You have to add the scale on your own. The whole FFT gives you also 1000 complex coefficients back when you give it 1000 samples. The range is from 0 to the sampling frequency.
Bins are separated by a frequency shift of Fs_normal/N.

Related

High-frequency spur after performing an FFT in MATLAB

I have a modulated signal, and now I want to perform an FFT. However, I am getting a spur at a high frequency, which should not be there (and if it should, I have no clue as to why).
Lvl=[0.5,0.9,0.5,0.5,0.1,0.1,0.9,0.5];
fa=60; %the frequency of the parasitic source in hertz
np=2; %number of periods per bit
kl=length(Lvl);
t=0:0.01*np/fa:np*kl/fa;
Sig=sin(2*pi*fa*t);
for n=1:1:101
Sig(n)=Sig(n)*Lvl(1);
end
for n=102:1:201
Sig(n)=Sig(n)*Lvl(2);
end
for n=202:1:301
Sig(n)=Sig(n)*Lvl(3);
end
for n=302:1:401
Sig(n)=Sig(n)*Lvl(4);
end
for n=402:1:501
Sig(n)=Sig(n)*Lvl(5);
end
for n=502:1:601
Sig(n)=Sig(n)*Lvl(6);
end
for n=602:1:701
Sig(n)=Sig(n)*Lvl(7);
end
for n=702:1:801
Sig(n)=Sig(n)*Lvl(8);
end
plot(t,Sig)
%FFT
y = fft(Sig);
f = (0:length(y)-1)*(1/(0.01*np/fa))/length(y);
plot(f,abs(y))
title('Magnitude')
I'm expecting just a spike at 60Hz with spurs around it, but instead I'm getting that and a large spike at almost 3kHz with spurs around it.
This peak at almost 3 kHz should be there, since the fft of a real is signal symmetric around the nyquist frequency (actually complex conjugate). The nyquist frequency is half the samping frequency, in your case sampling is done at 3000 Hz, thus the nyquist frequency is 1500 Hz. If you look closer at the peak, you will see that it is at 2940 Hz (which is 3000-60 Hz), due to the fact that the fft is mirrored around 1500 Hz.
There are plenty of sources that explain why this is a property of the Fourier transform (e.g. here).
The actual Fourier transform would be mirrored around the zero frequency, but the fft gives you the fast Fourier transform, which is mirrored around the nyquist frequency. You can use fftshift to center the spectrum around the zero frequency.
I took the liberty to shorten your code, by avoiding repetition of several for-loops, and added the fftshift. Since your signal is real, you can also choose to show only one side of the fft, but I'll leave that up to you.
Lvl=[0.5,0.9,0.5,0.5,0.1,0.1,0.9,0.5];
fa=60; % the frequency of the parasitic source in hertz
np=2; % number of periods per bit
kl = length(Lvl);
dt = 0.01*np/fa; % time step
Tend = np*kl/fa - dt; % time span
t = 0:dt:Tend; % time vector
N = length(t); % number samples
Sig=sin(2*pi*fa*t);
for n = 1:kl
ids = (1:100) + (n-1)*100;
Sig(ids) = Sig(ids).*Lvl(n);
end
% FFT
Y = fft(Sig);
fv = (0:N-1)/(N*dt); % frequency range
% FFT shift:
Y_shift = fftshift(Y);
fv_shift = (-N/2:N/2-1)/(N*dt); % zero centered frequency vector
% Plot
figure(1); clf
subplot(311)
plot(t,Sig)
title('Signal')
subplot(312)
plot(fv,abs(Y))
title('FFT Magnitude')
subplot(313)
plot(fv_shift,abs(Y_shift))
title('FFT Magnitude zero shift')

How do I create band-limited (100-640 Hz) white Gaussian noise?

I would like to create 500 ms of band-limited (100-640 Hz) white Gaussian noise with a (relatively) flat frequency spectrum. The noise should be normally distributed with mean = ~0 and 99.7% of values between ± 2 (i.e. standard deviation = 2/3). My sample rate is 1280 Hz; thus, a new amplitude is generated for each frame.
duration = 500e-3;
rate = 1280;
amplitude = 2;
npoints = duration * rate;
noise = (amplitude/3)* randn( 1, npoints );
% Gaus distributed white noise; mean = ~0; 99.7% of amplitudes between ± 2.
time = (0:npoints-1) / rate
Could somebody please show me how to filter the signal for the desired result (i.e. 100-640 Hz)? In addition, I was hoping somebody could also show me how to generate a graph to illustrate that the frequency spectrum is indeed flat.
I intend on importing the waveform to Signal (CED) to output as a form of transcranial electrical stimulation.
The following is Matlab implementation of the method alluded to by "Some Guy" in a comment to your question.
% In frequency domain, white noise has constant amplitude but uniformly
% distributed random phase. We generate this here. Only half of the
% samples are generated here, the rest are computed later using the complex
% conjugate symmetry property of the FFT (of real signals).
X = [1; exp(i*2*pi*rand(npoints/2-1,1)); 1]; % X(1) and X(NFFT/2) must be real
% Identify the locations of frequency bins. These will be used to zero out
% the elements of X that are not in the desired band
freqbins = (0:npoints/2)'/npoints*rate;
% Zero out the frequency components outside the desired band
X(find((freqbins < 100) | (freqbins > 640))) = 0;
% Use the complex conjugate symmetry property of the FFT (for real signals) to
% generate the other half of the frequency-domain signal
X = [X; conj(flipud(X(2:end-1)))];
% IFFT to convert to time-domain
noise = real(ifft(X));
% Normalize such that 99.7% of the times signal lies between ±2
noise = 2*noise/prctile(noise, 99.7);
Statistical analysis of around a million samples generated using this method results in the following spectrum and distribution:
Firstly, the spectrum (using Welch method) is, as expected, flat in the band of interest:
Also, the distribution, estimated using histogram of the signal, matches the Gaussian PDF quite well.

Calculate frequency bins of an audiosignal

I am doing a fft (stft) on a audio-file, which contains voice and music. I took out a range of 1-200 from signal, which i saved in a variable called, for example, frequency_band1. How can i calculate the frequency bins from variable, which stores my specificially chosen signal, on which the fft was applied before.? I think, read somewhere, that i needed to calculate fs/fftpoints. In my case, 44100/4096. Do i multiply it with my variable frequency_band1*(44100/4096)? This is done on matlab, and i need to do it, with a stft.
The output values of a DFT (FFT) are at frequencies (0:n-1)/n*fs where n is DFT size and fs is sample frequency.
Here's an example. This creates a sinusoid at a known frequency, performs the DFT of the whole signal (so n is signal size), and plots the spectrum using the above as frequency values.
fs = 44100; % sample frequency
t = 0:1/fs:.1; % 0.1-second time axis
x = sin(2*pi*300*t); % sinusoid of frequency 220 Hz
X = fft(x); % DFT of x
f = (0:numel(X)-1)/numel(X)*fs; % frequency axis of DFT
plot(f, abs(X)) % plot the spectrum in absolute value
grid % add grid
axis([0 1000 -500 2500])
You can check that the spectral line of this signal is where it should, that is, at 300 (Hz).

Matlab, FFT frequency range differences or are they the same?

I'm trying to understand how the FFT in matlab works, particularly, how to define the frequency range to plot it. It happens that I have read from matlab help links and from other discussions here and I think (guess) that I'm confused about it.
In the matlab link:
http://es.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html
they define such a frequency range as:
f = (0:n-1)*(fs/n)
with n and fs as:
n = 2^nextpow2(L); % Next power of 2 from length of signal x
fs = N/T; % N number of samples in x and T the total time of the recorded signal
But, on the other hand, in the previous post Understanding Matlab FFT example
(based on previous version of matlab), the resulting frequency range is defined as:
f = fs/2*linspace(0,1,NFFT/2+1);
with NFFT as the aforementioned n (Next power of 2 from length of signal x).
So, based on that, how these different vectors (equation 1 and final equation) could be the same?
If you can see, the vectors are different since the former has n points and the later has NFFT/2 points! In fact, the factor (fs/n) is different from fs/2.
So, based on that, how these different vectors (equation 1 and final equation) could be the same?
The example in the documentation from Mathworks plots the entire n-point output of the FFT. This covers the frequencies from 0 to nearly fs (exactly (n-1)/n * fs). They then make the following observation (valid for real inputs to the FFT):
The first half of the frequency range (from 0 to the Nyquist frequency fs/2) is sufficient to identify the component frequencies in the data, since the second half is just a reflection of the first half.
The other post you refer to just chooses to not show that redundant second half. It then uses half the number of points which also cover half the frequency range.
In fact, the factor (fs/n) is different from fs/2.
Perhaps the easiest way to make sense of it is to compare the output of the two expressions for some small value of n, says n=8 and setting fs=1 (since fs multiplies both expressions). On the one hand the output of the first expression [0:n-1]*(fs/n) would be:
0.000 0.125 0.250 0.500 0.625 0.750 0.875
whereas the output of fs/2*linspace(0,1,n/2+1) would be:
0.000 0.125 0.250 0.500
As you can see the set of frequencies are exactly the same up to Nyquist frequency fs/2.
The confusion is perhaps arising from the fact that the two examples which you have referenced are plotting results of the fft differently. Please refer to the code below for the references made in this explanation.
In the first example, the plot is of the power spectrum (periodogram) over the frequency range. Note, in the first plot, that the periodogram is not centered at 0, meaning that the frequency range appears to be twice that of the Nyquist sampling frequency. As mentioned in the mathworks link, it is common practice to center the periodogram at 0 to avoid this confusion (figure 2).
For the second example, taking the same parameters, the original plot is of amplitude of the fourier spectrum with a different normalization than in the first example (figure 3). Using the syntax of Matlab's full frequency ordering (as commented in the code), it is trivial to convert this seemingly different fft result to that of example 1; the identical result of the 0-centered periodogram is replicated in figure 4.
Thus, to answer your question specifically, the frequency ranges in both cases are the same, with the maximum frequency equal to the Nyquist sampling frequency as in:
f = fs/2*linspace(0,1,NFFT/2+1);
The key to understanding how the dfft works (also in Matlab) is to understand that you are simply performing a projection of your discrete data set into fourier space where what is returned by the fft() function in matlab are the coefficients of the expansion for each frequency component and the order of the coefficients is given (in Matlab as in example 2) by:
f = [f(1:end-1) -fliplr(f(1,2:end))];
See the Wikipedia page on the DFT for additional details:
https://en.wikipedia.org/wiki/Discrete_Fourier_transform
It might also be helpful for you to take the fft omitting the length as a power of 2 parameter as
y = fft(x).
In this case, you would see only a few non-zero components in y corresponding to the exact coefficients of your input signal. The mathworks page claims the following as a motivation for using or not using this length:
"Using a power of two for the transform length optimizes the FFT algorithm, though in practice there is usually little difference in execution time from using n = m."
%% First example:
% http://www.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html
fs = 10; % Sample frequency (Hz)
t = 0:1/fs:10-1/fs; % 10 sec sample
x = (1.3)*sin(2*pi*15*t) ... % 15 Hz component
+ (1.7)*sin(2*pi*40*(t-2)); % 40 Hz component
% Removed the noise
m = length(x); % Window length
n = pow2(nextpow2(m)); % Transform length
y = fft(x,n); % DFT
f = (0:n-1)*(fs/n); % Frequency range
power = y.*conj(y)/n; % Power of the DFT
subplot(2,2,1)
plot(f,power,'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf Periodogram}')
y0 = fftshift(y); % Rearrange y values
f0 = (-n/2:n/2-1)*(fs/n); % 0-centered frequency range
power0 = y0.*conj(y0)/n; % 0-centered power
subplot(2,2,2)
plot(f0,power0,'-o')
% plot(f0,sqrt_power0,'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram} Ex. 1')
%% Second example:
% http://stackoverflow.com/questions/10758315/understanding-matlab-fft-example
% Let's redefine the parameters for consistency between the two examples
Fs = fs; % Sampling frequency
% T = 1/Fs; % Sample time (not required)
L = m; % Length of signal
% t = (0:L-1)*T; % Time vector (as above)
% % Sum of a 3 Hz sinusoid and a 2 Hz sinusoid
% x = 0.7*sin(2*pi*3*t) + sin(2*pi*2*t); %(as above)
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
% NFFT == n (from above)
Y = fft(x,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
subplot(2,2,3)
plot(f,2*abs(Y(1:NFFT/2+1)),'-o')
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
% Get the 0-Centered Periodogram using the parameters of the second example
f = [f(1:end-1) -fliplr(f(1,2:end))]; % This is the frequency ordering used
% by the full fft in Matlab
power = (Y*L).*conj(Y*L)/NFFT;
% Rearrange for nicer plot
ToPlot = [f; power]; [~,ind] = sort(f);
ToPlot = ToPlot(:,ind);
subplot(2,2,4)
plot(ToPlot(1,:),ToPlot(2,:),'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram} Ex. 2')

Dividing a signal in channels

I have a signal in time domain (6000 samples from -100 to 1100 ps). I have to convert it into frequency domain and divide it into 100 channels, and find the center frequency of each channel.
I am not good in "MATLAB" so how to do that, help will be appreciated.
Based on my understanding of the question, you want to represent your signal in the frequency domain. Please study some tutorials on FFT to increase your understanding of the FFT details. A good start is this tutorial: FFT Tutorial using Matlab, which I used to write the code below.
close all;
clear all;
clc;
Fs = 5; % Sampling frequency (in THz)
Ts = 1/5; % Sampling period (in ps)
x = randn(1, 6000); % A random signal of 6000 points
t = [-100:Ts:1100-Ts]; % 6000 time points (in ps)
% Plot signal in time domain
figure;plot(t,x);
xlabel('Time (ps)'); ylabel('Signal');
N = 100; % Number of FFT points
X = fftshift(fft(x, N)); % Compute and shift FFT
absX = abs(X); % Compute absolute FFT values
% Frequency centers (frequency components) depend on the values of N and Fs
frequency_centers = Fs * [-N/2:N/2-1]/N;
% Plot signal in frequency domain
figure;plot(frequency_centers, absX);
xlabel('Frequency (THz)'); ylabel('abs FFT');
The variable frequency_centers shows the frequency components.
Since you have 6000 time samples, from -100 to 1100 ps, the sampling period is Ts = 1200/6000 = 0.2 ps and Fs = 1/Ts = 5 THz. Also, note that in order to have 6000 time samples (and not 6001), you need to drop one boundary time value (here I dropped 1100).