HTML5 audio
1.audio sprite
音频精灵的主要思想其实跟css精灵差不多,将一个音频合成到一个音频,然后通过currentTime获取当前播放时间进行区分,不过在这里执行以下代码之前需将audio
先加载到页面当中。当时怎么判断页面已经加载完声音呢,在移动端audio的很多属性支持的都不是很好,在尝试了很多也在网上找了很多资料之后,暂且发现可以使用AudioContext对象去管理与播放声音
<input type="button" value="加载声音" id="button" οnclick="loadSound()" />
<audio src="smbb.mp3" id="audio1"></audio>
<br/><br/><br/>
<input type="button" value="播放" id="play"/>
var audioSprite = document.getElementById("audio1");
audioData = {
shake: {
start: 0,
length: 10
},
win: {
start: 15,
length: 15
}
}
document.getElementById("play").addEventListener("click", function () {
audioSprite.play()
audioSprite.currentTime = audioData.shake.start;
//audioSprite.play();
}, false);
var handler = function () {
if (this.currentTime >= audioData.shake.start + audioData.shake.length) {
this.pause();
setTimeout(function () {
audioSprite.removeEventListener("timeupdate", handler, false);
audioSprite.currentTime = audioData.win.start;
audioSprite.play();
audioSprite.addEventListener("timeupdate", handler2, false);
}, 1000);
}
}
var handler2 = function () {
if (this.currentTime >= audioData.win.start + audioData.win.length) {
this.pause();
}
}
audioSprite.addEventListener("timeupdate", handler, false);
2.利用AudioContext,为了生成一个声音,需要创建一个或多个声音源,并且通过AudioContext对象将这些声音源连接在一起,这些声音源并不是直接连接,而是通过多个用于对音频信号的各种模块进行处理的AudioNodes对象间接连接.
一个AudioContext对象可以支持多个音频输入,可以支持音频图的生成,所以在一个音频处理应用程序中我们只需创建一个AudioContext对象(备注:今天调试的时候突然发现AudioContext这个API在安卓的微信浏览器中没定义。哎,突然很失落了,不过还好ios系统测试都没问题)
<span style="white-space:pre"> </span>var context;
if(webkitAudioContext){
context = new webkitAudioContext();
}else{
context = new AudioContext();//标准
}
2.1在创建了AudioContext对象之后,我们可以使用AudioBuffer对象加载音频数据。以上有个加载声音的按钮,我们通过点击该按钮后使用XMLHttpRequest对象获取服务器端的MP3文件中的音频数据。以下实例:
function loadSound() {
var request = new XMLHttpRequest();
request.open("GET", "smbb.mp3", true);
request.responseType = "arraybuffer";
request.onload = function () {
context.decodeAudioData(request.response, function (buffer) {
console.log(buffer)
}, onError);
}
request.send();
}
function onError(e) {
console.log(e);
}
在以上代码中用户点击“加载声音”按钮,执行javascript脚本代码中的loadSound函数,在该函数中,使用XMLHttpRequest对象获取服务器端的MP3文件中的音频数据,因为音频数据是二进制数据,所以讲XMLHttpRequest对象的responseType属性值设为“arraybuffer”。当接受到服务器的MP3文件中未解码的音频数据时,可以使用AudioContext对象的decodeAudioData方法将其解码。
AudioContext对象的decodeAudioData方法使用三个参数,其中第一个为一个加载了未解码的音频数据的ArrayBuffer对象,第2,3个参数都为一个函数,代表音频数据的解码处理执行成功时执行的回调函数与音频数据的解码处理执行失败时执行的回调函数.
2.2当音频加载完成之后我们就可以通过AudioBuffer对象的createBufferSource对象创建一个AudioBufferSourceNode对象(代表音频播放设备的声音源),并且将AudioBufferSourceNode对象的buffer属性值指定为AudioBuffer对象,代码如下
var source = context.createBufferSource();
source.buffer = buffer;
该buffer为上面例子decodeAudioData返回的buffer。
接下来,我们需要使用AudioBufferSourceNode对象的connect方法将声音源连接到AudioContext对象的destination属性值(代表音频播放设备)。
source.connect(context.destination);
AudioBufferSourceNode对象的connect方法使用一个参数,参数值为AudioContext对象的destination属性值,该属性值为客户端计算机上的音频播放设备
最后使用AudioBufferSourceNode对象的start方法播放声音
source.start(0)//备注:之前网上跟书上很多位置都是说使用noteOn方法,当时,我测试该方法未定义。使用start()方法可以播放,当时测试在IOS系统中如果start方法不传参数,该方法也是未定义,后来发现必须得给一个默认得参数。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!--,minimal-ui-->
<!--<meta name=”apple-mobile-web-app-capable” content=”yes” />
<meta name=”apple-mobile-web-app-status-bar-style” content=”black-translucent” />-->
<title>声音加载处理封装到一个类中</title>
</head>
<body style="height:600px">
<input type="button" value="加载声音" id="button" οnclick="loadSound()" />
<audio src="smbb.mp3" id="audio1"></audio>
<br/><br/><br/>
<input type="button" value="播放" id="play"/>
<script>
var audioBuffer = null;
var context;
if(webkitAudioContext){
context = new webkitAudioContext();
}else{
context = new AudioContext();
}
//加载音频数据
function loadSound() {
var request = new XMLHttpRequest();
request.open("GET", "smbb.mp3", true);
request.responseType = "arraybuffer";
request.onload = function () {
context.decodeAudioData(request.response, function (buffer) {
/*var audio = new Audio();
audio.src="smbb.mp3";
audio.play();*/
var audioSprite = document.getElementById("audio1");
audioData = {
shake: {
start: 0,
length: 10
},
win: {
start: 15,
length: 15
}
}
document.getElementById("play").addEventListener("click", function () {
audioSprite.play()
audioSprite.currentTime = audioData.shake.start;
//audioSprite.play();
}, false);
var handler = function () {
if (this.currentTime >= audioData.shake.start + audioData.shake.length) {
this.pause();
setTimeout(function () {
audioSprite.removeEventListener("timeupdate", handler, false);
audioSprite.currentTime = audioData.win.start;
audioSprite.play();
audioSprite.addEventListener("timeupdate", handler2, false);
}, 1000);
}
}
var handler2 = function () {
if (this.currentTime >= audioData.win.start + audioData.win.length) {
this.pause();
}
}
audioSprite.addEventListener("timeupdate", handler, false);
}, onError);
}
request.send();
}
function onError(e) {
console.log(e);
}
</script>
</body>
</html>
总结,HTML5的audioAPI功能确实很强大,研究起来也很有意思,不过暂且技术部到家,在琢磨的时候耗费的时间也不少,当然肯定也有漏洞,说的不对的地方还请见谅,下阶段还有更有意思的控制播放节奏,多个声音的交叉混合及多个声音文件之间的平滑过渡。。。