2015-06-19 99 views
0

我正在使用Novocaine框架來執行音調檢測。一切正常 - 只有使用圖形FFT表示,纔會出現一些問題。IOS和FFT(vDSP_fft_zrip):頻率低於appr。 100赫茲被切斷 - 爲什麼?

當我使用音頻文件輸入時,FFT工作正常 - 低於100赫茲的頻率顯示完美。

取而代之,當我使用麥克風作爲輸入時,100 Hz以下的頻率根本沒有顯示 - 我找不出原因!請參閱以下屏幕截圖:

正確顯示較高頻率(例如1000 Hz)!

這裏的FFT程序的源代碼:

- (NSMutableArray*)performFFT: (float*) data withFrames: (int) numSamples { 
 
    // 1. init 
 
    float bufferSize = numSamples; 
 
    uint32_t maxFrames = numSamples; 
 
    displayData = (float*)malloc(maxFrames*sizeof(float)); 
 
    bzero(displayData, maxFrames*sizeof(float)); 
 
    int log2n = log2f(maxFrames); 
 
    int n = 1 << log2n; 
 
    assert(n == maxFrames); 
 
    float nOver2 = maxFrames/2; 
 
    
 
    
 
    A.realp = (float*)malloc(nOver2 * sizeof(float)); 
 
    A.imagp = (float*)malloc(nOver2 * sizeof(float)); 
 
    fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2); 
 
    
 
    // 2. calcuate 
 
    bufferSize = numSamples; 
 
    float ln = log2f(numSamples); 
 
    vDSP_ctoz((COMPLEX*)data, 2, &A, 1, numSamples/2); 
 
    
 
    //fft 
 
    vDSP_fft_zrip(fftSetup, &A, 1, ln, FFT_FORWARD); 
 
    
 
    // Absolute square (equivalent to mag^2) 
 
    vDSP_zvmags(&A, 1, A.realp, 1, numSamples/2); 
 
    // make imaginary part to zero in order to filter them out in the following loop 
 
    bzero(A.imagp, (numSamples/2) * sizeof(float)); 
 
    
 
    //convert complex split to real 
 
    vDSP_ztoc(&A, 1, (COMPLEX*)displayData, 2, numSamples/2); 
 
    
 
    // Normalize 
 
    float scale = 1.f/displayData[0]; 
 
    vDSP_vsmul(displayData, 1, &scale, displayData, 1, numSamples); 
 
    
 
    
 
    //scale fft 
 
    Float32 mFFTNormFactor = 1.0/(2*numSamples); 
 
    vDSP_vsmul(A.realp, 1, &mFFTNormFactor, A.realp, 1, numSamples/2); 
 
    vDSP_vsmul(A.imagp, 1, &mFFTNormFactor, A.imagp, 1, numSamples/2); 
 

 
... 
 
}

爲進一步圖形化的問題,我用displayData。由於我對較低頻率感興趣(有一個獨立的基音檢測算法,可以很好地工作),我將採樣率降低到了11.025(而不是44100)。

在奴佛卡因,我提出以下電話:

1)輸入

[audioManager setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) { 
 
      
 
      // frequency analysis 
 
      vDSP_rmsqv(data, 1, &magnitude, numFrames*numChannels); 
 
      self->ringBuffer->AddNewInterleavedFloatData(data, numFrames, numChannels); 
 
... 
 
}

2)輸出:

[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) 
 
    { 
 
    self->ringBuffer->FetchInterleavedData(data, numFrames, numChannels); 
 
    .... 
 
    [fft performFFT:data withFrames:numFrames]; 
 
    ... 
 
    }

有人有想法嗎?

回答

1

這是因爲內置麥克風是一個電容話筒,並有一個高通濾波器來消除信號上的直流偏壓。

可以禁用HPF。直流偏置並不是一個問題,因爲它只會在FFT的bin#0中出現。

[[AVAudioSession sharedInstance] setMode: AVAudioSessionModeMeasurement error:NULL]; 

另請注意,FFT的窗口化也會影響FFT的低頻段的精度。對於任何給定的頻率,窗口中至少需要2 * PI樣本。

+0

謝謝marko! 我試過了,但沒有任何效果。 我不認爲這是問題的根源 - 我不能告訴你爲什麼: 我用一種自相關來執行音高檢測。音高檢測非常適用於從20 Hz到1000 Hz的所有頻率,因此200 Hz以下的頻率不會被切斷 - 我使用相同的硬件和相同的Novocaine架構。相反,當我切換到FFT時,200 Hz以下的所有頻率都被切斷。對我來說,這似乎很奇怪...... –

+0

看到我對FFT精度低頻效果窗口的建議。你的窗戶大小是多少? 您可能還想將一個方形窗口以外的東西應用於FFT。 – marko

+0

Hi Marko,老實說,我不知道與FFT結合的「開窗」。我知道採樣率,但不知道窗口大小。我怎樣才能實現這樣的窗口? –

0

音高與頻譜不同。低音聲音通常由大部分諧波和泛音能量組成,並且在基頻處沒有太多能量。因此FFT也不會在那裏找到太多。自相關在找到這些類型的諧波豐富的聲音的音高時稍微好一些。

除了iPhone麥克風對低頻能量不敏感,因爲它是中高頻率的音頻(有audio response graphs在線)。

另請注意,FFT緩衝區需要按比例更長,以便具有低頻內容的等效百分比(等分回火間距,以分爲單位)分辨率。對於低頻分辨率,通常需要比iOS音頻單元傳送的任何單個緩衝器更長的FFT。

+0

謝謝你,hotpaw2 - 你是對的:我的頻率檢測算法基於自相關而不是FFT。我只使用FFT來對光譜進行可視化處理,從而得到主音和相鄰的泛音。 –