Calculating the Fourier series coefficients for raw data [duplicate] - matlab

I have an FFT result. These are stored in two double arrays: a real part array and an imaginary part array. How do I determine the frequencies that correspond to each element in these arrays?
In other words, I would like have create an array that stores the frequencies for each real and imaginary component of my FFT.

The first bin in the FFT is DC (0 Hz), the second bin is Fs / N, where Fs is the sample rate and N is the size of the FFT. The next bin is 2 * Fs / N. To express this in general terms, the nth bin is n * Fs / N.
So if your sample rate, Fs is say 44.1 kHz and your FFT size, N is 1024, then the FFT output bins are at:
0: 0 * 44100 / 1024 = 0.0 Hz
1: 1 * 44100 / 1024 = 43.1 Hz
2: 2 * 44100 / 1024 = 86.1 Hz
3: 3 * 44100 / 1024 = 129.2 Hz
4: ...
5: ...
...
511: 511 * 44100 / 1024 = 22006.9 Hz
Note that for a real input signal (imaginary parts all zero) the second half of the FFT (bins from N / 2 + 1 to N - 1) contain no useful additional information (they have complex conjugate symmetry with the first N / 2 - 1 bins). The last useful bin (for practical aplications) is at N / 2 - 1, which corresponds to 22006.9 Hz in the above example. The bin at N / 2 represents energy at the Nyquist frequency, i.e. Fs / 2 ( = 22050 Hz in this example), but this is in general not of any practical use, since anti-aliasing filters will typically attenuate any signals at and above Fs / 2.

Take a look at my answer here.
Answer to comment:
The FFT actually calculates the cross-correlation of the input signal with sine and cosine functions (basis functions) at a range of equally spaced frequencies. For a given FFT output, there is a corresponding frequency (F) as given by the answer I posted. The real part of the output sample is the cross-correlation of the input signal with cos(2*pi*F*t) and the imaginary part is the cross-correlation of the input signal with sin(2*pi*F*t). The reason the input signal is correlated with sin and cos functions is to account for phase differences between the input signal and basis functions.
By taking the magnitude of the complex FFT output, you get a measure of how well the input signal correlates with sinusoids at a set of frequencies regardless of the input signal phase. If you are just analyzing frequency content of a signal, you will almost always take the magnitude or magnitude squared of the complex output of the FFT.

I have used the following:
public static double Index2Freq(int i, double samples, int nFFT) {
return (double) i * (samples / nFFT / 2.);
}
public static int Freq2Index(double freq, double samples, int nFFT) {
return (int) (freq / (samples / nFFT / 2.0));
}
The inputs are:
i: Bin to access
samples: Sampling rate in Hertz (i.e. 8000 Hz, 44100Hz, etc.)
nFFT: Size of the FFT vector

The FFT output coefficients (for complex input of size N) are from 0 to N - 1 grouped as [LOW,MID,HI,HI,MID,LOW] frequency.
I would consider that the element at k has the same frequency as the element at N-k since for real data, FFT[N-k] = complex conjugate of FFT[k].
The order of scanning from LOW to HIGH frequency is
0,
1,
N-1,
2,
N-2
...
[N/2] - 1,
N - ([N/2] - 1) = [N/2]+1,
[N/2]
There are [N/2]+1 groups of frequency from index i = 0 to [N/2], each having the frequency = i * SamplingFrequency / N
So the frequency at bin FFT[k] is:
if k <= [N/2] then k * SamplingFrequency / N
if k >= [N/2] then (N-k) * SamplingFrequency / N

Your kth FFT result's frequency is 2*pi*k/N.

Related

How to convert a spectrum from spatial frequency to cyc/deg

I have a hard time wrapping my head around this since there is non-linearity involved. How do I convert a spectrum I have in units "1/m" (or cycles per m) to "cycles/deg"?
Example: For simplicity let's work in one dimension and the screen of a laptop is 768 pixels on which I show the highest pixel frequency. I use MATLAB/Octave style code but I hope it's clear enough to act as pseudo code:
X = 768
x = 0:X-1
y = cos(2*pi/X*(X/2)*x)
The frequency in this signal is now pi radiants or 0.5 cycles/pixel (sampling rate is 1 pixel). I can create the frequency vectors:
w = linspace(0, 2*pi, length(x)) % in radiants
f = linspace(0, 1, length(x)) % in 1/pixel or cycles/pixel
I can easily convert this to spatial frequency in units [m] and frequency [cycles/m] when I know the pixel size. Let's assume one pixel is 0.5mm:
xm = x*0.5e-3 % for image in m
fm = f/0.5e-3 % frequency in 1/m
Plotting y versus xm shows now a waveform with 1 cycle per mm. Plotting the FFT of y versus fm shows a peak at 1000 cycles/m (or 1 cycle per mm), as expected.
How do I need to modify fm to arrive at fdeg, in other words, to show the FFT of y in cycles per degree, assuming distance from the screen is 60cm? I would assume
fdeg = 1/(2*atan(1/fm)/(2*0.6)*180/pi)
That would give me 20.97 cycles/deg. However, using the small angle approximation, 1mm should be roughly 1mm/0.6*180/pi=0.9549e-3 degree, so we have 1cycle per 0.9549e-3 degrees or 1/0.9549e-3=10.47 cycles per degree. This is off by a factor of 2.

define an interval for frequency of STFT outputs

As you know the STFT has a matrix result, with the dimension given by:
number of frequency bins * number of time frames.
For example, suppose that I have a signal with characteristics and I want to apply STFT method with the following input parameters:
sampling rate : 250,000 Hz;
data length : 498900 samples;
window length : nftt=625 samples;
hop size : 125 samples
With those parameters my STFT will have an output with size: 313*3987 (the method to calculate these values exists in some websites)
Now, my question is how can I define a limit for frequency dimension of STFT output? I think I should calculate my threshold values as an index number in STFT output, if so, how can I do it?
I have the frequency resolution, but when I multiply it by nfft, it's half of the value of sampling rate.
You haven't provided how you calculated the frequency resolution, but here is what it should be:
frequency_resolution = sampling_rate / nfft;
In your particular case with a sampling rate of 250,000Hz and nfft=625, this should give you a frequency resolution of 400Hz. You can verify that 625*400 is indeed equal to 250000.
Then, if you want to include frequencies from 0Hz to frequencies no greater than max_frequency as part of your STFT output, the maximum size along the frequency axis should be given by:
size_frequency_axis = 1 + floor(max_frequency / frequency_resolution);
As a special case you can also verify that when max_frequency is set to the Nyquist frequency (250000/2 = 125000), the computed size is 1+floor(125000/400) = 313 (which matches your full spectrum STFT output size).
As a generalization, if you want to include a range of frequencies not starting at 0Hz, then you can compute in a similar fashion the index of the minimum and maximum frequencies, and obtain the corresponding size with:
min_frequency_index = 1 + floor(min_frequency / frequency_resolution);
max_frequency_index = 1 + floor(max_frequency / frequency_resolution);
size_frequency_axis = max_frequency_index - min_frequency_index + 1;

Matlab-frequency bin of the positive and negative frequency

I am using MATLAB tutorial Frequency-Domain Linear Regression. There is one part of code, where is necessary to determine "frequency bin of the positive and negative frequency", for fft and ifft, this part of code:
freqbin = 72/12;
freqbins = [freqbin 72-freqbin]+1;
tsfit = zeros(72,1);
tsfit(freqbins) = tsdft(freqbins);
tsfit = ifft(tsfit);
mu = mean(ts);
tsfit = mu+tsfit;
Length of time series is 72, and there is 12 months is one cycle. How there can be only one frequency bin for positive frequency, how do we know that is exactly 72/12+1 (+1 is because first bin is for zero frequency), is that some formula or what?
Let's start with some general notes. If the sample rate is Fs, and the number of samples in the FFT is N, then the frequency of the bin with MATLAB index k is:
f_k = (k-1) * Fs / N ;
Or, conversely,
k = f_k * N / Fs + 1;
Hence, the elements of the FFT vector correspond to frequencies 0, Fs/N, 2*Fs/N, ..., (N-1)*Fs/N.
Note that the frequencies are invariant to shifts by Fs. In other words, f and f+Fs and f-Fs are all equivalent. So, you could consider the first half of the FFT vector to correspond to positive frequencies (index: 1 to N/2; frequency: 0 to (N/2-1)/N*Fs), and the second half to correspond to negative frequencies (index: N/2+1 to N; frequency: -Fs/2 to -Fs/N). Here I include 0 in the set of positive frequencies for brevity.
Now, coming to your specific example:
N = 72
Fs = 12 ; % samples per year
So, the positive frequency range is from 0 to Fs/2 = 6 cycles per year, corresponding to indices 1 to 36, respectively.
You are interested in finding the FFT sample corresponding to the frequency 1 cycle per year. That corresponds to index 1 * 72 / 12 + 1 = 7.
Since the FFT is symmetric for real signals, you are also interested in finding the FFT sample corresponding to the frequency -1 cycle per year, which, using the shift-invariance property, is also equivalent to -1 + Fs = 11 cycles per year. The corresponding index is (12-1) * 72 / 12 + 1 = 67.
In summary,
There are 36 positive frequencies (including 0), not 1.
The algorithm is interested in only one positive frequency with the highest magnitude.
That frequency happens to be 1 cycle per year. The corresponding MATLAB index is 7.
The mirror image of the frequency is -1 cycle per year, which corresponds to MATLAB index 67.

Hanning window and online FFT

I am learning DSP and I couldn't write a code to calculate and plot these figures (just magnitude of Hanning and triangular windows in frequency domain.) Could anyone please help me with the code?
I've read something related to online FFT, and, for example, they calculate online FFT with 1024 time steps. I don't understand what is 1024 time steps, and what are the influences of time step value to FFT analysis?
I hope the following piece of code is helpful to you.
L = 10;
win1 = hanning(L);
win2 = triang(L);
nfft = 64;
S1 = fft(win1,nfft);
S2 = fft(win2,nfft);
f = 1:nfft/2+1;
plot(f,10*log10(abs(S1(1:nfft/2+1))),'.-',f,10*log10(abs(S2(1:nfft/2+1))),'o-');
Annotation:
You can put win1 and win2 as Time-series signal. L is the length of win1 or win2. nfft is the length of FFT . if L < nfft , then the function fft() will add 0 to the rest of nfft. If L > nfft, then the function fft() will interception the length of L to equal nfft.
The frequency of the time steps or samples (Fs), divided by the number of time steps fed the FFT (the FFT length), gives you the frequency steps of the FFT result bins (up to Fs/2).
Regarding the 1024 "time steps" in your question, that is simply the number of samples that are taken from the time-domain signal.
As to how the 1024 time-domain samples influence the FFT, this involves the sampling frequency that was used to obtain the samples.
Sampling frequency is typically chosen to conform with the Nyquist-Shannon sampling theorem, which basically states that you must sample the time-domain signal at a frequency higher than "2F" if you want to resolve a frequency "F" via the FFT.
As for the Hann (Hanning) and Triangular window codes, they are as follows:
Hann window:
for( i=0; i<bufLen; i++ )
window[i] = 0.5 * ( 1 - cos( 2 * PI * i / (bufLen-1) ) )
Triangular window:
for( i=0; i<bufLen; i++ )
window[i] = 2/bufLen * ( (bufLen)/2 - abs( i-((bufLen-1)/2) ) )
...
The plot below is the frequency response of the Triangular window, in dB magnitude.
The plot below is the frequency response of the Triangular window, but now in linear magnitude.
You can plot the Hann, Triangular, and many other window functions here: Plot windows functions

Difficulty understanding the phase calculated by the FFT. Short matlab demo to illustrate

I'm testing the phase output of an fft of a sin signal and a cos signal.
The script below creates the signals and performs an FFT on them. Bins who's amplitude is below a threshold are zeroed for the phase spectrum because I am only interested in the phase of the signals.
% 10khz 10 second long time interval
t = 0:1 / 10000:10;
%1khz cos
c = cos(2 * pi * 1000 .* t);
%1khz sin
s = sin(2 * pi * 1000 .* t);
%ffts
C = fft(c)/length(c);
S = fft(s)/length(s);
%magnitude and phases of ffts
CA = abs(C); %cos magnitude
SA = abs(S); %sin magnitude
Cthresh = max(CA) * 0.5;
Sthresh = max(SA) * 0.5;
%find all indeces below the threshold
Crange = find(CA < Cthresh);
Srange = find(SA < Sthresh);
%set the indeces below the threshold to 0 - phase will be meaningless for
%noise values
CP = angle(C);
CP(Crange) = 0;
SP = angle(S);
SP(Srange) = 0;
If you plot CP - the phase of the cos - you will get a phase of 0.3142 in the bins corresponding to the frequency of the cos signal and zeros elsewhere. This is pi/10. I'm expecting to get pi. Why is this?
If you plot SP you get values of 1.2566. I'm expecting to get pi/2 or 1.5708. 80% of the expected value. What is causing these errors?
If your input signal is not perfectly periodic in the FFT aperture length (an exact integer number of full periods), the sinusoids will be discontinuous across the ends of the FFT aperture. Thus you will get a phase that is the average of the two different phases at both ends of the FFT input vector.
If you want a more sensible phase, reference the phase of your sinusoids to the center of the FFT input vector, and do an fft shift before the FFT. This will result in a continuous sinusoid at the zero phase reference position, with a single phase instead of a weird average value.
Also note that matlab may reference the phase to the second point in a sampled sinusoid, e.g. vectorElement[i=1], not the first, vectorElement[i=0]. This will have a phase of pi/10 for a sinusoid of period = 20 samples.
The issue you have is exactly what hotpaw2 has stated. You have 100001 samples in t, so you do not have a perfectly periodic signal, therefore you have leakage. That means that you've got a sin()/sin() function from your implicit rectangular window convolved with your solution. That's what changes your phase.
If instead you try the following:
t = 0:1 / 10000:9.9999;
c = cos(2 * pi * 1000 .* t);
%1khz sin
s = sin(2 * pi * 1000 .* t);
%ffts
C = fft(c)/length(c);
S = fft(s)/length(s);
you would find that the phase of the cosine is zero (which is what you would expect) and that the phase of sine is pi/2.
Performing a linear shift in the time domain (using fftshift) will merely introduce a linear phase term in the frequency domain, and will not resolve the original problem.
In practice, rather than trying to set the length of the sequence precisely to match the period of the signal, windowing should be applied if the signal is to be examined in the frequency domain. In that case you really should make sure that your signals are appropriately aligned so that the window attenuates the end points, thus smoothing out the discontinuity. This has the effect of broadening the main lobe of the FFT, but it also controls the leakage.