The JUCE documentation say performRealOnlyForwardTransform() does the following:

“On return, if dontCalculateNegativeFrequencies is false, the array will contain size complex real + imaginary parts data interleaved.”

However, in the “Visualise the frequencies of a signal in real time” tutorial (https://docs.juce.com/master/tutorial_spectrum_analyser.html), I do not see them getting the magnitude of each bin by using Pythagorean theorem.

This is what they do:

```
window.multiplyWithWindowingTable (fftData, fftSize); // [1]
// then render our FFT data..
forwardFFT.performFrequencyOnlyForwardTransform (fftData); // [2]
auto mindB = -100.0f;
auto maxdB = 0.0f;
for (int i = 0; i < scopeSize; ++i) // [3]
{
auto skewedProportionX = 1.0f - std::exp (std::log (1.0f - (float) i / (float) scopeSize) * 0.2f);
auto fftDataIndex = juce::jlimit (0, fftSize / 2, (int) (skewedProportionX * (float) fftSize * 0.5f));
auto level = juce::jmap (juce::jlimit (mindB, maxdB, juce::Decibels::gainToDecibels (fftData[fftDataIndex])
- juce::Decibels::gainToDecibels ((float) fftSize)),
mindB, maxdB, 0.0f, 1.0f);
scopeData[i] = level; // [4]
}
```

I suspect the magnitudes are extracted here somehow because scopeData has a size of 512 where fftData has a size of 2048, but I am confused about the math. Does anyone know how this math is getting the magnitudes of the FFT bins? Also, could anyone explain the math behind getting skewedProportionX?