2013-03-22 113 views
2

所以我試圖建立一個android應用程序,它作爲一個實時音頻分析器,作爲一個項目的先驅,將涉及檢測和過濾出某些聲音。如何從android上的實時FFT獲得最準確的音頻數據?

所以我認爲我已經掌握了離散傅立葉變換的基礎知識,但是我不確定實時頻率分析的最佳參數應該是什麼。

我得到的印象是,在理想情況下(無限計算能力),我會從44100樣本/秒PCM流中取得AudioRecord類中的所有樣本,並將它們通過44100元素fifo窗口「(用0填充2 ** 16,也許是漸變函數?),每次新樣本進入時在窗口上運行FFT。這會(我認爲)給我0 - 22KHz頻譜更新每秒44100次。

看來這不會發生在智能手機上。事情是,我不確定我應該減少哪些計算參數,以便讓我的Galaxy Nexus易於處理,同時仍然保持儘可能多的質量。最終我想要使用靈敏度更好的外置麥克風。

我認爲這將涉及到移動窗口不止一個採樣FFT之間的樣本,但我不知道在什麼時候,這會變得更加不利於精度/別名/不管只是在較小的窗口上做FFT,或者如果我忽略了第三種選擇。

由於我使用libgdx本地實現的KissFFT,我似乎能夠在44100個採樣點之間進行30-42個44100個元素FFT的處理,並且仍然具有響應性(意味着緩衝區從線程AudioRecord.read()的填充速度比fft的線程耗盡速度要快)。

所以我的問題是:

  1. 可能目前我得到的只是表現是最好的,我會得到什麼?還是看起來像我一定是愚蠢的,因爲更快的速度是可能的?
  2. 我的方法至少是基本正確的,還是我在完全錯誤的樹上吠叫?

我很樂意展示我的任何代碼,如果這可以幫助回答我的問題,但有很多,所以我想我會選擇性地做,而不是發佈這一切。

+0

您還應該每次使用窗口函數過濾矩形窗口,例如hanning或hamming窗口以獲得更好的準確性。當然這也會減慢執行速度 – SztupY 2013-03-22 23:09:27

+0

你的頻率分辨率要求是什麼?你實際上是否能夠一次顯示你從64k FFT中獲得的32k輸出樣本?我問,因爲考慮到緩存因素,FFT會變得效率低下,並且通常在現代x86 CPU上這一點大約爲32k-64k,所以對於手機或平板電腦來說,這可能要低得多。因此,降低FFT大小,同時降低頻率分辨率,可能確實會增加吞吐量。 – 2013-03-23 02:02:17

+0

「最準確」是沒有意義的。您需要定義您的實際精度需求,並進行時間頻率平衡。音頻處理通常在比1000mS短得多的塊上完成,可能只有25%到50%的重疊。 – hotpaw2 2013-03-24 00:35:39

回答

2

如果我俯瞰

第三個選擇是:在同一時間做兩,FFT的大小的減少以及更大的步長。您在評論中指出,您想要檢測「用嘴嗅吸/咀嚼」。所以,你想要做的是類似於語音識別的典型任務。在那裏,你通常以10ms的步長提取一個特徵向量(意思是每441個採樣Fs = 44.1kHz),並且要變換的信號窗口大約是步長大小的兩倍,因此20ms可以產生2^X FFT大小爲1024個採樣點(確保您選擇的FFT大小是2的冪,因爲它更快)。

任何窗口大小的增加或步長的減小都會增加數據,但主要會增加冗餘。

附加提示:

  • @SztupY正確地指出,你需要「窗口」你的信號的FFT之前,通常與漢時wondow。 (但這不是「過濾」,只是將每個樣本值與相應的窗口值相乘而不累積結果)。

  • 原始FFT輸出很難識別「嗅探/嘴巴咀嚼」,經典識別器由HMM或人工神經網絡組成,它們處理MFCC及其三角洲的序列。

可能目前我得到的只是表現是最好的,我會得到什麼?還是看起來像我一定是愚蠢的,因爲更快的速度是可能的?

它接近最好,但是您正在浪費所有的CPU功率來估計高度冗餘的數據,而不會爲識別器留下CPU電源。

我的方法是至少從根本上糾正或者我完全錯誤地吠叫樹?

考慮我的答案後,你可能會重新考慮你的方法。