上一篇 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
分析函数中调用。函数
最终效果请戳这里;
完整版代码,请戳这里吧;