2012-10-05 49 views
12

我試圖圍繞使用網絡音頻API重新創建類似
Winamp的10頻段均衡器。使用網絡音頻API創建10頻段均衡器

Winamp's 10-band equalizer

據我所知,我要創建10 Biquad Filters,設置其type2 (for a Bandpass filter)分別設置其frequency[60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000]。一旦我完成了這一步(這裏我有點困惑),然後我會爲每個頻段「band」創建一個單獨的Gain Node,並將其值綁定到一個滑塊。

<input id="someFreqBand" type="range" min="-12" max="12" step="0.1" value="0" onchange="slide()"/> 

假設所有的這是正確的,那麼剩下的唯一步驟是將所有10個增益節點連接到所述音頻上下文destination(我想象將採取所有10個頻率「帶」和混合/將其同步到一起)。這是創建Web Audio 10頻段均衡器的正確方法嗎?

我很困惑的主要問題是如何將信號源「連接」到10個頻帶濾波器(+相關增益節點),因爲所有節點只有一個輸入或輸出(包括目的地) 。

回答

7

正如馬特D所說,連接過濾器到同一目的地應該沒有問題。

但是我會說你可能想要使用類型5(峯化)的濾波器,它可以讓所有的頻率通過並且只在你設定的濾波器頻率上進行放大/減少。filter.frequency.value。這可以讓你串聯連接濾波器,所以你不需要10個獨立的音頻路徑。您也可以考慮使用低架濾波器作爲第一個濾波器,並使用高架濾波器作爲第十個濾波器,這在均衡器中很常見。不過,我不記得那是不是winamp的做法。最後,如果你使用串聯的峯化濾波器,每個頻率都不需要單獨的增益節點,只需爲特定濾波器設置filter.gain.value即可。

+0

除非我錯了,否則所有圖形均衡器都使用帶通濾波器。請參閱第4頁:https://rs6.eporia.com/company_38/techpaper106.pdf 低架/高架/峯值濾波器允許您直接在濾波器節點上調整增益,但不是帶通濾波器... – idbehold

+0

我不確定是否所有的圖形均衡器都使用帶通濾波器,但我相信在系列中使用峯化濾波器是獲得您所追求行爲的更簡單方法。正如Jagi所提到的那樣, –

+0

過濾器應串聯連接。 –

2

我很困惑的主要問題是如何將信號源「連接」到10個頻帶濾波器(+相關增益節點),因爲所有節點只有一個輸入或輸出(包括目的地)。

這是事實,但不要把它想象成只能連接到另一個物理輸入的物理輸出。 Web Audio節點的單個輸出可以連接到多個節點,並且節點也可以接收多個輸入。例如,假設您想通過5個過濾器並行連接一個輸入節點,然後將它們連接在一起。你可以做這樣的事情:

source.connect(filter1); 
source.connect(filter2); 
source.connect(filter3); 
source.connect(filter4); 
source.connect(filter5); 

filter1.connect(context.destination); 
filter2.connect(context.destination); 
filter3.connect(context.destination); 
filter4.connect(context.destination); 
filter5.connect(context.destination); 

這裏的關鍵見解是,調用.connect多次將輸出不能切換到不同的節點,而只是添加額外的輸出連接。換句話說,這是一個「扇出/扇入」系統。

+0

當規範說:'numberOfInputs:1. numberOfOutputs:1.'時,它看起來很糟糕的文檔。當'1'它們的意思是'many'。 – idbehold

+1

我承認它可能會更清楚,但該文檔仍然正確。一個輸出可以連接到多個輸入。想想它更像輸出*端口*的數量而不是輸出。 –

10

通過連接每個過濾器與目的地,你正在創建5個路徑(路線),所以你會聽到源聲音quintupling放大。這不是正確的方法。您必須將每個過濾器連接在一條線上。

source.connect(filter1); 
filter1.connect(filter2); 
filter2.connect(filter3); 
filter3.connect(filter4); 
filter4.connect(filter5); 
filter5.connect(context.destination);