webAudio API接口可以用来实现音乐可视化、音频剪辑、修声、语音、去声等等强大的操作
webAudioAPI接口关系图:
AudioContext是所有音频操作的前提,一个类似Canvas的ctx的上下文对象
var ac = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext)
//由于API兼容性问题,需要在创建时加上后缀
创建音频源 方法(1) 这种方式是通过请求方式播放音乐
var ac = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext)();
let url = './Kalimba.mp3';
//通过 fetch请求本地文件,返回样式设置为arraybuffer
fetch(url,{
responseType:'arraybuffer'
})
.then(res => {
//将返回的数据转成arrayBuffer数据,并返回
return res.arrayBuffer();
})
.then(res =>{
//使用ac.decodeAudioData(arrayBuffer, succ(buffer), err)方法音频解码,获取成功后调用第一个回调并返回buffer解码数据,失败则调用最后个回调
ac.decodeAudioData(res,(buffer)=>{
//创建bufferSource
let BufferSource = ac.createBufferSource();
//将返回的数据给它
BufferSource.buffer = buffer;
//直接连接音频聚集地
BufferSource.connect(ac.destination);
//开始播放
BufferSource[BufferSource.start ? 'start' : 'noteOn'](0);
},(err)=>{console.log(err);})
})
创建音频源 方法(2) 这种方式是通过 DOM元素 播放音乐
<input type="button" value="播放" onclick='music.play()'> //点击播放音乐
<input type="button" value="停止" onclick="music.pause()"> //点击停止音乐
<script>
var ac = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext);
//创建音乐DOM元素
let music = new Audio('./Kalimba.mp3');
//通过 DOM元素创建音频源
let source = ac.createMediaElementSource(music);
//直接连接音频聚集地
source.connect(ac.destination);
</script>
var audioCtx = new window.AudioContext();
var audioInput = document.getElementById("uploader"); //HTML语句:<input type="file" id="uploader" />
audioInput.onchange = function() {
//文件长度不为0则真的选中了文件,因为用户点击取消也会触发onchange事件。
if (audioInput.files.length !== 0) {
files = audioInput.files[0]; //得到用户选取的文件 //文件选定之后,马上用FileReader进行读入
fr = new FileReader();
fr.onload = function(e) {
var fileResult = e.target.result; //文件读入完成,进行解码
audioCtx.decodeAudioData(
fileResult,
function(buffer) {
let source = audioCtx.createBufferSource();
source.buffer = buffer; //将解码出来的数据放入source中 //转到播放和分析环节
source.connect(audioCtx.destination);
source.start(0);
},
function(err) {
alert("!Fail to decode the file"); //解码出错
}
);
};
fr.onerror = function(err) {
alert("!Fail to read the file"); //文件读入出错
};
fr.readAsArrayBuffer(files); //同样的,ArrayBuffer方式读取
}
};
gain是在音乐播放之前处理声音大小的中间件
这里使用DOM元素方式来演示 , 请求方式的设置也和它一样
<input type="button" value="播放" onclick='music.play()'> //点击播放音乐
<input type="button" value="停止" onclick="music.pause()"> //点击停止音乐
<input type="range" max="100" min="0" value="60" oninput="setGain(this)"> //控制音乐播放声音
<script>
var ac = new (window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext);
//创建音乐DOM元素
let music = new Audio('./Kalimba.mp3');
//通过 DOM元素创建音频源
let source = ac.createMediaElementSource(music);
//Gain连接destination
let gain = ac.createGain();
gain.connect(ac.destination);
//必须连接Gain , 不再是连接destination了,否则音频没有经过gain处理,效果不会生效
source.connect(gain);
//设置gain.gain.value 的值,跟随input的value改变,实现改变声音大小
function setGain(that)
{
gain.gain.value = that.value/that.max;
}
</script>
这个节点可以实现音频的可视化,是一个可视化中必不可少的重要步骤
//创建Analyser
var analyser = ac.createAnalyser();
//设置fftSize大小
analyser.fftSize = 512;
//链接destination Gain节点,随之Gain节点到终点去
analyser.connect(gain);
//创建Uint8Array数据,并运用frequencyBinCount 来获取fft的一半
var arr = new Uint8Array(analyser.frequencyBinCount);
//然后使用getByFrequencyData来获取范围频域
analyser.getByteFrequencyData(arr);
//最后配合Canvas和requestAnimationFrame(callback)动画函数来实现可视化;
var ctx = document.querySelector("canvas").getContext("2d");
ctx.canvas.width = document.body.clientWidth;
var width = ctx.canvas.width,
height = ctx.canvas.height;
window.onresize = function() {
ctx.canvas.width = document.body.clientWidth;
width = document.body.clientWidth;
let line = ctx.createLinearGradient(0, 0, 0, height);
line.addColorStop(1, "red");
line.addColorStop(0.5, "yellow");
line.addColorStop(0, "green");
ctx.fillStyle = line;
};
let line = ctx.createLinearGradient(0, 0, 0, height);
line.addColorStop(1, "red");
line.addColorStop(0.5, "yellow");
line.addColorStop(0, "green");
ctx.fillStyle = line;
function draw(Data) {
ctx.clearRect(0, 0, width, height);
var w = width / 128;
for (let i = 0; i < Data.length; i++) {
ctx.fillRect(
w * i,
height - (Data[i] / 256) * height,
(width / Data.length) * 1.5,
Data[i]
);
}
}
var ac = new (window.AudioContext ||
window.webkitAudioContext ||
window.mozAudioContext ||
window.msAudioContext)();
//创建gain 来控制声音大小
let gain = ac.createGain();
//链接音频终点
gain.connect(ac.destination);
//创建analyser 来实现可视化
let analyser = ac.createAnalyser();
analyser.fftSize = 512;
//链接gain
analyser.connect(gain);
//获取音乐数据
fetch("./music/Kalimba.mp3", {
responseType: "arraybuffer"
})
.then(res => res.arrayBuffer())
.then(res => {
ac.decodeAudioData(res, buffer => {
let bufferSource = ac.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.connect(analyser);
bufferSource[bufferSource.start ? "start" : "noteOn"](0);
});
});
(function() {
//创建数据
var arr = new Uint8Array(analyser.frequencyBinCount);
//解决各浏览器的兼容性问题
requestAnimationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame;
//创建动画函数
function animate() {
//获取频域
analyser.getByteFrequencyData(arr);
draw(arr);
//循环
requestAnimationFrame(animate);
}
//启动动画函数
requestAnimationFrame(animate);
})();
function setGain(that) {
gain.gain.value = +that.value / +that.max;
}