手把手教你用Js实现音频可视化

HTML5中提供了Web Audio API,开发者可以通过这个API为音频添加特效,实现音频可视化效果。下面我们就来一步步实现一个音频可视化webapp,文中描述如有错误或不足,欢迎斧正。
项目github地址,欢迎star,哈哈~

创建AudioContext

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

AudioContext接口表示有音频模块链接而成的音频处理图,每个模块对应一个AudioNode。AudioContext可以控制它所包含的节点的创建,以及音频处理、解码操作的执行。做任何事情之前都要先创建AudioContext对象,因为一切都发生在这个环境之中。

创建AudioBufferSourceNode

var AudioBufferSourceNode = audioCtx.createBufferSource();

AudioBufferSourceNode接口可以通过AudioBuffer对象来播放音频数据。下面我们需要获得音频数据,转换成AudioBuffer对象,赋值到AudioBufferSourceNode的buffer属性。

获取音频数据

这边所获得的音频数据最终是要转换成AudioBuffer对象,供AudioBufferSourceNode使用。AudioBuffer对象可以通过AudioContext.createBuffer来创建或者通过AudioContext.decodeAudioData解码音轨后返回。这边,我们decodeAudioData()方法解码来获得。decodeAudioData()方法可用于异步解码音频文件中的ArrayBuffer。ArrayBuffer数据可以通过XMLHttpRequest或者FileReader来获取。

FileReader获取本地音频ArrayBuffer

页面中添加input标签来获取本地音频


FileReader获取ArrayBuffer类型音频数据

document.getElementById('loadfile').onchange = function(){
    var file = this.files[0];
    var fr = new FileReader();

    fr.onload = function(e){
        audioCtx.decodeAudioData(e.target.result,function(buffer){
            playFun(buffer);  // 解码后返回的AudioBuffer对象作为播放函数的参数传入
        },function(err){
            console.log(err);
        })
    }
    fr.readAsArrayBuffer(file);
}
Ajax获取音频数据

这边把ajax获取音频数据封装到一个函数中

function getData() {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer'; // 设置数据类型为arraybuffer
  request.onload = function() {
    var audioData = request.response;
    audioCtx.decodeAudioData(audioData, function(buffer) {
        playFun(buffer); 
      },
      function(e){"Error with decoding audio data" + e.err});
  }
  request.send();
}

播放音频数据

现在我们已经获得音频数据并将其转换成AudioBuffer对象,下面就是音频数据的播放

function playFun(buffer){
  AudioBufferSourceNode.buffer = buffer; // AudioBuffer数据赋值给buffer属性
  //AudioBufferSourceNode.connect(audioCtx.destination); // 如果只是播放音频,这边就直接将AudioBufferSourceNode连接到AudioDestinationNode
  AudioBufferSourceNode.connect(AnalyserNode);  // 实现播放后,需要将bufferSourceNode连接到AnalyserNode,才能通过AnalyserNode获取后面可视化所需的数据
  AudioBufferSourceNode.loop = true;  // 循环播放,默认为false
  AudioBufferSourceNode.start(0); // 开始播放音频
}

音频数据可视化

创建AnalyserNode
var AnalyserNode = audioCtx.createAnalyser();

AnalyserNode节点可以提供实时的频率及时间域分析的信息。

获取音频频域数据
var arr = new Uint8Array(AnalyserNode.frequencyBinCount);//用于存放音频数据的数组,其长度是fftsize的一半
requestAnimationFrame = window.requestAnimationFrame ||
            window.webkitrequestAnimationFrame ||
            window.mozrequestAnimationFrame;//兼容
function fn(){
  AnalyserNode.getByteFrequencyData(arr);// 将音频频域数据复制到传入的Uint8Array数组
  draw(arr); // 频域数据作为参数传入绘制函数draw
  requestAnimationFrame(fn);
}
requestAnimationFrame(fn);

AnalyserNode.getByteTimeDomainData()方法用于获取音频时域数据,AnalyserNode.getByteFrequencyData()方法用于获取音频频域数据。当获取频域数据时,我们需要通过设置AnalyserNode.fftSize来控制频域数据转换长度;fftSize越大,其频域转换计算时间越长,其默认值为2048。同时,AnalyserNode.frequenceBinCount属性值与fftSize相关,其为fftSize值的一半,其决定音频可视化时有多少数值点。

音频音量控制

创建GainNode
GainNode = Musicvisualizer.ac[audioCtx.createGain?"createGain":"createGainNode"]();
AnalyserNode.connect(GainNode);  // AnalyserNode连接到GainNode
GainNode.connect(audioCtx.destination);  // GainNode连接到AudioDestinationNode

GainNode 接口表示音量变更,我们一般把这个节点放到倒数第二个进行连接,最后再将GainNode连接到AudioDestinationNode
至此,依赖Web Audio API实现音频可视化的整个过程就完成了。下面这幅图展示了整个流程。

手把手教你用Js实现音频可视化_第1张图片
Web Audio API音频可视化示例流程图

效果展示

最后,通过绘制,我们实现的效果图如下。数据实现了柱状和点状的可视化效果(项目github地址)。

MusicVisualizer.gif

参考

Web Audio API
Web Audio API的运用
基于Web Audio API实现音频可视化效果

你可能感兴趣的:(手把手教你用Js实现音频可视化)