那些 audio api的事 (一) AudioContext

引用 Getting Started with Web Audio API
http://www.html5rocks.com/en/tutorials/webaudio/intro/html

Introduction

Audio on the web has been fairly primitive up to this point and until very recently has had to be delivered through plugins such as Flash and QuickTime. The introduction of the audio element in HTML5 is very important, allowing for basic streaming audio playback. But, it is not powerful enough to handle more complex audio applications. For sophisticated web-based games or interactive applications, another solution is required. It is a goal of this specification to include the capabilities found in modern game audio engines as well as some of the mixing, processing, and filtering tasks that are found in modern desktop audio production applications.html5

在網絡上的音頻已經至關廣泛的時代,但直到最近咱們想聽音頻,不得不經過如Flash和QuickTime的插件播放。在HTML5音頻元素的引入是很是重要的,音頻元素容許基本的流式音頻播​​放。可是,它沒法處理更復雜的音頻應用。對於複雜的基於Web的遊戲或交互式應用,另外一種解決方案是必需的。這是本說明書的目的,包括在現代遊戲音頻引擎音頻混合處理,現代桌面音頻製做應用程序所包含的處理和過濾任務。node

The APIs have been designed with a wide variety of use cases in mind. Ideally, it should be able to support any use case which could reasonably be implemented with an optimized C++ engine controlled via JavaScript and run in a browser. That said, modern desktop audio software can have very advanced capabilities, some of which would be difficult or impossible to build with this system. Apple's Logic Audio is one such application which has support for external MIDI controllers, arbitrary plugin audio effects and synthesizers, highly optimized direct-to-disk audio file reading/writing, tightly integrated time-stretching, and so on. Nevertheless, the proposed system will be quite capable of supporting a large range of reasonably complex games and interactive applications, including musical ones. And it can be a very good complement to the more advanced graphics features offered by WebGL. The API has been designed so that more advanced capabilities can be added at a later time.web

這些API已經設計能夠知足各類各樣的使用案例。理想的是,它應該可以支持任何使用狀況下它能夠合理地具備優化C ++引擎經過JavaScript控制並在瀏覽器中運行來實現。這就是說,現代臺式音頻軟件能夠有很是高級的功能,其中的一些將難以或不可能創建與該系統。蘋果公司的Logic音頻就是這樣一個應用程序,它具備外部MIDI控制器,​​任意插件音頻效果和合成,高度優化的直接到磁盤的音頻文件讀取/寫入,支持緊密集成的時間伸縮,等等。儘管如此,所提出的系統將是至關可以支持大範圍的至關複雜的遊戲和交互式應用程序,包括音樂的。它能夠是一個很好的補充,經過WebGL的提供更先進的圖形功能。該API被設計成使更高級的功能能夠在之後的時間被加入。編程

Features

The API supports these primary features:api

  • Modular routing for simple or complex mixing/effect architectures,瀏覽器

including multiple sends and submixes.網絡

  • High dynamic range, using 32bits floats for internal processing.架構

  • Sample-accurate scheduled sound playback with low latency for musicalapp

applications requiring a very high degree of rhythmic precision such
as drum machines and sequencers. This also includes the possibility
of dynamic creation of effects.

  • 模塊化路由簡單或複雜的混合/效果架構,包括多個發送和子混音。

  • 高動態範圍,採用32bits floats進行內部處理。

  • 採樣精肯定時播放的聲音與音樂的低延遲 須要的節奏等精密程度很是高的應用 做爲鼓機和定序。 這也包括了可能性動態建立的效果。

  • Automation of audio parameters for envelopes, fade-ins / fade-outs,

granular effects, filter sweeps, LFOs etc.

  • Flexible handling of channels in an audio stream, allowing them to be

split and merged.

  • Processing of audio sources from an audio or video media element.

  • 自動化音頻參數信封,淡入/淡出,顆粒效果,過濾器掃描,低頻振盪器等。

  • 靈活的處理在音頻流的信道,使它們成爲拆分和合並。

  • 處理從音頻或視頻的媒體元素的音頻源。

  • Processing live audio input using a MediaStream from getUserMedia().

Integration with WebRTC Processing audio received from a remote peer
using a MediaStreamAudioSourceNode and [webrtc].

  • Sending a generated or processed audio stream to a remote peer using

a MediaStreamAudioDestinationNode and [webrtc].

  • Audio stream synthesis and processing directly in JavaScript.

  • 使用MediaStream的getUserMedia()方法處理現場音頻輸入。
    使用MediaStreamAudioSourceNode和[WebRTC],以實現將WebRTC從遠程對等體接收的音頻處理整合

  • 利用發送生成或處理的音頻流發送到遠程對等 一個MediaStreamAudioDestinationNode和[WebRTC]。

  • 在JavaScript中直接處理音頻流合成和加工。

  • Spatialized audio supporting a wide range of 3D games and immersive environments:

    • Panning models: equalpower, HRTF, pass-through

    • Distance Attenuation

    • Sound Cones

    • Obstruction / Occlusion

    • Doppler Shift

    • Source / Listener based

  • A convolution engine for a wide range of linear effects, especially very high-quality room effects. Here are some examples of possible effects:

    • Small / large room

    • Cathedral

    • Concert hall

    • Cave

    • Tunnel

    • Hallway

    • Forest

    • Amphitheater

    • Sound of a distant room through a doorway

    • Extreme filters

    • Strange backwards effects

    • Extreme comb filter effects

  • Dynamics compression for overall control and sweetening of the mix

  • Efficient real-time time-domain and frequency analysis / music visualizer support

  • Efficient biquad filters for lowpass, highpass, and other common filters.

  • A Waveshaping effect for distortion and other non-linear effects

  • Oscillators

  • 立體音效支持多種3D遊戲和沉浸式環境

  • 卷積引擎普遍的非線性效應,特別是很是高品質的室內效果。

  • 動態壓縮混合的整體控制和甜味劑

  • 高效的實時的時域和頻分析/音樂可視化支持

  • 高效雙二階濾波器的低通,高通,和其餘經常使用的過濾器

  • 失真等非線性效應整波效應

Modular Routing

Modular routing allows arbitrary connections between different AudioNode objects. Each node can have inputs and/or outputs. A source node has no inputs and a single output. A destination node has one input and no outputs, the most common example being AudioDestinationNode the final destination to the audio hardware. Other nodes such as filters can be placed between the source and destination nodes. The developer doesn't have to worry about low-level stream format details when two objects are connected together; the right thing just happens. For example, if a mono audio stream is connected to a stereo input it should just mix to left and right channels appropriately.

模塊化路由容許不一樣的對象AudioNode之間的任意鏈接。每一個節點能夠具備輸入和/或輸出。
源節點沒有輸入和一個輸出。目的節點有一個輸入和沒有輸出,最多見的例子是AudioDestinationNode最終目的地到音頻硬件。如過濾器的其餘節點能夠放置在源和目的地節點之間。開發人員沒必要擔憂低級別的流格式的細節時,兩個物體鏈接在一塊兒;正確的事情只是發生。
例如,若是一個單聲道的音頻流被鏈接到立體聲輸入應該只是混合到左和右聲道適當。

In the simplest case, a single source can be routed directly to the output. All routing occurs within an AudioContext containing a single AudioDestinationNode:

圖片描述

在最簡單的狀況下,單個源可直接路由到輸出​​。全部的路由時包含一個AudioDestinationNode的AudioContext內

AudioContext

一個AudioContext是用於管理和播放全部的聲音。爲了生產使用Web音頻API聲音,建立一個或多個聲源,並將它們鏈接到由所提供的聲音目的地AudioContext 實例。這方面並不須要是直接的,而且能夠經過任何數量的中間的AudioNodes充當用於音頻信號處理的模塊。

AudioContext的單個實例能夠支持多個聲音輸入和複雜的音頻圖表,因此咱們只須要其中的一個,由於咱們建立的每個音頻應用程序。
許多有趣的網絡音頻API的功能,如建立AudioNodes和音頻文件數據進行解碼的AudioContext的方法

下面的代碼片斷建立了一個AudioContext:

var context;
window.addEventListener('load', init, false);
function init() {
  try {
    // Fix up for prefixing
    window.AudioContext = window.AudioContext||window.webkitAudioContext;
    context = new AudioContext();
  }
  catch(e) {
    alert('Web Audio API is not supported in this browser');
  }
}

Loading sounds

網絡音頻API使用AudioBuffer用於中短長度的聲音。
其基本方法是使用XMLHttpRequest進行提取聲音文件。
API支持加載多種格式的音頻文件數據,如WAV,MP3,AAC,OGG等。
針對不一樣的音頻格式支持的瀏覽器有所不一樣。

var dogBarkingBuffer = null;
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();

function loadDogSound(url) {
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer';

  // Decode asynchronously
  request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
      dogBarkingBuffer = buffer;
    }, onError);
  }
  request.send();
}

音頻文件數據爲二進制(非文本),因此咱們設置要求responseType是「arraybuffer」。
有關ArrayBuffers的更多信息,
一旦(未譯碼)的音頻文件數據已被接收,則能夠保持左右購買解碼,或者它可被解碼立刻使用AudioContext decodeAudioData()方法。
這種方法須要存儲在request.response音頻文件數據的ArrayBuffer並異步進行解碼(不阻塞主JavaScript的執行線程)。
當decodeAudioData()完成後,它調用的回調函數,它提供解碼PCM音頻數據做爲AudioBuffer。

一旦被加載一個或多個AudioBuffers,那麼咱們就能夠播放聲音。
讓咱們假設咱們剛剛加載的AudioBuffer有狗叫的聲音,而且已完成加載過程。
而後咱們就能夠玩這個緩衝區用下面的代碼。

// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();

function playSound(buffer) {
  var source = context.createBufferSource(); // creates a sound source
  source.buffer = buffer;                    // tell the source which sound to play
  source.connect(context.destination);       // connect the source to the context's destination (the speakers)
  source.start(0);                           // play the source now
                                             // note: on older systems, may have to use deprecated noteOn(time);
}

Dealing with time: playing sounds with rhythm

網絡音頻API容許開發者精確安排播放。爲了證實這一點,讓咱們創建一個簡單的節奏軌道。
其中hihat是發揮每個八分音符,又踢又網羅玩法交替每季度,在4/4的時間。
假設咱們已經加載了踢,圈套和hihat緩衝區,要作到這一點的代碼很簡單:

for (var bar = 0; bar < 2; bar++) {
  var time = startTime + bar * 8 * eighthNoteTime;
  // Play the bass (kick) drum on beats 1, 5
  playSound(kick, time);
  playSound(kick, time + 4 * eighthNoteTime);

  // Play the snare drum on beats 3, 7
  playSound(snare, time + 2 * eighthNoteTime);
  playSound(snare, time + 6 * eighthNoteTime);

  // Play the hi-hat every eighth note.
  for (var i = 0; i < 8; ++i) {
    playSound(hihat, time + i * eighthNoteTime);
  }
}

不要輕易嘗試 那畫面太美 我不敢直視

Changing the volume of a sound

一,你可能想要作一個聲音的最基本的操做是改變它的音量。
經過GainNode才能使用Web API的音頻,咱們能夠路由咱們的源到目的地操縱量:
圖片描述

此鏈接創建能夠實現以下:

// Create a gain node.
var gainNode = context.createGain();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);

通過圖已經成立,你能夠經過編程操縱gainNode.gain.value以下改變音量:

// Reduce the volume.
gainNode.gain.value = 0.5;

大家試下調個幾千倍 那場面不敢直視

Cross-fading between two sounds

如今,假設咱們有一個稍微複雜的狀況,咱們正在玩多種聲音,但要跨越兩者之間褪色。
這是在一個DJ狀的應用,其中,咱們有兩個唱盤和但願可以從一個聲源到平移到另外一種常見的狀況。
圖片描述
要使用這樣的功能設置此,咱們簡單地建立兩個GainNodes,並經過鏈接節點每一個源

function createSource(buffer) {
  var source = context.createBufferSource();
  // Create a gain node.
  var gainNode = context.createGain();
  source.buffer = buffer;
  // Turn on looping.
  source.loop = true;
  // Connect source to gain.
  source.connect(gainNode);
  // Connect gain to destination.
  gainNode.connect(context.destination);

  return {
    source: source,
    gainNode: gainNode
  };
}

Equal power crossfading

一個天真的線性淡入淡出的方式表現出你的樣本之間平移量暢遊。
圖片描述

爲了解決這一問題,咱們使用一個等功率曲線,其中所述相應增益曲線是非線性的,並相交以更高的幅度。
這最大限度地減小體積驟降音頻區域之間,從而致使更均勻的交叉衰減,多是在電平略有不一樣區域之間。
圖片描述

Playlist crossfading

另外一種常見的平滑轉換應用是一個音樂播放器應用。
當一首歌曲的變化,咱們但願在淡出當前曲目了,褪去了新的,避免了不和諧的過渡。
要作到這一點,安排交叉淡入淡出的將來。
雖然咱們可使用的setTimeout執行此調度,這是不許確的。
隨着Web API的音頻,咱們可使用AudioParam界面安排爲參數的將來值,如GainNode的增益值。
所以,給定播放列表,咱們能夠軌道之間經過調度當前播放的曲目上的增益降低,並在接下來的一個增益提升升學,雙雙小幅以前,當前曲目播放結束:

function playHelper(bufferNow, bufferLater) {
  var playNow = createSource(bufferNow);
  var source = playNow.source;
  var gainNode = playNow.gainNode;
  var duration = bufferNow.duration;
  var currTime = context.currentTime;
  // Fade the playNow track in.
  gainNode.gain.linearRampToValueAtTime(0, currTime);
  gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
  // Play the playNow track.
  source.start(0);
  // At the end of the track, fade it out.
  gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
  gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
  // Schedule a recursive track change with the tracks swapped.
  var recurse = arguments.callee;
  ctx.timer = setTimeout(function() {
    recurse(bufferLater, bufferNow);
  }, (duration - ctx.FADE_TIME) * 1000);
}

Applying a simple filter effect to a sound

圖片描述
該網絡音頻API容許從一個音頻節點到另外一個你管的聲音,創造一個潛在的複雜的處理器鏈複雜的效果添加到您的soundforms。
這樣作的一個方法是把你的聲源和目的地之間BiquadFilterNodes。
這種類型的音頻節點能夠作各類的可用於構建圖形均衡器,甚至更復雜的效果,主要是爲了作選擇其中的聲音的頻譜的部分強調並制服低階濾波器。
支持的類型的過濾器包括:

  • Low pass filter

  • High pass filter

  • Band pass filter

  • Low shelf filter

  • High shelf filter

  • Peaking filter

  • Notch filter

  • All pass filter

和全部的過濾器所包含的參數,指定必定量的增益,在該應用過濾器的頻率和品質因數。
低通濾波器保持較低的頻率範圍,但丟棄高頻。
折斷點由頻率值肯定,而且Q因子是無單位,並肯定該圖的形狀。
增益隻影響特定的過濾器,如低貨架和峯值濾波器,而不是本低通濾波器。

在通常狀況下,頻率控制須要進行調整工做在對數標度,由於人的聽覺自己的工做原理相同(即,A 4爲440Hz的,和A5是880hz)。
欲瞭解更多詳細信息,請參閱上面的源代碼連接FilterSample.changeFrequency功能。
最後,請注意,示例代碼,您能夠鏈接和斷開濾波器,動態變化的AudioContext圖。
咱們能夠經過調用node.disconnect(outputNumber)斷開圖AudioNodes。
例如,要從新路線圖從去經過一個過濾器,以直接鏈接,咱們能夠作到如下幾點:

// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
相關文章
相關標籤/搜索