有節奏的音樂跳動

寫在最前:

 最近在作一些新技術的調研,不巧在掘金上看到有人分享系列關於h5技術的運用,主要包括一些音頻,媒體流,用戶位置,環境光等H5核心設備接口的運用,因此本身準備照着那個目錄動手作一番。這篇就是關於音頻對象AudioContext作的小小DEMO,固然看了下別人的DEMO了,但願各位讀者喜歡~html

 照例,貼下個人博客地址,別忘了去點贊哈~html5

成果展現:

audio

Git地址:

github.com/ry928330/we…git

功能說明:

1.根據你在頁面載入的音樂,以可視化的方式展現音樂的律動; 2.點擊模式切換,以時域波形的方式展現當前音樂的節奏。github

實現細節:

 整個DEMO其實比較簡單,主要就是熟悉一些跟Web Audio相關的API,因此講解的時候我會介紹下本次DEMO用到的一些API的使用方式。還有,本次DEMO的一個難點就是你看到的條形圖上頂部小方塊兒的下落特效,這個我也會作下解釋。頁面中所看到的動畫都是基於canvas繪製,這個我就很少說了。接下來,進入主題。web

建立基於audio的語音環境,代碼以下:canvas

window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
var audioContext = new AudioContext(); 
var analyser = audioContext.createAnalyser(); 
analyser.fftSize = 2048;
var audio = document.getElementById('audio');
var audioSrc = audioContext.createMediaElementSource(audio); 
audioSrc.connect(analyser);
analyser.connect(audioContext.destination);
複製代碼

 代碼就這麼幾行,挨個進行解釋。api

1.window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
2.var audioContext = new AudioContext(); 
複製代碼

 建立語音環境上下文,之後關於語音的一切操做都是在這個環境下進行。其實就跟canvas的getContext操做一個意思。爲了兼容不一樣的瀏覽器,加了不一樣的前綴。數組

3.var analyser = audioContext.createAnalyser();
4.analyser.fftSize = 2048;
複製代碼

 建立一個Analyser節點,能夠經過該節點獲取音頻信號的事件和頻率數據。而後經過語句4能夠設置頻域FFT(快速傅里葉變換)取樣點的多少。它的取值fftSize 屬性的值必須是從32到32768範圍內的2的非零冪,默認值是2048。可是,咱們用不到這麼多的點,因此後來只是選取了部分點的值用於展現音樂節奏。瀏覽器

5.var audioSrc = audioContext.createMediaElementSource(audio);
複製代碼

 建立一個MediaElementAudioSourceNode接口來關聯HTMLMediaElement. 這能夠用來播放和處理來自video或audio 元素的音頻。並且,咱們還能夠經過createMediaStreamSource()接口來獲取計算機麥克風或者其餘來源的音頻流MediaStream信息。bash

6.audioSrc.connect(analyser);
7.analyser.connect(audioContext.destination);
複製代碼

 將analyser節點關聯到目標音頻環境上來,這裏audioContext.destination返回AudioDestinationNode對象,AudioDestinationNode接口表示音頻圖形在特定狀況下的最終輸出地址,一般爲揚聲器。意思就是和音頻設備關聯。

獲取音頻數據,渲染可視化律動界面:

 環境建立結束以後,咱們就該取相關音頻數據,基於canvas渲染可視化律動界面了。代碼以下:

var array = new Uint8Array(analyser.frequencyBinCount); 
analyser.getByteFrequencyData(array);
複製代碼

 analyser.frequencyBinCount該值獲取fftSize值的一半,一般狀況下是等於將要用於可視化的數據數值的數量。而後,經過analyser.getByteFrequencyData(array)函數,將當前頻域數據拷貝進Uint8Array數組中。而後,就是本次的難點,如何渲染頂部降落方塊兒。

var barWidth = 10;
var gap = 2;
var barNum = Math.round(cWidth / (barWidth + gap));  //繪製多少個條形
for (var i = 0; i < barNum; i++) {
    var value = array[i];
    if (topArr.length < barNum) {
        topArr.push(value)
    }
    if (value < topArr[i]) {
        ctx.fillRect(i * (barWidth + gap), cHeight - (topArr[i] -= 1) - topHeight, barWidth, topHeight);
    } else {
        ctx.fillRect(i * (barWidth + gap), cHeight - value - topHeight, barWidth, topHeight);
        topArr[i] = value;
    }
}
複製代碼

 根據canvas的寬度以及條形的寬度和間距咱們計算了將要繪製的條形數量,而後該數量值也就決定了咱們用來選取的音頻數據的多少。對於頂部小方塊兒,咱們建立了一個數組,數組初始化值爲音頻數據,若是新的音頻數據比以前對應的初始化的數據值要大,咱們就直接繪製出頂部的小方塊兒,而後根據新的音頻數據更新初始化的數據值。反之,若是新來的音頻數據比初始化的數據要小,這時候,經過初始值的逐漸減一效果,達到小方塊兒不斷降落的特效。最後,對於條形的渲染以下:

var grd = ctx.createLinearGradient(i * barWidth, cHeight - value, i * barWidth, cHeight);
grd.addColorStop(0, "yellow");
grd.addColorStop(0.3, "rgb(255,0,0)");
grd.addColorStop(0.5, "rgb(200,0,0)");
grd.addColorStop(0.7, "rgb(150,20,20)");
grd.addColorStop(1, "rgb(100,0,0)");
ctx.fillStyle = grd;
ctx.fillRect(i * (barWidth + gap), cHeight - value, barWidth, topArr[i]);
ctx.fill();
複製代碼

 這裏,咱們給條形的顏色加了一個線性的漸變,讓其看上去稍微那麼好看些哈~(好像並無好看多少...)

波形模式的切換:

 有了前面音頻數據的條形渲染,這個就顯得更簡單了,就是數據源取值的不一樣而已,經過如下代碼將時域數據拷貝進array數組裏面,剩下的繪製就是經過canvas的moveTo以及lineTo的API了,我就不作詳細的介紹了。

analyser.getByteTimeDomainData(array);
複製代碼

參考資料:

1.http://www.codes5…

2.張鑫旭的利用HTML5Web Audio API給網頁JS交互增長聲音

3.MDN Web Audio 接口

相關文章
相關標籤/搜索