2013-04-02 48 views
2

我目前使用libsndfilePortAudio V19組合來從文件中讀取音頻數據並播放。 (請注意,我在運行Raspbian的Raspberry Pi上執行此操作。)我遇到的問題是,我需要實時動態控制以這種方式播放的每個音頻樣本的播放音量。我試圖使用系統調用通過alsamixer來操作全局播放音量,這在我的用例中是一個可接受的解決方案,但延遲太高而無法使用。實時控制音量

我正在尋求的是兩件事情之一:

  • 能,或通過設置修改處理實時音頻音量,無論是通過作用於由libsndfile檢索到的原始音頻數據的庫全球播放音量和最小延遲(亞毫秒)。圖書館必須是免費的(免費),並且可以在Raspbian上使用;許可證不是一個問題。

  • 需要應用於libsndfile檢索的音頻數據的數學變換,以便修改數據的音量級別,最好是目標音量在[0.0f,1.0f]範圍內的音量0.0f是無聲的,1.0f是來自文件的原始音量。

我試圖在這個問題上尋找有用的(免費)材料,並且找不到任何有用的東西。任何援助非常感謝!

回答

3

您可以通過對每個樣本應用乘數來操縱PCM音頻流的幅度。您可以在將每個緩衝區(樣本集)傳遞給PortAudio之前完成此操作。它很簡單:

float buffer[SAMPLES_PER_BUFFER]; 
const float volumeMultiplier = 0.2f; 
for(int i = 0; i < SAMPLES_PER_BUFFER; ++i) 
{ 
    buffer[i] *= volumeMultiplier; 
} 

但是,訣竅在於如何計算您的乘數。一般情況下,您不會注意到信號電平發生很大變化,直到您將整體信號電平減半爲volumeMultiplier = 0.5f。正如你可能知道人耳不會線性地感知音量水平的變化,而是以對數方式。下面的鏈接可能有助於解釋這一概念:

使用該信息的一個可能會改變上面的代碼是這樣的:

float buffer[SAMPLES_PER_BUFFER]; 
//volume in dB 0db = unity gain, no attenuation, full amplitude signal 
//   -20db = 10x attenuation, significantly more quiet 
float volumeLevelDb = -6.f; //cut amplitude in half; same as 0.5 above 
const float VOLUME_REFERENCE = 1.f; 
const float volumeMultiplier = (VOLUME_REFERENCE * pow(10, (volumeLevelDb/20.f); 
for(int i = 0; i < SAMPLES_PER_BUFFER; ++i) 
{ 
    buffer[i] *= volumeMultiplier; 
} 

對於你的目的可能並不重要,但如果是你需要將volumeLevelDb或volumeMultiplier的值附加到像滑塊小部件這樣的用戶界面上,這種差異將會很明顯。

您可以將此算法應用於任何數據類型。