AudioBufferに追加されるcopyFromChannelについて調べたのですが、この理解であっていますか？

Web Audio API のドラフト仕様で AudioBuffer に追加されている `copyFromChannel` と `copyToChannel` メソッドについて、今の API でも容易に同等の操作が可能なのに何故こういうAPIが必要なのか気になったので調べたメモ。

参照: http://webaudio.github.io/web-audio-api/#acquire-the-content

```cpp
interface AudioBuffer {
  readonly attribute float  sampleRate;
  readonly attribute long   length;
  readonly attribute double duration;
  readonly attribute long   numberOfChannels;

  // いままでこれだけだったのが
  Float32Array getChannelData(unsigned long channel);
    
  // この2つのメソッドが追加される
  void copyFromChannel(Float32Array destination, long channelNumber, optional unsigned long startInChannel = 0);
  void copyToChannel(Float32Array source, long channelNumber, optional unsigned long startInChannel = 0);
};
```

以下翻訳が目的ではないので、大まかな解釈を書いています。
間違っていたらコメント or 編集リクエストください！！！

> NOTE
>
> The methods `copyToChannel` and `copyFromChannel` can be used to fill part of an array by passing in a `Float32Array` that's a view onto the larger array. When reading data from an **`AudioBuffer`**'s channels, and the data can be processed in chunks, `copyFromChannel` should be preferred to calling `getChannelData` and accessing the resulting array, because it may avoid unnecessary memory allocation and copying.

`copyToChannel` と `copyFromChannel` はデータの部分的な操作ができる。
AudioBuffer から部分的にデータを読み込むときは `getChannelData` より `copyFromChannel` を使うべき。なぜなら `copyFromChannel` はメモリの確保やコピーを発生させないから。

:memo: _`getChannelData` を使うとメモリの確保やコピーが行われる場合がある？_

- - -

> An internal **operation acquire the contents of an `AudioBuffer`** is invoked when the contents of an **`AudioBuffer`** are needed by some API implementation. This operation returns immutable channel data to the invoker.

**operation acquire the contents of an `AudioBuffer`** (AudioBufferのデータ取得) は API の必要に応じて内部で実行される。この操作は不変のチャネルデータを返す。

:memo: _内部の実装の話であって、外部 (JavaScript側) からは観測できない。知っておかないと対応できない類のはなしっぽい。_

- - -

> When an **acquire the content operation** occurs on an **`AudioBuffer`**, run the following steps:

> 1. If any of the **`AudioBuffer`**'s `ArrayBuffer` have been neutered, abort these steps, and return a zero-length channel data buffers to the invoker.
> 2. Neuter all `ArrayBuffers` for arrays previously returned by `getChannelData` on this **`AudioBuffer`**.
> 3. Retain the underlying data buffers from those `ArrayBuffers` and return references to them to the invoker.
> 4. Attach `ArrayBuffers` containing copies of the data to the **`AudioBuffer`**, to be returned by the next call to `getChannelData`.

**acquire the content operation** は、以下の手順に従う:

1. いずれかの ArrayBuffer が無力化 (neutered) されているときこの手順は行わず、空のデータを返す。
2. ArrayBuffer のデータを無力化する (JavaScript側から見えなくなる)
3. ArrayBuffer のデータを保持し、参照を返します (C++で見えるようにする)
4. (C++側で) 保持しているデータは、(JS側の) getChannelData によって返される

:memo: _たぶん 4 の時に ArrayBuffer の再確保 (アロケートとコピー) が行われる。_

- - -

> The **acquire the contents of an AudioBuffer** operation is invoked in the following cases:

> - When `AudioBufferSourceNode.start` is called, it acquires the contents of the node's `buffer`. If the operation fails, nothing is played.
> - When a **`ConvolverNode`**'s `buffer` is set to an **`AudioBuffer`** while the node is connected to an output node, or a **`ConvolverNode`** is connected to an output node while the **`ConvolverNode`**'s `buffer` is set to an **`AudioBuffer`**, it acquires the content of the **`AudioBuffer`**.
> - When the dispatch of an **`AudioProcessingEvent`** completes, it acquires the contents of its `outputBuffer`.

**acquire the contents** は以下の場合に起こる

- `AudioBufferSourceNode.start` が呼ばれたとき
- 他のノードに接続されている `ConvolverNode` の buffer がセットされたとき
- buffer がセットされている `ConvolverNode` が他のノードに接続されたとき
- `AudioProcessingEvent` が完了したとき

:memo: _上記のときに AudioBuffer の内容が実装側に転送されて、JavaScript 側から触れなくなる。_

- - -

たぶんこういうことだと思う。

```javascript
var audioContext = new AudioContext();
var audioBuffer = audioContext.createBuffer(1, 10000, 44100);
var convolver = audioContext.createConvolver();

audioBuffer.getChannelData(0).set([ 0, 1, 2, 3, 4, 5, 6, 7 ]);

var savedBuffer = audioBuffer.getChannelData(0);

console.log(savedBuffer); // [ 0, 1, 2, 3, 4, 5, 6, 7, 0 ... 0 ]

convolver.buffer = audioBuffer;
convolver.connect(audioContext.destination); // ここで acquire the contents 

// acquire the contents により JavaScript側から参照できなくなる
console.log(savedBuffer); // []

// getChannelData をすればデータを見ることはできる
// このときに ArrayBuffer の再確保 (アロケートとコピー) が行われる
var tempBuffer = audioBuffer.getChannelData(0);
console.log(tempBuffer); // [ 0, 1, 2, 3, 4, 5, 6, 7, 0 ... 0 ]
console.log(tempBuffer.buffer.byteLength); // 10000 * 4
// getChannelData だと呼ばれるたびに 40000バイトの ArrayBuffer が生成される(場合がある)

// 新しい API を使う場合
var tempBuffer = new Float32Array(8);
audioBuffer.copyFromChannel(tempBuffer, 0);
console.log(tempBuffer); // [ 0, 1, 2, 3, 4, 5, 6, 7 ]
console.log(tempBuffer.buffer.byteLength); // 8 * 4
// copyFromChannel だとあらかじめ確保している領域に書き込むだけなので、メモリ確保等は起こらない
```