tags:

views:

107

answers:

1

I'm looking at the aurioTouch sample application for the iPhone SDK. It has a basic spectrum analyzer implemented when you choose the "FFT" option. One of the things the app is lacking is X axis labels (i.e. the frequency labels).

In the aurioTouchAppDelegate.mm file, in the function - (void)drawOscilloscope at line 652, it has the following code:

if (displayMode == aurioTouchDisplayModeOscilloscopeFFT)
{           
    if (fftBufferManager->HasNewAudioData())
    {
        if (fftBufferManager->ComputeFFT(l_fftData))
            [self setFFTData:l_fftData length:fftBufferManager->GetNumberFrames() / 2];
        else
            hasNewFFTData = NO;
    }

    if (hasNewFFTData)
    {

        int y, maxY;
        maxY = drawBufferLen;
        for (y=0; y<maxY; y++)
        {
            CGFloat yFract = (CGFloat)y / (CGFloat)(maxY - 1);
            CGFloat fftIdx = yFract * ((CGFloat)fftLength);

            double fftIdx_i, fftIdx_f;
            fftIdx_f = modf(fftIdx, &fftIdx_i);

            SInt8 fft_l, fft_r;
            CGFloat fft_l_fl, fft_r_fl;
            CGFloat interpVal;

            fft_l = (fftData[(int)fftIdx_i] & 0xFF000000) >> 24;
            fft_r = (fftData[(int)fftIdx_i + 1] & 0xFF000000) >> 24;
            fft_l_fl = (CGFloat)(fft_l + 80) / 64.;
            fft_r_fl = (CGFloat)(fft_r + 80) / 64.;
            interpVal = fft_l_fl * (1. - fftIdx_f) + fft_r_fl * fftIdx_f;

            interpVal = CLAMP(0., interpVal, 1.);

            drawBuffers[0][y] = (interpVal * 120);

        }
        cycleOscilloscopeLines();

    }

}

From my understanding, this part of the code is what is used to decide which magnitude to draw for each frequency in the UI. My question is how can I determine what frequency each iteration (or y value) represents inside the for loop.

For example, if I want to know what the magnitude is for 6kHz, I'm thinking of adding a line similar to the following:

if (yValueRepresentskHz(y, 6))
  NSLog(@"The magnitude for 6kHz is %f", (interpVal * 120));

Please note that although they chose to use the variable name y, from what I understand, it actually represents the x-axis in the visual graph of the spectrum analyzer, and the value of the drawBuffers[0][y] represents the y-axis.

+1  A: 

I believe that the frequency of each bin it is using is given by

yFract * hwSampleRate * .5

I'm fairly certain that you need the .5 because yFract is a fraction of the total fftLength and the last bin of the FFT corresponds with half of the sampling rate. Thus, you could do something like

NSLog(@"The magnitude for %f Hz is %f.", (yFract * hwSampleRate * .5), (interpVal * 120));

Hopefully that helps to point you in the right direction at least.

Justin Peel