本系列文章主要是介紹 Web Audio API 的相關知識,以及 web語音通信 中會遇到的一些問題,闡述可能存在錯誤,還請多多斧正!
通過設備獲取音頻流會不可避免的滲入一些雜音,這些雜音可能來自你周邊的環境,也有可能來自錄音設備本身,一些低頻的聲音還好,人耳難以分辨出來,但是那些高頻的白噪聲對音質的影響是特別大的,如我們聽收音機沒有調到正確的頻率上,會聽到吱吱茲茲的刺耳的雜音。這些雜音不僅增大了音頻流信號本身的體積,而且我們的耳朵也不喜歡,所以在傳輸之前必須對音頻做相應的濾波處理。
本文地址:http://www.cnblogs.com/hustskyking/p/webAudio-filter.html,轉載請注明源地址。
P.S:請在較新版的 chrome 火狐 Firefox 中測試。
一、濾波節點
1. 接口介紹
頻率,是單位時間內完成振動的次數,是描述振動物體往復運動頻繁程度的量。一段音頻流中包含了各種頻率,溫和的音樂頻率在一個范圍之內,超過這個范圍的聲音一般就是噪聲,人和人之間的語音交流,聲音也是在一定的頻段之中。
在 AudioContext 中用於濾波的節點叫做 BiquadFilterNode,Biquad 是雙二階的意思,這里涉及到了很多通信中專業詞匯,我們暫時可以不用在意。BiquadFilterType 包含了各種濾波類型:
enum BiquadFilterType { "lowpass", "highpass", "bandpass", "lowshelf", "highshelf", "peaking", "notch", "allpass" };
用的比較多的就是 lowpass(低通濾波),highpass(高通濾波),bandpass(帶通濾波)。低通濾波就是過濾某個臨界點的高頻信號,只讓低頻信號通過,高通濾波反之。帶通濾波就是允許某個頻段的信號通過。這個節點的參數比較多:
attribute BiquadFilterType type; readonly attribute AudioParam frequency; // in Hertz readonly attribute AudioParam detune; // in Cents readonly attribute AudioParam Q; // Quality factor readonly attribute AudioParam gain; // in Decibels void getFrequencyResponse(Float32Array frequencyHz, Float32Array magResponse, Float32Array phaseResponse); };
其中幾個參數的取值范圍是:
Q 默認是 1, 取值從 0.0001 到 1000.
gain 默認是 0, 取值從 -40 到 40.
2. 初始化接口
我們可以在初始化的時候將 BiquadFilterType 送進去:
// 初始化為低通濾波 var filter = context.createBiquadFilter("lowpass");
當然,我們也可以通過設置他的 AudioParam 來控制參數:
var filter = context.createBiquadFilter(); // 設置為低通濾波 filter.type = filter.LOWPASS; // 只允許頻率小於 800Hz 的音頻信號通過 filter.frequency.value = 800;
兩只方式都是一樣的,都好控制。
3. DEMO 測試
簡單點的話,中間只用一個 filter 節點就可以了,使用低通濾波,將頻率設置為 800Hz,可以聽到聲音很悶,聲音不是變小了,而是變悶了~節點之間的連接方式是:
Source -> Filter -> Destination
代碼:
var AudioContext = AudioContext || webkitAudioContext; var context = new AudioContext; //創建節點 var audio = new Audio("http://qianduannotes.duapp.com/file/SuperMario.mp3"); audio.loop = true; var media = context.createMediaElementSource(audio); var filter = context.createBiquadFilter(); filter.type=filter.LOWPASS; filter.frequency.value=800; //連接:media → filter → destination media.connect(filter); filter.connect(context.destination);
audio.play();
為了方面查看改變頻率之后波形的變化,我做了一些處理:
Source -> Filter -> Analyser -> Destination
|
+-----> 波形繪制到 Canvas

<canvas id="canvas" width="400" height="300"></canvas><br /> <input type="range" min="0" max="100" id="volume" /> <input type="button" onclick="audio.play()" value="播放" /> <input type="button" onclick="audio.pause()" value="暫停" /> <script type="text/javascript"> var AudioContext=AudioContext||webkitAudioContext; var context=new AudioContext; //創建節點 var audio = new Audio("http://qianduannotes.duapp.com/file/SuperMario.mp3"); audio.loop = true; var media=context.createMediaElementSource(audio); var filter=context.createBiquadFilter(); var analyser=context.createAnalyser(); //只允許小於800的頻率通過 filter.type=filter.LOWPASS; filter.frequency.value=800; //Canvas初始化 var width=canvas.width,height=canvas.height; var g=canvas.getContext("2d"); g.translate(0.5,height/2+0.5); //連接:media → filter → analyser → destination media.connect(filter); filter.connect(analyser); analyser.connect(context.destination); //以fftSize為長度創建一個字節數組作為數據緩沖區 var output=new Uint8Array(analyser.fftSize); //播放幀 (function callee(e){ analyser.getByteTimeDomainData(output); //將緩沖區的數據繪制到Canvas上 g.clearRect(-0.5,-height/2-0.5,width,height); g.beginPath(); for(var i=0;i<width;i++) g.lineTo(i,height*(output[output.length*i/width|0]/256-0.5)); g.stroke(); //請求下一幀 requestAnimationFrame(callee); })(); //播放 audio.play(); load = volume.onchange = function(){ filter.frequency.value = volume.value * volume.value; } </script>
這里頻率的變化是:
filter.frequency.value = volume.value * volume.value;
線性變化可能不太明顯,所以改成了平方變化。
二、小結
濾波在通信中一個重要的意義是減少數據傳輸量,節約頻帶,提高傳送效率,在硬件設備還未跟上語音通信的 web環境中,這個操作是十分有意義的!
本節重點是介紹 BiquadFilterNode 在 AudioContext 環境中的使用,比較簡單。
三、參考資料
- http://www.w3.org/TR/webaudio/ W3C Group
- http://www.web-tinker.com/ 次碳酸鈷