Sample audio between certain frequencies

Hello.
I’m making a specialized kind of spectrum analyzer and there’s a narrow frequency band that I’m interested in. So I’d like to put the whole “resolution” of samples/bins to work only on that band, for increased precision and at the same time saving processing.
How can it be done?

Unfortunately that’s not how it works - frequency domain transformations like fourier transform are exact, eg. they contain the complete amount of information to go back and forth. This also means there’s “no more” information (resolution) to extract by only focusing on certain bands. You can certainly interpolate if you want, though.

These transformations are naturally an expression of the uncertainty principle, so if you want, you can increase the transform size which will increase resolution but reduce locality information.

FFTs are O(n log n) which is quite good already, but you can look up the Goertzel algorithm which is capable of computing only a single arbitrary frequency in O(N) time.

Thank you, I’ve read about Fourier transforms and I’m almost able to understand what you mean, i.e. you need the whole to generate the “overlapping” frequencies in FFT.
With all my reading of FFT and digital sampling I’ve still got a long way to go until I understand them, in order to get to where I need.

What I need specifically, is being able to detect a main frequency with at least 1 Hz precision in range 0 - 4000 Hz.
If I’m not mistaken, the maximum precision is 2.68 Hz (22000 / 8192).

In theory I could consider the whole spectrum 0 - 4000 Hz instead of 0 - 22000 Hz. I’d need a sampling rate of no more than ~8000 Hz. This is where I get lost.

Is the value of 22000 hard coded? What am I missing?

This would be my preferred solution. If not, you mentioned interpolation but I don’t see how you could interpolate. For the sake of example, let’s take a sound of 292 Hz. With 2048 samples (10.74 Hz / bin) it would be somewhere in 28th bin, 290 → 300. How could interpolation be used in this case?

I’m not sure, this sounds like your sampling rate (although uncommon, sure it’s not 24k ?).

In general, for precision / (spatial) resolution, the only factor that really matters is N / sampling rate, there are no hardcoded numbers. So for instance, resampling to 8000hz from 22000hz also removes 4/11 samples and hence your “precision factor” remains the same.

Unless you wanted to preserve the transform size whilst downsampling, in which case this would be equivalent to a larger transform size on the original signal (precision wise, in the frequency area you are interested in). Except you would get aliasing and potentially unexpected lobe distortion from your downsampling filter - which is also not free.

You can perfectly interpolate a fourier transform using the sinc() brickwall filter. Notice this is equivalent to zero-padding the FFT. Less precisely, you can do a parabolic fit which is the usual cheap method.

This is quite a common problem. Usually, you find the largest bin, and then use a parabolic fit to assume the peak of the lobe: Peak Detection (Steps 3 and 4)

You can see an implementation I did here: Bitbucket

However, it’s not always the largest bin that is the fundamental. If you want to be more precise, you need to account for fluctuations (median filters), properly window the signal, do harmonic analysis etc. I applied some of these here:
https://bitbucket.org/Mayae/signalizer/src/989d0353e41dad141862976f2f9fb8596d391f11/Source/Oscilloscope/OscilloscopeDSP.inl#lines-59

1 Like

Thank you for the comprehensive and useful reply! And sorry for not replying earlier.
I’ve studied all the info you provided and based on that I’m going to implement the simplest version of a spectrum analyzer.