web Audio學習與音頻播放

隨着瀏覽器的越發強大,用瀏覽器自帶的api操作音頻已經不是難事了。我們來使用web audio api簡單地處理下音頻資源。

簡介

在學習web audio api之前,先了解三個概念:

  • 音頻源,也就是音頻輸入,可以是直接從設備輸入的音頻,也可以是遠程獲取的音頻文件。
  • 處理節點,分析器和處理器,比如音調節點,音量節點,聲音處理節點。
  • 輸出源,指音頻渲染設備,一般情況下是用戶設備的揚聲器,即context.destination。

其實,音頻源和輸出源也都可以視爲節點,這三者的關係可以用這張圖表示:

2019-04-08_200826.png

當然,實際使用中,可能會有n個處理節點,都可以使用connect依次關聯起來。

音頻文件播放

假如現在要用web audio api播放本地的一個音樂文件,按照前面的流程,我們來試下。

文件上傳

既然音頻文件來自本地,那麼得支持文件上傳:

<input type="file" id="file" accept="audio/x-wav,audio/mpeg" />

我這兒限制了先顯示wav和mp3兩種格式。

文件讀取

給input增加change事件,處理選中的文件:

var context = new (window.AudioContext || window.webkitAudioContext)();

document.getElementById('file').addEventListener('change', function(e) {
    var read = new FileReader();

    read.onload = function() {
        // 將arrayBuffer轉成audioBuffer
        context.decodeAudioData(this.result, function(buffer) {
            playSound(buffer);
        }, function() {
            console.log('error');
        });
    };
    // 利用filereader將file轉成arraybuffer格式
    read.readAsArrayBuffer(this.files[0]);
});

丟了一段代碼,我們來看下,new AudioContext(),創建audio的上下文環境,至於webkitAudioContext是兼容較低版本的chrome的。

fileReader大夥應該見到的比較多了吧,這兒用他讀取對應file對象中的文件數據,readAsArrayBuffer表示讀取結果用arrayBuffer對象顯示,由於此方法是異步讀取的,所以只能放在onload回調中處理。

而我們拿到的arrayBuffer不能直接給web audio播放,需要使用decodeAudioData()方法將arrayBuffer轉成audioBuffer,那麼此時轉化後的audioBuffer就是音頻源啦。decodeAudioData更多介紹可以查看MDN:https://developer.mozilla.org...

注:w3c文檔上說明decodeAudioData支持audio標籤支持的所有音頻格式。

音頻播放

音頻數據到手,接下來就是播放啦。

文件上傳後,我們拿到了音頻audioBuffer形式的數據,接下來使用createBufferSource()方法播放音頻數據,再connect到destination就可以播放了。

// 播放音頻
function playSound(buffer) {
    var source = context.createBufferSource();

    // 設置數據
    source.buffer = buffer;
    // connect到揚聲器
    source.connect(context.destination);
    source.start();
}

一個簡單的音頻文件播放器就完成了,如果是從服務器上獲取文件也是類似的,只不過是多了個ajax處理。

代碼地址:webAudio播放本地音樂

音頻的話,可以去一些音樂網站下載,如果懶得下的話,我這直接提供音頻下載:林俊杰_-_我還想她.mp3

小bug

當連續選擇多個文件時,你會發現,多個音頻文件一起播放了,因此,多音頻輸入時,都一起connect到context.destination上就可以實現一起播放了。對於此處,這應該算是個bug,查看AudioBufferSourceNode文檔,可以利用stop()方法去處理,大夥自個想下,處理下咯。

前面的例子裏只出現了音頻源和音頻輸出,並未出現處理節點。接下來,我們嘗試自己創建音頻,並使用音量處理節點。

自制音頻並播放

創建音頻源

此處我們不使用外部的音頻文件,而是使用createOscillator()方法創建音頻源。

該方法返回OscillatorNode,可以通過frequency屬性設置他的振盪頻率,type屬性則可以用來指定要播放的波形。更多屬性和方法參考OscillatorNode文檔

var context = new (window.AudioContext || window.webkitAudioContext)();
var oscillator = context.createOscillator();
// oscillator.type = 'sine';
// oscillator.frequency.value = 800;  // 頻率800Hz,默認440

創建音量處理節點

使用createGain()方法,修改返回值中的value,既可以改變音量大小。

var gainNode = context.createGain();
gainNode.gain.value = 0.8; // 音量 0 ~ 1

節點關聯與播放

將這些”節點”connect起來就可以播放了。

oscillator.connect(gainNode); // 音頻源關聯到音量
gainNode.connect(context.destination); // 音量關聯到揚聲器

// chrome 73 需要用戶點擊纔可播放
document.getElementById('start').addEventListener('click', function() {
    oscillator.start();
});

雖然播放後是一片噪音,不過簡單的web audio api我們已經會使用啦。

代碼地址:webAudio製造噪音並播放

其他

自己嘗試過程中,在控制檯下遇到這個警告:

The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.

2019-04-09_191004.png

大概意思就說AudioContext需要用戶手動觸發,所以只需要將new AudioContext()移動到事件內部就行了。

總結

我們已經能夠使用web audio播放本地音樂和製造噪音了,接下來,可以嘗試下其他的api了。

閱讀原文

歡迎關注微信公衆號[ 我不會前端 ]或掃描下方二維碼!

weixin8cm.jpg

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章