随着浏览器的越发强大,用浏览器自带的 api 操作音频已经不是难事了。我们来使用 web audio api 简单地处理下音频资源。
简介
在学习 web audio api 之前,先了解三个概念:
音频源,也就是音频输入,可以是直接从设备输入的音频,也可以是远程获取的音频文件。
处理节点,分析器和处理器,比如音调节点,音量节点,声音处理节点。
输出源,指音频渲染设备,一般情况下是用户设备的扬声器,即 context.destination。
其实,音频源和输出源也都可以视为节点,这三者的关系可以用这张图表示:
当然,实际使用中,可能会有 n 个处理节点,都可以使用 connect 依次关联起来。
音频文件播放
假如现在要用 web audio api 播放本地的一个音乐文件,按照前面的流程,我们来试下。
文件上传
既然音频文件来自本地,那么得支持文件上传:
<input type=”file” id=”file” accept=”audio/x-wav,audio/mpeg” />
我这儿限制了先显示 wav 和 mp3 两种格式。
文件读取
给 input 增加 change 事件,处理选中的文件:
var context = new (window.AudioContext || window.webkitAudioContext)();
document.getElementById(‘file’).addEventListener(‘change’, function(e) {
var read = new FileReader();
read.onload = function() {
// 将 arrayBuffer 转成 audioBuffer
context.decodeAudioData(this.result, function(buffer) {
playSound(buffer);
}, function() {
console.log(‘error’);
});
};
// 利用 filereader 将 file 转成 arraybuffer 格式
read.readAsArrayBuffer(this.files[0]);
});
丢了一段代码,我们来看下,new AudioContext(),创建 audio 的上下文环境,至于 webkitAudioContext 是兼容较低版本的 chrome 的。
fileReader 大伙应该见到的比较多了吧,这儿用他读取对应 file 对象中的文件数据,readAsArrayBuffer 表示读取结果用 arrayBuffer 对象显示,由于此方法是异步读取的,所以只能放在 onload 回调中处理。
而我们拿到的 arrayBuffer 不能直接给 web audio 播放,需要使用 decodeAudioData()方法将 arrayBuffer 转成 audioBuffer,那么此时转化后的 audioBuffer 就是音频源啦。decodeAudioData 更多介绍可以查看 MDN:https://developer.mozilla.org…。
注:w3c 文档上说明 decodeAudioData 支持 audio 标签支持的所有音频格式。
音频播放
音频数据到手,接下来就是播放啦。
文件上传后,我们拿到了音频 audioBuffer 形式的数据,接下来使用 createBufferSource()方法播放音频数据,再 connect 到 destination 就可以播放了。
// 播放音频
function playSound(buffer) {
var source = context.createBufferSource();
// 设置数据
source.buffer = buffer;
// connect 到扬声器
source.connect(context.destination);
source.start();
}
一个简单的音频文件播放器就完成了,如果是从服务器上获取文件也是类似的,只不过是多了个 ajax 处理。
代码地址:webAudio 播放本地音乐。
音频的话,可以去一些音乐网站下载,如果懒得下的话,我这直接提供音频下载:林俊杰_-_我还想她.mp3
小 bug
当连续选择多个文件时,你会发现,多个音频文件一起播放了,因此,多音频输入时,都一起 connect 到 context.destination 上就可以实现一起播放了。对于此处,这应该算是个 bug,查看 AudioBufferSourceNode 文档,可以利用 stop()方法去处理,大伙自个想下,处理下咯。
前面的例子里只出现了音频源和音频输出,并未出现处理节点。接下来,我们尝试自己创建音频,并使用音量处理节点。
自制音频并播放
创建音频源
此处我们不使用外部的音频文件,而是使用 createOscillator()方法创建音频源。
该方法返回 OscillatorNode,可以通过 frequency 属性设置他的振荡频率,type 属性则可以用来指定要播放的波形。更多属性和方法参考 OscillatorNode 文档。
var context = new (window.AudioContext || window.webkitAudioContext)();
var oscillator = context.createOscillator();
// oscillator.type = ‘sine’;
// oscillator.frequency.value = 800; // 频率 800Hz,默认 440
创建音量处理节点
使用 createGain()方法,修改返回值中的 value,既可以改变音量大小。
var gainNode = context.createGain();
gainNode.gain.value = 0.8; // 音量 0 ~ 1
节点关联与播放
将这些”节点”connect 起来就可以播放了。
oscillator.connect(gainNode); // 音频源关联到音量
gainNode.connect(context.destination); // 音量关联到扬声器
// chrome 73 需要用户点击才可播放
document.getElementById(‘start’).addEventListener(‘click’, function() {
oscillator.start();
});
虽然播放后是一片噪音,不过简单的 web audio api 我们已经会使用啦。
代码地址:webAudio 制造噪音并播放。
其他
自己尝试过程中,在控制台下遇到这个警告:
The AudioContext was not allowed to start. It must be resumed (or created) after a user gesture on the page.
大概意思就说 AudioContext 需要用户手动触发,所以只需要将 new AudioContext()移动到事件内部就行了。
总结
我们已经能够使用 web audio 播放本地音乐和制造噪音了,接下来,可以尝试下其他的 api 了。
阅读原文。
欢迎关注微信公众号 [我不会前端] 或扫描下方二维码!