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 = (CG开发者_如何学GoFloat)(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.
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.
精彩评论