Web Audio API の使用 - Web API

Web Audio API の使用
=================

Web Audio API の入門を見てみましょう。ここではいくつかの概念を短く確認してから、簡単な boombox の例で、音声トラックの読み込み、再生と一時停止、音量やステレオ位置の変更の方法を学びましょう。

Web Audio API は `<audio>` メディア要素を置き換えるものではなく、むしろその機能を補完するものであり、 `<canvas>` が `<img>` 要素と並行して存在するのと似ています。どちらを利用するかは、その目的によります。音声トラックの再生を制御したいだけであれば、 `<audio>` メディア要素の方がよりよく、 Web Audio API よりも早く解決できるでしょう。再生だけでなくもっと複雑な音声処理が必要であれば、 Web Audio API ははるかに強力な制御を行うことができます。

Web Audio API の強力な要素の一つは、厳格な「音声の呼び出しの制限」がないことです。例えば、同時に 32 音や 64 音などの上限はありません。プロセッサーの能力があれば、1,000 以上の音を詰まることなく再生することもできます。

コード例
----

boombox の外見は次の通りです。

![boombox の外見で、再生、パン、音量コントロールがあります](/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API/boombox.png)

これは古いカセットデッキで、再生ボタンがあり、音量とステレオ位置を変更することができる音量とパンのスライダーがあります。なお、もっと複雑にすることもできますが、この段階で簡単に学ぶには理想的なものです。

こちらから最終的なデモを Codepen で確認するか、ソースコードを GitHub で見るかしてください。

ブラウザーの対応
--------

最新のブラウザーは Web Audio API のほとんどの機能によく対応しています。 API の機能はたくさんありますので、もっと正確な情報は、各リファレンスページのブラウザー互換性一覧表をチェックする必要があるでしょう。

音声グラフ
-----

Web Audio API の中にあるすべてのものは音声グラフの概念に基づいており、ノードから成っています。

Web Audio API は**音声コンテキスト**に含まれる音声操作を扱い、**モジューラールーティング**が作れるように設計されています。基本的な音声の編集は**音声ノード**で行われ、それは互いに結びつき、**音声ルーティンググラフ**を構成します。加工する音を入力する入力ノード、望み通りに音を加工する加工ノード、音を保存したり聴いたりすることができる出力ノード (出力先) から成ります。

それぞれの音声ソースは、単一のコンテキストであっても、異なるチャンネルレイアウトに対応しています。このモジュラー設計によって、動的な効果を持つ複雑なオーディオ関数を作成することができます。

音声コンテキスト
--------

Web Audio API で何かをすることができるようにするには、音声コンテキストのインスタンスを作成する必要があります。この後で、 API のすべての機能にアクセスすることができます。

```js
// 古いブラウザー向け
const AudioContext = window.AudioContext || window.webkitAudioContext;

const audioContext = new AudioContext();
```

これを実行するとどうなるのでしょうか。 `BaseAudioContext` が自動的に生成され、オンライン音声コンテキストに拡張されます。これを行うのは、ライブサウンドを再生しようとしているからです。

**メモ:** 音声データを処理したいだけ、例えば、バッファリングとストリーミングのみを行い再生するのでなければ、 `OfflineAudioContext` を作成するようにしたほうが良いかもしれません。

音声の読み込み
-------

作成した音声コンテキストには、そこで再生する音声が必要になります。これを行う API は少ししかありません。簡単な方法で始めてみましょう — boombox を使うと、曲のトラック全体を再生するのが普通です。また、アクセシビリティのために、そのトラックを DOM に公開したほうがいいしょう。このページの曲を公開するために `<audio>` 要素を使用します。

```html
<audio src="myCoolTrack.mp3" type="audio/mpeg"></audio>
```

**メモ:** 読み込もうとしている音声ファイルが別なドメインにある場合は、 `crossorigin` 属性を使用する必要があるでしょう。詳しくはオリジン間リソース共有 (CORS) を参照してください。

Web Audio API を使用してできるすばらしいことをすべて利用するためには、この要素で入力元をつかみ、作成したコンテキストに*送り込む*ことが必要です。幸いにもちょうどこれを行うメソッド — `AudioContext.createMediaElementSource` が存在します。

```js
// get the audio element
const audioElement = document.querySelector("audio");

// pass it into the audio context
const track = audioContext.createMediaElementSource(audioElement);
```

**メモ:** 上記の `<audio>` 要素は DOM 内では `HTMLMediaElement` 型のオブジェクトで表され、これは独自の機能のセットを持っています。これらはすべてそのままです。 Web Audio API で音声を利用できるようにするだけです。

音声の制御
-----

ウェブ上で音声を再生するとき、ユーザーが制御できるようにすることが重要です。目的によって無数の選択肢がありますが、ここでは音声の再生と一時停止、トラックの音量と左右のパンの変更の機能を提供します。

JavaScript コードからプログラム的に音声を制御することは、ブラウザーの自動再生の対応方針の影響を受けますので、ユーザー (またはホワイトリスト) の許可がないとブロックされる場合があります。自動再生の方針は通常、明示的な許可かスクリプトが音声を再生できるようになる前のユーザーのページへの反応を必要とします。

これらの特別な要件が基本的に設定されているのは、予想外の音が迷惑で邪魔になり、アクセシビリティの問題を引き起こす可能性があるためです。これについては、記事メディアと Web Audio API の自動再生ガイドをご覧ください。

このスクリプトはユーザー入力イベント (例えば再生ボタンのクリック) への応答で音声を再生しているため、良い形であり自動再生ブロックの問題はないでしょう。ですから、再生や一時停止機能についての話を始めましょう。再生ボタンはトラックの再生中には一時停止ボタンに変わります。

```html
<button data-playing="false" role="switch" aria-checked="false">
  <span>Play/Pause</span>
</button>
```

トラックを再生する前に、音声グラフを音声ソースまたは入力ノードから出力先へ接続する必要があります。

既に入力ノードについては、 audio 要素を API に渡すことで作成しました。ほとんどの場合は、出力ノード作成する必要はなく、他のノードを `BaseAudioContext.destination` へ接続するだけです。

```js
track.connect(audioContext.destination);
```

これらのノードを図示するのによい方法は、音声グラフを描画することです。これは現在の音声グラフの見え方を表します。

![an audio graph with an audio element source connected to the default destination](/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API/graph1.jpg)

これで再生と一時停止機能を追加できるようになりました。

```js
// select our play button
const playButton = document.querySelector("button");

playButton.addEventListener(
  "click",
  function () {
    // check if context is in suspended state (autoplay policy)
    if (audioContext.state === "suspended") {
      audioContext.resume();
    }

    // play or pause track depending on state
    if (this.dataset.playing === "false") {
      audioElement.play();
      this.dataset.playing = "true";
    } else if (this.dataset.playing === "true") {
      audioElement.pause();
      this.dataset.playing = "false";
    }
  },
  false,
);
```

また、トラックの再生が終了したらどうするかを考慮しておく必要があります。 `HTMLMediaElement` は `ended` イベントを再生終了時に一度発生させるので、これを待ち受けして関連するコードを実行します。

```js
audioElement.addEventListener(
  "ended",
  () => {
    playButton.dataset.playing = "false";
  },
  false,
);
```

音の加工
----

基本的な加工ノードを追加して、音を変化させてみましょう。これは Web Audio API が本当に役立ち始めるところです。まず最初に、音量を変化させてみましょう。これは音の波がどれだけ大きいかを表す `GainNode` を使用すれば実現できます。

Web Audio API でノードを作成することができる方法は二通りあります。コンテキスト自身のファクトリメソッド (例えば `audioContext.createGain()`) を使用するか、ノードのコンストラクター (例えば `new GainNode()`) です。ここではファクトリメソッドを使用します。

```js
const gainNode = audioContext.createGain();
```

音声グラフを以前のものから更新する必要があり、入力を gain に接続してから、 gain ノードを出力先に接続します。

```js
track.connect(gainNode).connect(audioContext.destination);
```

これで音声グラフはこのようになります。

![an audio graph with an audio element source, connected to a gain node that modifies the audio source, and then going to the default destination](/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API/graph2.jpg)

gain の既定値は 1 です。これは現在の音量を同じに維持します。 gain は最小値がおよそ-3.4 で最大値はおよそ 3.4 です。ここで boombox は gain を最大 2 (元の音量の倍)、最小 0 (結果的に音声をミュートします) の範囲で動かせるようにします。

ユーザーがこれを制御できるようにしましょう。 — range 入力を使用します。

```html
<input type="range" id="volume" min="0" max="2" value="1" step="0.01" />
```

**メモ:** range 入力は、音声ノードの値を更新するのに実に手軽な入力型です。 range の値を音声ノードの引数に直接設定したり、使用したりすることができます。

それでは、ユーザーが値を変更したときに入力された値を取得して gain の値を更新するようにしましょう。

```js
const volumeControl = document.querySelector("#volume");

volumeControl.addEventListener(
  "input",
  function () {
    gainNode.gain.value = this.value;
  },
  false,
);
```

**メモ:** ノードオブジェクトの値 (例えば `GainNode.gain`) は単純な値ではなく、実際には `AudioParam` 型のオブジェクト — これが引数と呼ばれています。なぜかといえば、 `GainNode.gain` の `value` プロパティを設定しなければならず、 `gain` を直接設定するだけではないからです。これによってはるかに柔軟になり、例えば特定の値のセットを引数で渡して、一定の期間にわたって変化させたりすることができます。

素晴らしい、ユーザーがトラックの音量を追更新できるようになりました。ミュート機能を追加したい場合も gain ノードは完全なノードです。

アプリにステレオ位置を追加
-------------

学んだことを練習するために、もう一つの加工ノードを追加してみましょう。

ユーザーがステレオ機能を持っている場合、左右のスピーカーの間で音のバランスを変更する `StereoPannerNode` ノードがあります。

`StereoPannerNode` は、左右間のステレオパンを行う単純な用途のためのものです。 `PannerNode` というものもあり、こちらはもっと複雑な効果を生成するための、 3D 空間や音声の*空間化*などを大幅に制御することができます。これはゲームや 3D アプリなどで使用され、例えば頭上を飛ぶ鳥や、ユーザーの背後から聞こえる音などを生成します。

図示すると、音声グラフは次のようになります。

![入力ノード、2つの加工ノード (gain ノードと stereo panner ノード)、出力ノードを示した音声グラフを表す図です。](/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API/graphPan.jpg)

今回はノードを作成するコンストラクターメソッドを使用しましょう。この方法では、コンテキストとその特定のノードが取るオプションを渡す必要があります。

```js
const pannerOptions = { pan: 0 };
const panner = new StereoPannerNode(audioContext, pannerOptions);
```

**メモ:** ノードを作成するコンストラクターメソッドは、いまのところすべてのブラウザーで対応されている訳ではありません。古いファクトリメソッドの方がより広く対応されています。

個々の値の範囲は -1 (はるか左) と 1 (はるか右) の間です。今回も range 型の入力でこの引数を変更できるようにしましょう。

```html
<input type="range" id="panner" min="-1" max="1" value="0" step="0.01" />
```

以前行ったのと同じ方法で、この入力から得た値を使ってパンの値を調整します。

```js
const pannerControl = document.querySelector("#panner");

pannerControl.addEventListener(
  "input",
  function () {
    panner.pan.value = this.value;
  },
  false,
);
```

また音声グラフを調整して、すべてのノードを互いに接続しましょう。

```js
track.connect(gainNode).connect(panner).connect(audioContext.destination);
```

アプリに行うべき残りの作業はについては、こちらから Codepen 上で最終的なデモを確認してみてください。

まとめ
---

素晴らしい！ boombox が出来上がり、「テープ」を再生したり、音量やステレオ位置を調整したりできるようにするために、かなり基本的な音声グラフの作業を行いました。

これは、音声をウェブサイトやウェブアプリに追加するために始める必要がある基本事項のかなりの部分を構成しています。 Web Audio API にはさらに多くの機能がありますが、ノードの概念を把握し、音声グラフをまとめると、より複雑な機能を見に行くことができます。

他の例
---

Web Audio API についてもっと学ぶことができる他の例があります。

Voice-change-O-matic は、楽しい音声加工および音の視覚化を行うウェブアプリで、様々な効果や視覚化を選択することができます。このアプリケーションはかなり初歩的ですが、 Web Audio API の複数の機能を同時に使用する例を示しています。 (Voice-change-O-matic をライブで実行)

![音の波が表示され、音声効果や視覚化を選択することができるユーザーインターフェイス。](/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API/voice-change-o-matic.png)

他にも特に Web Audio API を紹介するために開発されたアプリケーションとして Violent Theremin があり、これはマウスポインターを動かすことで音高や音量を変更することができるシンプルなウェブアプリケーションです。これはサイケデリックなライトショーも提供します。 (Violent Theremin のソースコードを見る)

![虹色に埋め尽くされたページで、 Clear screen と mute と書かれた2つのボタンがあります。](/ja/docs/Web/API/Web_Audio_API/Using_Web_Audio_API/violent-theremin.png)

他にも例としては webaudio-examples リポジトリを参照してください。


Visualizations with Web Audio API - Web API

Visualizations with Web Audio API
=================================

Web Audio API の最も興味深い機能の 1 つは、オーディオソースから周波数、波形、その他のデータを抽出し、それを使用してビジュアライゼーションを作成する機能です。この記事では、方法について説明し、いくつかの基本的な使用例を示します。

**メモ:** すべてのコードスニペットの実際の例は、Voice-change-O-matic のデモでご覧いただけます。

基本的な概念
------

オーディオソースからデータを抽出するには `AudioContext.createAnalyser()` メソッドを使用して作成された `AnalyserNode` が必要です。 例:

```js
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var analyser = audioCtx.createAnalyser();
```

このノードは、ソースと destination の間のある時点でオーディオソースに接続されます。例:

```js
source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
analyser.connect(distortion);
distortion.connect(audioCtx.destination);
```

**メモ:** 入力がソースに対し、直接または別のノードを介して接続されているかぎり、アナライザの出力を別のノードに接続する必要はありません。

アナライザノードは、`AnalyserNode.fftSize`プロパティ値（指定されていない場合は、デフォルトは 2048 です）として指定する内容に応じて、特定の周波数ドメインで高速フーリエ変換（fft）を使用してオーディオデータをキャプチャします。

**メモ:** `AnalyserNode.minDecibels`と`AnalyserNode.maxDecibels`を使用して、fft データスケーリング範囲の最小値と最大値を指定することもできます。`AnalyserNode.smoothingTimeConstant`。それらの使い方の詳細については、それらのページをお読みください。

データを取得するには、周波数データを取得するために`AnalyserNode.getFloatFrequencyData()`および`AnalyserNode.getByteFrequencyData()`メソッドを使用する必要があります。`AnalyserNode.getByteTimeDomainData()`と `AnalyserNode.getFloatTimeDomainData()`を使用して波形データを取得します。

これらのメソッドはデータを指定された配列にコピーするので、データを受け取る前に新しい配列を作成して呼び出す必要があります。最初のものは 32 ビットの浮動小数点数を生成し、2 番目と 3 番目のものは 8 ビットの符号なし整数を生成するため、標準の JavaScript 配列ではなく、扱うデータに応じて`Float32Array` (en-US)または `Uint8Array` (en-US)配列を使う必要があります。

たとえば、2048 の fft サイズを扱っているとします、fft の半分である`AnalyserNode.frequencyBinCount`の値を返し、frequencyBinCount を引数として Uint8Array()を呼び出します。これがその fft サイズで収集するデータポイントの数です。

```js
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
```

実際にデータを取得して配列にコピーするには、配列を引数として渡して、必要なデータ収集メソッドを呼び出します。 例:

```js
analyser.getByteTimeDomainData(dataArray);
```

オーディオデータを配列に取り込んだ時点で可視化することができます。たとえば、HTML5 `<canvas>`にプロットすることができます。

いくつかの具体例を見てみましょう。

波形/オシロスコープの作成
-------------

オシロスコープのビジュアライゼーション（ Voice-change-O-matic の元のコードの Soledad Penadés に感謝します）を作成するには、前のセクションで説明した標準パターンに従って、バッファを設定します。

```js
analyser.fftSize = 2048;
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
```

次に、新しいビジュアライゼーションディスプレイの準備をするために、先に描画されたキャンバスをクリアします。

```js
canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
```

ここで `draw()` 関数を定義します。

```js
function draw() {
```

ここで `requestAnimationFrame()` を使用して、描画関数が開始後にループを維持します。

```js
var drawVisual = requestAnimationFrame(draw);
```

次に、TimeDomainData を取得し、配列にコピーします。

```js
analyser.getByteTimeDomainData(dataArray);
```

次に、初期値としてキャンバスを単色で塗りつぶします。

```js
canvasCtx.fillStyle = "rgb(200, 200, 200)";
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
```

描画する波の線幅と線の色を設定し、パスを描画します。

```js
canvasCtx.lineWidth = 2;
canvasCtx.strokeStyle = "rgb(0, 0, 0)";
canvasCtx.beginPath();
```

キャンバスの幅を配列の長さ(先ほど定義した frequencyBinCount と等しい)で除算することによって描かれる線の各セグメントの幅を決定し、次に、変数 x を定義して、パスの各セグメントを描画するために移動する位置を定義します。

```js
var sliceWidth = (WIDTH \* 1.0) / bufferLength;
var x = 0;
```

次にループを実行して、バッファ内の各ポイントの波の小さなセグメントの位置を、配列からのデータポイント値に基づいて特定の高さに定義し、線を次の波セグメントが描画されるべき場所に移動させます。

```js
for (var i = 0; i < bufferLength; i++) {
  var v = dataArray[i] / 128.0;
  var y = (v \* HEIGHT) / 2;

  if (i === 0) {
    canvasCtx.moveTo(x, y);
  } else {
    canvasCtx.lineTo(x, y);
  }

  x += sliceWidth;
}
```

最後に、キャンバスの右端の途中で線を終え、次に定義した線を描画します。

```js
      canvasCtx.lineTo(canvas.width, canvas.height/2);
      canvasCtx.stroke();
    };
```

このコードの最後では、 `draw()` 関数を呼び出してプロセス全体を開始します。

```js
draw();
```

これにより、1 秒に数回更新する素晴らしい波形表示が得られます。

![a black oscilloscope line, showing the waveform of an audio signal](/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API/wave.png)

周波数棒グラフの作成
----------

次に作成する素敵な小さなサウンドビジュアライゼーションは、Winamp のような周波数棒グラフの 1 つです。私たちは Voice-change-O-matic で入手できるものを持っています。それがどのように行われたかを見てみましょう。

まず、アナライザとデータ配列を設定し、`clearRect()` で現在のキャンバス表示を消去します。これまでの唯一の違いは、fft サイズをもっと小さくすることです。これは、グラフの各バーを細い一筋ではなくバーのように見えるほど大きくするためです。

```js
analyser.fftSize = 256;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
var dataArray = new Uint8Array(bufferLength);

canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
```

次に、`draw()` 関数をオフにし、`requestAnimationFrame()` でループを設定して、表示されたデータが更新されるようにしてから、各アニメーションフレームで表示をクリアします。

```js
    function draw() {
      drawVisual = requestAnimationFrame(draw);

      analyser.getByteFrequencyData(dataArray);

      canvasCtx.fillStyle = 'rgb(0, 0, 0)';
      canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
```

今度はバーの幅をキャンバスの幅をバーの数で割った値（バッファの長さ）に等しくなるように設定します。しかし、その幅を 2.5 倍にしています。なぜなら、毎日聞いている音の大部分が特定の低い周波数帯にあるので、ほとんどの周波数がその中にオーディオを持たないものとして戻ってくるからです。空の棒グラフを表示したくないので、棒の位置をずらして、意味のある高さを持つものでキャンバスの表示を埋めます。

そして、変数 `barHeight` と、現在のバーを描画する画面上の横位置を記録する変数 `x` を設定します。

```js
var barWidth = (WIDTH / bufferLength) \* 2.5;
var barHeight;
var x = 0;
```

前と同じように、for ループを開始し、`dataArray` の各値について繰り返します。それぞれの値について、`barHeight` を配列の値に設定し、`barHeight` に基づいて塗りつぶしの色を設定し（高めのバーは明るくなります）、`barWidth` の幅および `barHeight/2` の高さを持つ棒を、キャンバスの水平方向 `x` ピクセルの位置に描画します（我々は最終的に各バーを半分にカットすることにしたので、キャンバスにすべて収まるようになりました）。

各バーを描画する垂直オフセット位置については説明が必要でしょう。`HEIGHT-barHeight/2` です。私は、垂直位置を 0 に設定した場合のように各バーが上から下に表示されるのではなく、キャンバスの下から出すようにしたいため、これを実行しています。そのため、毎回垂直位置に、キャンバスの高さから `barHeight/2` を引いたものをセットしています。したがって、各バーは、キャンバスの途中から下まで描画されます。

```js
      for(var i = 0; i < bufferLength; i++) {
        barHeight = dataArray[i]/2;

        canvasCtx.fillStyle = 'rgb(' + (barHeight+100) + ',50,50)';
        canvasCtx.fillRect(x,HEIGHT-barHeight/2,barWidth,barHeight);

        x += barWidth + 1;
      }
    };
```

ここでも、コードの最後に `draw()` 関数を呼び出して、プロセス全体を動かすように設定します。

```js
draw();
```

このコードでは、次のような結果が得られます。

![a series of red bars in a bar graph, showing intensity of different frequencies in an audio signal](/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API/bar-graph.png)

**メモ:** この記事に記載されている例では、`AnalyserNode.getByteFrequencyData()`と`AnalyserNode.getByteTimeDomainData()`で使用法が示されています。実際の例は`AnalyserNode.getFloatFrequencyData()`と`AnalyserNode.getFloatTimeDomainData()`にあるので、私たちの Voice-change-O-matic-float-data デモを参照してください（ソースコードも参照してください）— これは、元の Voice-change-O-matic とまったく同じですが、符号なしバイトデータではなく、Float データを使用しています。


Basic concepts behind Web Audio API - Web API

Basic concepts behind Web Audio API
===================================

この記事では、アプリを経由した音声伝達方法の設計をする際に、十分な情報に基づいた決断をする助けとなるよう、 Web Audio API の特徴がいかに働いているか、その背後にある音声理論について説明します。この記事はあなたを熟練のサウンドエンジニアにさせることはできないものの、Web Audio API が動く理由を理解するための十分な背景を提供します。

オーディオグラフ
--------

Web Audio API は、オーディオコンテキスト内部でのオーディオオペレーションに対するハンドリングを含み、**モジュラールーティング**を可能とするためにデザインされてきました。基本となる音声操作を成す要素は、**オーディオルーチングラフ**を形作るために、互いに接続される**オーディオノード**によります。様々なタイプのチャンネルレイアウトと共に、いくつかの音声源もまた、単一のコンテキスト内部にて支持されています。このモジュラーデザインは、複雑なオーディオ機能を、ダイナミックな音響効果と共に創造するために必要な柔軟性を与えています。

オーディオノードは、それら入出力を経由し接続され、単一あるいは複数の音声源から開始される一連のチェーンを作り、一つ以上のノードを経由しつつ、最終的な行き先に届き終了します。ただし、たとえば、音声データを視覚化することのみを求める場合などは、このような目的地は省いて構いません。シンプルで典型的な Web Audio ワークフローでは、以下のようになります:

1. オーディオコンテキストの作成。
2. `<audio>` タグ、オシレーター、ストリーム等といった、該当コンテキスト内での音声源の作成。
3. リバーブ、バイカッドフィルター、パンナーコンプレッサーといった、音響効果用ノードの作成。
4. 例えばあなたのシステムのスピーカーなど、音声の最終的な行き先の選択。
5. 音声効果を（あるのならば）かけた後、最後に選択した行き先へ届いて終了する、音声源からの接続の確立。

**メモ:** 信号上で利用できるオーディオチャンネルの数字は、2.0 や 5.1 のように、しばしば、数値の形式で表現されます。これはchannel notationと呼ばれます。最初の数値は、該当の信号が含んでいるオーディオチャンネルの数です。ピリオドの後にある数値は、低音増強用出力として確保されているチャンネルの数を示しています。それらはしばしば**サブウーファー**とも称されます。

![A simple box diagram with an outer box labeled Audio context, and three inner boxes labeled Sources, Effects and Destination. The three inner boxes have arrow between them pointing from left to right, indicating the flow of audio information.](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/webaudioAPI_en.svg)

各入出力は、互いに特定のオーディオレイアウトを代表する、一つ以上のオーディオ**チャンネル**により構成されます。個別のチャンネル構造それぞれは、モノラル、ステレオ、クアッド、5.1 等を含んでサポートされています。

![Show the ability of AudioNodes to connect via their inputs and outputs and the channels inside these inputs/outputs.](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/mdn.png)

音声源はいくつかの方法で取得できます:

* JavaScript 内部で(オシレーターのような)オーディオノードにより、直接音声を生成。
* 未加工の PCM データから生成(この場合、該当オーディオコンテキストは、対応している音声フォーマット形式へのデコード手段を有しています)。
* (`<video>` や `<audio>` のような)HTML media elements より取得。
* (webcam やマイクロフォンのような)Web RTC `MediaStream` により直接取得。
オーディオデータ: サンプルとは？
-----------------

オーディオシグナルのプロセス中では、**サンプリング**とは連続的な信号を離散的な信号へ変換することを意味します。あるいは別の言い方をすると、バンドのライブ演奏のような連続的な音波を、コンピューターがその音声を区別されたブロックで処理できるようになる(離散時間信号の)一連のサンプルに変換します。

より詳しい情報は、Wikipedia の Sampling(Signal processing)から見ることができます。

オーディオバッファー: フレーム、サンプル、チャンネルセクション
--------------------------------

`AudioBuffer`は、チャンネルの数(モノラルの場合は 1,ステレオの場合は 2、等)、バッファー長すなわちバッファーに格納されているサンプルフレーム数、サンプルレートすなわち 1 秒間に再生されるサンプルフレーム数を、そのパラメーターとして持っています。

例として、float32 型の値 1 つは、(ステレオの場合は左側あるいは右側といった)特定のチャンネルにおいて、各特定時点おけるオーディオストリームの値を表しています。フレームまたはサンプルフレームは、一定時点における、音声を再生する全チャンネル分の値すべてのまとまりです。全チャンネルの全サンプルが一緒に再生されます(ステレオならば 2 チャンネル分、5.1 ならば 6 チャンネル分、等)。

サンプルレートとは、1 秒間に再生される、それらサンプルの数(または、1 フレームのサンプルすべてが同時に再生させることから、フレーム)であり、単位は Hz で測定されます。サンプルレートが高まるにつれ、音質は向上します。

モノラルとステレオのオーディオバッファーを見てみましょう。それらは 1 秒間、44100Hz で再生されます。

* モノラルバッファーは 44100 サンプル、44100 フレームで構成され、length プロパティは 44100 となる。
* ステレオバッファーは 88200 サンプル、44100 フレームで構成され、length プロパティは、そのフレーム数に等しいため 44100 のままである。

![A diagram showing several frames in an audio buffer in a long line, each one containing two samples, as the buffer has two channels, it is stereo.](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/sampleframe-english.png)

バッファが再生されると、最も左のサンプルフレームが聞こえ、次にそのサンプルフレームのすぐ隣のサンプルフレームが続いてゆきます。ステレオの場合、両方のチャンネルから同時に聴こえます。サンプルフレームは、チャンネルの数とは独立しているため非常に便利であり、正確に音声を取り扱う有効な手段として、時間を表現してくれます。

**メモ:** フレーム数から秒数を得るためには、フレーム数をサンプルレートで単に除算するだけです。サンプル数からフレーム数を得るためには、チャンネル数で単に除算するだけです。

以下はいくつかの単純なサンプルです:

```js
var context = new AudioContext();
var buffer = context.createBuffer(2, 22050, 44100);
```

**メモ:** デジタルオーディオにおいて、**44100**Hz(**44.1kHz** とも表記される)は一般的なサンプリング周波数です。なぜ 44.1kHz なのでしょう？

第一に、人間の耳の可聴範囲は、大雑把に 20 から 20000Hz の範囲です。Nyquist-Shannon のサンプリング定理により、サンプリング周波数は再現したい最大周波数の 2 倍以上でなくてはなりません。したがって、サンプリングレートは 40kHz 以上でなくてはなりません。

第二に、シグナルはサンプリング前に、偽信号の発生をさせないため、ローパスフィルタリングされていなければなりません。理想的ローパスフィルターが 20kHz 以下の周波数を(減衰させずに)完璧に通し、20kHz 以上の周波数を完璧に遮断する一方で、実際には、周波数が部分的に減衰する場所となる、トランジションバンドが必要です。このバンドが広くなるにつれ、減衰フィルターを作るのは簡単かつ効率的になります。44.1kHz サンプリング周波数は、2.05kHz のトランジションバンドを与えます。

この呼び出しをする場合、チャンネル数 2 のステレオバッファーを取得し、AudioContext 上で(非常に一般的で、通常のサウンドカードではほとんどはレートとなる)44100Hz にて再生される音源が、0.5 秒間続きます: 22050 フレーム/44100Hz = 0.5 秒。

```js
var context = new AudioContext();
var buffer = context.createBuffer(1, 22050, 22050);
```

この呼び出しをする場合、モノラルバッファーをチャンネル数 1 で取得し、AudioContext 上で 44100Hz にて再生される際に自動で 44100Hz へ*再サンプリングされ*(したがって 44100 フレームとなり)、1 秒間続きます: 44100 フレーム/44100Hz = 1 秒。

**メモ:** オーディオの再サンプリングは、画像のサイズ変更と非常に似たものです。例えば 16x16 の画像があり、32x32 のスペースを満たしたいとします。サイズ変更(あるいは再サンプリング)を行い、結果として(サイズ変更アルゴリズムの違いに依存して、ぼやけたりエッジができたりと)画質の低下を伴いますが、スペースを減らすサイズ変更済み画像が作れます。再サンプリングされたオーディオもまったく同じです。スペースを保てるものの、実際には高音域のコンテンツや高音を適切に再現することはできません。

### バッファーセクションの平面性対交差性

Web AudioAPI は平面的なバッファー形式を採用しています。左右のチャンネルは、以下のように格納されています:
```

LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR (for a buffer of 16 frames)
```

これは音声処理における一般的な形式です: これにより各チャンネルの独立した処理が簡単になります。

代わりの方式としては、交差的な形式が用いられます:
```

LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR (for a buffer of 16 frames)
```

この形式は、大掛かりな処理を必要としない音声を、格納し再生する目的として一般的です。例えばデコード済み MP3 音楽ストリームなどがあります。

Web Audio API は、音声処理に適することを理由に、平面的なバッファー**のみ**を採用しています。通常は平面的ですが、再生用に音声がサウンドカードへ送られる際は、交差的に変換されます。反対に、MP3 音声がデコードされる場合、元々は交差形式だったものの、音声処理のため平面形式へと変換されます。

オーディオチャンネル
----------

異なるオーディオバッファーでは、それぞれ異なった数のチャンネルを含んでいます: より基本的なモノラルとステレオ(それぞれチャンネル数 1 と 2)から始まり、より複雑なクアッドもしくは 5.1 のような、異なるサウンドサンプルが各チャンネルに含まれ、よりリッチな音声体験を導くセットもあります。チャンネルは通常、以下のテーブルに示される、標準的な略語によって示されます:

| *Mono* | `0: M: mono` |
| --- | --- |
| *Stereo* | `0: L: left 1: R: right` |
| *Quad* | `0: L: left 1: R: right 2: SL: surround left 3: SR: surround right` |
| *5.1* | `0: L: left 1: R: right 2: C: center 3: LFE: subwoofer 4: SL: surround left 5: SR: surround right` |

### アップミキシングとダウンミキシング

入力と出力のチャンネル数が一致しない場合、以下のルールに基づいてアップミキシングまたはダウンミキシングが行われます。これは`AudioNode.channelInterpretation` プロパティを `speakers` または `discrete` へとセットしてコントロールできます。

| 説明 | 入力チャンネル | 出力チャンネル | ミキシングルール |
| --- | --- | --- | --- |
| `speakers` | `1` *(Mono)* | `2` *(Stereo)* | *モノラルからステレオへのアップミックス。*`M`入力チャンネルは(`L` と
 `R` の)両出力チャンネル用に使われます。`output.L = input.Moutput.R = input.M` |
| `1` *(Mono)* | `4` *(Quad)* | *モノラルからクアッドへのアップミックス。*`M`
 入力チャンネルは(`L` と
 `R` の)ノンサラウンド出力チャンネル用に使われます。(`SL`
 と `SR` の)サラウンド出力チャンネルは無音です。`output.L = input.Moutput.R = input.Moutput.SL = 0output.SR
= 0` |
| `1` *(Mono)* | `6` *(5.1)* | *モノラルから 5.1.へのアップミックス。*`M`
 入力チャンネルは(`C`
 の)ノン中央出力チャンネル用に使われます。その他すべての(`L`,
 `R`, `LFE`, `SL`,
 `SR`)出力チャンネルは無音です。`output.L = 0output.R = 0``output.C = input.Moutput.LFE = 0output.SL = 0output.SR
= 0` |
| `2` *(Stereo)* | `1` *(Mono)* | *モノラルからステレオへのダウンミックス。*(`L`
 と
 `R`
 の)両入力チャンネルは等しく結合され、単一出力チャンネル(`M`)になります。`output.M = 0.5 * (input.L + input.R)` |
| `2` *(Stereo)* | `4` *(Quad)* | *ステレオからクアッドへのアップミックス。*左右(`L`
 と `R`)入力チャンネルはそれぞれ(`L` と
 `R` の)ノンサラウンド出力チャンネル用に使われます。(`SL`
 と `SR` の)サラウンド出力チャンネルは無音です。`output.L = input.Loutput.R = input.Routput.SL = 0output.SR
= 0` |
| `2` *(Stereo)* | `6` *(5.1)* | *ステレオから 5.1.へのアップミックス。*左右(`L`
 と `R`)入力チャンネルはそれぞれ(`L` と
 `R` の)ノンサラウンド出力チャンネル用に使われます。(`SL`
 と
 `SR`
 の)サラウンド出力チャンネル、中央チャンネル(`C`)、サブウーファー(`LFE`)はすべて同様に無音です。`output.L = input.Loutput.R = input.Routput.C = 0output.LFE
= 0output.SL = 0output.SR = 0` |
| `4` *(Quad)* | `1` *(Mono)* | *クアッドからモノラルへのダウンミックス。*(`L`,
 `R`, `SL`,
 `SR`)入力チャンネルは等しく結合され、単一出力チャンネル(`M`)になります。`output.M = 0.25 * (input.L + input.R + input.SL + input.SR)` |
| `4` *(Quad)* | `2` *(Stereo)* | *クアッドからステレオへのダウンミックス。両左入力チャンネル*(`L` と
 `SL`)は等しく結合され、単一左出力チャンネル(`L`)になります。同様に、*両右入力チャンネル*(`R`
 と
 `SR`)は等しく結合され、単一右出力チャンネル(`R`)になります。`output.L = 0.5 * (input.L + input.SL``)``output.R = 0.5 * (input.R + input.SR``)` |
| `4` *(Quad)* | `6` *(5.1)* | *クアッドから 5.1.へのアップミックス。*(`L`,
 `R`, `SL`,
 `SR`)入力チャンネルはそれぞれ(`L` と
 `R`
 の)出力チャンネル用に使われます。中央チャンネル(`C`)、サブウーファー(`LFE`)は無音です。`output.L = input.Loutput.R = input.Routput.C = 0output.LFE
= 0output.SL = input.SLoutput.SR = input.SR` |
| `6` *(5.1)* | `1` *(Mono)* | *5.1.からモノラルへのダウンミックス。左チャンネル*(`L`, `SL`)、右チャンネル(`R`,
 `SR`)、中央チャンネルはそれぞれ混合されます。サラウンドチャンネルは僅かに減衰され、標準側面チャンネルは利用のために、単一チャンネルを`√2/2`
 で乗算したものとして出力が補強されます。サブウーファー`(LFE)`チャンネルは失われます。`output.M = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL +
input.SR)` |
| `6` *(5.1)* | `2` *(Stereo)* | *5.1.からステレオへのダウンミックス。*中央チャンネルは各側面サラウンドチャンネル(`SL` と
 `SR`)と合算され、各側面チャンネルへ混合されます。2
 チャンネルへとミックスダウンされる過程は低労力で行われ、各々の場合について、`√2/2`
 で乗算されます。サブウーファー (`LFE`)
 チャンネルは失われます。`output.L = input.L + 0.7071 * (input.C + input.SL)output.R =
input.R` `+ 0.7071 * (input.C + input.SR)` |
| `6` *(5.1)* | `4` *(Quad)* | *5.1.からクアッドへのダウンミックス。*中央チャンネルは各側面ノンサラウンドチャンネル(`L` と
 `R`)と合算され、各側面チャンネルへ混合されます。2
 チャンネルへとミックスダウンされる過程は低労力で行われ、各々の場合について、`√2/2`
 で乗算されます。サラウンドチャンネルへの伝達には変化がありません。サブウーファー
 (`LFE`) チャンネルは失われます。`output.L = input.L + 0.7071 * input.Coutput.R = input.R +
0.7071 * input.C`output.SL = input.SLoutput.SR = input.SR`` |
| その他、非標準レイアウト |
 非標準チャンネルレイアウトは `channelInterpretation` を
 `discrete`
 へセットしたものとして操作されます。新たなスピーカーレイアウトの将来的な定義を、仕様書でははっきりと認めています。従ってこの予備部分は、チャンネルに用いられる特定の数字が示すブラウザーの挙動が、将来的に変更された場合のために用意されたものではありません。
  |
| `discrete` | 各 (`x`) | 各 (`y`) (`x<y` の場合) | *離散チャンネルのアップミックス。*各出力チャンネルに、それに対応する同番号の入力チャンネルによる入力をします。対応する入力チャンネルが存在しないチャンネルは無音になります。 |
| 各 (`x`) | 各 (`y`) (`x>y` の場合) | *離散チャンネルのダウンミックス。*各出力チャンネルに、それに対応する同番号の入力チャンネルによる入力をします。対応する出力チャンネルが存在しない入力チャンネルは無視されます。 |

視覚化
---

原則、オーディオ視覚化は出力オーディオデータ(基本的にはゲインまたは周波数データ)に時間毎にアクセスすることで行われ、更にグラフなどの視覚化出力へ渡すためのグラフィカル技術が用いられます。Web Audio API は `AnalyserNode` で、経由して渡されたオーディオ信号を変換せず利用することができます。ただしその出力は、`<canvas>` などのような視覚化技術へ受け渡せるオーディオデータです。

![Without modifying the audio stream, the node allows to get the frequency and time-domain data associated to it, using a FFT.](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/fttaudiodata_en.svg)

以下のメソッドを利用して、データの取得が可能です。

`AnalyserNode.getFloatFrequencyData()`

現在の周波数データを渡された `Float32Array` (en-US) 型配列にコピーします。

`AnalyserNode.getByteFrequencyData()`

現在の周波数データを渡された `Uint8Array` (en-US) 型配列(符号なしバイト配列)にコピーします。

`AnalyserNode.getFloatTimeDomainData()`

現在の波形データまたはタイムドメインデータを渡された`Float32Array` (en-US)型配列にコピーします。

`AnalyserNode.getByteTimeDomainData()`

現在の波形データまたはタイムドメインデータを渡された`Uint8Array` (en-US)型配列(符号なしバイト配列)にコピーします。

**メモ:** より詳しい情報は、Web Audio API 記事中の Visualizations with Web Audio API を参照してください。

立体化
---

(Web Audio API の `PannerNode` と `AudioListener` ノードによって操作される)立体音響化によって、オーディオシグナルの、空間を介した点における位置や振る舞いをモデル化することができ、その音声をリスナーが聞くことができます。

パンナーの位置は、直行座標の右側に描かれています。ドップラー効果を作るに必要な、速度ベクトルを用いた移動、そして方向コーンを用いた方向性があります。このコーンは、例えば無指向性音源などのため、とても大きくなり得ます。

![The PannerNode brings a spatial position and velocity and a directionality for a given signal.](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/pannernode_en.svg)

リスナーの位置は、直行座標の右側に描かれています。度ベクトルを用いた移動と、リスナーの頭がポイントされている(頭部側と顔面側の)二方向ベクターを用いた方向性があります。これらはそれぞれリスナーの頭部の頂点からの方向と、リスナーの鼻にポイントされている方向とを定義しており、これらは直角となっています。

![We see the position, up and front vectors of an AudioListener, with the up and front vectors at 90° from the other.](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/WebAudioListenerReduced.png)

**メモ:** より詳しい情報は、Web audio spatialization basics (en-US) を参照してください。

ファンインとファンアウト
------------

オーディオ用語では、**fan-in** は`ChannelMergerNode` が一連の単一入力ソースを受け、単一マルチチャンネル信号を出力するプロセスを意味します。

![](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/fanin.svg)

**Fan-out** はその対となるプロセスを意味します。`ChannelSplitterNode` が一つのマルチチャンネル入力源を受け、複数のモノラル出力信号を出力します。

![](/ja/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API/fanout.svg)


高度なテクニック: オーディオの生成とシーケンス - Web API

高度なテクニック: オーディオの生成とシーケンス
========================

このチュートリアルでは、音の作成と変更、時間とスケジューリングについて述べます。サンプルの読み込み、エンベロープ、フィルター、ウェーブテーブル、周波数変調を紹介します。これらの用語に慣れていて、ウェブオーディオAPIによるアプリケーションの入門を探しているなら、あなたは正しい場所に来ました。

**メモ:** 下記デモのソースコードは GitHub の MDN webaudio-examples リポジトリーの step-sequencer サブディレクトリーにあります。ライブデモを見ることもできます。

デモ
--

これからとても単純なステップシーケンサーを見ていきます。

![再生と BPM マスターコントロール、 4 つの異なる形で音色を制御する機能を備えたサウンドシーケンサーアプリケーションです。](/ja/docs/Web/API/Web_Audio_API/Advanced_techniques/sequencer.png)

実際には、ライブラリーを使う方が簡単です。ウェブオーディオ API は、それを前提に構築されています。もっと複雑なものを作ろうとしているのであれば、 tone.js が始めるには最適な場所でしょう。しかし、私たちは学習の練習として、最初の原理からこのようなデモを作成する方法を示したいと思います。

インターフェイスはマスターコントローラーで構成されており、シーケンサーを再生/停止したり、BPM（1　分間の拍数）を調整して「音楽」を速くしたり遅くしたりすることができます。

4 つの異なる音（ボイス）を鳴らすことができます。各ボイスには 4 つのボタンがあり、音楽の 1 小節のそれぞれの拍に 1 つずつ対応しています。それらが有効になると、音符が音になります。楽器が演奏すると、この拍の集合を移動され、小節をループします。

各ボイスにはローカルコントロールもあり、ボイスを作成するために使用する各テクニック特有のエフェクトや引数を操作することができます。使用しているメソッドは以下の通りです。

| ボイス名 | 技術 | 関連するウェブオーディオ API の機能 |
| --- | --- | --- |
| "Sweep" | 発振器、周期波 | `OscillatorNode`,
 `PeriodicWave` |
| "Pulse" | 発振器の乗算 | `OscillatorNode` |
| "Noise" | ランダムノイズバッファー、バイクワッドフィルター | `AudioBuffer`,
 `AudioBufferSourceNode`,
 `BiquadFilterNode` (en-US) |
| "Dial up" | サンプル音を読み込んで再生 | `BaseAudioContext/decodeAudioData`,
 `AudioBufferSourceNode` |

**メモ:** 私たちがこのインストゥルメントを作成したのは、音を良くするためではなく、デモコードを提供するためです。このデモは、そのようなインストの非常に単純化されたバージョンを表します。音はダイアルアップモデムに基づいています。このような機器がどのような音で鳴るのかご存じない方は、こちらで試聴できます。

音声コンテキストの作成
-----------

すぐに使用することになりますが、ウェブ音声 API アプリは音声コンテキストから始まります。

```js
const audioCtx = new AudioContext();
```

"sweep" — 発振器、周期波、エンベロープ
------------------------

"sweep" 音、つまりダイヤルアップした時に聞こえる最初の音を呼び出すために、音を生成する発振器を作成します。

`OscillatorNode` で、基本的な波形（サイン波、矩形波、三角波、ノコギリ波）が決まります。しかし、既定値では標準の波形を使用する代わりに、 `PeriodicWave` インターフェイスと波形テーブルに設定した値を使って自分自身で作成します。このカスタム波を発振器で使用するには、`PeriodicWave()` コンストラクターを使用します。

### 周期波

最初に、周期波を作成します。そのためには、 `PeriodicWave()` コンストラクターに実数と虚数の値を渡す必要があります。

```js
const wave = new PeriodicWave(audioCtx, {
  real: wavetable.real,
  imag: wavetable.imag,
});
```

**メモ:** この例では、波動テーブルは非常に多くの値があるため、別個の JavaScript ファイル (`wavetable.js`) で保持されています。 Google Chrome Labs のウェブオーディオ API の例で得られる波形テーブルのリポジトリーから取りました。

### 発振器

これで `OscillatorNode` を作成し、その波を作成したものに設定することができます。

```js
function playSweep(time) {
  const osc = new OscillatorNode(audioCtx, {
    frequency: 380,
    type: "custom",
    periodicWave: wave,
  });
  osc.connect(audioCtx.destination);
  osc.start(time);
  osc.stop(time + 1);
}
```

ここで関数に時刻の引数を渡していますが、これは後で掃除のスケジュールを立てるのに使用します。

### 振幅の制御

これは素晴らしいことですが、振幅エンベロープがあればいいと思いませんか？単純なものを作成して、ウェブオーディオ API でエンベロープを作成するのに必要なメソッドを使用してみましょう。

エンベロープにアタックとリリースがあるとします。インターフェイスの範囲入力を使ってユーザーがこれらを制御できるようにします。

```html
<label for="attack">Attack</label>
<input
 name="attack"
 id="attack"
 type="range"
 min="0"
 max="1"
 value="0.2"
 step="0.1" />

<label for="release">Release</label>
<input
 name="release"
 id="release"
 type="range"
 min="0"
 max="1"
 value="0.5"
 step="0.1" />
```

これで JavaScript で変数を作成し、入力値が更新されたときにその変数を変更するようにします。

```js
let attackTime = 0.2;
const attackControl = document.querySelector("#attack");
attackControl.addEventListener(
  "input",
  (ev) => {
    attackTime = parseInt(ev.target.value, 10);
  },
  false,
);

let releaseTime = 0.5;
const releaseControl = document.querySelector("#release");
releaseControl.addEventListener(
  "input",
  (ev) => {
    releaseTime = parseInt(ev.target.value, 10);
  },
  false,
);
```

### 最終的な playSweep() 関数

これで `playSweep()` 関数を展開させることができました。 `GainNode` を追加して、それを音声グラフに接続して、音に振幅の変化を加える必要があります。ゲインノードは 1 つのプロパティを持っています。 `gain` で `AudioParam` 型です。

これは有用なことです。これで、ゲイン値に関する音声引数のメソッドのパワーを利用し始めることができます。ある時刻に値を設定することもできますし、 `AudioParam.linearRampToValueAtTime` のようなメソッドで時間を値を変更することもできます。

前述のように、アタックとリリースには `linearRampToValueAtTime` メソッドを使用します。このメソッドには 2 つの引数を取ります。設定したい引数の値（この場合はゲイン）と、いつ設定するかです。この場合、いつかは入力コントロールで制御します。例えば下記の例では、アタック範囲を定義する時刻の間、ゲインは直線的に 1 に増加します。同様に、リリースの場合、ゲインは、リリース入力が設定されている時刻にわたって、直線的な割合で 0 に集合します。

```js
const sweepLength = 2;
function playSweep(time) {
  const osc = new OscillatorNode(audioCtx, {
    frequency: 380,
    type: "custom",
    periodicWave: wave,
  });

  const sweepEnv = new GainNode(audioCtx);
  sweepEnv.gain.cancelScheduledValues(time);
  sweepEnv.gain.setValueAtTime(0, time);
  sweepEnv.gain.linearRampToValueAtTime(1, time + attackTime);
  sweepEnv.gain.linearRampToValueAtTime(0, time + sweepLength - releaseTime);

  osc.connect(sweepEnv).connect(audioCtx.destination);
  osc.start(time);
  osc.stop(time + sweepLength);
}
```

"pulse" — 低周波発振器変調
------------------

これで sweep ができました。次に移動して、素敵なパルス音を見てみましょう。基本的な発振器で、 2 つ目の発振器で変調することで実現できます。

### 初期発振器

最初の `OscillatorNode` はスイープ音と同じように設定しますが、独自の波形を設定するための波形テーブルを使用しません。

```js
const osc = new OscillatorNode(audioCtx, {
  type: "sine",
  frequency: pulseHz,
});
```

これで `GainNode` を作成します。 2 つ目の低周波発振器で発振させる `gain` 値です。

```js
const amp = new GainNode(audioCtx, {
  value: 1,
});
```

### 第二の低周波発振器の作成

これで、最初のサイン波の増幅率を変えるために、 2 つ目の矩形波（またはパルス）発振器を作成します。

```js
const lfo = new OscillatorNode(audioCtx, {
  type: "square",
  frequency: 30,
});
```

### グラフの接続

ここで重要なのは、グラフを正しく接続することと、両方の発振器を起動することです。

```js
lfo.connect(amp.gain);
osc.connect(amp).connect(audioCtx.destination);
lfo.start();
osc.start(time);
osc.stop(time + pulseTime);
```

**メモ:** また、作成するどちらの発振器にも既定値の波形テーブルを使用する必要はありません。前と同じように波形テーブルと周期波メソッドを使用できます。最小のノードで、多くの可能性があります。

### パルスのユーザーコントロール

UI コントロールのために、発振器の両方の周波数を公開し、範囲入力で制御できるようにしましょう。一方は音程を変更し、もう一方はパルスが最初の波をどのように変調するかを変更します。

```html
<label for="hz">Hz</label>
<input
 name="hz"
 id="hz"
 type="range"
 min="660"
 max="1320"
 value="880"
 step="1" />
<label for="lfo">LFO</label>
<input name="lfo" id="lfo" type="range" min="20" max="40" value="30" step="1" />
```

前回と同様に、ユーザーが引数の範囲を変更したときに、引数を変化させます。

```js
let pulseHz = 880;
const hzControl = document.querySelector("#hz");
hzControl.addEventListener(
  "input",
  (ev) => {
    pulseHz = parseInt(ev.target.value, 10);
  },
  false,
);

let lfoHz = 30;
const lfoControl = document.querySelector("#lfo");
lfoControl.addEventListener(
  "input",
  (ev) => {
    lfoHz = parseInt(ev.target.value, 10);
  },
  false,
);
```

### 最終的な playPulse() 関数

`playPulse()` 関数の全体は以下のようになります。

```js
const pulseTime = 1;
function playPulse(time) {
  const osc = new OscillatorNode(audioCtx, {
    type: "sine",
    frequency: pulseHz,
  });

  const amp = new GainNode(audioCtx, {
    value: 1,
  });

  const lfo = new OscillatorNode(audioCtx, {
    type: "square",
    frequency: lfoHz,
  });

  lfo.connect(amp.gain);
  osc.connect(amp).connect(audioCtx.destination);
  lfo.start();
  osc.start(time);
  osc.stop(time + pulseTime);
}
```

"noise" — バイクワッドフィルター付きランダムノイズバッファー
-----------------------------------

ノイズを出すことが必要になりました。モデムにはすべてノイズがあります。音声データの場合、ノイズは単なる乱数なので、コードで作成するのは比較的簡単なことです。

### 音声バッファーの作成

しかし、ウェブオーディオ API が理解できる空のコンテナーを作成する必要があります。そこで `AudioBuffer` オブジェクトの出番です。ファイルを取得してバッファーにデコードすることもできますし（チュートリアルの後半で説明します）、空のバッファーを作成してデータを入れることもできます。

ノイズについては、後者で説明します。最初に、作成するバッファーサイズを計算する必要があります。これには `BaseAudioContext.sampleRate` プロパティが使用できます。

```js
const bufferSize = audioCtx.sampleRate \* noiseDuration;
// 空のバッファーを作成
const noiseBuffer = new AudioBuffer({
  length: bufferSize,
  sampleRate: audioCtx.sampleRate,
});
```

これで -1 から 1 の間の乱数で埋めることができます。

```js
// バッファーにノイズを充填
const data = noiseBuffer.getChannelData(0);
for (let i = 0; i < bufferSize; i++) {
  data[i] = Math.random() \* 2 - 1;
}
```

**メモ:** なぜ -1～1 なのでしょうか？ファイルやスピーカーに音を出力する場合、 0dB が上限のスケール（メディアや DAC の固定的な数値の限界）を表す数値が必要です。浮動小数点の音声では、 1 は信号の数学的処理をするために「上限」に割り当てられる便利な数字です。そのため、発振器、ノイズジェネレーター、そして他の音源は、通常 -1 から 1 の範囲の双極信号を出力します。ブラウザーはこの範囲外の値をクランプします。

### バッファーソースの作成

これで音声バッファーができ、データが入りました。バッファーをソースとして使用できるノードをグラフに追加する必要があります。そのために `AudioBufferSourceNode` を作成し、作成したデータを渡します。

```js
// 作成したデータのバッファーソースを作成
const noise = new AudioBufferSourceNode(audioCtx, {
  buffer: noiseBuffer,
});
```

これを音声グラフにつないで再生します。

```js
noise.connect(audioCtx.destination);
noise.start();
```

かなりヒスノイズというか、ちぐはぐな音であることにお気づきでしょう。ホワイトノイズを作成したのですから、そうあるべきです。値が-1から1まで広がっていますが、これはすべての周波数にピークがあることを意味しています。この関数を0.5から-0.5までの値のみに変更し、ピークを取り除き、不快感を縮小することも可能です。作成したノイズをフィルターに通してみましょう。

### バイクワッドフィルターを追加して混合

ピンクまたはブラウンノイズの範囲にあるものが必要です。高い周波数と単発の低い周波数をカットしたいのです。バンドパスバイクワッドフィルターを選びましょう。

**メモ:** ウェブオーディオ API には、 `BiquadFilterNode` (en-US) と `IIRFilterNode` の 2 つの種類のフィルタノードがあります。ほとんどの場合、バイクワッドフィルタで十分です - ローパス、ハイパス、バンドパスなどの様々な種類があります。しかし、もっと特注のものを探しているのであれば、 IIR フィルターが良い選択肢かもしれません。詳しくは IIR フィルターの使用 (en-US)を参照してください。

この配線は、前に見たのと同じです。 `BiquadFilterNode` (en-US) を作成し、必要なプロパティを設定し、グラフを通して接続します。例えば、バンドパス型で周波数を設定するには、中間周波数を調整します。しかし、ローパスでは、一番上の周波数を設定します。

```js
// 出力フィルター
const bandpass = new BiquadFilterNode(audioCtx, {
  type: "bandpass",
  frequency: bandHz,
});

// グラフへ接続
noise.connect(bandpass).connect(audioCtx.destination);
```

### ノイズユーザーコントロール

UI 上では、前回と同じように、ノイズの継続時間と帯域したい周波数を公開し、ユーザーが範囲入力とイベントハンドラーを使って調整できるようにします。

```html
<label for="duration">Duration</label>
<input
 name="duration"
 id="duration"
 type="range"
 min="0"
 max="2"
 value="1"
 step="0.1" />

<label for="band">Band</label>
<input
 name="band"
 id="band"
 type="range"
 min="400"
 max="1200"
 value="1000"
 step="5" />
```

```js
let noiseDuration = 1;
const durControl = document.querySelector("#duration");
durControl.addEventListener(
  "input",
  (ev) => {
    noiseDuration = parseFloat(ev.target.value);
  },
  false,
);

let bandHz = 1000;
const bandControl = document.querySelector("#band");
bandControl.addEventListener(
  "input",
  (ev) => {
    bandHz = parseInt(ev.target.value, 10);
  },
  false,
);
```

### 最終的な playNoise() 関数

`playNoise()` 関数の全体は次のようになります。

```js
function playNoise(time) {
  const bufferSize = audioCtx.sampleRate \* noiseDuration; // set the time of the note

  // Create an empty buffer
  const noiseBuffer = new AudioBuffer({
    length: bufferSize,
    sampleRate: audioCtx.sampleRate,
  });

  // Fill the buffer with noise
  const data = noiseBuffer.getChannelData(0);
  for (let i = 0; i < bufferSize; i++) {
    data[i] = Math.random() \* 2 - 1;
  }

  // Create a buffer source for our created data
  const noise = new AudioBufferSourceNode(audioCtx, {
    buffer: noiseBuffer,
  });

  // Filter the output
  const bandpass = new BiquadFilterNode(audioCtx, {
    type: "bandpass",
    frequency: bandHz,
  });

  // Connect our graph
  noise.connect(bandpass).connect(audioCtx.destination);
  noise.start(time);
}
```

"Dial-up" — 音の例の読み込み
--------------------

これまで使用してきたメソッドを使って、いくつかの発振器を一緒に鳴らすことで、電話のダイヤル音 (DTMF) をエミュレートすることは、十分に簡単です。代わりに、この節ではサンプルファイルを読み込んで、その内容を見ていきます。

### サンプルの読み込み

使用する前にファイルが読み込まれ、バッファーにデコードされたことを確認したいので、 `async` 関数を作成してこれをできるようにしましょう。

```js
async function getFile(audioContext, filepath) {
  const response = await fetch(filepath);
  const arrayBuffer = await response.arrayBuffer();
  const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
  return audioBuffer;
}
```

そして、この関数を呼び出すときに `await` 演算子を使うことで、実行が完了したときに後続のコードを確実に実行することができます。

サンプルを設定するために、もう一つ `async` 関数を作成しましょう。この2つの非同期関数を素敵なプロミスパターンで結合することで、このファイルが読み込まれてバッファーされたときにさらなるアクションを実行することができます。

```js
async function setupSample() {
  const filePath = "dtmf.mp3";
  const sample = await getFile(audioCtx, filePath);
  return sample;
}
```

**メモ:** 上記の関数を簡単に変更し、ファイルの配列を引き継いでループさせ、複数のサンプルを読み込むことができます。このテクニックは、より複雑なインストゥルメントやゲームに便利でしょう。

We can now use `setupSample()` like so:

```js
setupSample().then((sample) => {
  // sample is our buffered file
  // …
});
```

サンプルを再生する準備ができたら、プログラムに UI を設定すれば、使えるようになります。

### サンプルの再生

他の音と同じように、 `playSample()` 関数を作成しましょう。今回は `AudioBufferSourceNode` を作成し、取得しデコードしたバッファーデータを入れて再生します：

```js
function playSample(audioContext, audioBuffer, time) {
  const sampleSource = new AudioBufferSourceNode(audioContext, {
    buffer: audioBuffer,
    playbackRate,
  });
  sampleSource.connect(audioContext.destination);
  sampleSource.start(time);
  return sampleSource;
}
```

**メモ:** `stop()` は `AudioBufferSourceNode` で呼び出すことができますが、これはサンプルの再生が完了したときに自動的に行われます。

### ダイアルアップのユーザーコントロール

`AudioBufferSourceNode` には `playbackRate` プロパティがあります。このプロパティを UI に公開し、サンプルを速くしたり遅くしたりできるようにしましょう。先ほどと同じような方法で行います。

```html
<label for="rate">Rate</label>
<input
 name="rate"
 id="rate"
 type="range"
 min="0.1"
 max="2"
 value="1"
 step="0.1" />
```

```js
let playbackRate = 1;
const rateControl = document.querySelector("#rate");
rateControl.addEventListener(
  "input",
  (ev) => {
    playbackRate = parseInt(ev.target.value, 10);
  },
  false,
);
```

### 最終的な playSample() 関数

次に `playSample()` 関数に `playbackRate` プロパティを更新する行を追加します。最終的にはこのようになります。

```js
function playSample(audioContext, audioBuffer, time) {
  const sampleSource = new AudioBufferSourceNode(audioCtx, {
    buffer: audioBuffer,
    playbackRate,
  });
  sampleSource.connect(audioContext.destination);
  sampleSource.start(time);
  return sampleSource;
}
```

**メモ:** この音声ファイルは soundbible.com から引用しました。

時刻に合わせた音声の再生
------------

デジタル音声アプリケーションでよくある問題は、ビートが一定に保たれ、時刻がずれないように音を再生することです。

`for` ループの中で再生するように音色をスケジュールすることもできますが、この場合の最大の問題は再生中に更新することで、そのための UI コントロールはすでに実装しています。また、楽器全体の BPM コントロールを検討するのも実にいいでしょう。音符がいつ演奏されるかを先に見て、それをキューに入れるのです。 `currentTime` プロパティで正確な時刻に始めることができ、変更も考えることができます。

**メモ:** この記事は、 Chris Wilson's A Tale Of Two Clocks (2013) の記事を大幅に縮小したもので、このメソッドについてもっと詳しく書かれています。ここですべてを繰り返す意味はありませんが、この記事を読んでこのメソッドを使用することを強くお勧めします。ここでのコードの多くは彼のメトロノームの例から引用しています。彼はこの記事の中で参照しています。

既定の BPM (beats per minute) を設定することから始めましょう。この BPM はユーザーも制御することができます。

```js
let tempo = 60.0;
const bpmControl = document.querySelector("#bpm");

bpmControl.addEventListener(
  "input",
  (ev) => {
    tempo = parseInt(ev.target.value, 10);
  },
  false,
);
```

そして、どれくらい先まで見ていくのか、どれくらい先のスケジュールを定義する変数を作成します。

```js
const lookahead = 25.0; // How frequently to call scheduling function (in milliseconds)
const scheduleAheadTime = 0.1; // How far ahead to schedule audio (sec)
```

音符を 1 拍分前に移動し、 4 番目（最後）の音符に到達したら最初の音符にループで戻る関数を作成してみましょう。

```js
let currentNote = 0;
let nextNoteTime = 0.0; // when the next note is due.

function nextNote() {
  const secondsPerBeat = 60.0 / tempo;

  nextNoteTime += secondsPerBeat; // Add beat length to last beat time

  // Advance the beat number, wrap to zero when reaching 4
  currentNote = (currentNote + 1) % 4;
}
```

演奏する音符の参照キューと、前回作成した関数を使用して演奏する機能を作成したいと思います。

```js
const notesInQueue = [];

function scheduleNote(beatNumber, time) {
  // Push the note on the queue, even if we're not playing.
  notesInQueue.push({ note: beatNumber, time });

  if (pads[0].querySelectorAll("input")[beatNumber].checked) {
    playSweep(time);
  }
  if (pads[1].querySelectorAll("input")[beatNumber].checked) {
    playPulse(time);
  }
  if (pads[2].querySelectorAll("input")[beatNumber].checked) {
    playNoise(time);
  }
  if (pads[3].querySelectorAll("input")[beatNumber].checked) {
    playSample(audioCtx, dtmf, time);
  }
}
```

ここでは、現在の時刻を見て、次の音符の時刻と比較します。両者が一致すると、前回までの 2 つの関数を呼び出します。

`AudioContext` オブジェクトインスタンスには `currentTime` プロパティがあり、最初にコンテキストを作成してから何秒経ったかを取得することができます。ステップシーケンサでタイミングをとるために使用します。これは非常に正確で、小数点以下 15 桁程度で正確な浮動小数点値を返します。

```js
let timerID;
function scheduler() {
  // While there are notes that will need to play before the next interval,
  // schedule them and advance the pointer.
  while (nextNoteTime < audioCtx.currentTime + scheduleAheadTime) {
    scheduleNote(currentNote, nextNoteTime);
    nextNote();
  }
  timerID = setTimeout(scheduler, lookahead);
}
```

`draw()` 関数も UI を更新するために必要で、そうすれば拍子がいつ進むかを見ることができます。

```js
let lastNoteDrawn = 3;
function draw() {
  let drawNote = lastNoteDrawn;
  const currentTime = audioCtx.currentTime;

  while (notesInQueue.length && notesInQueue[0].time < currentTime) {
    drawNote = notesInQueue[0].note;
    notesInQueue.shift(); // Remove note from queue
  }

  // We only need to draw if the note has moved.
  if (lastNoteDrawn !== drawNote) {
    pads.forEach((pad) => {
      pad.children[lastNoteDrawn \* 2].style.borderColor = "var(--black)";
      pad.children[drawNote \* 2].style.borderColor = "var(--yellow)";
    });

    lastNoteDrawn = drawNote;
  }
  // Set up to draw again
  requestAnimationFrame(draw);
}
```

すべてを用意する
--------

これで、あとはインストゥルメントを演奏する前にサンプルを読み込むだけです。ファイルが取得され、デコードされると消えるローディング画面を追加します。そして、プレイボタンのクリックイベントを使用してスケジューラーを開始できるようにします。

```js
// When the sample has loaded, allow play
const loadingEl = document.querySelector(".loading");
const playButton = document.querySelector("#playBtn");
let isPlaying = false;
setupSample().then((sample) => {
  loadingEl.style.display = "none";

  dtmf = sample; // to be used in our playSample function

  playButton.addEventListener("click", (ev) => {
    isPlaying = !isPlaying;

    if (isPlaying) {
      // Start playing

      // Check if context is in suspended state (autoplay policy)
      if (audioCtx.state === "suspended") {
        audioCtx.resume();
      }

      currentNote = 0;
      nextNoteTime = audioCtx.currentTime;
      scheduler(); // kick off scheduling
      requestAnimationFrame(draw); // start the drawing loop.
      ev.target.dataset.playing = "true";
    } else {
      clearTimeout(timerID);
      ev.target.dataset.playing = "false";
    }
  });
});
```

まとめ
---

これでブラウザー内に楽器ができました。これらのテクニックを発展させて、もっと手の込んだものを作成することができます。


Cache: matchAll() メソッド - Web API

Cache: matchAll() メソッド
======================

**`matchAll()`** は `Cache` インターフェイスのメソッドで、`Cache` オブジェクト内の一致するすべてのレスポンスの配列に解決される `Promise` を返します。

構文
--

```js
matchAll()
matchAll(request)
matchAll(request, options)
```

### 引数

`request` 省略可

`Cache` 内でレスポンスを見つけようとしている `Request`。 これは、`Request` オブジェクトまたは URL です。この引数を省略すると、このキャッシュ内のすべてのレスポンスのコピーが取得されます。

`options` 省略可

実行する照合の特定の制御オプションを設定できるオプションオブジェクト。 使用可能なオプションは次のとおりです。

`ignoreSearch`

論理値で、照合操作で URL のクエリー文字列を無視するかどうかを指定します。 `true` に設定すると、`http://foo.com/?value=bar` の `?value=bar` 部分を、照合の実行時に無視します。 既定値は `false` です。

`ignoreMethod`

論理値で、`true` に設定すると、照合操作で `Request` の `http` メソッドを検証しないようにします（通常は、`GET` および `HEAD` のみが許可されます）。 既定値は `false` です。

`ignoreVary`

論理値で、`true` に設定すると、`VARY` ヘッダーの照合を実行しないように照合操作に指示します。 つまり、URL が一致する場合、`Response` オブジェクトに `VARY` ヘッダーがあるかどうかに関係なく一致します。 既定値は `false` です。

### 返値

`Cache` オブジェクト内のすべての一致するレスポンスの配列に解決される `Promise`。

**メモ:** `Cache.match()` は、一致するすべてのレスポンスの配列で解決するのではなく、最初に一致するレスポンスのみ（つまり、`response[0]`）で解決することを除いて、基本的に `Cache.matchAll()` と同じです。

例
-

以下の例では、 `v1` キャッシュにある、URL `/` と潜在的な引数に一致するすべてのレスポンスを受け取ります。 `{ ignoreSearch: true }` を使用することで、 `matchAll` を使用すると、 `/` だけでなく `/?value=bar` も取得することができます。

そして、一致したレスポンスの数をログ出力します。

```js
caches.open("v1").then((cache) => {
  cache.matchAll("/", { ignoreSearch: true }).then((responses) => {
    console.log(`Found ${responses.length} matching responses`);
  });
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-matchall |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


Cache: add() メソッド - Web API

Cache: add() メソッド
=================

**`add()`** は `Cache` インターフェイスのメソッドで、URL を受け取り、リソースを取得して、指定されたキャッシュに結果のレスポンスオブジェクトを追加します。

`add()` メソッドは、機能的に次の例と同じです。

```js
fetch(url).then((response) => {
  if (!response.ok) {
    throw new TypeError("bad response status");
  }
  return cache.put(url, response);
});
```

より複雑な操作では、 `Cache.put()` を直接使用する必要があります。

**メモ:** `add()` は、前にキャッシュに保存された、リクエストに一致するキー/値の組を上書きます。

構文
--

```js
add(request)
```

### 引数

`request`

キャッシュに加えるリクエスト。 `Request` オブジェクトか URL を指定できる。

この引数は `Request()` コンストラクターの引数として使用されるので、 URL はそのコンストラクターと同じルールに従います。すなわち、URL はベース URL からの相対パスです。ベース URL は、ウィンドウコンテキストでは文書内の `baseURI`、ワーカーコンテキストでは `WorkerGlobalScope.location` が該当します。

### 返値

`undefined` で解決する `Promise` です。

### 例外

`TypeError`

URL スキームが `http` でも `https` でもない場合。

レスポンスステータスが 200 番台（つまり、成功レスポンス）ではありません。これはリクエストが成功を返さない場合や、リクエストがオリジン間の CORS ではないリクエスト (*cross-origin no-cors* request) の場合も発生します（この場合、ステータスが常に 0 と報告されます）。

例
-

このコードブロックは、`InstallEvent` が発行されるのを待ってから、アプリがインストールプロセスを処理するために、`waitUntil` を実行します。この処理は、新しいキャッシュを作成するための `CacheStorage.open` の呼び出しと、資産を追加するための `Cache.add` の使用で構成されています。

```js
this.addEventListener("install", (event) => {
  event.waitUntil(caches.open("v1").then((cache) => cache.add("/index.html")));
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-add |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


Cache: delete() メソッド - Web API

Cache: delete() メソッド
====================

**`delete()`** は `Cache` インターフェイスのメソッドで、キーがリクエストである `Cache` 項目を探し、見つかった場合はその `Cache` 項目を削除して、`true` に解決する `Promise` を返します。 `Cache` 項目が見つからない場合は、`false` に解決します。

構文
--

```js
delete(request)
delete(request, options)
```

### 引数

`request`

削除しようとしている `Request`。 これは、`Request` オブジェクトまたは URL です。

`options` 省略可

プロパティが `delete` 操作でどのように照合するかを制御するオブジェクト。 使用可能なオプションは次のとおりです。

`ignoreSearch`

論理値で、照合操作で URL のクエリー文字列を無視するかどうかを指定します。 `true` に設定すると、`http://foo.com/?value=bar` の `?value=bar` 部分を、照合の実行時に無視します。既定値は `false` です。

`ignoreMethod`

論理値で、`true` に設定すると、照合操作が `Request` の `HTTP` メソッドを検証しないようにするします（通常、`GET` および `HEAD` のみが許可されます）。既定値は `false` です。

`ignoreVary`

論理値で、`true` に設定すると、`VARY` ヘッダーを照合しないように照合操作に指示します。 つまり、URL が一致した場合は、`Response` オブジェクトに `VARY` ヘッダーがあるかどうかに関係なく一致します。既定値は `false` です。

`cacheName`

文字列で、検索対象の特定のキャッシュを表します。 このオプションは `Cache.delete()` では無視されることに注意してください。

### 返値

キャッシュ項目が削除された場合は `true`、それ以外の場合は `false` に解決する `Promise` です。

例
-

```js
caches.open("v1").then((cache) => {
  cache.delete("/images/image.png").then((response) => {
    someUIUpdateFunction();
  });
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-delete |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


Cache: put() メソッド - Web API

Cache: put() メソッド
=================

**`put()`** は `Cache` インターフェイスのメソッドで、キーと値のペアを現在の `Cache` オブジェクトに追加することができます。

多くの場合、やりたいことは、ただ 1 つ以上のリクエストを `fetch()` して、その結果を直接キャッシュに追加するだけです。そのような場合は、`Cache.add()` や `Cache.addAll()` を使用した方がよいでしょう。 これらはこうした操作を 1 つ以上行うための一括操作関数であるためです。

```js
fetch(url).then((response) => {
  if (!response.ok) {
    throw new TypeError("Bad response status");
  }
  return cache.put(url, response);
});
```

**メモ:** `put()` は、リクエストが以前にキャッシュに保存されたものと一致すると、キーと値のペアを上書きします。

**メモ:** `Cache.add` や `Cache.addAll` は、200 台にない `Response.status` 値を持つレスポンスをキャッシュしませんが、 `Cache.put` では、リクエストとレスポンスのペアを格納できます。結果的に、`Cache.add` や `Cache.addAll` は不透明なレスポンスを格納するために使用できませんが、 `Cache.put` では可能です。

構文
--

```js
put(request, response)
```

### 引数

`request`

キャッシュに追加する `Request` オブジェクトまたは URL。

`response`

リクエストと合う `Response`。

### 返値

`undefined` で解決する `Promise` です。

### 例外

`TypeError`

URL スキームが `http` または `https` のどちらでもない場合に返されます。

例
-

この例は、MDN の simple-service-worker の例からのものです（simple-service-worker をライブで見る）。 ここでは、`FetchEvent` が発生するのを待ちます。 次のようなカスタムレスポンスを作成します。

1. `CacheStorage.match()` を使用して、リクエストの一致が `CacheStorage` にあるかどうかを確認します。 もしそうなら、それを提供します。
2. そうでない場合は、`v1` キャッシュを `open()` で開き、`Cache.put()` を使用して既定のネットワークリクエストをキャッシュに入れ、 `return response.clone()` を使用して既定のネットワークリクエストのクローンを返します。 `put()` がレスポンスの本体を消費するため、クローンが必要です。
3. これが失敗した場合（ネットワークがダウンしているなど）、代替レスポンスを返します。

```js
let response;
const cachedResponse = caches
  .match(event.request)
  .catch(() => fetch(event.request))
  .then((r) => {
    response = r;
    caches.open("v1").then((cache) => {
      cache.put(event.request, response);
    });
    return response.clone();
  })
  .catch(() => caches.match("/gallery/myLittleVader.jpg"));
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-put |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


Cache: match() メソッド - Web API

Cache: match() メソッド
===================

**`match()`** は `Cache` インターフェイスのメソッドで、`Cache` オブジェクトで最初に一致したリクエストに関連付けられた `Response` に解決される `Promise` を返します。一致するものが見つからない場合、`Promise` は `undefined` に解決されます。

構文
--

```js
match(request)
match(request, options)
```

### 引数

`request`

`Cache` 内でレスポンスを見つけようとしている `Request`。 これは、`Request` オブジェクトまたは URL です。

`options` 省略可

`match` 操作のオプションを設定するオブジェクト。 使用可能なオプションは次のとおりです。

`ignoreSearch`

論理値で、URL のクエリー文字列を無視するかどうかを指定します。 例えば、`true` に設定すると、`http://foo.com/?value=bar` の `?value=bar` の部分は、照合の実行時に無視されます。 既定値は `false` です。

`ignoreMethod`

論理値で、`true` に設定すると、照合操作が `Request` の `http` メソッドを検証しないようにします（通常、`GET` および `HEAD` のみが許可されます）。 既定値は `false` です。

`ignoreVary`

論理値で、`true` に設定すると、`VARY` ヘッダーの照合を実行しないように照合操作に指示します。 つまり、URL が一致する場合、`Response` オブジェクトに `VARY` ヘッダーがあるかどうかに関係なく一致します。 既定値は `false` です。

### 返値

リクエストに一致した最初の `Response` に解決し、一致するものが見つからない場合は `undefined` に解決する `Promise` です。

**メモ:** `Cache.match()` は、一致するすべてのレスポンスの配列で解決するのではなく、最初に一致したレスポンスのみ（つまり、`response[0]`）で解決することを除いて、基本的に `Cache.matchAll()` と同じです。

例
-

この例は、カスタムオフラインページの例（ライブデモ）からの引用です。 リクエストが失敗した場合、キャッシュを使用して選択したデータを提供します。 `catch()` 句は、`fetch()` の呼び出しが例外をスローしたときにトリガーされます。 `catch()` 句の内部では、 `match()` を使用して正しいレスポンスを返します。

この例では、HTTP の GET メソッドで取得された HTML 文書のみがキャッシュされます。 `if ()` 条件が false の場合、このフェッチハンドラーはリクエストに介入しません。他のフェッチハンドラーが登録されている場合、それらは `event.respondWith()` を呼び出す機会を得ます。 フェッチハンドラーが `event.respondWith()` を呼び出さなかった場合、リクエストはブラウザーによって処理され、サービスワーカーが関与していないかのように処理されます。 `fetch()` が 4xx または 5xx の範囲のレスポンスコードで有効な HTTP レスポンスを返す場合、`catch()` は呼び出されません。

```js
self.addEventListener("fetch", (event) => {
  // これが HTML 文書に対する GET リクエストである場合のみ、event.respondWith() を呼び出します。
  if (
    event.request.method === "GET" &&
    event.request.headers.get("accept").includes("text/html")
  ) {
    console.log("フェッチイベントの処理: ", event.request.url);
    event.respondWith(
      fetch(event.request).catch((e) => {
        console.error("フェッチ失敗、代わりにオフラインページに戻ります。", e);
        return caches
          .open(OFFLINE\_CACHE)
          .then((cache) => cache.match(OFFLINE\_URL));
      }),
    );
  }
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-match |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


Cache: addAll() メソッド - Web API

Cache: addAll() メソッド
====================

**`addAll()`** は `Cache` インターフェイスのメソッドで、URL の配列を受け取り、それらを取得して、指定されたキャッシュに結果のレスポンスオブジェクトを追加します。取得の間に作成されたリクエストオブジェクトは、格納されるレスポンス操作のキーになります。

**メモ:** `addAll()` は、リクエストと一致する、以前にキャッシュに格納されたキーと値のペアをすべて上書きしますが、結果として生じる `put()` 操作が、同じ `addAll()` メソッドによって直前にキャッシュに格納された項目を上書きしようとすると失敗します。

構文
--

```js
addAll(requests)
```

### 引数

`requests`

キャッシュに追加したいリソースのリクエストの配列です。 `Request` オブジェクトまたは URL が指定できます。

これらのリクエストは `Request()` コンストラクターの引数として使用されるので、 URL はそのコンストラクターと同じルールに従います。すなわち、URL はベース URL からの相対パスです。ベース URL は、ウィンドウコンテキストでは文書内の `baseURI`、ワーカーコンテキストでは `WorkerGlobalScope.location` が該当します。

### 返値

`undefined` で解決する `Promise` です。

### 例外

`TypeError`

URL スキームが `http` でも `https` でもない場合。

レスポンスステータスが 200 番台（つまり、成功レスポンス）ではありません。これはリクエストが成功を返さない場合や、リクエストがオリジン間の CORS ではないリクエスト (*cross-origin no-cors* request) の場合も発生します（この場合、ステータスが常に 0 と報告されます）。

例
-

このコードブロックは、`InstallEvent` が発行されるのを待ってから、アプリのインストールプロセスを処理するために、`waitUntil` を実行します。この処理は、新しいキャッシュを作成するための `CacheStorage.open` の呼び出しと、一連の資産を追加するための `addAll()` の使用で構成されています。

```js
this.addEventListener("install", (event) => {
  event.waitUntil(
    caches
      .open("v1")
      .then((cache) =>
        cache.addAll([
          "/",
          "/index.html",
          "/style.css",
          "/app.js",
          "/image-list.js",
          "/star-wars-logo.jpg",
          "/gallery/",
          "/gallery/bountyHunters.jpg",
          "/gallery/myLittleVader.jpg",
          "/gallery/snowTroopers.jpg",
        ]),
      ),
  );
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-addAll |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


Cache: keys() メソッド - Web API

Cache: keys() メソッド
==================

**`keys()`** は `Cache` インターフェイスのメソッドで、`Cache` のキーを表す `Request` の配列に解決される `Promise` を返します。

リクエストは、挿入されたのと同じ順序で返されます。

**メモ:** レスポンスに `VARY` ヘッダーが設定されている場合、URL が重複しているがヘッダーが異なるリクエストを返すことができます。

構文
--

```js
keys()
keys(request)
keys(request, options)
```

### 引数

`request` 省略可

特定のキーが必要な場合、返してほしい `Request`。 これは、`Request` オブジェクトまたは URL です。

`options` 省略可

プロパティが `keys` 操作でどのように照合するかを制御するオブジェクト。 使用可能なオプションは次のとおりです。

`ignoreSearch`

論理値で、照合操作で URL のクエリー文字列を無視するかどうかを指定します。 `true` に設定すると、`http://foo.com/?value=bar` の `?value=bar` 部分を、照合の実行時に無視します。既定値は `false` です。

`ignoreMethod`

論理値で、`true` に設定すると、照合操作が `Request` の `HTTP` メソッドを検証しないようにするします（通常、`GET` および `HEAD` のみが許可されます）。既定値は `false` です。

`ignoreVary`

論理値で、`true` に設定すると、`VARY` ヘッダーを照合しないように照合操作に指示します。 つまり、URL が一致した場合は、`Response` オブジェクトに `VARY` ヘッダーがあるかどうかに関係なく一致します。既定値は `false` です。

`cacheName`

文字列で、検索対象の特定のキャッシュを表します。 このオプションは `Cache.keys()` によって無視されることに注意してください。

### 返値

`Cache` キーの配列に解決される `Promise` です。

例
-

```js
caches.open("v1").then((cache) => {
  cache.keys().then((keys) => {
    keys.forEach((request, index, array) => {
      cache.delete(request);
    });
  });
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # cache-keys |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`


AudioNode: context プロパティ - Web API

AudioNode: context プロパティ
========================

`AudioNode` インターフェイスの読み取り専用プロパティ `context` は、関連付けられた `BaseAudioContext`、すなわちこのノードが参加している処理グラフを表すオブジェクトを返します。

値
-

この `AudioNode` の構築に用いられた `AudioContext` または `OfflineAudioContext` です。

例
-

```js
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
oscillator.connect(gainNode).connect(audioCtx.destination);

console.log(oscillator.context); // AudioContext
console.log(oscillator.context === audioCtx); // true
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-context |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: numberOfInputs プロパティ - Web API

AudioNode: numberOfInputs プロパティ
===============================

`AudioNode` インターフェイスの `numberOfInputs` は、このノードに供給される入力の数を返します。音源ノードは `numberOfInputs` の値が 0 であるノードという定義です。

値
-

0 以上の整数です。

例
-

```js
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode).connect(audioCtx.destination);

console.log(oscillator.numberOfInputs); // 0
console.log(gainNode.numberOfInputs); // 1
console.log(audioCtx.destination.numberOfInputs); // 1
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-numberofinputs |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: channelCountMode プロパティ - Web API

AudioNode: channelCountMode プロパティ
=================================

`AudioNode` インターフェイスの `channelCountMode` プロパティは、ノードの入力と出力でチャンネルを対応させる方法を表す列挙値です。

値
-

以下が、列挙値 `channelCountMode` の取りうる値とその意味です。

`max`

 チャンネルの数は、全接続における最大のチャンネル数です。
 この場合、`channelCount` は無視され、アップミキシングのみが発生します。

以下の `AudioNode` の子におけるデフォルト値です: `GainNode`, `DelayNode`, `ScriptProcessorNode`, `BiquadFilterNode` (en-US), `WaveShaperNode` (en-US)

`clamped-max`

チャンネル数は、全接続における最大のチャンネル数ですが、`channelCount` の値を上限とします。

以下の `AudioNode` の子におけるデフォルト値です: `PannerNode`, `ConvolverNode`, `DynamicsCompressorNode` (en-US)

`explicit`

チャンネル数は、`channelCount` の値になります。

以下の `AudioNode` の子におけるデフォルト値です: `AudioDestinationNode`, `AnalyserNode`, `ChannelSplitterNode`, `ChannelMergerNode`

**メモ:** 仕様書の以前のバージョンでは、`ChannelSplitterNode` でのデフォルト値は `max` でした。

例
-

```js
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

oscillator.channelCountMode = "explicit";
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-channelcountmode |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: numberOfOutputs プロパティ - Web API

AudioNode: numberOfOutputs プロパティ
================================

`AudioNode` インターフェイスの `numberOfOutputs` プロパティは、このノードからの出力の数を返します。出力先ノード (`AudioDestinationNode` など) では、この属性の値は 0 です。

値
-

0 以上の整数です。

例
-

```js
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode).connect(audioCtx.destination);

console.log(oscillator.numberOfOutputs); // 1
console.log(gainNode.numberOfOutputs); // 1
console.log(audioCtx.destination.numberOfOutputs); // 0
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-numberofoutputs |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: disconnect() メソッド - Web API

AudioNode: disconnect() メソッド
============================

`AudioNode` インターフェイスの **`disconnect()`** メソッドは、このメソッドが呼ばれたノードから 1 個または複数のノードを切断します。

構文
--

```js
disconnect()
```

### 引数

`disconnect()` メソッドには、切断するノードを決めるための引数の異なる組み合わせを受け付けるいくつかのバージョンがあります。引数が渡されない場合は、すべての出力の接続が切断されます。

`destination` 省略可

切断する 1 個または複数のノードを表す `AudioNode` または `AudioParam` です。値が `AudioNode` の場合は、切断する対象の 1 個のノードを表し、他の任意の引数 (`output` および `input`) によって切断する入力や出力を絞り込むことができます。値が `AudioParam` の場合は、この `AudioParam` への接続が終了し、変更が反映されるとこのパラメーターの計算におけるこのノードの担当部分は 0 になります。

`output` 省略可

この `AudioNode` のどの出力を切断するかを表すインデックスです。インデックス番号は出力のチャンネル数に基づいて決められます。(オーディオチャンネルを参照してください)

`input` 省略可

指定の出力先 `AudioNode` へのどの入力を切断するかを表すインデックスです。インデックス番号は入力のチャンネル数に基づいて決められます。(オーディオチャンネルを参照してください)

### 返値

なし (`undefined`)

### 例外

`IndexSizeError` `DOMException`

`input` または `output` として指定された値が無効な (存在しないノードを指しているか、許される範囲の外である) とき投げられます。

`InvalidAccessError` `DOMException`

`disconnect()` が呼ばれたノードが指定された `destination` ノードに接続されていないとき投げられます。

例
-

```js
const AudioContext = window.AudioContext || window.webkitAudioContext;

const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

gainNode.disconnect();
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-disconnect |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: channelInterpretation プロパティ - Web API

AudioNode: channelInterpretation プロパティ
======================================

`AudioNode` インターフェイスの **`channelInterpretation`** プロパティは、入力と出力の数が違う場合に入力のチャンネルを出力のチャンネルに対応付ける方法を表す列挙値です。たとえば、これによりモノラルの入力をステレオや 5.1 チャンネルの出力にアップミキシングする方法や、クアッドチャンネルの入力をステレオやモノラルの出力にダウンミキシングする方法が決まります。

このプロパティには、`speakers` と `discrete` の 2 個の選択肢があります。これらの説明は、Basic concepts behind Web Audio API > アップミキシングとダウンミキシングにあります。

値
-

値の説明は、Basic concepts behind Web Audio API > アップミキシングとダウンミキシングにあります。

簡単にいうと:

`speakers`

一般的なスピーカーの入力と出力の設計の組み合わせ (モノラル、ステレオ、クアッド、5.1) 用の「通常の」対応付けを使用します。たとえば、この設定では、モノラルの入力はステレオの出力の両方のチャンネルに出力されます。

`discrete`

入力のチャンネルは順に出力のチャンネルに対応付けられます。出力より入力が多い場合は、余った入力は捨てられます。入力の方が少ない場合は、余った出力は無音になります。

例
-

```js
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

oscillator.channelInterpretation = "discrete";
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-channelinterpretation |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: connect() メソッド - Web API

AudioNode: connect() メソッド
=========================

`AudioNode` インターフェイスの `connect()` メソッドは、ノードの出力のうち 1 個を接続先に接続できます。接続先は、別の `AudioNode` を用いる (音声データを指定のノードに導く) こともできますし、`AudioParam` を用いる (ノードの出力データにより時間経過とともに自動的にパラメーターの値を変える) こともできます。

構文
--

```js
connect(destination)
connect(destination, outputIndex)
connect(destination, outputIndex, inputIndex)
```

### 引数

`destination`

接続する `AudioNode` または `AudioParam` です。

`outputIndex` 省略可

 この `AudioNode` のどの出力を接続先に接続するかを指定するインデックスです。インデックス番号は出力のチャンネル数に基づいて決められます。(オーディオチャンネルを参照してください)
 ある出力のある入力への接続は 1 回しかできません (2 回目以降は無視されます) が、`connect()` を複数回呼ぶことで 1 個の出力を複数の入力に接続できます。これによりファンアウトを実現できます。デフォルト値は 0 です。

`inputIndex` 省略可

接続先のどの入力をこの `AudioNode` に接続するかを指定するインデックスです。デフォルト値は 0 です。インデックス番号は入力のチャンネル数に基づいて決められます。(オーディオチャンネルを参照してください) ある `AudioNode` を別の `AudioNode` に接続し、この `AudioNode` を再び最初の `AudioNode` に接続することで、閉路を作ることもできます。

### 返値

接続先がノードの場合は、`connect()` は接続先の `AudioNode` オブジェクトを返すので、複数の `connect()` の呼び出しを連続させることができます。このインターフェイスの実装が古く、`undefined` を返すブラウザーもあります。

接続先が `AudioParam` の場合は、`connect()` は `undefined` を返します。

### 例外

* `IndexSizeError` `DOMException`
    + : `outputIndex` または `inputIndex` として指定された値が存在する入力や出力に対応しないとき投げられます。
* `InvalidAccessError` `DOMException`
    + : 接続先のノードが接続元のノードと同じ音声コンテキストにないとき投げられます。
* `NotSupportedError` `DOMException`
    + :指定された接続により (音声が同じノードを繰り返し流れる) 閉路が作られ、この閉路の中に同じ音声フレームを無限に参照して処理結果の波形が詰まるのを防ぐ `DelayNode` オブジェクトがないとき投げられます。接続先を `AudioParam` として引数 `inputIndex` が使われたときも投げられます。
例
-

### 音声入力への接続

`connect()` メソッドの最もわかりやすい使い方は、次の処理のためにあるノードの音声出力を別のノードの音声入力に接続することです。たとえば、`MediaElementAudioSourceNode` が出力する音声 (`<audio>` などの HTML メディア要素が出力する音声) を `BiquadFilterNode` (en-US) を用いて実装されたバンドパスフィルターに通し、音声をスピーカーに送る前にノイズを減らすことができます。

この例では発振器を作成し、ゲインノードに接続することで、ゲインノードが発振器ノードの音量を制御できるようにします。

```js
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
```

### AudioParam の例

この例では、`GainNode` のゲインの値を遅い周波数を設定した `OscillatorNode` を用いて変えます。この手法は、*LFO* により制御されたパラメーターと呼ばれます。

```js
const audioCtx = new AudioContext();

// 音を出すため通常の発振器を作成する
const oscillator = audioCtx.createOscillator();

// LFO (Low-frequency oscillator) として用い、
// パラメーターを制御する 2 個目の発振器を作成する
const lfo = audioCtx.createOscillator();

// 2 個目の発振器の周波数を低く設定する
lfo.frequency.value = 2.0; // 2Hz (1 秒あたり 2 回の振動)

// ゲインの AudioParam が LFO により制御されるゲインノードを作成する
const gain = audioCtx.createGain();

// LFO をゲインの AudioParam に接続する。これは、LFO の値は
// 音声は生成せず、かわりにゲインの値を変えるということである
lfo.connect(gain.gain);

// 音を出す発振器をゲインノードに接続する
oscillator.connect(gain);

// ゲインノードを出力先に接続し、音を聞けるようにする
gain.connect(audioCtx.destination);

// 音を出す発振器を起動する
oscillator.start();

// ゲインの値を変える発振器を起動する
lfo.start();
```

#### AudioParam のポイント

`connect()` を複数回呼ぶことにより、1 個の `AudioNode` の出力を複数の `AudioParam` に接続したり、複数の `AudioNode` の出力を 1 個の `AudioParam` に接続したりできます。これにより、ファンインとファンアウトに対応しています。

`AudioParam` は接続された任意の `AudioNode` から計算された音声データを受け取り、(モノラルでなければ) ダウンミキシングによりモノラルに変換します。そして、それを同様の他の出力、およびスケジュールされた時間での変化を含むそのパラメーター本来の値 (音声の接続がないとき通常 `AudioParam` が取るはずの値) とミックスします。

そのため、`AudioParam` の値を中央の周波数に設定し、音源と `AudioParam` の間で `GainNode` を用いて `AudioParam` の変化の幅を調整することで、`AudioParam` が変化する範囲を設定できます。

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-connect |
| Web Audio API # dom-audionode-connect-destinationparam-output |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


AudioNode: channelCount プロパティ - Web API

AudioNode: channelCount プロパティ
=============================

`AudioNode` インターフェイスの **`channelCount`** プロパティは、このノードへの入力についてアップミキシングとダウンミキシングを行う際、何個のチャンネルを用いるかを決定するとき用いる整数です。

`channelCount` の使用法と正確な定義は、`AudioNode.channelCountMode` の値によって以下のようになります。

* `channelCountMode` の値が `max` のときは、無視されます。
* `channelCountMode` の値が `clamped-max` のときは、最大値として用いられます。
* `channelCountMode` の値が `explicit` のときは、ちょうどの値として用いられます。
値
-

整数です。

例
-

```js
const audioCtx = new AudioContext();

const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();

oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);

oscillator.channelCount;
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audionode-channelcount |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Web Audio API の使用


ポップオーバー API の使用 - Web API

ポップオーバー API の使用
===============

**ポップオーバー API** は、他のページコンテンツの上に表示するポップオーバーコンテンツを表示するための、標準的な、一貫性のある、柔軟な仕組みを開発者に提供します。ポップオーバーコンテンツは、HTML 属性を用いて宣言的に、または JavaScript を用いて制御することができます。この記事では、この機能のすべてを使用するための詳細なガイドを提供します。

宣言的なポップオーバーの作成
--------------

最も単純な形では、ポップオーバーのコンテンツを含むHTML要素に `popover` 属性を追加すれば、ポップオーバーが作成されます。また、ポップオーバーとそのコントロールを関連付けるために `id` が必要です。

```html
<div id="mypopover" popover>ポップオーバーコンテンツ</div>
```

**メモ:** 値なしで `popover` 属性を追加すると、 `popover="auto"` を設定するのと同じになります。

この属性を追加すると、`display: none` をその要素に設定することで、ページ読み込み時に非表示にすることができます。ポップオーバーの表示・非表示を切り替えるには、いくつかの制御ボタンを追加する必要があります。`<button>`（または `<input>` の `type="button"`）に `popovertarget` 属性を、制御するポップオーバーの ID を値として設定することすることにより、ポップオーバー制御ボタンに設定することができます。

```html
<button popovertarget="mypopover">Toggle the popover</button>
<div id="mypopover" popover>Popover content</div>
```

既定では、ボタンはトグルボタンになっています。繰り返し押すと、ポップオーバーの表示と非表示が切り替わります。

この動作を変更したい場合は、`popovertargetaction` 属性を使用します - これは `"hide"`、`"show"`、`"toggle"` の何れかの値を取ります。例えば、表示ボタンと非表示ボタンを別個に作成するには、次のようにします。

```html
<button popovertarget="mypopover" popovertargetaction="show">
  Show popover
</button>
<button popovertarget="mypopover" popovertargetaction="hide">
  Hide popover
</button>
<div id="mypopover" popover>Popover content</div>
```

基本的な宣言的ポップオーバーの例（ソース）で、上記のコード片がどのように見えるかを確認できます。

**メモ:** `popovertargetaction` 属性が省略されると、制御ボタンで実行される既定のアクションは `"toggle"` になります。

ポップオーバーが表示されると、`display: none`が削除されて最上位レイヤー (en-US)に配置され、他のすべてのページのコンテンツの上に置かれるようになります。

自動状態と「簡単な解除」
------------

上記のように、ポップオーバー要素に `popover` または `popover="auto"` が設定されている場合、その要素は**自動状態** (auto state) であると言います。自動状態について注意すべき重要な動作が 2 つあります。

* ポップオーバーは「簡単に解除する」("light dismissed") ことができます。これは、ポップオーバーの外側をクリックするか、`Esc` キーを押すことによって、ポップオーバーを閉じることができるという意味です。
* 通常、一度に表示できるポップオーバーは 1 つだけです。すでに 1 つのポップオーバーが表示されているとき に 2つ目を表示すると、最初のポップオーバーが閉じてしまいます。このルールの例外は、入れ子のオートポップオーバーがある場合です。詳しくは、入れ子のポップオーバーの節を参照してください。

**メモ:** `popover="auto"` ポップオーバーは、文書内の他の要素で `HTMLDialogElement.showModal()` や `Element.requestFullscreen()` の呼び出しが成功した場合にも閉じます。しかし、これらのメソッドを表示されているポップオーバーに対して呼び出すと失敗することに留意してください。しかし、現在表示されていない `popover` 属性を持つ要素に対してこれらのメソッドを呼び出すことはできます。

自動状態は、一度に単一のポップオーバーだけを示したい場合に有益な機能です。表示したいチュートリアルの UI メッセージが複数あるが、表示が乱雑になって混乱するのを避けたい場合や、新しい状態が前回の状態を上書きするようなステータスメッセージを表示する場合などに利用できます。

上記のような動作は、複数の自動ポップオーバーの例（ソース）で実際に見ることができます。ポップオーバーを表示した後に簡単に解除してみて、同時に両方を表示しようとしたときにどうなるかを見てみましょう。

手動のポップオーバー状態の使用
---------------

自動状態のほかに、**手動状態**があり、これはポップオーバー要素に `popover="manual"` を設定することで設定することができます。

```html
<div id="mypopover" popover="manual">Popover content</div>
```

この状態では、次のようになります。

* ポップオーバーは「簡単に解除する」ことはできませんが、宣言的な表示/非表示/トグルボタン（先に見たとおり）は引き続き機能します。
* 独立した複数のポップオーバーを同時に表示することができます。

この動作は、複数の手動ポップオーバーの例（ソース）で確認することができます。

JavaScript でポップオーバーを表示
----------------------

JavaScript API を使用してポップオーバーを制御することもできます。

`HTMLElement.popover` プロパティを使用して、`popover` 属性を取得したり設定したりすることができます。これを使用して JavaScript でポップオーバーを作成することができ、機能検出にも利用できます。例えばこのようになります。

```js
function supportsPopover() {
  return HTMLElement.prototype.hasOwnProperty("popover");
}
```

同様に、

* `HTMLButtonElement.popoverTargetElement` と `HTMLInputElement.popoverTargetElement` は `popovertarget` 属性に相当し、ポップオーバーに対する制御ボタンの設定を行うことができますが、プロパティ値としては制御すべきポップオーバーの DOM 要素の参照を取ります。
* `HTMLButtonElement.popoverTargetAction` と `HTMLInputElement.popoverTargetAction` は HTML の `popovertargetaction` グローバル属性に相当し、制御ボタンがもたらすアクションを指定することができるようにします。

この 3 つを組み合わせると、次のようにポップオーバーとその制御ボタンをプログラム的に設定することができます。

```js
const popover = document.getElementById("mypopover");
const toggleBtn = document.getElementById("toggleBtn");

const keyboardHelpPara = document.getElementById("keyboard-help-para");

const popoverSupported = supportsPopover();

if (popoverSupported) {
  popover.popover = "auto";
  toggleBtn.popoverTargetElement = popover;
  toggleBtn.popoverTargetAction = "toggle";
} else {
  toggleBtn.style.display = "none";
}
```

また、表示・非表示を制御するためにいくつかのメソッドがあります。

* `HTMLElement.showPopover()` でポップオーバーを表示します。
* `HTMLElement.hidePopover()` でポップオーバーを非表示にします。
* `HTMLElement.togglePopover()` でポップオーバーをトグル切り替えします。

例えば、ボタンをクリックしたり、キーボードの特定のキーを押したりすることで、ポップオーバーのオン/オフの切り替えを支援する機能を提供したい場合があります。最初のものは宣言的に実現できますが、上に示したように JavaScript を使用して実現することもできます。

2 つ目については、ポップオーバーを開くためのキーと閉じるためのキーの 2 つをプログラムするイベントハンドラーを作成することができます。

```js
document.addEventListener("keydown", (event) => {
  if (event.key === "h") {
    if (popover.matches(":popover-open")) {
      popover.hidePopover();
    }
  }

  if (event.key === "s") {
    if (!popover.matches(":popover-open")) {
      popover.showPopover();
    }
  }
});
```

この例では、`Element.matches()` を使用して、ポップオーバーが現在表示されているかどうかをプログラムで調べています。`:popover-open` 擬似クラスは、現在表示されているポップオーバーだけに一致します。これは、すでに表示されているポップオーバーを表示しようとしたり、すでに非表示になっているポップオーバーを非表示にしようとしたときに発生するエラーを避けるために重要です。

別の方法として、次のように単一のキーでポップオーバーの表示と非表示をプログラムすることができます。

```js
document.addEventListener("keydown", (event) => {
  if (event.key === "h") {
    popover.togglePopover();
  }
});
```

JavaScript のポップオーバーのプロパティ、機能検出、`togglePopover()' メソッドの動作は、トグルヘルプ UI の例（ソース）をご覧ください。

タイマーによるポップオーバーの自動解除
-------------------

もう一つ、JavaScript でよくあるパターンが、一定の時刻が経過すると自動的にポップオーバーを解除することです。例えば、一度に複数のアクション（例えば複数のファイルのアップロードなど）があり、それぞれのアクションが成功または失敗したときに通知を示す「トースト」通知のシステムを作成したい場合があります。この場合、手動ポップオーバーを使用して、複数のアクションを同時に示し、`setTimeout` を使用して解除できるようにしたいとします。このようなポップオーバーを処理する関数は次のようなものです。

```js
function makeToast(result) {
  const popover = document.createElement("article");
  popover.popover = "manual";
  popover.classList.add("toast");
  popover.classList.add("newest");

  let msg;

  if (result === "success") {
    msg = "Action was successful!";
    popover.classList.add("success");
    successCount++;
  } else if (result === "failure") {
    msg = "Action failed!";
    popover.classList.add("failure");
    failCount++;
  } else {
    return;
  }

  popover.textContent = msg;
  document.body.appendChild(popover);
  popover.showPopover();

  updateCounter();

  setTimeout(() => {
    popover.hidePopover();
    popover.remove();
  }, 4000);
}
```

また、`beforetoggle` イベントを使用して、ポップオーバーが表示されたり非表示になったりした後に続く動作をさせることもできます。この例では、`moveToastsUp()` 関数を実行して、新しいトーストが現れるたびに、トーストがすべて画面の内側へ移動して、場所を確保するようにしています。

```js
popover.addEventListener("toggle", (event) => {
  if (event.newState === "open") {
    moveToastsUp();
  }
});

function moveToastsUp() {
  const toasts = document.querySelectorAll(".toast");

  toasts.forEach((toast) => {
    if (toast.classList.contains("newest")) {
      toast.style.bottom = `5px`;
      toast.classList.remove("newest");
    } else {
      const prevValue = toast.style.bottom.replace("px", "");
      const newValue = parseInt(prevValue) + 50;
      toast.style.bottom = `${newValue}px`;
    }
  });
}
```

上記の例のスニペットが実際に使われている様子は、トーストポップオーバーの例（ソース）をご覧ください。また、説明のためのコメントも充実しています。

入れ子のポップオーバー
-----------

複数のオートポップオーバーを一度に表示しないというルールには、例外があります。互いに入れ子になっている場合です。これらの場合、複数のポップオーバーは、互いの関係から、同時に開くことが許可されます。このパターンは、入れ子式ポップオーバーメニューのような用途に役立ちます。

入れ子のポップオーバーを作成する方法は、3 つあります。

1. DOM での直接の子孫にする

```html
<div popover>
  親
  <div popover>子</div>
</div>
```

2. 要素を呼び出し/制御

```html
<div popover>
  親
  <button popovertarget="foo">こちらをクリック</button>
</div>

<div popover id="foo">子</div>
```

3. `anchor` 属性による

```html
<div popover id="foo">親</div>

<div popover anchor="foo">子</div>
```

例ば、入れ子メニューの例（ソース）を参照してください。マウスやキーボードの操作でサブポップオーバーを適切に表示・非表示を切り替えるため、また、どちらかのオプションが選択されたときに両方のメニューを非表示にするために、いくつかのイベントハンドラーが使用されていることがわかります。SPA や複数ページのウェブサイトでは、新しいコンテンツの読み込みをどのように処理するかによって、これらのうちのいくつかは必要ないかもしれませんが、このデモでは説明のために含めています。

ポップオーバーのスタイル付け
--------------

ポップオーバー API は、注目に値するいくつかの関連する CSS 機能が利用可能である。

実際のポップオーバーのスタイル設定では、単純な属性セレクター (`[popover]`) ですべてのポップオーバーを選択するか、新しい擬似クラス、`:popover-open` を使用して開くためのポップオーバーを選択することが可能です。

記事の始めにリンクした最初の 2、3 の例を見て、ポップオーバーがビューポートの中央に現れていることに気づいたかもしれません。これは既定のスタイル設定であり、UA スタイルシートでこのように実現されています。

```css
[popover] {
  position: fixed;
  inset: 0;
  width: fit-content;
  height: fit-content;
  margin: auto;
  border: solid;
  padding: 0.25em;
  overflow: auto;
  color: CanvasText;
  background-color: Canvas;
}
```

既定のスタイル設定を上書きして、ビューポート上の他の場所にポップオーバーが現れるようにするには、上記のスタイルを次のように上書きする必要があります。

```css
:popover-open {
  width: 200px;
  height: 100px;
  position: absolute;
  inset: unset;
  bottom: 5px;
  right: 5px;
  margin: 0;
}
```

ポップオーバーの位置指定の例（ソース）で、その独立した例を見ることができます。

`::backdrop` 擬似要素は、最上位レイヤー (en-US)にあるポップオーバー要素のすぐ後ろに配置される全画面要素で、必要に応じてポップオーバーの後ろのページコンテンツに効果を追加することができるようにします。例 えば、ユーザーの注意をポップオーバーに集中させるために、ポップオーバーの後ろのコンテンツをぼかしたい場合があります。

```css
::backdrop {
  backdrop-filter: blur(3px);
}
```

これがどのように描画されるかという考えについては、ポップオーバーの背景をぼかす例（source）を参照してください。

最後にアニメーションについてですが、多くの人がポップオーバーの表示と非表示をアニメーションで表現したいと思うでしょうから、特に触れる必要があります。。現状では、ポップオーバーをアニメーションで実現するためには、CSS の動作のいくつかの更新が必要です。特に、`display: none` から移行する際に、要素のアニメーションを可能にします。ポップオーバーにアニメーションが利用できるようになったら、すぐにこの記事を更新します。


HIDConnectionEvent() - Web API

HIDConnectionEvent()
====================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`HIDConnectionEvent()`** コンストラクターは、新しい `HIDConnectionEvent` オブジェクトを生成します。通常は、イベントは Input レポートを受信した際に生成されるため、このコンストラクターは使用されません。

構文
--

```js
new HIDConnectionEvent(type, options)
```

### 引数

`type`

 イベントの名前を表す文字列です。
 大文字と小文字は区別され、ブラウザーは `connect` または `disconnect` に設定します。

`options`

オブジェクトです。*`Event()` で定義されたプロパティに加えて* 、以下のプロパティを持つことができます。

`device`

Input レポートを送信したデバイスを表す `HIDDevice` のインスタンスです。

### 返値

新しい `HIDConnectionEvent` オブジェクトを返します。

仕様書
---

| Specification |
| --- |
| WebHID API # dom-hidconnectionevent-constructor |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HIDConnectionEvent.device - Web API

HIDConnectionEvent.device
=========================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

`HIDConnectionEvent` インターフェイスの読み取り専用プロパティ **`device`** は、この接続イベントに関係する `HIDDevice` のインスタンスを返します。

値
-

`HIDDevice` です。

例
-

この例では、`connect` イベントと `disconnect` イベントにイベントリスナーを登録します。そして、コンソールに `HIDDevice.productName` を出力します。

```js
navigator.hid.addEventListener("connect", ({ device }) => {
  console.log(`HID が接続されました : ${device.productName}`);
});

navigator.hid.addEventListener("disconnect", ({ device }) => {
  console.log(`HID が切断されました : ${device.productName}`);
});
```

仕様書
---

| Specification |
| --- |
| WebHID API # dom-hidconnectionevent-device |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextDecoder: TextDecoder() コンストラクター - Web API

TextDecoder: TextDecoder() コンストラクター
===================================

**`TextDecoder()`** コンストラクターは、引数で指定されたエンコーディング用に新しく作成された `TextDecoder` オブジェクトを返します。

構文
--

```js
new TextDecoder()
new TextDecoder(label)
new TextDecoder(label, options)
```

### 引数

`label` 省略可

 文字列で、既定値は `"utf-8"` です。
 これは何れかの有効なラベルです。

`options` 省略可

次のプロパティを持つオブジェクトです。

`fatal`

 論理値で、無効なデータをデコードした場合に `TextDecoder.decode()` メソッドが `TypeError` を発生させるかどうかを示します。
 既定値では `false` であり、これはデコードする際に不正なデータを置換文字で置き換えることを意味します。

`ignoreBOM`

 論理値で、バイトオーダーマークを無視するか否かを示します。
 既定値は `false` です。

### 例外

`RangeError`

`label` の値が未知の場合、または `'replacement'` デコードアルゴリズムにつながる値のいずれか（`"iso-2022-cn"` または `"iso-2022-cn-ext"`）になっている場合に発生します。

例
-

```js
const textDecoder1 = new TextDecoder("iso-8859-2");
const textDecoder2 = new TextDecoder();
const textDecoder3 = new TextDecoder("csiso2022kr", { fatal: true }); // TypeError 例外を発生できるようにします。
const textDecoder4 = new TextDecoder("iso-2022-cn"); // RangeError 例外が発生します。
```

仕様書
---

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textdecoder① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 所属先の `TextDecoder` インターフェイス。


TextDecoder: ignoreBOM プロパティ - Web API

TextDecoder: ignoreBOM プロパティ
============================

**`ignoreBOM`** は `TextDecoder` インターフェイスの読み取り専用プロパティで、バイトオーダーマークが無視されるかどうかを示す論理値です。

値
-

`true` ならばバイトオーダーマークが無視されます。そうでなければ `false` になります。

仕様書
---

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textdecoder-ignorebom① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextDecoder: encoding プロパティ - Web API

TextDecoder: encoding プロパティ
===========================

**`TextDecoder.encoding`** は読み取り専用のプロパティで、特定のデコーダオブジェクトが使用するデコードアルゴリズムの名前が入った文字列を返します。

エンコーダーは コンストラクター の `label` 引数で設定し、既定値は `utf-8` となります。

値
-

小文字の ASCII 文字列で、以下のいずれかの値を取ります。

* ウェブで推奨されているエンコーディング: `'utf-8'`
* 古いシングルバイトのエンコーディング:
 'ibm866',
 'iso-8859-2',
 'iso-8859-3',
 'iso-8859-4',
 'iso-8859-5',
 'iso-8859-6',
 'iso-8859-7',
 'iso-8859-8''`,
 'iso-8859-8i',
 'iso-8859-10',
 'iso-8859-13',
 'iso-8859-14',
 'iso-8859-15',
 'iso-8859-16',
 'koi8-r',
 'koi8-u',
 'macintosh',
 'windows-874',
 'windows-1250',
 'windows-1251',
 'windows-1252',
 'windows-1253',
 'windows-1254',
 'windows-1255',
 'windows-1256',
 'windows-1257',
 'windows-1258',
 'x-mac-cyrillic'
* 中国語（簡体字）の古いマルチバイトエンコーディング:
 'gbk',
 'gb18030'
* 中国語（繁体字）の古いマルチバイトエンコーディング:
 'big5'
* 日本語の古いマルチバイトエンコーディング:
 'euc-jp',
 'iso-2022-jp',
 'shift-jis'
* 韓国語の古いマルチバイトエンコーディング:
 'euc-kr'
* 古いその他のエンコーディング:
 'utf-16be',
 'utf-16le',
 `'x-user-defined'`
* 特殊なエンコーディング、`'replacement'`
 これは、空の入力を空の出力に、他にも任意の長さの入力を単一の置換文字にデコードします。
 クライアントとサーバー間でエンコーダーを不一致にする攻撃に対する防御に用いられます。
 `ISO-2022-CN`, `ISO-2022-CN-ext`, 'iso-2022-kr', 'hz-gb-2312' のエンコーダーも、置換エンコーディングに割り当てられています。
仕様書
---

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textdecoder-encoding① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 所属先の `TextDecoder` インターフェイス。


TextDecoder: fatal プロパティ - Web API

TextDecoder: fatal プロパティ
========================

**`fatal`** は `TextDecoder` インターフェイスの読み取り専用プロパティで、エラーモードが fatal であるかどうかを論理値で示します。

 このプロパティが `true` であった場合、デコーダーがデコード中に正しくない形のデータに遭遇した場合、`TypeError` が発生します。
 `false` であった場合、デコーダーは無効なデータを置換文字 `U+FFFD` (�) で置き換えます。
 このプロパティの値は `TextDecoder()` コンストラクターで設定されます。

値
-

 論理値で、エラーモードが `fatal` に設定されている場合は `true` となります。
 そうでない場合は `false` となり、エラーモードが `replacement` であることを示します。

仕様書
---

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textdecoder-fatal① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextDecoder: decode() メソッド - Web API

TextDecoder: decode() メソッド
==========================

**`TextDecoder.decode()`** メソッドは、引数として渡されたバッファーからデコードしたテキストを含む文字列を返します。

 デコードするメソッドは、現在の `TextDecoder` オブジェクトで定義されます。
 これには、データの予想されるエンコードや、デコードエラーの処理方法などが含まれます。

構文
--

```js
decode()
decode(buffer)
decode(buffer, options)
```

### 引数

`buffer` 省略可

デコードするエンコードされたテキストが入っている、`ArrayBuffer`、`TypedArray`、`DataView` の何れかのオブジェクトです。

`options` 省略可

以下のプロパティを持つオブジェクトです。

`stream`

 論理値のフラグで、以後 `decode()` を呼び出す際に、追加データが続くかどうかを示します。
 データを塊で処理する場合は `true` に設定し、最後の塊、またはデータが塊でない場合は `false` に設定します。
 既定値は `false` です。

### 例外

`TypeError`

`TextDecoder.fatal` プロパティが `true` の場合、デコードエラーがあると発生します。

### 返値

文字列です。

例
-

この例では、ユーロ記号 € をエンコードし、デコードしています。

### HTML

```html
<p>Encoded value: <span id="encoded-value"></span></p>
<p>Decoded value: <span id="decoded-value"></span></p>
```

### JavaScript

```js
const encoder = new TextEncoder();
const array = encoder.encode("€"); // Uint8Array(3) [226, 130, 172]
document.getElementById("encoded-value").textContent = array;

const decoder = new TextDecoder();
const str = decoder.decode(array); // String "€"
document.getElementById("decoded-value").textContent = str;
```

### 結果

仕様書
---

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textdecoder-decode① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 所属先の `TextDecoder` インターフェイス。


CSSImportRule: layerName プロパティ - Web API

CSSImportRule: layerName プロパティ
==============================

Baseline 2022
-------------

Newly availableSince March 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
**`layerName`** は `CSSImportRule` インターフェイスの読み取り専用プロパティで、 `@import` アットルールで作成されたカスケードレイヤーの名前を返します。

作成したレイヤーが無名であった場合、文字列は空文字列 (`""`) となり、レイヤーが作成されていない場合は `null` オブジェクトとなります。

値
-

空文字列、または `null` オブジェクトです。

例
-

この文書の単一のスタイルシートには、 3 つの `@import` ルールが含まれています。最初の宣言は、スタイルシートを名前付きレイヤーにインポートします。 2 つ目の宣言は、スタイルシートを無名レイヤーにインポートします。 3 つ目の宣言は、レイヤー宣言なしでスタイルシートをインポートします。

`layerName` プロパティは、インポートされたスタイルシートに関連付けられているレイヤーの名前を返します。

```css
@import url("style1.css") layer(layer-1);
@import url("style2.css") layer;
@import url("style3.css");
```

```js
const myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].layerName); // `"layer-1"` を返す
console.log(myRules[1].layerName); // `""` (an anonymous layer) を返す
console.log(myRules[2].layerName); // `null` を返す
```

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssimportrule-layername |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 学習領域: カスケードレイヤー
* `@import` および `@layer`


CSSImportRule: stylesheet プロパティ - Web API

CSSImportRule: stylesheet プロパティ
===============================

**`styleSheet`** は `CSSImportRule` インターフェイスの読み取り専用プロパティで、 `@import` アットルールによって指定された CSS スタイルシートを返します。これは `CSSStyleSheet` オブジェクトの形です。

`@import` アットルールには、常に関連付けられたスタイルシートがあります。

値
-

`CSSStyleSheet` です。

例
-

このスタイルシートは単一の `@import` ルールが記載されています。したがって、 CSS ルールのリストの最初の項目は `CSSImportRule` になります。 `styleSheet` プロパティはインポートされたスタイルシートを返します。

```css
@import url("style.css") screen;
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].styleSheet); // CSSStyleSheet オブジェクトを返す
```

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssimportrule-stylesheet |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSImportRule: href プロパティ - Web API

CSSImportRule: href プロパティ
=========================

**`href`** は `CSSImportRule` インターフェイスの読み取り専用プロパティで、 `@import` アットルールで指定された URL を返します。

解決された URL は、関連づけられてたスタイルシートの `href` 属性となります。

値
-

文字列です。

例
-

このスタイルシートには単一の `@import` ルールだけが含まれています。したがって、 CSS ルールのリストの最初の項目は `CSSImportRule` になります。 `href` プロパティはインポートしたスタイルシートの URL を返します。

```css
@import url("style.css") screen;
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].href); // style.css を返す
```

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssimportrule-href |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSImportRule: supportsText プロパティ - Web API

CSSImportRule: supportsText プロパティ
=================================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`supportsText`** は `CSSImportRule` インターフェイスの読み取り専用プロパティで、 `@import` アットルールで指定された supports 条件を返します。

値
-

文字列、または `null` です。

例
-

この文書の単一のスタイルシートには 3 つの `@import` ルールが含まれています。最初の宣言は、 `display: flex` に対応している場合にスタイルシートをインポートします。 2 つ目の宣言は、 `:has` セレクターに対応している場合にスタイルシートをインポートします。 3 つ目の宣言は、対応条件なしにスタイルシートをインポートします。

The `supportsText` property returns the import conditions associated with the at-rule.

```css
@import url("style1.css") supports(display: flex);
@import url("style2.css") supports(selector(p:has(a)));
@import url("style3.css");
```

```js
const myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].supportsText); // `"display: flex"` を返す
console.log(myRules[1].supportsText); // `"selector(p:has(a))"` を返す
console.log(myRules[2].supportsText); // `null` を返す
```

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssimportrule-supportstext |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* 機能クエリーの使用
* `@import` and `@supports`


CSSImportRule: media プロパティ - Web API

CSSImportRule: media プロパティ
==========================

**`media`** は `CSSImportRule` インターフェイスの読み取り専用プロパティで、 `MediaList` オブジェクトを返します。ここには関連付けられたスタイルシートの `media` 属性の値が入っています。

値
-

`MediaList` オブジェクトを返します。

`media` の値は、 `media` 属性を格納した文字列（`"print"` など）を渡すことで設定することができます。

例
-

### メディアプロパティの取得

このスタイルシートには単一の `@import` ルールが記載されています。したがって、 CSS ルールのリストの最初の項目は `CSSImportRule` になります。 `media` プロパティは `MediaList` オブジェクトを返します。この中には `mediaText` プロパティの値 `screen` が含まれます。

```css
@import url("style.css") screen;
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].media); // MediaList を返す
```

### メディアプロパティの設定

関連するスタイルシートの `media` 属性を変更するには、 `media` の値に新しい値を格納した文字列を設定します。

```js
let myRules = document.styleSheets[0].cssRules;
myRules[0].media = "print";
```

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssimportrule-media |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer: error イベント - Web API

ServiceWorkerContainer: error イベント
==================================

**非推奨:** この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。

**非標準:** この機能は標準ではなく、標準化の予定もありません。公開されているウェブサイトには使用しないでください。ユーザーによっては使用できないことがあります。実装ごとに大きな差があることもあり、将来は振る舞いが変わるかもしれません。

`error` イベントは、サービスワーカーでエラーが発生したときに発生します。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("error", (event) => {});

onerror = (event) => {};
```

イベント型
-----

一般的な `Event` です。

例
-

```js
navigator.serviceWorker.onerror = (errorevent) => {
  console.error(`受信したエラーメッセージ: ${errorevent.message}`);
};
```

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer.register() - Web API

ServiceWorkerContainer.register()
=================================

**`register()`** は `ServiceWorkerContainer` インターフェイスのメソッドで、所与の `scriptURL` の `ServiceWorkerRegistration` を作成または更新します。

成功した場合、サービスワーカー登録は、提供されたスクリプト URL (`scriptURL`) を*スコープ* (`scope`) に結び付け、その後スコープをナビゲーションでの照合に使用します。 このメソッドは、制御されたページから無条件に呼び出すことができます。 つまり、アクティブな登録があるかどうかを最初に確認する必要はありません。

*スコープ*の意味と使用法についてはしばしば混乱があります。 サービスワーカーは自身の場所よりも広いスコープを持つことはできないため、既定よりも狭いスコープが必要な場合にのみ、`scope` オプションを使用してください。

構文
--

```js
register(scriptURL)
register(scriptURL, options)
```

### 引数

`scriptURL`

サービスワーカースクリプトの URL。 登録されたサービスワーカーファイルには、有効な JavaScript の MIME タイプが必要です。

`options` 省略可

登録オプションを含むオブジェクト。 現在利用可能なオプションは次のとおりです。

`scope`

文字列で、サービスワーカーの登録スコープを定義する URL を表します。 つまり、サービスワーカーが制御できる URL の範囲です。 これは通常、相対 URL です。 これは、アプリケーションのベース URL を基準にしています。 既定では、サービスワーカー登録の `scope` 値は、サービスワーカースクリプトが配置されているディレクトリーになります。 動作の詳細については、例の節を参照してください。

`type`

文字列で、作成するワーカーの種類を指定します。有効な値は次の通りです。

`'classic'`

読み込んだサービスワーカーは、標準のスクリプトの中にあります。これは既定値です。

`'module'`

読み込まれたサービスワーカーは、 ES モジュールにあり、 import 文は、ワーカーのコンテキストで利用できます。

`updateViaCache`

文字列で、更新時にサービスワーカースクリプトのリソースに HTTP キャッシュを使用する方法を示します。メモ: これはサービスワーカースクリプトとそのインポートのみを参照し、これらのスクリプトによってフェッチされた他のリソースは参照しません。

`'all'`

HTTP キャッシュは、メインスクリプトとインポートされたすべてのスクリプトについて照会されます。 HTTP キャッシュに新しいエントリーが見つからなかった場合、スクリプトはネットワークからフェッチされます。

`'imports'`

HTTP キャッシュはインポート用に照会されますが、メインスクリプトは常にネットワークから更新されます。 HTTP キャッシュにインポート用の新しいエントリーが見つからなかった場合、ネットワークからフェッチされます。

`'none'`

HTTP キャッシュは、メインスクリプトとそのインポートには使用されません。すべてのサービスワーカースクリプトリソースは、ネットワークから更新されます。

### 返値

`ServiceWorkerRegistration` オブジェクトで解決する `Promise`。

例
-

ここで説明する例は、サービスワーカーのスコープがページにどのように適用されるかをよりよく理解するために、まとめて理解する必要があります。

次の例では、`scope`（を省略した場合）の既定値を使用しています。 この場合、サービスワーカーは `example.com/index.html` とその下のページ（`example.com/product/description.html` など）を制御します。

```js
if ("serviceWorker" in navigator) {
  // 既定のスコープを使用して、
  // サイトのルートでホストされるサービスワーカーを登録します。
  navigator.serviceWorker.register("/sw.js").then(
    (registration) => {
      console.log("サービスワーカー登録成功:", registration);
    },
    /\*catch\*/ (error) => {
      console.error(`サービスワーカー登録失敗: ${error}`);
    },
  );
} else {
  console.error("サービスワーカーに対応していません。");
}
```

次のコードは、 `example.com/index.html` に含まれている場合、上記の例とまったく同じページに適用されます。 スコープが含まれている場合は、ページの場所をベースとして使用することに注意してください。

あるいは、このコードが `example.com/product/description.html` のページに含まれている場合、`'./'` のスコープは、サービスワーカーが `example.com/product` の下のリソースにのみ適用されることを意味します。

```js
if ("serviceWorker" in navigator) {
  // スコープを手動で宣言
  navigator.serviceWorker.register("/sw.js", { scope: "./" }).then(
    (registration) => {
      console.log("サービスワーカー登録成功:", registration);
    },
    /\*catch\*/ (error) => {
      console.error(`サービスワーカー登録失敗: ${error}`);
    },
  );
} else {
  console.error("サービスワーカーをサポートしていません。");
}
```

*scope* の意味と使用方法について、しばしば混乱があります。サービスワーカーは自分自身のロケーションよりも広いスコープを保有することはできないので、 `scope` オプションは既定より狭いスコープが必要なときのみ使用してください。

以下のコードは、サイトのルートにある `example.com/index.html` に記載した場合、 `example.com/product` 以下のリソースにのみ適用されます。

```js
if ("serviceWorker" in navigator) {
  // スコープを手動で宣言
  navigator.serviceWorker.register("/sw.js", { scope: "/product/" }).then(
    (registration) => {
      console.log("サービスワーカー登録成功:", registration);
    },
    /\*catch\*/ (error) => {
      console.error(`サービスワーカー登録失敗: ${error}`);
    },
  );
} else {
  console.error("サービスワーカーをサポートしていません。");
}
```

しかし、サーバーは、サービスワーカー スクリプトに Service-Worker-Allowed ヘッダーを設定することで、この制限を取り除くことができ、そのサービスワーカーの最大スコープをサービスワーカーの位置より上に指定することができます。

仕様書
---

| Specification |
| --- |
| Service Workers # navigator-service-worker-register |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer.getRegistration() - Web API

ServiceWorkerContainer.getRegistration()
========================================

**`getRegistration()`** は `ServiceWorkerContainer` インターフェイスのメソッドで、スコープ URL が指定された文書の URL と一致する `ServiceWorkerRegistration` オブジェクトを取得します。 このメソッドは、`ServiceWorkerRegistration` または `undefined` に解決される `Promise` を返します。

構文
--

```js
getRegistration()
getRegistration(clientURL)
```

### 引数

`clientURL` 省略可

この URL に照合するスコープを持つ登録が返されます。関連の URL は、現在のクライアントを基点として解決されます。この引数が指定されなかった場合、既定では現在のクライアントの URL が使用されます。

### 返値

`ServiceWorkerRegistration` オブジェクトまたは `undefined` に解決される `Promise` です。

例
-

```js
navigator.serviceWorker.getRegistration("/app").then((registration) => {
  if (registration) {
    document.querySelector("#status").textContent =
      "ServiceWorkerRegistration が見つかりました。";
  }
});
```

仕様書
---

| Specification |
| --- |
| Service Workers # navigator-service-worker-getRegistration |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer.ready - Web API

ServiceWorkerContainer.ready
============================

**`ready`** は `ServiceWorkerContainer` インターフェイスの読み取り専用プロパティは、サービスワーカーがアクティブになるまでコードの実行を遅らせる方法を提供します。 決して拒否しない `Promise` を返し、現在のページに関連する `ServiceWorkerRegistration` がアクティブ（`active`）ワーカーを持つまで無期限に待機します。 その条件が満たされると、`ServiceWorkerRegistration` で解決されます。

値
-

`Promise` で、決して拒否されず、最終的には `ServiceWorkerRegistration` で解決される可能性があります。

例
-

```js
if ("serviceWorker" in navigator) {
  navigator.serviceWorker.ready.then((registration) => {
    console.log("サービスワーカーがアクティブ:", registration.active);

    // この時点で、registration.pushManager.subscribe() などの
    // アクティブなサービスワーカーを必要とするメソッドを呼び出すことができます
  });
} else {
  console.error("サービスワーカーをサポートしていません。");
}
```

仕様書
---

| Specification |
| --- |
| Service Workers # navigator-service-worker-ready |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer.controller - Web API

ServiceWorkerContainer.controller
=================================

**`controller`** は `ServiceWorkerContainer` インターフェイスの読み取り専用プロパティで、`ServiceWorker` オブジェクトの状態が `activating` または `activated` ならそれ (`ServiceWorkerRegistration.active` で返されるのと同じオブジェクト) を返します。このプロパティはリクエストが強制リフレッシュ（*Shift* + リフレッシュ）やアクティブワーカーがない場合は `null` を返します。

### 値

`ServiceWorker` オブジェクト。

例
-

```js
if ("serviceWorker" in navigator) {
  // 1 回限りのチェックを行って、サービスワーカーが制御しているかどうかを確認します。
  if (navigator.serviceWorker.controller) {
    console.log(
      `このページを現在制御しているもの: ${navigator.serviceWorker.controller}`,
    );
  } else {
    console.log("このページは現在サービスワーカーによって制御されていません。");
  }
} else {
  console.log("サービスワーカーをサポートしていません。");
}
```

仕様書
---

| Specification |
| --- |
| Service Workers # navigator-service-worker-controller |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer: controllerchange イベント - Web API

ServiceWorkerContainer: controllerchange イベント
=============================================

**`controllerchange`** は `ServiceWorkerContainer` インターフェイスのイベントで、文書の関連する `ServiceWorkerRegistration` が新しいアクティブ (`active`) ワーカーを取得したときに発生します。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("controllerchange", (event) => {});

oncontrollerchange = (event) => {};
```

イベント型
-----

一般的な `Event` です。

例
-

```js
// TBD
```

仕様書
---

| Specification |
| --- |
| Service Workers # dom-serviceworkercontainer-oncontrollerchange |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


ServiceWorkerContainer: message イベント - Web API

ServiceWorkerContainer: message イベント
====================================

**`message`** イベントは、サービスワーカーからメッセージを受信するために、サービスワーカーによって制御されるページで使用します。

このイベントはキャンセル不可で、バブリングしません。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("message", (event) => {});

onmessage = (event) => {};
```

イベント型
-----

`MessageEvent` です。 `Event` を継承しています。

Event

MessageEventイベントプロパティ
---------

*このインターフェイスは親である `Event` からプロパティを継承しています。*

`MessageEvent.data` 読取専用

メッセージ送信元によって送信されたデータです。

`MessageEvent.origin` 読取専用

文字列で、メッセージ送信元のオリジンを表します。

`MessageEvent.lastEventId` 読取専用

文字列で、このイベントの一意の ID を表します。

`MessageEvent.source` 読取専用

`MessageEventSource` （`WindowProxy`、`MessagePort`、`ServiceWorker` の何れかのオブジェクト）で、メッセージの送信元を表します。

`MessageEvent.ports` 読取専用

`MessagePort` オブジェクトの配列で、メッセージが送信されるチャンネルに関連するポートを表します（チャンネルメッセージングや、共有ワーカーにメッセージを送信する場合など、適切な場合）。

例
-

この例では、サービスワーカーは `fetch` イベントからクライアントの ID を取得し、`Client.postMessage` を使用してメッセージを送信します。

```js
// サービスワーカー内
async function messageClient(clientId) {
  const client = await clients.get(clientId);
  client.postMessage("こんにちはクライアント！");
}

addEventListener("fetch", (event) => {
  messageClient(event.clientId);
  event.respondWith(() => {
    // …
  });
});
```

クライアントは `message` イベントを待ち受けしてメッセージを受信できます。

```js
// main.js
navigator.serviceWorker.addEventListener("message", (message) => {
  console.log(message);
});
```

あるいは、クライアントは `onmessage` イベントハンドラーでメッセージを受信することもできます。

```js
// main.js
navigator.serviceWorker.onmessage = (message) => {
  console.log(message);
};
```

仕様書
---

| Specification |
| --- |
| Service Workers # dom-serviceworkercontainer-onmessage |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* サービスワーカーの基本的なコード例
* ServiceWorker の準備はできていますか？（英語）
* ウェブワーカーの使用