11

私はこれらの質問を読みました:

Apple FFT および Accelerate フレームワークの使用

Accelerate フレームワークを使用して FFT を実行する場合、バッファを設定するにはどうすればよいですか?

iOS FFT Accerelate.framework は、再生中にスペクトルを描画します

それらはすべて、加速フレームワークで fft をセットアップする方法を説明しています。彼らの助けを借りて、fft をセットアップし、基本的なスペクトラム アナライザを入手することができました。現在、fft から取得したすべての値を表示しています。ただし、特定の周波数を再設定する 10 ~ 15、または可変数のバーのみを表示したいと考えています。iTunes や WinAmp Level Meter と同じです。1. ある範囲の周波数からマグニチュード値を平均化する必要がありますか? それとも、特定の周波数バーのマグニチュードを示しているだけですか? 2. また、マグニチュード値を db に変換する必要がありますか? 3. データを特定の範囲にマッピングするにはどうすればよいですか。サウンドのビット深度の最大 db 範囲に対してマッピングしますか? ビンの最大値を取得すると、最大マッピング値がジャンプします。

私のRenderCallback:

static OSStatus PlaybackCallback(void *inRefCon,
                                 AudioUnitRenderActionFlags *ioActionFlags,
                                 const AudioTimeStamp *inTimeStamp,
                                 UInt32 inBusNumber,
                                 UInt32 inNumberFrames,
                                 AudioBufferList *ioData)
{
    UInt32 maxSamples = kAudioBufferNumFrames;

    UInt32 log2n = log2f(maxSamples); //bins
    UInt32 n = 1 << log2n;

    UInt32 stride = 1;
    UInt32 nOver2 = n/2;

    COMPLEX_SPLIT   A;
    float          *originalReal, *obtainedReal, *frequencyArray, *window, *in_real;

    in_real = (float *) malloc(maxSamples * sizeof(float));

    A.realp = (float *) malloc(nOver2 * sizeof(float));
    A.imagp = (float *) malloc(nOver2 * sizeof(float));
    memset(A.imagp, 0, nOver2 * sizeof(float));

    obtainedReal = (float *) malloc(n * sizeof(float));
    originalReal = (float *) malloc(n * sizeof(float));
    frequencyArray = (float *) malloc(n * sizeof(float));

    //-- window

    UInt32 windowSize = maxSamples;
    window = (float *) malloc(windowSize * sizeof(float));

    memset(window, 0, windowSize * sizeof(float));
    //    vDSP_hann_window(window, windowSize, vDSP_HANN_DENORM);

    vDSP_blkman_window(window, windowSize, 0);

    vDSP_vmul(ioBuffer, 1, window, 1, in_real, 1, maxSamples);

    //-- window

    vDSP_ctoz((COMPLEX*)in_real, 2, &A, 1, maxSamples/2);

    vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
    vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_INVERSE);

    float scale = (float) 1.0 / (2 * n);

    vDSP_vsmul(A.realp, 1, &scale, A.realp, 1, nOver2);
    vDSP_vsmul(A.imagp, 1, &scale, A.imagp, 1, nOver2);

    vDSP_ztoc(&A, 1, (COMPLEX *) obtainedReal, 2, nOver2);
    vDSP_zvmags(&A, 1, obtainedReal, 1, nOver2);

    Float32 one = 1;
    vDSP_vdbcon(obtainedReal, 1, &one, obtainedReal, 1, nOver2, 0);

    for (int i = 0; i < nOver2; i++) {
        frequencyArray[i] = obtainedReal[i];
    }


    // Extract the maximum value
    double fftMax = 0.0;
    vDSP_maxmgvD((double *)obtainedReal, 1, &fftMax, nOver2);

    float max = sqrt(fftMax);
}

音楽を再生すると、-96db から 0db までの値が得られます。点をプロットする:

CGPointMake(i, kMaxSpectrumHeight * (1 - frequencyArray[i]/-96.));

私のかなり丸みを帯びた曲線を与えています:

プロット1

db に変換しない場合は、配列の値に 10000 を掛けてプロットし、素敵なピークを得ることができます。

プロット2

私は何か完全に間違っていますか?可変数のバーを表示するにはどうすればよいですか?

4

1 に答える 1