FFT Amplitude


It has been a while since I used an FFT and instead of porting some old C# sharp code I’m trying out juce’s.

Here’s what I understand:
The frequency of bin[x] = Fs / nth Record.
In the past I have multiplied the real and imageinary parts but using fft::performFrequencyOnlyForwardTransform only modifies the array going in. Is the data in that array a linear amplitude?

My other question is if say the FFT is (10th Order) 512 bins do I need to supply 512 or 1024 samples? (my guess is that if its OnlyForward like the method implies - I only need 512)…

Am I off in my assumption?

How to cast from IIRCoefficents to array of float

Yes, the amplitude is linear with values from 0 to the FFT size (0 - 512 for 10th order).

1024 samples for FFT size of 512.


Cheers Jimmi, that helps.


Either I understood that wrong, or it is not accurate:

The size is 2^order (or 1 << order), so size of 10 should be 1024.

The array for processing needs to be 2 * fft.getSize() = 2048, see the docs for FFT::perform().

The size of the array passed in must be 2 * getSize(), and the first half should contain your raw input sample data.

And the number of samples to supply are fft.getSize(), at the beginning of the array.


Your right…

I was using bufferSize = 1 << 10 so my code, just minced my terms in the post.
Good spot.

in my .h

    enum {
        fftOrder = 10,
        fftSize = 1 << fftOrder
    DSP::Delay<float> delay{fftSize};
    float fftData [2 * fftSize];

So I need to double my delay line size before copying to fftData for visualisation


I do feel that the FFT sample should have maybe 2 different views. While the WaterFall style is nice use case using a max bin value to make visual more prominent disguises real value of data, Maybe a more traditional FFT view would be useful.


If you want to make a “falling down” path, at least make sure that the rate is calculated against the sample rate!

In my initial setup I used

	// Curve lowers with a frame rate of 25 to zero in around a second
	FloatVectorOperations::multiply (levels, 0.9f, numBins);
	for (auto i = 0; i < numBins; ++i)
		// "Add" new peak levels to the fallback curve
		if (binPeaks[i] > levels[i])
			levels[i] = binPeaks[i];

This works nicely at 48 kHz - haven’t yet checked at 96 or 192, maybe the results are the same :slight_smile: Too hot here (30 degrees) to think about it in more depth :smiley:


When I wrote my spectro stuff, I also ran into the buffer size issue, with nasty crashes. But okay, it IS commented in the Juce source and docs. I was confused by my IPP code, which did not use a buffer twice the size.


It’s a traditional FFT window that I’m creating not a WaterFall one like the example. My code is frame rate independant … (it waits for proper handoff before updating view and handoff is governed by data)

Were getting the first shower in 6 weeks on the Wirral so I’m feeling a little more productive :wink:


It’s looking good now. I just need to have some sort of scaler as my FFT display cuts off at -40db to +12db


Congrats! Are you painting with a path or with lines? Paths are quite expensive, I pre-allocate them, hoping this helps. I also use a roundedPath for up to 1 kHz, which looks a lot nicer in the low end (with few bins)


Have you applied a window, like Hann or Hamming to the FFT input? With a Hann you should apply a +6dB correction.


Would love to use paths but CPU gets hot. viewport is 956 x 432 and openGL. Normal render just isn’t stable and I’m quite sure I’m not doing anything I shouldn’t.

The guide lines in the background are on a persistent image. I do have a scaler on there so I can see what I’m doing. Is +6db a standard?


Same here, with an Eq grid as image. I am not having that much CPU to worry about in my implementation, but the FFT surely is faster than a single path render :wink:

I got the 6 dB correction from literature about the Hann window, which I use.

I currently have no good video capture app on Windows, maybe I can post later this week how my spectrogram looks.




(work in progress)


So my amplitudes seem way off … I’m scaling a hell of a lot more than 6db. You’ve sold me on the the path. Looks cleaner!


The dB range of my grid is probably off in this image (should be 24 I believe), but it is of course a bit arbitrary what level range you use for the spectrum in an Eq display.

I hope you understand my meaning of “scaling”: if you apply a Hann window to the FFT input, to avoid leaking false frequencies, you have to adjust with 6 dB for what the Hann window drops at both sides of the “window”


Are you using soft renderer ?


Not yet switched on OpenGL, will do later and do measurements.