上一篇 web audio API 音樂可視化(一)介紹了一些基本的API,以及如何簡單的播放一個音頻,本篇介紹一下怎麼對獲取到的音頻進行分析,並將分析後的數據繪製成圖像。javascript
最終效果請戳這裏;html
完整版代碼請戳這裏,若是還看得過眼,請給一個start⭐java
分析音頻要用到一個音頻分析對象AnalyserNode
,它能實時分析音頻資源的頻域和時域信息,但不會對音頻流作任何處理。建立方法:git
var analyser = ac.createAnalyser()
;github
要用到的屬性和方法:web
要實時的分析音頻數據並繪製成圖形,就要用到一個
requestAnimationFrame
動畫函數,實時得去分析數據進行圖像渲染,此動畫函數默認的是每秒調用60次。算法
var size = 128; var xhr = new XMLHttpRequest(); var ac = new window.AudioContext(); var analyser = ac.createAnalyser(); var gainNode = ac[ac.createGain ? "createGain" :"createGainNode"](); gainNode.connect(ac.destination); analyser.fftSize = size * 2; analyser.connect(gainNode); function getMusic(name){ xhr.abort(); xhr.open("get","media/"+name); xhr.responseType = "arraybuffer"; xhr.onload = function(){ ac.decodeAudioData(xhr.response,function(buffer){ var bufferSource = ac.createBufferSource(); bufferSource.buffer = buffer; bufferSource.connect(analyser); bufferSource[bufferSource.start ? "start" : "noteOn"](0); },function(err){ console.log(err) }) }; xhr.send(); } //實時分析音頻函數 function analysis(){ var arr = new Uint8Array(analyser.frequencyBinCount); requestAnimationFrame = window.requestAnimationFrame; function a(){ analyser.getByteFrequencyData(arr); draw(arr); //調用繪圖函數 console.log(arr); //在控制檯能夠看到輸出的音頻數據 requestAnimationFrame(a); } requestAnimationFrame(a); } analysis();
接下來就是畫圖函數了。canvas
對於canvas不熟悉的童鞋,請參照canvas基礎知識api
//建立canvas 並添加到文檔中 var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); $(".content").html(canvas); //.content是須要展現圖形的位置 var height = $(".content").height(); var width = $(".content").width(); canvas.width = width; canvas.height = height; function resize(){ //若是窗口的大小改變了,繪圖跟着改變 canvas.height = height; //設置繪圖相關的參數和屬性 canvas.width = width; var line = ctx.createLinearGradient(0,0,0,height); line.addColorStop(0,"#CD96CD"); line.addColorStop(0.5,"#C6E2FF"); line.addColorStop(1,"#00BFFF"); ctx.fillStyle = line; } resize(); function draw(arr){ //參數arr就是上面分析函數裏獲得的arr ctx.clearRect(0,0,width,height); //每次畫圖以前先清空畫布 var w = width / size; //平均每一個柱的寬度 size 要畫的柱子的個數 for(var i=0;i<size;i++){ //柱子的個數 var h = arr[i] / 256 * height; //每一個柱的高度 ctx.fillRect(w*i,height - h,w *0.6, h); //w*i 表示第i個柱子的起始點的x座標,height - h表示第i個柱子的起始點的y座標,w*0.6表示柱子的寬度,h是高度 } }
draw
函數在 analysis
分析函數中調用。函數
最終效果請戳這裏;
完整版代碼,請戳這裏吧;