Question

I'm trying to create an audio visualizer.

I'm using the fast Fourier transform to find the frequencies.

memset(_window, 0, sizeof(float)*_windowSize);
memset(_A.imagp, 0, nOver2 * sizeof(float));

vDSP_hann_window(_window, _windowSize, vDSP_HANN_NORM);

for (int i=0; i < _windowSize; i++) {
    if (player && ioData) {
        _inPutBuffer[i] = ((SInt16*) ioData->mBuffers[0].mData)[i];
    }
}

vDSP_vmul(_inPutBuffer, 1, _window, 1, _transferBuffer, 1, _windowSize);

vDSP_ctoz((COMPLEX*)_transferBuffer, 2, &(_A), 1, nOver2);

vDSP_fft_zrip(_fftSetup, &_A, stride, log2n, FFT_FORWARD);

vDSP_vsmul(_A.realp, 1, &_scale, _A.realp, 1, nOver2);
vDSP_vsmul(_A.imagp, 1, &_scale, _A.imagp, 1, nOver2);

_A.imagp[0] = 0.0f;

vDSP_zvmags(&_A, 1, _obtainedReal, 1, nOver2);

float frequencyArray[n];

for (int i=1; i <=kIndicatorsCount; i++ ) {
    float res = 0;
    for (int j=0; j <=32; j++) {
        res += _obtainedReal[i*32+j];
    }
    res = res / 32;
    OutputBuff[i] = res;
}

But the output is very different values, for example, in one case the output values ​​can be from 0 to 1, and the other from 0 to 5.0E +6.

Is it possible to bring the output values ​​to a certain range (Eg 0 to 1)?

Was it helpful?

Solution

The magnitude output of the FFT is usually visualized in decibels for this very reason. Decibels allow very small components to still be seen when large components are present. The conversion is simple. Since vDSP_zvmags gives the squared magnitude, you can convert to dB with:

dbval = 10 * log10(mag2val);

or see vDSP_vdbcon.

This could be normalized between 0 and 1 by dividing by the maximum value of your dB values, but you probably don't want to change this reference point dynamically since it would cause visualization of a constant magnitude to jump around. It would probably be better to just figure out what ranges are typical and normalize to that fixed value.

OTHER TIPS

The problem should be vDSP_zvmags(&_A, 1, _obtainedReal, 1, nOver2);

As per Apple doc : vDSP_zvmags Calculates the squared magnitudes of complex vector A.

I mean the magnitude is per Pitagora Theorem and you should use vDSP_vpythg (Vector Pythagoras; single precision.)

After that you can use decibel conversion vDSP_vdbcon with flag __vDSP_F to Power (0) or amplitude (1) flag

Hope this help

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top