20.JS | Web Audio API (上) 你的音谱

“如毒似魅,如解似仙。程序世界,代码纷纷,web audio是流经存在的邂逅。九十刹那为一念,一念中一刹那经九百生灭,盘舞环形地来寻你。"
—— 题记

正文


Web Audio简介

Web Audio API为控制网页的音频提供了强有力的后盾,允许开发人员为音频添加效果,创建音频可视化等等。

20.JS | Web Audio API (上) 你的音谱_第1张图片
源自网络.png
20.JS | Web Audio API (上) 你的音谱_第2张图片
源自网络.png

百科:音频和声音

20.JS | Web Audio API (上) 你的音谱_第3张图片
百度百科

20.JS | Web Audio API (上) 你的音谱_第4张图片
百度百科

Web audio的内容和用途

Web Audio API包含通过audio context操控音频,不同类型的源也可以被一个环境支持,并允许模块路由。利用audio nodes(连接一起形成了audio routing graph)执行操作,模块的设计为创建复杂音频功能提供灵活性。

根据英文解释,它是在audio context里操控音乐的发生,无论是一首或多首,都可以在一个audio context里搞定,相当于为audio的控制设置了一个环境,我们在这个操控室里统筹音乐。环境有了,用什么来操作,audio nodes,相当于各种操纵杆。也有这么一个比喻说,“想象卡拉OK设备,DVD机相当于音频音源,音响相当于音频播放设备,混响器(主要用于把你的声音与背景音乐合成最终输出到音响上)相当于音频处理模块”,然后各个模块通过电线连接,最终接在音响上。

Web audio的工作流程
  1. 创建音频环境(audio context)
  2. 在音频环境里,创建源 —— 比如
  3. 创建效果节点,比如reverb, biquad filter, panner, compressor
  4. 选择音频的最终输出口,比如扬声器
  5. 连接 源——效果——目的地(输入——处理——输出)
20.JS | Web Audio API (上) 你的音谱_第5张图片
图例.png

部分属性方法解释

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

20.JS | Web Audio API (上) 你的音谱_第6张图片
官方图例.png

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 有个“射后不管”模式,一劳永逸:一旦开始,所有节点的引用都可以被删除,并且自动回收。

20.JS | Web Audio API (上) 你的音谱_第7张图片
官方图例.png
  • ** 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,将音频流从输入传递到输出,允许获取和处理生成的数据,并创建音频可视化。
拥有一个输出,一个输出,尽管输出没有链接,节点也会工作。

20.JS | Web Audio API (上) 你的音谱_第8张图片
官方图例.png
  • ** 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()

举个简单的例子,结合音频链路和代码:

  1. 创建上下文,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);
}
20.JS | Web Audio API (上) 你的音谱_第9张图片
console.log(audioCtx).png
  1. 利用方法createBufferSource()创建audioBufferSourceNode音频源对象;
source = audioCtx.createBufferSource();
20.JS | Web Audio API (上) 你的音谱_第10张图片
console.log(source)
  1. 完成获取需要播放的音频数据后,利用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); });
    };
  1. audioBufferSourceNode对象的buffer属性接收audioBuffer数据
source.buffer = buffer;
20.JS | Web Audio API (上) 你的音谱_第11张图片
console.log(buffer)
  1. 通过connect()将audioBufferSourceNode对象连接到audioContext的desitination(speakers)
source.connect(audioCtx.destination);
  1. 从最开始播放
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/

你可能感兴趣的:(20.JS | Web Audio API (上) 你的音谱)