ArrayBufferについて

WebSocketやchrome.socket、AudioやVideo APIなどが進んできたせいで、JavaScriptで生データを触ることが増えてきています。 その時に使えるのがArrayBufferというオブジェクトなんですがいまいち整理がついてないので、MDNを訳しながら、まとめてみました。

ちなみにMDNでは

Webアプリケーションがパワフルになってくるに連れて、audioやvideoの操作などの機能や、WebSocketsを用いた生データのアクセスなどが追加され、その結果、早く・容易に生のバイナリデータをJavaScirptコードで扱うことのできる機能が必要なことが明確になって来ました過去には文字列として生データを扱い、charCodeAt()を用いてデータバッファからバイトを読み取るようなこともされていました。

とあります。この機能がArrayBufferですね。

Typed Array Specification

ArrayBufferとView

できる限りの柔軟さと効率を考えて、JavaScriptでは実装をbufferとviewに分割しました。

Buffer (ArrayBuffer classによって実装)

まさにデータの塊です。フォーマットもされておらず、アクセスするメカニズムも提供されていません。ただ、バッファのサイズ(bit)を指定して、メモリ上に領域を確保するだけです。ここにアクセスするために利用するのが Viewです。

View (ArrayBufferView classとそのサブクラスによって実装)

ArrayBufferにアクセスするために利用するのがviewでコンテキスト(ここでは、int8やuint8といったdata typeや、開始オフセット、要素数などを指します)を提供します。

感覚的にはCで考えてvoid*で受けてmemcpyで適当に切り取って、castして読み込むことと近いかと思っています。

viewについて

viewはLow LevelのAPIを提供するDataViewとtypeコンテキストを持つArrayBufferView(Xには型とサイズが入ります)の2つに大別されます。

DataView MDN

DataViewは型とオフセット、16bit以上の場合は、endianの指定を持つアクセサを提供します。

  • Read
unsigned byte getUint8(unsigned long byteOffset);
  • Write
void setUint8(unsigned long byteOffset, unsigned byte value);

その他の型とサイズはリンクを参照してください。

ArrayBufferView

DataViewは一つ一つbufferを触るAPIを提供していましたが、bufferをより扱いやすくするために、ArrayBufferViewというclassが用意されています。 このclassにより、オフセット(デフォルト0)、長さ(デフォルトはbufferの最大値まで)にもとづいてbufferを型とサイズの配列として扱うことができるようになります。

Type SIze Description Equivalent C type
Int8Array 1 8-bit twos complement signed integer signed char
Uint8Array 1 8-bit unsigned integer unsigned char いわゆるbyte
Int16Array 2 16-bit twos complement signed integer short
Uint16Array 2 16-bit unsigned integer unsigned short
Int32Array 4 32-bit twos complement signed integer int
Uint32Array 4 32-bit unsigned integer unsigned intN
Float32Array 4 32-bit IEEE floating point number float
Float64Array 8 64-bit IEEE floating point number double

コンテキスト付きArrayBufferViewは下記のように使います

var buffer = new ArrayBuffer(32); // 32 bit のbufferを確保
console.log(buffer.byteLength); // => 32
var int8array = new Int8Array(buffer); // 8 bitで4つの要素を持つArray
console.log(int8array.length); // => 4

例えばInt8ArrayのコンストラクタはこうなっていますMDN

Int8Array Int8Array(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length);

ArrayBufferの最初にヘッダ情報などが含まれている場合、offsetで開始位置を適当にすることで、扱いやすいです。

ArrayBufferTypeは、確保してあるbufferに対しての操作を提供するだけなので、例えば、Int8Arrayで操作した後に、Int16Arrayで読み込む、といったことも可能になります。

イメージ

f:id:muddydixon:20120930013129j:plain

こんな感じでheader付きのArrayBufferがあった場合、最初のheaderをDataViewで直接読み込んで、オフセットかけて残りのデータを読み込む、とかがリアルな用途かと思います。

参考

更新履歴

  • 2012/09/30 1:58 ArrayBufferType => ArrayBufferView