“如毒似魅,如解似仙。程序世界,代码纷纷,web audio是流经存在的邂逅。九十刹那为一念,一念中一刹那经九百生灭,盘舞环形地来寻你。"
—— 题记
正文
Web Audio简介
Web Audio API为控制网页的音频提供了强有力的后盾,允许开发人员为音频添加效果,创建音频可视化等等。
百科:音频和声音
Web audio的内容和用途
Web Audio API包含通过audio context操控音频,不同类型的源也可以被一个环境支持,并允许模块路由。利用audio nodes(连接一起形成了audio routing graph)执行操作,模块的设计为创建复杂音频功能提供灵活性。
根据英文解释,它是在audio context里操控音乐的发生,无论是一首或多首,都可以在一个audio context里搞定,相当于为audio的控制设置了一个环境,我们在这个操控室里统筹音乐。环境有了,用什么来操作,audio nodes,相当于各种操纵杆。也有这么一个比喻说,“想象卡拉OK设备,DVD机相当于音频音源,音响相当于音频播放设备,混响器(主要用于把你的声音与背景音乐合成最终输出到音响上)相当于音频处理模块”,然后各个模块通过电线连接,最终接在音响上。
Web audio的工作流程
- 创建音频环境(audio context)
- 在音频环境里,创建源 —— 比如<audio>, oscillator, stream
- 创建效果节点,比如reverb, biquad filter, panner, compressor
- 选择音频的最终输出口,比如扬声器
- 连接 源——效果——目的地(输入——处理——输出)
部分属性方法解释
AudioContext
音频上下文对象,相当于声音容器,处理音频的前提环境
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx = new AudioContext();
** AudioContext.destination
**
返回对象 AudioDestinationNode
,表示环境里的所有音频的最终目标,代表实际的音频渲染设备,例如扬声器。AudioContext.decodeAudioData()
用于异步解析 ArrayBuffer
里的音乐文件。这种情况下,ArrayBuffer 通过XMLHttpRequest
或 FileReader
加载。解析后的音频缓冲被重复抽样到AudioContext的采样率,然后用于callback或者promise。
这是从音轨创建Web音频API的音频源的首选方法。
利用回调:
audioCtx.decodeAudioData(audioData, function(decodedData) {
// use the decoded data here
});
或者利用promise:
audioCtx.decodeAudioData(audioData).then(function(decodedData) {
// use the decoded data here
});
** AudioContext.createBufferSource()
**
用于创建新的音频节点对象 AudioBufferSourceNode,来播放 AudioBuffer
的音乐数据。而AudioBuffers是通过 AudioContext.createBuffer
来创建或者 AudioContext.decodeAudioData
成功解码音轨时返回。** AudioContext.createAnalyser() **
创建分析节点对象 AnalyserNode
,被用来展示音频时间和频率数据,并创建数据可视化。
AudioNode
用于表示像音频源的节点(例如,HTML <audio>或<video>元素,振荡器节点等),音频目的地,中间处理模块(例如像BiquadFilterNode或ConvolverNode)或音量控制(如GainNode)。
AudioNode具有输入和输出,每个都有一定数量的通道。零输入但有一个或多个输出的AudioNode称为源节点(source node)。不同节点的音频处理是不同的,总之,节点解读其输入,进行一些音频相关处理,并为其输出生成新的值,或者简单的让音频通过(例如,在 AnalyserNode
里,其中处理的结果被单独访问)
连接不同的节点可以组成一个处理图(* processing graph *),同样包含在 AudioContext
中。一般来说,处理节点继承AudioNode的方法和属性,但会在顶部定义自身功能。有关更多详细信息,请参阅各个节点页面,如 Web Audio API 首页所列。
- ** AudioNode.connect()
**
允许将当前节点的输出连接到目的,可以是音频节点(将声音数据定向到指定节点),或AudioParam
,以便节点的输出数据随时间自动更改该参数的值。
var destinationNode = AudioNode.connect(destination, outputIndex, inputIndex);
AudioNode.connect(destination, outputIndex);
** AudioBufferSourceNode **
操作audioBuffer对象里的音频数据,把audioBuffer中的数据转化为音频信号,作为音频源,零输入,一个输出,属于Audio Node。输出的通道数量对应着音频缓冲区的通道数量。如果没有任何的缓冲区,也就是说,如果AudioBufferSourceNode 的值为null,输出为包含静音的一个通道。一个 AudioBufferSourceNode
只可以播放一次;常说,AudioBufferSourceNodes 有个“射后不管”模式,一劳永逸:一旦开始,所有节点的引用都可以被删除,并且自动回收。
- ** AudioBufferSourceNode.buffer
**
音频缓冲区,表示播放的音频集,当被设置值为null的时候,会被定义为静音单声道。
var source = audioCtx.createBufferSource();
// from audioCtx.createBuffer, or audioCtx.decodeAudioData
source.buffer = myBuffer;
** AudioBufferSourceNode.start()
**
音乐的开始播放。AudioBufferSourceNode.start()仅对应一个。如果再次播放,需要另创建一个AudioBufferSourceNode 。这些节点是很容易创建的,AudioBuffers 也能够反复利用。** AudioBufferSourceNode.stop()
**
音乐的停止播放。AudioBufferSourceNode.stop()是被允许暂停多个音乐。最近的声音将会替代原先的,没有完全到缓冲区的末尾。
AnalyserNode
能提供实时频率以及时间域分析信息的节点,它是一个AudioNode,将音频流从输入传递到输出,允许获取和处理生成的数据,并创建音频可视化。
拥有一个输出,一个输出,尽管输出没有链接,节点也会工作。
- ** AnalyserNode.frequencyBinCount **
无符号长整型值,是FFT大小的一半。这通常等于将要用于可视化的数据值的数量。
var audioCtx = new AudioContext();
var analyser = audioCtx.createAnalyser();
var bufferLength = analyser.frequencyBinCount;
- ** AnalyserNode.getByteFrequencyData() **
将当前数据频率复制转化为Uint8Array
。
如果数组具有比AnalyserNode.frequencyBinCount更少的元素,则会删除多余的元素。如果它具有比所需要的更多的元素,则忽略多余的元素。
var audioCtx = new AudioContext();
var analyser = audioCtx.createAnalyser();
var dataArray = new Uint8Array(analyser.frequencyBinCount); // Uint8Array should be the same length as the frequencyBinCount
analyser.getByteFrequencyData(dataArray); // fill the Uint8Array with data returned from getByteFrequencyData()
举个简单的例子,结合音频链路和代码:
- 创建上下文,audio context;
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx;
// var source;
try {
audioCtx = new AudioContext();
console.log('support');
} catch (e) {
alert('Your browser does not support AudioContext!');
console.log(e);
}
- 利用方法createBufferSource()创建audioBufferSourceNode音频源对象;
source = audioCtx.createBufferSource();
- 完成获取需要播放的音频数据后,利用decodeAudioData()解码数据;
var request = new XMLHttpRequest();
//初始化 HTTP 请求参数, 配置请求类型,文件路径等
request.open('GET', 'audio/music.mp3', true);
// 配置数据返回类型,从服务器取回二进制数据
request.responseType = 'arraybuffer';
// 获取完成,对音频进一步操作,解码
request.onload = function() {
var audioData = request.response;
audioCtx.decodeAudioData(audioData, function(buffer) {
……
},
function(e) { console.log("Error with decoding audio data" + e.err); });
};
- audioBufferSourceNode对象的buffer属性接收audioBuffer数据
source.buffer = buffer;
- 通过connect()将audioBufferSourceNode对象连接到audioContext的desitination(speakers)
source.connect(audioCtx.destination);
- 从最开始播放
source.start(0);
附简单例子最终代码:
// create environment -- audio context
// define variables
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioCtx;
var source;
try {
audioCtx = new AudioContext();
console.log('support');
console.log(audioCtx)
} catch (e) {
alert('Your browser does not support AudioContext!');
console.log(e);
}
// use XHR to load an audio track, and
// decodeAudioData to decode it and stick it in a buffer.
// Then we put the buffer into the source
var getData = function() {
// create audio node to play the audio in the buffer
source = audioCtx.createBufferSource();
console.log(source)
// 请求
var request = new XMLHttpRequest();
//初始化 HTTP 请求参数, 配置请求类型,文件路径等
request.open('GET', 'audio/music.mp3', true);
// 配置数据返回类型,从服务器取回二进制数据
request.responseType = 'arraybuffer';
// 获取完成,对音频进一步操作,解码
request.onload = function() {
var audioData = request.response;
audioCtx.decodeAudioData(audioData, function(buffer) {
source.buffer = buffer;
source.connect(audioCtx.destination);
source.loop = true;
},
function(e) { console.log("Error with decoding audio data" + e.err); });
};
// 发送一个 HTTP 请求
request.send();
};
// play audio
getData();
source.start(0);
【零零碎碎,通过一点点阅读官方英文文档,与部分中文文档的理解整理,web audio实现了跟音频的通信,会耗硬件资源,适用性没有canvas那么广,或许这也是中文文档并不多的原因,音乐世界,趣味无穷。震撼于它跟canvas结合制造的效果,欲知后事如何,且听下回分解吧~】
参考文章:
https://developer.mozilla.org/en-US/docs/Web_Audio_API/Using_Web_Audio_API
https://github.com/wendellvian/blog/wiki/%E9%87%8D%E6%96%B0%E8%AE%A4%E8%AF%86Audio%E4%B9%8B%E7%9C%8B%E5%BE%97%E8%A7%81%E7%9A%84%E9%9F%B3%E4%B9%90_20160725
http://www.ayqy.net/blog/web-audio-api%E8%A7%A3%E6%9E%90/