2014-09-22 127 views
0

我用這個代碼(基於蘋果的audioRouch樣品):如何獲得iOS在FFT頻率上加速FFT結果?

void FFTHelper::ComputeFFT(Float32* inAudioData, Float32* outFFTData) 
{ 
    if (inAudioData == NULL || outFFTData == NULL) return; 

    // Generate a split complex vector from the real data 
    vDSP_ctoz((COMPLEX *)inAudioData, 2, &mDspSplitComplex, 1, mFFTLength); 

    // Take the fft and scale appropriately 
    vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, mLog2N, kFFTDirection_Forward); 
    vDSP_vsmul(mDspSplitComplex.realp, 1, &mFFTNormFactor, mDspSplitComplex.realp, 1, mFFTLength); 
    vDSP_vsmul(mDspSplitComplex.imagp, 1, &mFFTNormFactor, mDspSplitComplex.imagp, 1, mFFTLength); 

    // Zero out the nyquist value 
    mDspSplitComplex.imagp[0] = 0.0; 

    // Complex vector magnitudes squared; single precision. 
    // Calculates the squared magnitudes of complex vector A. 
    vDSP_zvmags(&mDspSplitComplex, 1, outFFTData, 1, mFFTLength); 

} 

爲了計算上儘可能簡單的FFT - 1Hz的正弦波(1個單位移):

Float32 waveFreq   = 1.0; 
    int  samplesCount  = 1024; 
    Float32 samplesPerSecond = 1000;  //sample rate 
    Float32 dt = 1/samplesPerSecond; 
    Float32 sd = M_PI * 2.0 * waveFreq; 

    FFTHelper *mFFTHelper = new FFTHelper(samplesCount); 

    Float32 NyquistMaxFreq = samplesPerSecond/2.0; 
    Float32 fftDataSize  = samplesCount/2.0; 

    Float32 *sinusoidOriginal = (Float32 *)malloc(sizeof(Float32) * samplesCount); 
    Float32 *outFFTData = (Float32 *)malloc(sizeof(Float32) * fftDataSize); 

    // 2. Generate sin samples: 
    for (int i = 0; i < samplesCount; i++) { 

     Float32 x = dt * i; 
     sinusoidOriginal[i] = sin(sd * x) + 1; 
     [originalPlot addVector2D:GLVector2DMake(x, sinusoidOriginal[i])]; 
    } 

    mFFTHelper->ComputeFFT(sinusoidOriginal, outFFTData); 

    for (int i = 0; i < fftDataSize; i++) { 

      Float32 hz = ((Float32)i/(Float32)fftDataSize) * NyquistMaxFreq; 
      GLfloat mag = outFFTData[i]; 
      [fftPlot addVector2D:GLVector2DMake(hz, 0)]; 
      [fftPlot addVector2D:GLVector2DMake(hz, mag)]; 

    } 

結果我得到的是:

enter image description here

黑線是來自FTT的繪圖儀結果,水平定位在它們的頻率上。 DC值(左起第一條黑線)看起來正常,正確表示y = sin(x)+1垂直偏移。

但爲什麼第二條黑線表示竇性方程中存在的唯一頻率,沒有大小= 1,並且不完全保持在1Hz?

任何人都可以指向我的vDSP函數將FFT結果轉換爲輸入信號的幅度單位嗎?

回答

2

簡短的回答:

你似乎使用的代碼從這個地方我的回答:https://stackoverflow.com/a/19966776/468812 ,它的偉大,但:

你不能避免在信號中的這些額外的頻率。

您生成的信號(正弦波)是一個無限信號。 如果你「裁剪它」和「只使用一段信號」,它會在兩端引入「剪切噪聲」。

但是,您可以通過在FFT之前採用較大的輸入塊和using windowing來最小化噪聲。 Accelerate Framework提供了一些很好且簡單的窗口函數。 (例如Hann Function,vDSP_hann_window) 另外 - 使用更大的輸入塊。更大的輸入更精確的是頻率檢測。

請參閱this article,谷歌:頻譜泄漏,窗口功能。