Last night I was able to derive the relationship between the three largest amplitude lines in the FFT of a sinusoid under an implicit "rect" window (described by a sinc (or sin(x)/x) function), and under a raised cosine Hanning window (the sum of three shifted sinc functions), when the spectral peak lies between the FFT lines. In particular I was able to show that the ratio of the two largest amplitude lines allows the true frequency to be very easily computed.
If the largest amplitude A(L) occurs at line L in the FFT, and the second largest at line L+1, we can define the ratio R = A(L)/A(L+1), and the true frequency f of the input is simply:
f = (L +/- 1/(1+R))* Fsample/fftLength.......................(1)
for the implicit rect window, and
f = (L +/- (2-R)/(1+R))* Fsample/fftLength.................(2)
if the data is windowed with a Hanning window before the FFT, and where it is + if A(L+1) > A(L-1), and - if A(L-1)>A(L+1).
It doesn't get much easier!
I've reinvented the wheel many times in my career, and I found out today that (1) was proposed by Jain et al in 1979, and is known as Jain's algorithm, however I can find no reference to (2).
I've spent the day today simulating (1) and (2) in MATLAB, and writing Teensy Audio objects for both. I've looked at the effect of non-sinusoidal input waveforms (square wave and triangle), and additive noise. My conclusion is that the Hanning windowed version (2) is least sensitive to the spectral leakage from harmonics in the non-sinusoidal waveforms, and to additive random noise, and adjacent contaminating signals for a couple of reasons. I'll be doing more simulations and will follow up with the full derivation of (1) and (2).
I have attached a .zip file with fully functional .h, .cpp, and example .ino files for
FFTInterpHann1024 and FFTInterpHann256 Audio objects. You will see that they give sub-Hz accuracy for both FFT lengths, but that the 256 unsmoothed output has a bit more jitter. You can also add noise to look for bias in the estimates. This is a work-in-progress, and I would be delighted if they could be given a real workout in practical applications.
If the largest amplitude A(L) occurs at line L in the FFT, and the second largest at line L+1, we can define the ratio R = A(L)/A(L+1), and the true frequency f of the input is simply:
f = (L +/- 1/(1+R))* Fsample/fftLength.......................(1)
for the implicit rect window, and
f = (L +/- (2-R)/(1+R))* Fsample/fftLength.................(2)
if the data is windowed with a Hanning window before the FFT, and where it is + if A(L+1) > A(L-1), and - if A(L-1)>A(L+1).
It doesn't get much easier!
I've reinvented the wheel many times in my career, and I found out today that (1) was proposed by Jain et al in 1979, and is known as Jain's algorithm, however I can find no reference to (2).
I've spent the day today simulating (1) and (2) in MATLAB, and writing Teensy Audio objects for both. I've looked at the effect of non-sinusoidal input waveforms (square wave and triangle), and additive noise. My conclusion is that the Hanning windowed version (2) is least sensitive to the spectral leakage from harmonics in the non-sinusoidal waveforms, and to additive random noise, and adjacent contaminating signals for a couple of reasons. I'll be doing more simulations and will follow up with the full derivation of (1) and (2).
I have attached a .zip file with fully functional .h, .cpp, and example .ino files for
FFTInterpHann1024 and FFTInterpHann256 Audio objects. You will see that they give sub-Hz accuracy for both FFT lengths, but that the 256 unsmoothed output has a bit more jitter. You can also add noise to look for bias in the estimates. This is a work-in-progress, and I would be delighted if they could be given a real workout in practical applications.
Attachments
Last edited: