I have a signal that varies in frequency and amplitude, and I want to create a moving window that takes a number of samples, finds out the "dominant frequency" in the window using FFT, and stores the frequency in another vector, before moving the window one step until the entire original signal has been analyzed.
This is what I have come up with so far, but the resulting graph looks very weird, so it's not working the way I want it to...
Fs = 200; % Samples per second
samples = 100; % Window size (samples)
freq = zeros(samples,1); % Output vector, starting with zeroes
% Move the window along the signal, starting at "samples" offset
for x = samples+1:1:length(signal)
% Get samples from signal in the "window"
windowFreq = signal(x-samples:x);
% Perform FFT
myFFT = fftshift( fft(windowFreq) );
% Store "dominant frequency" from the FFT
freq(x) = max(myFFT);
end
plot(freq);
I have found few problems in your approach.
Moving window FFT should only be used for constant frequency signals (if number input samples remains the same):
The input of FFT should be an integer number of cycles of the base frequency and the dominant frequency should be one of the harmonic of the base frequency. Now if the frequency is varying with each moving window, the number of input samples to FFT should also vary. Instead of going further into details, I will illustrate this concept with the following example:
Here you will get the dominatingFreq equals to 50 hz, which is correct.
Now change the signal frequency to 60 hz without changing the cycleEnd and samplingFrequency. The results will be incorrect. You need to change the values of sampling frequency and cycleEnd to 6000 hz and 0.0167 seconds respectively to get correct results (you can also change the number of samples given that it's an integer).
What if dominating frequency is an inner-harmonic?
In your example the base frequency is 2 hz.$$baseFrequency = \frac{samplingFrequency}{NumberOfSamples}$$If the dominating frequency is an inter-harmonic (not an integer multiple of base frequency), it will not be clearly present in the output.
Few bugs in your code
freq(x) = max(myFFT)is not the frequency (its frequency strength at a given frequency). Use insteadmax(fshift(1, find(powershift == max(powershift))))to get highest positive dominating frequency.Minor remarke: Index of frequency starts from 100 in your code.
I can't provide you an exact solution to your problem but you can try to use an enhanced version of DFT for this specific case. Otherwise you can also have a look at least squares base algorithm which is known to free from obligation of integer number of input cycles.
I hope that helps.