HTML5 ——web audio API 音乐可视化(二)

时间:2022-04-11 12:52:38

上一篇 web audio API 音乐可视化(一)介绍了一些基本的API,以及如何简单的播放一个音频,本篇介绍一下怎么对获取到的音频进行分析,并将分析后的数据绘制成图像。

最终效果请戳这里;

完整版代码请戳这里,如果还看得过眼,请给一个start⭐️

一、API介绍###

分析音频要用到一个音频分析对象AnalyserNode,它能实时分析音频资源的频域和时域信息,但不会对音频流做任何处理。创建方法:

var analyser = ac.createAnalyser();

要用到的属性和方法:

  • fftSize:设置FFT(FFT是离散傅里叶变换的快速算法,用于将一个信号变换到频域)值得大小,用于分析得到的频域,为32-2048之间的2的整数次倍,默认为2048。实时得到的音频频域的数据个数为fftSize的一半;
  • frequencyBinCount:FFT值的一半,即实时得到的音频频域的数据个数;
  • getByteFrequencyData(Uint8Array):复制音频当前的频域数据(数量是frequencyBinCount)到Uint8Array中。

要实时的分析音频数据并绘制成图形,就要用到一个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 并添加到文档中
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分析函数中调用。

最终效果请戳这里;

完整版代码,请戳这里吧;