A guideline on better Spectrum Analyzers

Ive been using the juce fft class for some time now and the bad resolution for low frequencies really bothers me. Im currently aware of two solutions and I know there are already threads out there, but I really want to know what the common approach is.

Implementing my own cqt transform?
Switching to some sort of fft with overlapping buffers?
A combination of both above?
Or is there another way to get high order ffts with good performance?

1 Like

I tend to use a a circular buffer of samples for FFTs so I can still display at 60fps while still using large block sizes of 65k. You lose some precision in the time domain (since peaks tend to ‘hang-around’ for a while, instead of decaying instantly) but you get the added precision in the frequency domain.

I always wondered if you could do some trick to pitch-shift the sound up a few octaves, process the FFT, then shift the calculated frequency bins back down. No idea if that’d work - the pitch shifting would likely alter the frequency content a lot.

1 Like

Im not quite sure if Im understanding what you did in the first sentence. Something like this?
If not are there any other resource you can provide to help me get started?
I thought about Splitting the Input into multiple frequencybands and downsample the lower freq band since smaller max Freq = larger portion of fft points on low frequencies but maybe Im missing a fundamental problem with this approach.

pitchshifting itself is something that uses a buffer and adds latency. think of it, if you wanna put a sinewave an octave higher your buffer must be at least the size of that sine wave. and at that point you could have also just used FFT on that buffer already

It’s actually quite easy to overlap FFTs. For example, look at the function pushNextSampleIntoFifo in this tutorial: Tutorial: Visualise the frequencies of a signal in real time

Replace the line fifoIndex = 0; with the following:

const int overlap = 8; 
const int hopSize = fftSize / overlap; 
for (int i = 0; i < fftSize - hopSize; ++i) 
    fifo [i] = fifo [i + hopSize];
fifoIndex = fftSize - hopSize;

That already does the trick. It’s of course a somewhat crude way to do it but it can get you started. Play around with different values for overlap and fftSize.

Another thing to consider is to use splines, as they can make your displays look much nicer. A nice introduction to Catmull-Rom splines is here: Programming & Using Splines