I'm trying something rather simple which is getting the correct values in a spectrum of a signal with a fixed length. I don't know the containing frequencies and therefor I can't chose the number of fft nodes accordingly. This leaves me with the problem of leakage. I try to avoid that by using a window to fade out the beginning and end of my time signal. With that I'm having problems to get the right amplitudes. Here is what I've done so far:
- compensate the windowing by multiplying the spectrum by a factor
- two-sided to single-sided spectrum -> multiplying spectrum amplitude by two
- normalice spectrum amplitude by dividing by the number of frequency nodes 'N'
As long as the number of fft nodes equals the number in my time signal it works well. But when the number of fft nodes are less than the time signal nodes the amplitudes of the spectrum are getting wrong.
I built a little example which calculates three spectrums:
- Using fft() with windowing
- Using fft() without windowing
- Using spectrogram()
By changing the SampleTime one can change the length of the time signal and by changing N one can change the number of FFT nodes. With the following setting all amplitudes are correct, but for the spectrum with the Hanning window. Why is it that much off? Thank you for any help in advance.
SampleTime=0.001;
Fs=1/SampleTime;
t=0:SampleTime:10;
y=2*sin(2*pi*10*t)+3*cos(2*pi*30*t); % Time Signal
fn = Fs/2; % Nyquistfrequency
N = 1001; % FFT-length (use N=2^x to use DFT-Algorithm)
df = Fs/N; % frequency resolution
%% Generating spectrum using fft()
win = hann(length(y))'; % generate Hanning window for Time Signal
ywin = y.*win*length(win)/sum(win); % amplitude correction to get correct values with window
Hwin = fft(ywin, N); % spectrum of windowed signal
H = fft(y,N); % complex spectrum of signal without window
amplHwin = abs(Hwin); % absolute values of spectrum of windowed signal
amplH = abs(H); % absolute values of spectrum without window
% Double sided spectrum -> single sided spectrum of windowed signal
amplitudengang = fftshift(amplH/N);
amplitudengang = amplitudengang(ceil(length(amplitudengang)/2+1):end);
amplitudengang(2:end) = amplitudengang(2:end)*2;
% Double sided spectrum -> single sided spectrum of unwindowed signal
amplitudengangwin = fftshift(amplHwin/N);
amplitudengangwin = amplitudengangwin(ceil(length(amplitudengangwin)/2+1):end);
amplitudengangwin(2:end) = amplitudengangwin(2:end)*2;
%% Generating spectrum using spectrogram()
noverlap = floor(0.5*N);
window = hann(N);
[B,F,T] = spectrogram(y,window,noverlap,N,Fs);
% Scaling
FFTScalingFactor = 2 * 1 / N; % 2 for Hanning window, 2^(-1/2) for RMS, 1 for peak
A = FFTScalingFactor * B;
B = FFTScalingFactor * abs(B);
B(2:end-1,:) = 2.*B(2:end-1,:); % single side spectrum with even block length
%% Plots
x_fn = 0 : df : fn-df; % Frequency vector
figure
subplot(2,2,1)
plot(x_fn,amplitudengangwin,'r')
hold on
plot(x_fn,amplitudengang)
legend('Hanning window','no window')
title('FFT()')
subplot(2,2,3)
plot(t,y)
title('Time signal')
subplot(2,2,2)
plot(F,B(:,1))
title('Spectrogram()')