Определение того, какие частоты соответствуют оси x в примере приложения aurioTouch - PullRequest
4 голосов
/ 01 июня 2010

Я смотрю пример приложения aurioTouch для iPhone SDK. Он имеет базовый анализатор спектра , реализованный при выборе опции «БПФ». Одной из вещей, которой не хватает в приложении, являются метки оси X (то есть метки частоты).

В файле aurioTouchAppDelegate.mm , в функции - (void)drawOscilloscope в строке 652 он имеет следующий код:

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();

    }

}

Насколько я понимаю, эта часть кода используется для определения того, какую величину рисовать для каждой частоты в пользовательском интерфейсе. Мой вопрос заключается в том, как определить частоту каждой итерации (или значение y) внутри цикла for.

Например, если я хочу узнать, какова величина для 6 кГц, я подумываю добавить строку, подобную следующей:

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

Обратите внимание, что хотя они решили использовать имя переменной y, насколько я понимаю, она фактически представляет ось x на визуальном графике анализатора спектра и значение drawBuffers[0][y] представляет ось Y.

1 Ответ

5 голосов
/ 01 июня 2010

Я считаю, что частота каждого бина, который он использует, определяется как

yFract * hwSampleRate * .5

Я вполне уверен, что вам нужен .5, потому что yFract - это часть общего fftLength, а последний бин FFT соответствует половине частоты дискретизации. Таким образом, вы можете сделать что-то вроде

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

Надеюсь, это поможет вам, по крайней мере, указать правильное направление.

...