Community /

FFT test: FFT in Minim and Matlab

Since I’m studying the spectrum characteristics of brainwaves with FFT in Matlab, I want to apply my algorithm later into OpenBCI GUI. Knowing that OpenBCI Processing GUI uses Minim to compute FFT, I want to know more about the difference, so I did this test to compare the FFTs in Minim and in Matlab.
I basically used the same combined sine signal for both of them, then calculate with both FFT functions and compare the values.
data = 0.7*sin(2*pi*50*t) + sin(2*pi*70*t);
It turns out that the FFT in Minim are basically the same as FFT in Matlab, except that Minim FFT only calculates half of the spectrogram, and simply replace the other half with data on Nyquist (i = Nfft/2). It doesn’t matter because both sides of FFT contain the same information, Minim could be doing so out of efficiency consideration.
Raw FFT
in Matlab:
fft_mag = abs(fft(data,Nfft));
fft_mag =fft_mag[1:Nfft/2 + 1];
equals in Minim:
fft.forward(data);
fft.getBand(i)      from i = 0 to i = Nfft/2
Screen Shot 2016-07-07 at 10.54.57 AM
Double-sided amplitude spectrum:
If you want to get the double-sided amplitude spectrum in quantity peak, you need to divide the FFT result by Nfft.
in matlab:
fft_double = abs(fft(data,Nfft))/N
in Minim:
(after fft.forward(data))
for (int i = 0; i < fft.specSize(); i++) {
    fft.setBand(i, fft.getBand(i) / fft.timeSize());
}
In original data, there are two sine components that have peak amplitude respectively of 0.7 and 1.0. In the graph, you can see both the peak amplitude are halved to 0.35 and 0.5 and mirrored across Nyquist frequency. (basically the same, here I changed the other sine wave freq from 70 to 80 for testing)
Screen Shot 2016-07-07 at 11.15.21 AM
Single-sided amplitude spectrum: 
By converting to single-sided spectrum you can have the actual amplitude value.
It’s simply multiply everything by two in the double-sided amplitude spectrum, except the two end points at i = 0 and i = Nfft/2 (Nyquist frequency). See also this Matlab example.
Screen Shot 2016-07-07 at 11.24.28 AM
So in the graph you can see the amplitude map recovers the two peaks, around 0.67 at 50Hz and 0.85 at 70Hz, with a little energy loss as compared to 0.7 and 1.0 as original amplitude.
Screen Shot 2016-07-07 at 1.12.20 PM
Complete code in Matlab:
Fs = 250; % Sampling frequency
L = 256;
T = 1/Fs;
t = (0:L-1)*T; % Time vector
f = (0:L/2)*Fs/L;
S = 0.7*sin(2*pi*50*t) + sin(2*pi*70*t);
fft1 = fft(S,256);
fft1= abs(fft1)/L;
fft_single = fft1(1:L/2+1);
fft_single(2:end-1) = 2* fft_single(2:end-1);
plot(f,fft_single)
xlabel('frequency/Hz');
ylabel('amplitude');
Complete code in Processing:
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

FFT fft;
float[] data;
int fs = 250;
int L = 256;
float T = 1.0f/ fs;

void setup() {
size(256,256);
data = new float[256];
fft = new FFT(L,fs);

for (int i = 0; i < L; i++) {
    data[i] = 0.7*sin(2*PI*50*i*T) + sin(2*PI*70*i*T);
}
fft.forward(data);
for (int i = 0; i < fft.specSize(); i++)
{
    fft.setBand(i,fft.getBand(i)/fft.timeSize());
}
for (int i = 1; i < fft.specSize() - 1; i++) {
    fft.setBand(i,fft.getBand(i) * 2);
}
for (int i = 0; i < fft.specSize(); i++) {
    println(i,fft.getBand(i));
    line( i*2, height, i*2, height - fft.getBand(i)*L);
}
}
Reference:

Leave a Reply