在浏览器中,我们通常使用 audio 标签来播放音频:

    1. <audio controls> <source src="myAudio.mp3" type="audio/mpeg"> <source src="myAudio.ogg" type="audio/ogg"></audio>

    虽然 audio 标签使用起来很简单,但也存在一些局限。比如它只控制音频的播放、暂停、音量等。如果我们想进一步控制音频,比如通道合并和拆分、混响、音高和音频幅度压缩等。那么仅仅使用 audio 标签是做不到的。为了解决这个问题,我们需要使用 Web Audio API

    Web Audio API 提供了一个非常高效和通用的系统来控制 Web 上的音频,允许开发人员为音频添加特殊效果、可视化音频、添加空间效果等等。Web Audio API 让用户能够在音频上下文(AudioContext)中进行音频操作,具有模块化路由的特点。基本的音频操作是在音频节点上执行的,这些节点连接在一起形成一个音频路由图。

    接下来,我将演示如何利用 AudioContext 对象来播放音频:

    <br />在以上代码中,我们使用FileReaderAPI 来读取音频文件的数据。然后创建一个AudioContext对象并使用该对象上的decodeAudioData方法解码音频。获取到解码后的数据后,我们会继续创建一个AudioBufferSourceNode对象来存储解码后的音频数据,然后将AudioBufferSourceNode对象与context.destination对象连接起来,最后调用start` 方法播放音频。

    看到这里,是不是觉得使用 AudioContext 播放音频文件很麻烦?实际上它非常强大。下面我将介绍如何使用 AudioContextAnalyserNodeCanvas 来实现音频可视化的功能。

    可视化音频文件主要分为以下 3 个步骤:

    • 获取音频文件数据;
    • 获取音频文件频率数据;
    • 使用 Canvas API 实现数据可视化。

    1、获取音频文件数据

    在以下的代码中,我们使用 FileReader API 来读取音频文件的数据。然后创建一个 AudioContext 对象并使用该对象上的 decodeAudioData 方法解码音频。当然,你也可以从网络上下载音频文件。

    inputFile.onchange = function(event) { const file = event.target.files[0]; const reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onload = evt=>{ const encodedBuffer = evt.currentTarget.result; const context = new AudioContext(); context.decodeAudioData(encodedBuffer, decodedBuffer=>{ const dataSource = context.createBufferSource(); dataSource.buffer = decodedBuffer; analyser = createAnalyser(context, dataSource); bufferLength = analyser.frequencyBinCount; frequencyData = new Uint8Array(bufferLength); dataSource.start(); drawBar(); } ) }

    2、获取音频文件频率数据

    要获取频率数据,我们需要利用 AnalyserNode 接口,该接口提供实时频率和时域分析信息。

    const analyser = audioCtx.createAnalyser(); analyser.fftSize = 512; const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); analyser.getByteFrequencyData(dataArray);

    AnalyserNode 对象上的 getByteFrequencyData() 方法会将当前频率数据复制到传入的 Uint8Array 对象。

    3、使用 Canvas API 实现数据可视化

    获取频率数据后,我们就可以使用 Canvas API 实现数据可视化,比如使用 CanvasRenderingContext2D 接口中的 fillRect 方法,对数据进行可视化。

    function drawBar() {requestAnimationFrame(drawBar); analyser.getByteFrequencyData(frequencyData); canvasContext.clearRect(0, 0, canvasWidth, canvasHeight); let barHeight, barWidth, r, g, b; for (let i = 0, x = 0; i < bufferLength; i++) { barHeight = frequencyData[i]; barWidth = canvasWidth / bufferLength * 2; r = barHeight + 25 * (i / bufferLength); g = 250 * (i / bufferLength); b = 50; canvasContext.fillStyle = "rgb(" + r + "," + g + "," + b + ")"; canvasContext.fillRect(x, canvasHeight - barHeight, barWidth, barHeight); x += barWidth + 2; } }

    分析完上面的处理流程,我们来看一下完整的代码:

    `
    浏览器打开包含上述代码的网页,然后选择一个音频文件后,你就可以看到类似的图形。

    audio - 图1

    事实上,我们有了频率数据之后,我们还可以使用 Canvas API 绘制其他漂亮的图形。

    audio - 图2

    audio - 图3

    以上图形是使用 Github 上的第三方库 vudio.js 生成的。如果你有其它很酷的音频可视化效果,欢迎给我留言哈。

    https://github.com/alex2wong/vudio.js
    https://mp.weixin.qq.com/s/hqQs7rzZZXC_sjtD79cWkA