AudioContext 是 HTML5 中新增的一个关于音频处理的对象。虽然我们平时提到 HTML5 音频都会想到 audio 标签,但是今天我们要讲的 AudioContext 对象要比 audio 标签更加的强大,它能实现 audio 标签所不能实现的功能,比如一个展示音频频谱的插件。
介绍
AudioContext 对象是一个音频处理上下文,表示由音频模块连接而成的音频处理图,每个模块对应一个 AudioNode。
AudioContext 可以控制它所包含的节点的创建,以及音频处理、解码操作的执行。
做任何事情之前都要先创建 AudioContext 对象,因为一切都发生在这个环境之中。
而通过 AudioContext 创建的处理节点(audioNode)可以理解成一个个管道函数,我们把这些节点按一定次序连接起来,音频数据就会按次序通过这些节点,并做相应的处理,如下图:
实现
实现过程直接看代码吧,主要就是要注意下面几点:
- 音频数据来源可以是一个 audio 标签,也可以是 Blob 数据,对应的方法分别是 createBufferSource() 和 createMediaElementSource()。需要注意的是,因为浏览器同源策略的原因,非同源音频无法进行解析。
- 获取分析器数据的方法需要传入一个类型数组(Uint8Array)
- 分析器获取数据的方法没有返回值,它只会将数据填入传入方法的类型数组中
// Audio 分析器
function AudioAnalyser(audioEl, analyserCount, fftIndex) {
var audioContext = new AudioContext(),
audioBufferSource = audioContext.createMediaElementSource(audioEl),
audioAnalyserList = [],
audioSplitter = audioContext.createChannelSplitter(analyserCount),
audioMerger = audioContext.createChannelMerger(analyserCount);
// 创建分析器列表
for (var i = 0; i < analyserCount; i++) {
var analyser = audioContext.createAnalyser();
analyser.fftSize = Math.pow(2, fftIndex);
audioAnalyserList.push(analyser);
}
// 连接 Audio 节点
audioBufferSource.connect(audioSplitter);
audioAnalyserList.forEach(function (analyser, index) {
audioSplitter.connect(analyser, index);
analyser.connect(audioMerger, 0, index);
});
audioMerger.connect(audioContext.destination);
// 获取分析器数据方法
function getByteFrequencyDataList() {
var arrayBuffer;
return audioAnalyserList.map(function (analyser) {
arrayBuffer = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(arrayBuffer);
return arrayBuffer;
});
}
function getByteFrequencyDataCount() {
var count = 0;
audioAnalyserList.forEach(function (analyser) {
count += analyser.frequencyBinCount;
});
return count;
}
return {
getByteFrequencyDataList: getByteFrequencyDataList,
getByteFrequencyDataCount: getByteFrequencyDataCount
}
}