0
0

I am using FMOD for audio analysis, using system::getSpectrumto get the frequency data. My question here is about what data does FMOD use behind the scene to perform the FFT. For example, if my output rate is at 44100Hz and I call getSpectrum() 30 times a second (every 0.03333 seconds) with 1024 samples:

system.getSpectrum(data, 1024, 0, FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS);

Does FMOD just take the last 1024 PCM samples that were played and perform the FFT on those? In this case, if 1470 samples were actually read and played between getSpectrum() calls, only the last 1024 samples are dealt with and we lose the info on the intermediate 446 floats. Then the precision of the interval at which I call getSpectrum becomes incredibly important, because I don’t get the same results if I call it after 0.033 seconds onnce and after 0.034 seconds the next, which makes the whole thing very dependent on FPS and totally undetermined. Can anyone provide me with insight on the under-the-hood mechanics of FMOD and how to get this to be deterministic?

  • You must to post comments
0
0

The getSpectrum function is mainly for visualizations, but to answer your question it updates every time the mixer gets updated, so once every 1024 samples by default for example on windows.
The size you specify is how far into the past it buffers, and performs the fft on that. You could theoretically get a DSP callback to get the state of the FFT so you are in sync with the mixer.

There are no overlapping windows, so a blackman harris window will basically squash the tail ends of the window each time.
The values are also massaged into a format that makes it 0.0 to 1.0 (it takes the real/imaginary part of the complex #, gets the length of those 2 values as a 2D vector, then scales it up by 2.5 to get it into a similar db level as the input. It clamps the result at 1.0 as well.

You can get quite an accurate frequency out of it though if you process the whole window with something like this

[code:r7gm25uq]
int nyquist = length / 2;
float dominant = 0.0f;
{
float average = 0.0f;
float power = 0.0f;

    for (int i = 0; i < nyquist-1; ++i)
    {
        float hz = i * (rate * 0.5f) / (nyquist-1);

        if (spectrum[i] > 0.0001f) // aritrary cutoff to filter out noise
        {
            average += spectrum[i] * hz;
            power += spectrum[i];
        }
    }

    if (power > 0.0001f)
    {
        dominant = average / power;
    }
    else
    {
        dominant = 0;
    }
}

[/code:r7gm25uq]

  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.