Web Audio学习与音频播放
随着浏览器的越发强大,用原生js操作音频已经不是难事了。我们来使用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/zh-CN/docs/Web/API/AudioContext/decodeAudioData。
注:w3c文档上说明decodeAudioData支持audio标签支持的所有音频格式。MDN提示ArrayBuffer类型的对象旨在保存小型音频片段,通常小于45秒,对于较长的声音,实现它的对象MediaElementAudioSourceNode(audio元件)更合适。
音频播放
音频数据到手,接下来就是播放啦。
文件上传后,我们拿到了音频audioBuffer形式的数据,接下来使用createBufferSource()方法播放音频数据,再connect到destination就可以播放了。
// 播放音频
function playSound(buffer) {
var source = context.createBufferSource();
// 设置数据
source.buffer = buffer;
// connect到扬声器
source.connect(context.destination);
source.start();
}
一个简单的音频文件播放器就完成了,如果是从服务器上获取文件也是类似的,只不过是多了个ajax处理。
代码地址:webAudio播放本地音乐。
音频的话,可以去一些音乐网站下载,如果懒得下的话,我这直接提供音频下载:[download id="1075"]
小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了。
想要看js录音的可以看这篇文章:纯js实现录音与播放。