音频

在过去,想要在网页上构建有声web只能借助Flash等插件,自从web步入HTML5时代后,除插件机制外,我们还可以运用HTML5提供的原生API来实现这一需求。

本节我们就来探究一下这些原生API。

 

概述

简介

Web Audio API最早是Chrome社区提出并支持的,它是一套全新的相对独立的接口系统,对音频文件拥有很高的处理权限以及内置相关的音频专业效果的处理方法,可以完全独立于<audio>标签存在。简单的说它就是一组JavaScript API,它提供了一系列处理与合成音频的方法。

Web Audio API本身并不是<audio>标签的替代品,而是对<audio>标签功能上的补充。如果是简单的展现音频则<audio>标签足以应对,如果需要负责的音频操作,则应该是使用Web Audio API。

特点

* 更精准的时间控制 * 可独立于<audio>标签,允许多音频文件同时播放 * 模块化的接口设计方式,让音频操作更具灵活特性 * 更多音频专业对口的操作方法

工作流程

1. 创建AudioContext实例对象(下文中简称ac) 2. 为ac内置音源,如<audio>标签,震动发声器,音频流等 3. 创建效果节点(effect node)如reverb、biquad filter、compressor等 4. 选择音频的最终输出节点,如电脑扬声器 5. 连接各处理后的效果节点(源-效果-目的地 输入-处理-输出)

名词简介

AudioContext

AudioContext是管理和控制音频的核心,作为音频接口上下文对象,它包含了音频信号的路由图,用来连接各AudioNodes。

AudioNodes

音频的输入、输出以及中间处理的节点或模块

AudioDestinationNode

音频信号处理后的最终目的地

AudioBuffer

音频缓冲器,表示驻留在内存中的音频内容

AudioBufferSourceNode

由AudioBuffer产生音频的AudioNode

MediaElementAudioSourceNode

来源于audio标签、video标签或其他元素的音频资源

AnalyserNode

提供实时频率以及时间域分析信息的节点,它是一个AudioNode,将音频流从输入传递到输出,允许获取和处理生成的数据,并创建音频可视化。 * .frequencyBinCount * .getByteFrequencyData

路由图

AudioContext中包含了许许多多的几点,大致分为三类:源、目标和中间节点。 一个完整的路由图就是将每个用到的节点以串联的方式一个一个连接起来组成的。这其中源节点和目的节点是必须的而中间节点(提供了各式各样的功能和效果)则是可选的。

代码示例

基本操作

window.onload = init;
var context, bufferLoader;
// loading audio file
function init () {
  window.AudioContext = window.AudioContext || window.webkitAudioContext;
  context = new AudioContext();
  bufferLoader = new BufferLoader(context, [
    "somPath/someFile.wav",
    "somePath/anotherFile.wav"
  ], finishedLoading);
 bufferLoader.load();
};

// control bufferList
function finishedLoading(bufferList) {
  bufferList.forEach(function(buffer) {
    playSound(buffer, 0);
  });
};

// play sound with given buffer and time
function playSound(buffer, time) {
  time = time || 0;
  var source = context.createBufferSource();
  source.buffer = buffer;
  source.connect(context.destination);
  source.start(time);
};

// change volume sound
function changeVolume(source, value) {
  var gainNode = context.createGain();
  source.connect(gainNode);
  gainNode.connect(context.destination);
  gainNode.gain.value = value;
}

静音

  var mute = document.querySelector(".mute");
  mute.onclick = function() {
    if(mute.id === "") {
      gainNode.disconnect(context.destination);
      mute.id = "activated";
      mute.innerHTML = "Unmute";
    } else {
      gainNode.connect(context.destination);
      mute.id = "";
      mute.innerHTML = "Mute";
    }
  }

使用Canvas实现可视化效果

  // 获取实时表示频率信息的数组
  var analyser = context.createAnalyser(),
      array = new Uint8Array(analyser.frequencyBinCount);
  analyser.getByteFrequencyData(array);
  
  function createCanvas(width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width || 300;
    canvas.height = height || 300;
    return canvas;
  }
  var canvas = createCanvas(),
      cxt = canvas.getContext("2d");
  function draw(size) {
    cxt.clearRect(0, 0, canvas.width, canvas.height);
    var w = canvas.width / size;
    for(i = 1; i < size; i++) {
      var h1 = array[i] / 256 * canvas.height;
          h2 = canvas.height - h1;
      cxt.beginPath();
      cxt.fillRect(w * i, h2, w * 0.6, h1);
      cxt.closePath();
    }
  }