2015-02-08 104 views
1

我最近選擇了一個項目,我需要對傳入的麥克風數據執行實時滑動FFT分析。我選擇的環境是OpenGL和Cinder,並使用C++。STFT /滑動FFT實時數據

這是我第一次在音頻編程方面的經驗,我有點困惑。

這就是我想在我OpenGL應用程序來實現:

enter image description here

因此,在每一幀,有輸入數據的一部分。在for循環(因此多次通過)中,將消耗當前數據的窗口並對其執行FFT分析。對於for循環的下一次迭代,窗口將通過數據等提前「跳躍大小」,直到達到數據的末尾。

現在這個過程必須是連續的。但是,正如你在上圖中看到的那樣,只要我當前的應用程序框架結束並且下一幀的數據進入時,我就無法選擇離開前一幀的位置(因爲數據已經消失)。你可以在圖中看到藍色區域在兩幀之間。

現在你可以說,選擇window-size/hop-size的方式永遠不會發生,但這是不可能的,因爲這些參數應該在我的項目中留給用戶配置。

對於面向C++ 11的這種處理的建議也非常受歡迎!

謝謝!

+0

我不明白這個字眼:*「只要N個樣本的數量完成,當前緩衝區的處理完成,下一個輸入緩衝區的第一窗塊將不相關的差距與上次窗口塊到k來自上一個緩衝區的數據「* - 也許您可以爲我們繪製該部分的一些ASCII圖表? – 2015-02-09 05:17:38

+0

@JohnZwinck我收錄了一張圖片,希望能夠展示我想要達到的目標。謝謝! – Sepehr 2015-02-09 19:39:21

回答

1

不知道我理解你的方案100%,但聽起來像你可能想要使用循環緩衝區。沒有「標準」循環緩衝區,但是there's one in Boost

但是,如果您計劃使用2個線程進行處理,則需要鎖定。例如,一個線程將等待音頻輸入,然後取出緩衝區鎖定,並從音頻緩衝區複製到循環緩衝區。第二個線程將週期性地取緩衝區鎖並讀取下一個k元素,如果緩衝區中至少有k可用...

您需要適當調整緩衝區的大小,並確保始終處理數據比輸入速率更快,以避免循環緩衝區中的損失...

不確定爲什麼你提到緩衝區是無鎖的,是否是一個要求,我會嘗試帶鎖的循環緩衝區首先,從概念上來看似乎更簡單,並且只有在必要時才能實現無鎖定,因爲在這種情況下數據結構可能更復雜(但也許是「生產者 - 消費者」無鎖隊列將起作用)...

HTH。

+0

在libcinder中有一個[RingBuffer類](https://github.com/cinder/Cinder/blob/master/include/cinder/audio/dsp/RingBuffer.h)用於這個目的(迎合音頻處理)。 – 2015-12-11 04:34:17

1

感謝您發佈圖形 - 這很好地說明了問題。

您真正需要的是一個大小爲(window - 1)的緩衝區,您可以從「上一個」幀中存儲零個或多個樣本,以便在「下一個」幀中進行處理。在C++中,這將是:

std::vector<Sample> interframeBuffer; 
interframeBuffer.reserve(windowSize - 1); 

然後,當您是從當前幀的端部內windowSize樣本,而不是處理將它們存儲與interframeBuffer.push_back(sample)樣本。當你開始處理下一幀,你首先要做:

for (const Sample& sample : interframeBuffer) { 
    process(sample); 
} 
interframeBuffer.clear(); 

你應該使用單一載體的全部時間,將其清除和重新建它根據需要,以避免內存分配。這就是爲什麼我們在頂部叫reserve() - 爲了避免延遲。調用clear()不釋放內存,它只是將size()重置爲零。