介绍 Web Audio 一个强大的音频处理系统
Web Audio 是一套在 Web 上处理音频的 API
使用这套 API 可以实现很多功能
比如:音乐可视化、音色合成器、动态混音、声音特效、
3D空间音频、均衡器、环境混响等
可以应用在音乐播放器、电子音乐软件、游戏音效、音乐游戏、直播互动等领域
AudioContext 为音频处理提供一个上下文环境
他也是一个中央控制器
控制着音频路由图中的各个音频模块
处理音频都需要创建一个 AudioContext 实例,可全局共享
音频节点需要包含在 AudioContext 中
每个音频节点只能关联一个 AudioContext
音频节点是音频路由图中的基本单位
音频节点通过它们的输入输出相互连接
形成一个链或者一个简单的网
音频节点可以分为三类:
Source Node:能产生音频的节点,只有输出,没有输入
Process Node:对音频进行处理的节点,有输入和输出
Destination Node:通常为音频播放设备,如扬声器
许多音频节点相互连接,构建了一个路由图,就是所谓的音频路由图
一个简单的音频播放示例:
const ac = new AudioContext()
const $audio = document.querySelector('#audio');
const sourceNode = ac.createMediaElementSource($audio); // 从 audio 标签创建一个音频源节点
const gainNode = ac.createGain(); // 创建一个增益节点
gainNode.gain.value = 0; // 将增益设置为 0(相当于音量设置为 0)
$audio.addEventListener('play', () => {
gainNode.gain.exponentialRampToValueAtTime(1, 1); // 在 1 秒的时间内指数增长到 1,实现一个播放渐入效果
});
sourceNode.connect(gainNode); // 音频源节点连接到增益节点
gainNode.connect(ac.destination); // 增益节点连接到 destination 进行播放
Web 中的音频源包括:
网络加载的音频文件,需要将其转换成音频源节点,才能连接到路由图中
比如我们经常使用的 <audio> 标签,它是不能直接连接到其它音频节点的
需要这样:
const ac = new AudioContext();
const $audio = document.querySelector('#audio');
// 从 <audio> 创建一个音频源节点
const sourceNode = ac.createMediaElementSource($audio);
sourceNode.connect(/* 其它音频节点 */);
使用 HTTP 请求,将二进制的音频数据下载到本地后
再创建一个音频源节点,例如这样:
const ac = new AudioContext();
const source = ac.createBufferSource();
source.connect(ac.destination);
fetch('xxx.mp3')
.then(res => res.arrayBuffer())
.then(async buffer => {
// 将解码后的数据(AudioBuffer)加载到了 source.buffer 属性中
source.buffer = await ac.decodeAudioData(buffer);
source.start();
});
除了从网络/本地加载音频文件外,
我们还可以自己创建一个 buffer 丢给 source.buffer 来制造一些声音
比如下面的这个示例,使用随机函数生成一个白噪声音频:
OscillatorNode 是一个振荡器节点,它可以产生一个周期信号
他有四种基本类型:
例子:
const ac = new AudioContext();
const oscillator = ac.createOscillator();
// type 可能的值为 square, sine, sawtooth, triangle 默认为 sine
oscillator.type = 'square';
oscillator.frequency.value = 440; // 不能直接给 frequency 赋值,可以设置其 value
oscillator.connect(ac.destination);
oscillator.start();
演示:
使用音频流来创建一个音频源节点
常见的音频流由麦克风、WebRTC 产生
介绍几个常用的音频分析处理相关的 API:
AnalyserNode 对音频信号进行实时的快速傅立叶变换(FFT)
得到音频的时域/频域数据,用于实现时域分析、频域分析、音频可视化等
用法与示例:
const ac = new AudioContext();
// 创建一个 AnalyserNode
const analyser = ac.createAnalyser();
// fftSize 指定要进行 FFT 的采样数据的窗口大小,它的值必须是 2 的非零整数倍
analyser.fftSize = 2048;
// analyser.frequencyBinCount 是时域/频域数据的长度,它是 fftSize 的一半
// 因为实时音频信号的傅立叶变换具有对称性,只需要获取一半数据即可
const dataArray = new Uint8Array(analyser.frequencyBinCount);
// analyser.getByteTimeDomainData(dataArray) 方法将数据填充到 8 位无符号整型数组中
analyser.getByteTimeDomainData(dataArray);
绘制一首音乐的波形:
简单的音乐播放动效:
BiquadFilterNode 是一个双二阶数字滤波器
滤波器的作用是对特定频率的输入信号进行增强/减弱
通常用来控制音调、做均衡器
用法与示例:
const ac = new AudioContext();
// 创建一个双二阶滤波器
const filter = ac.createBiquadFilter();
// 他有 4 个关键的参数:type, frequency, Q, gain
filter.type = 'peaking'; // 设置类型为峰值滤波器
filter.Q.value = 1; // 峰值滤波器的带宽
filter.frequency.value = 1000; // 中心频率
filter.gain.value = 5; // 增益,单位 db
// ...
source.connect(filter);
filter.connect(ac);
均衡器演示:
所有的滤波器类型及对应的参数说明:
ConvolverNode 对音频信号进行线性卷积运算
将特定的脉冲信号与音频进行卷积运算后
会获得畸变效果,可以用来做环境混响效果
用法与示例:
const ac = new AudioContext();
// 解码加载好的冲激信号
const impulse = ac.decodeAudioData(arrayBuffer);
// 创建一个卷积器节点
const convolver = ac.createConvolver();
// buffer: AudioBuffer 类型,一个冲激信号(必须是 .wav 格式的文件)
convolver.buffer = impulse;
source.connect(convolver);
convolver.connect(ac.destination);
混响效果演示:
谢谢!
参考资料: