摘要:前言本文翻譯自上的利用,這是中的的一個入門教程。原文是英文,但有日本同志翻譯的日文版。這是為了提供一個基本的低音増幅效果在這個例子中可以設定過濾器的種類,周波數,甚至的值。如果是過濾器的話,可以提供一個比指定周波數低的低音増幅。
前言
本文翻譯自MDN上的《Web Audio APIの利用》,這是HTML5中的Web Audio API的一個入門教程。原文是英文,但有日本同志翻譯的日文版。我更熟悉日文,所以主要根據日文版翻譯成簡體中文,也會對照英文版的。
Web Audio API的使用Web Audio API提供給你一個簡單卻強大的機制,你可以利用它去實現與操作web應用內的音頻內容。通過它,在網頁中你也可以進行混音、音效、平移等各種復雜的音頻處理功能的開發。這篇文章主要想通過兩個簡單的例子來說明Web Audio API的基礎使用方法。
Web Audio API并不是替代
Web Audio API的一個強大之處是它沒有嚴格的[發出聲音的數目的限制]。例如,一秒內可以同時發出32個聲音或64個聲音,但這并不是上限。CPU的處理能力足夠的話,1000多種聲音也可以不經過壓縮直接播放。如果這樣發展下去的話,幾年之后的中高端聲卡的負荷會大大降低的吧。
PS:補充點背景知識,這里提到的32,64指的是復音數。復音數指MIDI樂曲在一秒鐘內發出的最大聲音數目。關于復音數和MIDI樂曲可以百度一下。聲卡硬件會限制復音數,部分軟件使用CPU實現聲音播放的也會限制復音數。但理論上只要CPU處理能力夠強復音數是不受限的。所以上段提及Web Audio Api是軟件,但它沒有復音數限制,所以說到只要CPU處理能力夠強,未來或許能夠降低對中高端聲卡性能的需求
例子為了展示Web Audio API的用法,我們編寫了一些例子,這些例子會不斷地增加更新。請大家發揚開源
精神為項目添加用例或者提出更好的改善意見!
PS:這些例子最好在最新版chrome中運行
首先介紹一下 Voice-change-O-matic 。這是一個有變聲及聲音可視化功能的網頁應用,且有一些變聲效果與可視化效果可供選擇。雖然這個應用還有許多可以改善的地方,但也不失為綜合使用Web Audio API的許多功能的一個好例子。(可以在這里運行 Voice-change-O-matic)
PS:上面的這個例子我運行沒效果啊,不知道怎么玩
*PS:感謝vino24補充的,該例子需要https,在chrome下可運行
為了理解Web Audio而編寫的另一個例子就是這個Violent Theremin。這是一個簡單的應用,它允許你通過鼠標指針的移動來改變頻率和音量。另外,鼠標移動過程還有迷幻光彩的視覺效果。(Violent Theremin的源碼在這里)
基本思路備注:下面列舉的大多數的代碼片段都在Violent Theremin中有使用。
Web Audio API的架構設計使得它能夠輕松實現模塊路由,其中包括對上下文中的音頻內容的操作?;镜囊纛l編輯可以使用audio node進行。但這些節點相互可以連接起來,可以構成一個節點圖。多個音源或者不同種類的頻道最終都可以對應到一個上下文中。這樣模塊化的設計是為了提供足夠靈活的特性以便開發可以動態改變效果的復雜的音頻編輯功能。
audio node有入口和出口,多個節點構成類似鏈表一樣的結構。從一個或者多個音源出發,經過一個或者多個處理節點,最終輸出到輸出節點(輸出終端,一般是揚聲器)。(如果有需求的話,也可以不指定輸出節點。例如,想把音頻數據用圖表的形式展現的場合等。)web audio的一個簡單的典型的流程類是下面這樣子:
創建AudioContext對象
在AudioContext對象內設置音源,例如
創建effect node(效果節點)。例如reverb, biquad filter, panner, compressor(這些都是音頻特效)
選擇音頻的最終輸出節點。例如,你的電腦的揚聲器
音頻經過效果節點處理后,然后輸出到下一個節點,這些節點連接起來
創建AudioContext對象首先,為了構建audio節點圖,我們首先要創建創建AudioContext對象。最簡單的方法就像這樣:
var audioCtx = new AudioContext();
備注:雖然可以在一個document中創建多個AudioContext對象,但這恐怕沒什么卵用。
但是,Webkit/Blink內核的瀏覽器不需要前綴,Firefox(desktop/mobile/OS)的瀏覽器可能需要前綴,所以為了兼容性考慮,最好寫成這樣:
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();創建AudioSource
通過創建的AudioContext對象的方法,我們可以進行各種各樣的操作。最初進行的就是,準備要播放的音源。下面列出的東西都可以作為音源:
使用震動發聲器與JavaScript創建音源的情況:使用AudioContext.createOscillator這個方法創建OscillatorNode。之后就可以利用震動發聲器做音源了。
使用原始的PCM數據的情況:如果是可以識別的特定的格式的話(mp3之類的),使用AudioContext的特定的decode方法,來獲得PCM數據。詳細情況可以看這些,AudioContext.createBuffer()、AudioContext.createBufferSource()、AudioContext.decodeAudioData() 。
使用
從WebRTC MediaStream(WebRTC媒體流)輸入音頻源的情況:可以使用麥克風或者Web攝像頭。具體情況看這個,AudioContext.createMediaStreamSource()
簡單地把震動發聲器作為音源,使用gain節點控制音量,這就構成我我們接下來要說的例子:
oscillator = audioCtx.createOscillator(); var gainNode = audioCtx.createGain();
備注:如果要播放音樂文件(mp3之類的),一般要利用XHR載入文件數據,那之后創建BufferSource。在這個示例Voice-change-O-matic有代碼。
備注:Scott Michaud封裝了載入和解碼音頻的代碼,開源了一個庫,叫AudioSampleLoader。使用這個的話,XHR以及buffer的操作都會變得異常簡單。
輸入與輸出的連接要想音源(輸入)通過揚聲器(輸出)播放出來,就必須要把兩者連接起來。將被連接的節點作為參數,調用原來節點的的connect方法就可以建立節點間的連接。大多數類型的節點對象都擁有這個方法。
關于標準的輸出節點可以參考,AudioContext.destination。標準的輸出節點通常是設備的揚聲器。把oscillator連接到gainNode上,gainNode的輸出連接到標準輸出上,代碼如下:
oscillator.connect(gainNode); gainNode.connect(audioCtx.destination);
但如果像Voice-change-O-matic一樣,比較復雜的情況的話。需要像下面一樣將多個節點連接起來,形成一張圖。:
source = audioCtx.createMediaStreamSource(stream); source.connect(analyser); analyser.connect(distortion); distortion.connect(biquadFilter); biquadFilter.connect(convolver); convolver.connect(gainNode); gainNode.connect(audioCtx.destination);
上面的代碼創建出的audio圖如下:
多個節點可以同時連接同一個節點。也可以讓多個音源通過一個效果節點,達到混音的效果。
備注:Firefox 32 以上版本,在Firefox開發工具中Web Audio編輯器了。有了它之后大大提高了對audio節點圖進行debug的效率。
播放與音調的設定創建完audio節點圖后,就可以通過設定audio節點的屬性值或者調用方法來調整節點的效果。下面的例子,我們來設定下震動發聲器的音調,使用Hz這個單位,如下:
oscillator.type = 0; // sine wave,正弦波 oscillator.frequency.value = 2500; // value in hertz oscillator.start();
在Violent Theremin這個程序中,設定了音量與周波數的最大值,如下:
var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var maxFreq = 6000; var maxVol = 1; var initialFreq = 3000; var initialVol = 0.5; // set options for the oscillator oscillator.type = 0; // sine wave oscillator.frequency.value = initialFreq; // value in hertz oscillator.start(); gainNode.gain.value = initialVol;
加下來是隨著鼠標的移動,按照設定改變周波數。鼠標指針的X坐標和Y坐標以及周波數和音量的最大值,這些決定了最終輸出聲音的周波數和音量。代碼如下:
// Mouse pointer coordinates var CurX; var CurY; // Get new mouse pointer coordinates when mouse is moved // then set new gain and putch values document.onmousemove = updatePage; function updatePage(e) { CurX = (window.Event) ? e.pageX : event.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); CurY = (window.Event) ? e.pageY : event.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); oscillator.frequency.value = (CurX/WIDTH) * maxFreq; gainNode.gain.value = (CurY/HEIGHT) * maxVol; canvasDraw(); }利用Canvas實現簡單的可視化效果
canvasDraw()是一個每次鼠標移動都會調用的方法。每次調用這個方法,都會在鼠標指針位置所在的地方,把輸出音頻的周波數和音量用不同大小和不同顏色表現(畫)出來。
function random(number1,number2) { var randomNo = number1 + (Math.floor(Math.random() * (number2 - number1)) + 1); return randomNo; } var canvas = document.querySelector(".canvas"); canvas.width = WIDTH; canvas.height = HEIGHT; var canvasCtx = canvas.getContext("2d"); function canvasDraw() { rX = CurX; rY = CurY; rC = Math.floor((gainNode.gain.value/maxVol)*30); canvasCtx.globalAlpha = 0.2; for(i=1;i<=15;i=i+2) { canvasCtx.beginPath(); canvasCtx.fillStyle = "rgb(" + 100+(i*10) + "," + Math.floor((gainNode.gain.value/maxVol)*255) + "," + Math.floor((oscillator.frequency.value/maxFreq)*255) + ")"; canvasCtx.arc(rX+random(0,50),rY+random(0,50),rC/2+i,(Math.PI/180)*0,(Math.PI/180)*360,false); canvasCtx.fill(); canvasCtx.closePath(); } }靜音
按下靜音按鈕后,會執行下面的函數。通過把Gain節點與前面連接的節點切斷,使得聲音的輸出消失。再按一次按鈕,就會恢復節點之間的連接,使得聲音恢復輸出。
var mute = document.querySelector(".mute"); mute.onclick = function() { if(mute.id == "") { gainNode.disconnect(audioCtx.destination); mute.id = "activated"; mute.innerHTML = "Unmute"; } else { gainNode.connect(audioCtx.destination); mute.id = ""; mute.innerHTML = "Mute"; } }其他的節點
在 Web Audio API中其他還有很多的種類的節點可以使用。創建節點、節點與節點之間連接起來,形成節點圖,之后通過屬性和方法來改變聲音。從這些點來看,所以節點的使用方式都差不多。
下面,我們概要地看一下幾個節點。各個節點的詳細情況可以在Web_Audio_API中看。
Wave shaper 節點通過AudioContext.createWaveShaper這個方法,可以創建WaveShaper節點。
var distortion = audioCtx.createWaveShaper();
要想讓這個對象工作,必須給予與決定波形的函數。通過將這個函數應用于輸入的波形,WaveShaper節點可以扭曲聲音。對新手來說,一開始寫出這個函數是很困難的吧。通過在網絡上搜索,選用合適的方案就好了。下面是一個發布在Stack Overflow上的例子:
function makeDistortionCurve(amount) { var k = typeof amount === "number" ? amount : 50, n_samples = 44100, curve = new Float32Array(n_samples), deg = Math.PI / 180, i = 0, x; for ( ; i < n_samples; ++i ) { x = i * 2 / n_samples - 1; curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) ); } return curve; };
在Voice-Change-O-Metic這個例子中,創建了一個叫做distortion的WaveShaper節點,提供了必要的音頻扭曲效果。代碼如下:
source.connect(analyser); analyser.connect(distortion); distortion.connect(biquadFilter); ... distortion.curve = makeDistortionCurve(400);雙二階過濾器
雙二階過濾器的內部有多個配置項目??梢酝ㄟ^AudioContext.createBiquadFilter這個方法創建。
var biquadFilter = audioCtx.createBiquadFilter();
在Voice-Change-o-Metic這個例子中,使用的是典型的lowshelf 過濾器。這是為了提供一個基本的低音増幅效果:
biquadFilter.type = "lowshelf"; biquadFilter.frequency.value = 1000; biquadFilter.gain.value = 25;
在這個例子中可以設定過濾器的種類,周波數,甚至gain的值。如果是lowshelf過濾器的話,可以提供一個比指定周波數低25dB的低音増幅。
關于其他的Web Audio API的內容使用Web Audio API的話,可以做到音頻的可視化與立體化(例如音頻平移等)。關于這些,我們在其他的文檔中說明。
后記終于完了。
翻譯技術文章遠比想象的要困難,特別是遇到很多陌生的某個領域下的專有詞匯。
日語真是神奇,很多硬是用片假名套英文的情況,呵呵呵,讓我想起了,特律風。
文中不免有錯的地方,希望大家能指出來,幫助文章更好,謝謝。
感謝,@說說說說
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79643.html
摘要:你知道在瀏覽器環境下能夠利用到的提交請求數據的方式有哪些嗎這些方式各自有什么特點呢在什么情況下使用呢讓我們一起來整理一下。其實這也是能夠利用到的提交請求數據的方式之一。 你知道在瀏覽器環境下JavaScript能夠利用到的提交/請求數據的方式有哪些嗎?這些方式各自有什么特點呢?在什么情況下使用呢?讓我們一起來整理一下。 基礎知識 建議大家先看完這幾篇文章,了解一下基礎知識 HTTP訪...
摘要:做一個搬運工,希望自己能努力學習,也希望大神們的東西能讓更多的人看到不斷更新更新日志新增了網絡安全分類,整理了排版布局新增了的鏈接,將一些雜七雜八的東西弄到了一篇新文章上了,叫做積累與雜貨鋪一以及相關教程的規范與相關中文學習大本營中文文檔簡 做一個搬運工,希望自己能努力學習,也希望大神們的東西能讓更多的人看到 不斷更新 更新日志:2017.10.13 新增了網絡安全分類,整理了排版布局...
摘要:做一個搬運工,希望自己能努力學習,也希望大神們的東西能讓更多的人看到不斷更新更新日志新增了網絡安全分類,整理了排版布局新增了的鏈接,將一些雜七雜八的東西弄到了一篇新文章上了,叫做積累與雜貨鋪一以及相關教程的規范與相關中文學習大本營中文文檔簡 做一個搬運工,希望自己能努力學習,也希望大神們的東西能讓更多的人看到 不斷更新 更新日志:2017.10.13 新增了網絡安全分類,整理了排版布局...
閱讀 574·2021-11-18 10:02
閱讀 1057·2021-11-02 14:41
閱讀 684·2021-09-03 10:29
閱讀 1901·2021-08-23 09:42
閱讀 2737·2021-08-12 13:31
閱讀 1207·2019-08-30 15:54
閱讀 1960·2019-08-30 13:09
閱讀 1434·2019-08-30 10:55