やったー、ブラウザだけでFLVできたよー\(^o^)/

やったー、ブラウザだけでFLVできたよー\(^o^)/

http://simpleflv.com/

1.画像とmp3をウィンドウにドロップする。
2.幅と高さを設定する。
3.Generateボタンを押す。

これだけだよ!
しかもオフラインでも動くよ!

だけど、ChromeとFirefoxでしか動かないよ!
Chromeだとちゃんとした名前をつけて保存できるのでChrome推奨だよ!
posted by 右京 | javascript

Flash Screen Video v1(javascript)

実はffmpeg -vcodec flashsvで作成できた。
吐き出したhex dumpを見ながら、よしよしあってるぞという感じで確かめたので正しいです。
(https://github.com/ukyo/jsziptools https://github.com/ukyo/ffDataViewに依存しています)

/**
* Flash Screen Video v1
* show swf file format spec v10
*
* @constructor
* @param {Array} rgba
* RGBA array. Pixels are orderd from top left to right bottom.
* example: [R, G, B, A, R, G, B, A, ...]
* @param {number} width
* @param {number} height
*/
function ScreenVideo(rgba, width, height){
this.width = width;
this.height = height;
this.bgr = new Uint8Array(width * height * 3);

var x, y, j, i = 0;

for(y = height - 1; y >= 0; --y) {
for(x = 0; x < width; ++x) {
j = (x + y * width) * 4;
this.bgr[i + 2] = rgba[j++];
this.bgr[i + 1] = rgba[j++];
this.bgr[i] = rgba[j++];
i += 3;
}
}
}

/**
* Create a ScreenVideo instance from a context of canvas.
* @param {ImageData} imageData
* @return {ScreenVideo}
* @example ScreenVideo.createFromImageData(ctx.getImageData(0, 0, 32, 32));
*/
ScreenVideo.createFromImageData = function(imageData){
return new ScreenVideo(imageData.data, imageData.width, imageData.height);
};

ScreenVideo.prototype = {
/**
* get BGR array.
* @param {number} sx start of x
* @param {number} sy start of y
* @param {number} ex end of x
* @param {number} ey end of y
* @return {Uint8Array} (ex - sx) * (ey - sy) * 3
*/
getImageData: function(sx, sy, ex, ey){
sx = this._trim(sx, this.width);
ex = this._trim(ex, this.width);
sy = this._trim(sy, this.height);
ey = this._trim(ey, this.height);
var ret = new Uint8Array((ex - sx) * (ey - sy) * 3),
i, p;
for(i = sy; i < ey; ++i) {
p = i * this.width;
ret.set(this.bgr.subarray((p + sx) * 3, (p + ex) * 3), (ex - sx) * i * 3);
}
return ret;
},

/**
* get blocks
* @param {number} bw block width
* @param {number} bh block height
* @return {Array.<ArrayBuffer>}
*/
getBlocks: function(bw, bh){
var blocks = [],
i, j, n, m, header, data;
for(i = 0, n = this.width; i < n; i += bw) {
for(j = 0, m = this.height; j < m; j += bh) {
data = jz.zlib.compress(this.getImageData(i, j, i + bw, j + bh));
header = DataView.create(new ArrayBuffer(2));
header.setUint16(0, data.byteLength);
blocks[blocks.length] = concatBytes(header.buffer, data);
}
}
return blocks;
},

/**
* get a SCREENVIDEOPACKET
* @param {number} bw
* @param {number} bh
* @return {ArrayBuffer}
*/
getScreenVideoPacket: function(bw, bh){
var blockWidth = (bw / 16) - 1,
blockHeight = (bh / 16) - 1,
blocks = this.getBlocks(bw, bh),
header = new Uint8Array(4);
header[0] = (blockWidth << 4) | (this.width >>> 8);
header[1] = this.width & 0xff;
header[2] = (blockHeight << 4) | (this.height >>> 8);
header[3] = this.height & 0xff;
return concatBytes.apply(null, [header].concat(blocks));
},

/**
* trim
* @param {number} x
* @param {number} max
* @erturn {number}
*/
_trim: function(x, max){
return Math.max(0, Math.min(max, x));
}
};

/**
* @param {...(ArrayBuffer|Uint8Array|Int8Array)} args
* @return {ArrayBuffer}
*/
function concatBytes(args){
var args = Array.prototype.slice.apply(arguments),
offset = 0,
size = 0,
i, n, ret;
for(i = 0, n = args.length; i < n; ++i) {
if(args[i].constructor === ArrayBuffer) args[i] = new Uint8Array(args[i]);
size += args[i].length;
}
ret = new Uint8Array(size);
for(i = 0; i < n; ++i) {
ret.set(args[i], offset);
offset += args[i].length;
}
return ret.buffer;
}
posted by 右京 | javascript

mp3をサンプルごとに分割(javascript)

ID3を飛ばす処理をgetStartOffsetに書かないと・・・。
あと、webstormを試しに使ってみたけど、補完能力高すぎだろ(ほかのjsからも補完される)。

var VERSION_TABLE = [
2, //version 2.5
null, //reserved
1, //version 2
0 //version 1
],
LAYER_TABLE = [
null, //reserved
2, //layer 3
1, //layer 2
0 //layer 1
],
BIT_RATE_TABLE = [
//version 1
[
[0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448], //layer 1
[0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384], //layer 2
[0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320] //layer 3
],
//version 2
[
[0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256], //layer 1
[0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160], //layer 2
[0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160] //layer 3
],
//version 2.5
[
[0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
[0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
[0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160]
]
],
SAMPLING_RATE_TABLE = [
[44100, 48000, 32000], //version 1
[22050, 24000, 16000], //version 2
[11025, 12000, 8000] //version 2.5
],
SAMPLES_PER_FRAME_TABLE = [
[384, 1152, 1152], //version 1
[384, 1152, 576], //version 2
[384, 1152, 576] //version 2.5
],
BITS_PER_SLOT_TABLE = [
32, //layer 1
8, //layer 2
8 //layer 2.5
];

/**
* split a mp3 buffer to samples
* @param {ArrayBuffer} buffer
* @return {Array}
*/
function splitMp3(buffer){
var bytes = new Uint8Array(buffer),
offset = getStartOffset(bytes),
ret = [],
streamLength;

while(offset < bytes.length) {
streamLength = getStreamLength(bytes.subarray(offset));
ret.push(bytes.subarray(offset, offset + streamLength));
offset += streamLength;
}

return ret;
}


function getStartOffset(bytes){
return 0;
}

/**
* get a length of a mp3 stream.
* @param {Uint8Array} bytes
* @return {number}
*/
function getStreamLength(bytes){
var version = VERSION_TABLE[(bytes[1] >> 3) & 3],
layer = LAYER_TABLE[(bytes[1] >> 1) & 3],
isCrc = bytes[1] & 1,
bitRate = BIT_RATE_TABLE[version][layer][bytes[2] >> 4] * 1000,
samplingRate = SAMPLING_RATE_TABLE[version][(bytes[2] >> 2) & 3],
isPadding = (bytes[2] >> 1) & 1,
channel = bytes[3] >> 6,
modeExtension = (bytes[3] >> 4) & 3,
isProtect = (bytes[3] >> 3) & 1,
isOriginal = (bytes[3] >> 2) & 1,
emphasis = bytes[3] & 3,
samplesPerFrame = SAMPLES_PER_FRAME_TABLE[version][layer],
bitsPerSlot = BITS_PER_SLOT_TABLE[layer];

return ~~(samplesPerFrame * bitRate / (bitsPerSlot * samplingRate) + isPadding);
}
posted by 右京 | javascript

DataView.createが欲しいなぁ

qiitaに投稿してもあんまり反応がなかった・・・。マニアックすぎるんですかね。まずArrayBufferを作って、それをもとにTypedArrayを作ったときってもちろんもとのArrayBufferを参照しているだけなんだけど、これをけっこう忘れちゃうんだよね。例えば、Uint8ArrayからDataViewのインスタンスを作ろうってときに、けっこうnew DataView(bytes.buffer)なんとことやっちゃったりして。これは別にエラーもくそも出ずに出力だけ想定外になるからどこでミスったのかわからなくなる。想定通りやる場合はnew DataView(bytes.buffer, bytes.byteOffset, bytes.length)みたいにしなきゃいけない。いちいちね。

そこで以下のようなものを作っておくとミスを減らせますよって話。

/**
* @param {Uint8Array|Int8Array|ArrayBuffer} bytes
* @param {number} byteOffset
* @param {number} byteLength
* @return {DataView}
*/
DataView.create = function(bytes, byteOffset, byteLength){
var constructor = bytes.constructor;
if(constructor === ArrayBuffer) {
byteOffset = byteOffset || 0;
byteLength = byteLength || bytes.byteLength;
return new DataView(bytes, byteOffset, byteLength);
} else if(constructor === Uint8Array || constructor === Int8Array) {
byteOffset = byteOffset != null ? byteOffset : bytes.byteOffset;
byteLength = byteLength != null ? byteLength : bytes.length;
return new DataView(bytes.buffer, byteOffset, byteLength);
} else {
throw 'TypeError';
}
};

というか、そもそもコンストラクタにUint8ArrayやInt8Arrayを渡してもOKにすればいいんじゃないかなぁと。

ffDataViewでは、そういうちょっと便利な関数も使えるようになっているのでどうぞ。
ukyo/ffDataView
posted by 右京 | javascript

jsziptools 1.1

ukyo/jsziptools

jsziptools更新しました。最近作ったffDataViewを使うようにしました。それとjz.zip.packはArrayBufferを返すようになりました。あとは色々とリファクタリングしまいた。で、何が嬉しいかっていうと、結構速くなったかなって。日曜日にはmp4.jsとflv.jsを直したいなーーー。それでもってNicoNico Audio Extratorに反映できたら最高ですね。
posted by 右京 | javascript

Firefox用のDataViewクラス

FirefoxがいつまでたってもDataViewを実装しないので作った。

ukyo/ffDataView

実はjDataViewというのもあったんだけど、TypedArrayとかArrayBufferがないところでDataViewを使う理由はない(あるかもしれないけど)ので、基本的にネイティブのAPIで組んでみた。ファイルサイズも2.8KBなっちゃったりしていい感じだね!
posted by 右京 | javascript

Javascriptのprototype継承はちょっとややこしいよねー

継承するだけで色々と理解しなければいけないことがある。やはりJavascriptは初心者向け言語ではない。

posted by 右京 | javascript

Pure Javascriptのflv parser

Javascriptでflvをパースします。多分ほとんどの環境で一瞬〜一秒以内くらいでパース、mp3の抽出までできます。worker内でも使えるはず。

ukyo/flv.js - GitHub

Example:
//ファイル読み込み
var xhr = new XMLHttpRequest();
xhr.open('GET', 'file.flv');
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && ~~(xhr.status / 100) == 2){
var flv = new Flv(xhr.response);
console.log(JSON.parse(flv.parse(), null, 2));
location.href = flv.extractMp3();
}
};
xhr.send();

Source code:
var Flv = (function(window){

var BlobBuilder = window.BlobBuider || window.MozBlobBuilder || window.WebKitBlobBuilder;
Blob.prototype.slice = Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice;

var TAG_TYPE_AUDIO = 0x08,
TAG_TYPE_VIDEO = 0x09,
TAG_TYPE_META = 0x12;

/**
* @constructor
*
* @param {ArrayBuffer} buffer
*/
function Flv(buffer){
this.buffer = buffer;
this.bytes = new Uint8Array(buffer);
var bb = new BlobBuilder();
bb.append(buffer);
this.blob = bb.getBlob();
}

Flv.prototype = {

/**
* Parse flv.
* @return {Object}
*/
parse: function(){
var o = {},
offset = 0;

//flv header
o.header = {}
o.header.signature = this.str(offset, 3);
offset += 3;
o.header.version = this.ui8(offset);
offset++;
o.header.flags = this.ui8(offset);
offset++;
o.header.offset = this.ui32(offset);
offset += 4;

offset += 4;

//flv tags
o.tags = [];
while(offset < this.bytes.length) {
var tag = {};
tag.type = this.ui8(offset);
offset++;
tag.bodyLength = this.ui24(offset);
offset += 3;
tag.timestamp = this.ui24(offset);
offset += 3;
tag.timestampExtended = this.ui8(offset);
offset++;
tag.streamId = this.ui24(this);
offset += 3;
//skip body
offset += tag.bodyLength;
tag.previousTagSize = this.ui32(offset);
offset += 4;
o.tags.push(tag);
}

return o;
},

/**
* Extract mp3 from flv
* @return {Blob}
*/
extractMp3: function(){
var o = this.parse(),
offset = 13,
bb = new BlobBuilder();
for(var i = 0, n = o.tags.length; i < n; ++i){
offset += 11;
o.tags[i].type === TAG_TYPE_AUDIO && bb.append(this.blob.slice(offset + 1, offset + o.tags[i].bodyLength));
offset += o.tags[i].bodyLength + 4;
}
return bb.getBlob();
},

/**
* unsigned 8 bit int.
* @param {number} offset
* @return {number}
*/
ui8: function(offset){
return this.bytes[offset];
},

/**
* unsigned 16 bit int.
* @param {number} offset
* @return {number}
*/
ui16: function(offset){
return this.bytes[offset] << 8 | this.bytes[offset + 1];
},

/**
* unsigned 24 bit int.
* @param {number} offset
* @return {number}
*/
ui24: function(offset){
return this.bytes[offset] << 16 | this.bytes[offset + 1] << 8 | this.bytes[offset + 2];
},

/**
* unsigned 32 bit int.
* @param {number} offset
* @return {number}
*/
ui32: function(offset){
return this.bytes[offset] << 24 | this.bytes[offset + 1] << 16 | this.bytes[offset + 2] << 8 | this.bytes[offset + 3];
},

/**
* string
* @param {number} offset
* @param {number} n
* @return {number}
*/
str: function(offset, n){
var ret = [];
for(var i = offset, end = offset + n; i < end; ++i){
ret[ret.length] = this.bytes[i];
}
return String.fromCharCode.apply(null, ret);
}
};

return Flv;

})(this);
posted by 右京 | javascript

JavaScriptで決定木

とんでもない手抜きがあるけど、目的変数が2値だったら意外といけそうですね。
表を操作する部分を分離してやると70行くらいなのでお手頃です。

ukyo/DecisionTreeSample - GitHub
posted by 右京 | javascript

javascriptで表を扱う

ちょっと汎用性が高いものが欲しかったので。
相変わらず英語は苦手。
(けっこう間違ってたので修正)
(function(window){

/**
* It is a utility of 2 dimension array.
*
* @constructor
* @param {Array} arr
* @param {number} n Number of rows.
* @param {number} m Number of columns.
*
* //Example
* var table = Table([
* 1, 2, 3, 4,
* 2, 3, 4, 5,
* 3, 1, 1, 1,
* 2, 3, 3, 3,
* 1, 1, 2, 1
* ], 5, 4);
*/
function Table(arr, n, m){
this.arr = arr.slice(0);
this.n = n;
this.m = m;
}

Table.prototype = {
/**
* Add a row.
*
* @param {Array} arr
* @param {number} i
*/
addRow: function(arr, i){
i = i > this.n ? this.n : i;
i = i < 0 ? 0 : i;
Array.prototype.splice.apply(this.arr, [i * this.m, 0].concat(arr));
this.n++;
},

/**
* Remove a row.
*
* @param {number} i
*/
removeRow: function(i){
this.arr.splice(i * this.m, this.m);
this.n--;
},

/**
* Remove a column.
*
* @param {number} i
*/
removeColumn: function(i){
for(var j = this.n - 1; j >= 0; --j) this.arr.splice(j * this.m + i, 1);
this.m--;
},

/**
* Add a column.
*
* @param {Array} arr
* @param {number} i
*/
addColumn: function(arr, i){
i = i > this.m ? this.m : i;
i = i < 0 ? 0 : i;
for(var j = this.n - 1; j >= 0; --j){
Array.prototype.splice.apply(this.arr, [j * this.m + i, 0, arr[j]]);
}
this.m++;
},

/**
* Get a row.
*
* @param {number} i
* @return {Array}
*/
getRow: function(i){
return this.arr.slice(this.m * i, this.m * (i + 1));
},

/**
* Get a column.
*
* @param {number} i
* @return {Array}
*/
getColumn: function(i){
var ret = [];
for(var j = 0; j < this.n; ++j) ret[ret.length] = this.getValue(i, j);
return ret;
},

/**
* Get a value from a cell.
*
* @param {number} x
* @param {number} y
* @return {*} value
*/
getValue: function(x, y){
return this.arr[x + y * this.m];
},

/**
* Set a value to a cell.
*
* @param {number} x
* @param {number} y
* @param {*} value
*/
setValue: function(x, y, value){
this.arr[x + y * this.m] = value;
},

/**
* Get indeces of value in a column.
*
* @param {*} value
* @param {number} i Index of column
* @return {Array} Value indeces
*/
getIndecesOfValueInColumn: function(value, i){
var col = this.getColumn(i), ret = [];
for(var j = 0; j < this.n; ++j){
if(this.getValue(i, j) == value) ret[ret.length] = j;
}
return ret;
},

/**
* Get indeces of value in a row.
*
* @param {*} value
* @param {number} i Index of row
* @return {Array} Value indeces
*/
getIndecesOfValueInRow: function(value, i){
var row = this.getRow(i), ret = [];
for(var j = 0; j < this.m; ++j){
if(this.getValue(j, i) == value) ret[ret.length] = j;
}
return ret;
},

/**
* Get kinds of value in a row.
*
* @param {number} i
* @return {Array}
*/
getKindsOfValueInRow: function(i){
var row = this.getRow(i), ret = [], o = {};
for(var j = 0; j < this.m; ++j) o[row[j]] = true;
for(var k in o) o.hasOwnProperty(k) && ret.push(k);
return ret;
},

/**
* Get kinds of value in a column.
*
* @param {number} i
* @return {Array}
*/
getKindsOfValueInColumn: function(i){
var col = this.getColumn(i), ret = [], o = {};
for(var j = 0; j < this.n; ++j) o[col[j]] = true;
for(var k in o) o.hasOwnProperty(k) && ret.push(k);
return ret;
},

/**
* Create a sub table.
*
* @param {Object} obj
* @return {Table}
*
* //Example
*
* //If you want to include rows or columns,
* //use rowInclude or colInclude.
* var subTable = table.subTable({
* rowInclude: [0, 1],
* colInclude: [3]
* });
*
* //If you want to exclude rows or columns,
* //use rowExclude or colExclude.
* var subTable2 = table.setSubTable({
* rowExclude: [1],
* colExclude: [1, 3]
* });
*/
subTable: function(obj){
var i, _obj = {}, table, exclude;

table = this.copy();

function getExclude(include, exclude, l){
var tmp = [], _exclude = [];
if(exclude) {
_exclude = exclude;
} else if(include) {
for(i = 0; i < l; ++i) _exclude[i] = i;
for(i = include.length - 1; i >= 0; --i) _exclude.splice(include[i], 1);
}
return _exclude;
}

exclude = getExclude(obj.rowInclude, obj.rowExclude, this.n);
for(i = exclude.length - 1; i >= 0; --i) table.removeRow(exclude[i]);

exclude = getExclude(obj.colInclude, obj.colExclude, this.m);
for(i = exclude.length - 1; i >= 0; --i) table.removeColumn(exclude[i]);

return table;
},

/**
* @return {Table}
*/
copy: function(){
return new Table(this.arr, this.n, this.m);
}
};

window["Table"] = Table;

})(this);
posted by 右京 | javascript

javascriptでzlib,gzip,zip形式のデータを圧縮・展開するツールjsziptoolsを整備した

バイナリ解析するときに障害になるのが圧縮されたデータ。
最初に作ったときは単純にzipファイルを圧縮・展開するだけのツールだったんだけど、
色々といじっている内にzlib,gzip形式のバイナリデータにも対応しないといけないなと思って作りました。

ネームスペースはjzで、zlibの圧縮・展開はjz.zlib.compress,jz.zlib.decompress、
gzipはjz.gz.compress,jz.gz.decompressで行います。

zipの圧縮・展開はちょっと変わってjz.zip.compress(またはjz.zip.pack),jz.zip.decompress(jz.zip.unpack)になりました。

各compress,decompressにはショートカットを用意してあります。
compressはc、decompressはdで使用することができます(jz.zlib.cみたいな感じ)。

まぁ、こんな感じです。詳しくはgithubで。
ukyo/jsziptools - GitHub
posted by 右京 | javascript

jsziptoolsのzipで個別に圧縮率を設定できるようにした

書こうと思って忘れそうになってた。まぁ、タイトル通りです。

例えば、epubを作るときにmimetypeだけ無圧縮にすることができるよという話。
var blob = jsziptools.zip([
{name: 'mimetype', str: 'application/epub+zip', level: 1/*ここで設定*/},
{name: 'META-INF' children: [
{name: 'container.xml', str: 'コンテナ'}
]},
{name: 'file.opf', str: 'タイトルとか'},
{name: 'toc.ncx', str: '目次'}
{name: 'body.html', str: 'hogehoge'},
{name: 'style.css', str: 'fugafuga'}
], 6/*全体の圧縮レベル*/);
posted by 右京 | javascript

JavaScriptでzip,unzipするライブラリjsziptools

作った。
ukyo/jsziptools - GitHub
chrome,firefoxあたりで動きます。コードをちょっと変えればIE10でも動くかも。


実はStringベースでzip,unzipできるライブラリというのはすでにあります。
JSZip: JavaScript zip class
zip inflate on javascript

jsziptoolsはBlobBuilder,TypedArrayなどHTML5のAPIをつかった割とモダンな実装です。
これらを使うことによって、より巨大なファイルを扱えたり、より高速に実行できたりします。

inflate,deflateに関してはMasanao Izumo氏が作成したライブラリを
stringから配列(逆も)に変換している部分を排除して全体を無名関数でラップしたものを使用しています。
http://www.onicos.com/staff/iz/amuse/javascript/expert/

使い方:
//zip
//jsziptools.zipの引数は配列の中にオブジェクトを並べる感じ。
//folderはchildrenという配列があるかどうかで判断
//strという要素を持っている場合は文字列として読み込む
//urlという要素を持っている場合はAjaxで読み込む
var b = jsziptools.zip([
{name: "foo", childern: [ //folder
{name: "hello.txt", str: "Hello World!"}, //string
{name: "bar.js", url: "../src/bar.js"} //xhr
]}
]);
//download a zip file
location.href = b;


//unzip

//jsziptools.unzipの引数はArrayBufferか文字列を受け取る
//ArrayBufferの場合はそれをそのまま使う
//文字列の場合はURLとして、Ajaxで読み込む
var loader = jsziptools.unzip("foo.zip");
//get file pathes.
loader.getFileNames();

//getFileHogeで読み込むまで解凍されない。
//getFileAsArray,getFileAsBlobは同期
//getFileAsText,getFileAsDataURL,getFileAsBinaryStringは非同期(FileReaderが非同期だから)
//file is read lazy.
loader.getFileAsText(loader.getFileNames[0], function(result){
alert(result);
});

一応DEMO(なんの面白みもないデモですが):
http://dl.dropbox.com/u/142237/jsziptools/example/example.html
posted by 右京 | javascript

AjaxでArrayBuffer→TypedArrayの例

メモ

Three.jsで使われているのだけど、自分でヘッダを定義しておいて部分的にTypedArrayで切り出すとコピーなしで高速に処理することができる(ネイティブだし)。

https://github.com/mrdoob/three.js/blob/master/src/extras/loaders/BinaryLoader.js
posted by 右京 | javascript

ArrayBufferの分割

メモ

TypedArrayはArrayBufferオブジェクトを参照しているだけです。
具体的にはこういうこと。
var aa = new ArrayBuffer(1024);
var ia1 = new Uint8Array(aa);
var ia2 = new Uint8Array(aa);
ia1[0] = 1;
//1と表示される
alert(ia2[0]);

注意したいのはsubarrayの動作。
var aa = new ArrayBuffer(1024);
var ia = new Uint8Array(aa);
var bb = new BlobBuilder();
//これは先頭から512byte返すのではなく元々のArrayBufferが返ってくる。
bb.append(ia.subarray(0,512).buffer);

ただし、TypedArrayのコンストラクタの引数にTypedArrayを渡すとコピーになる。
これを利用するとArrayBufferの一部分だけを切り取れる。
var aa = new ArrayBuffer(1024);
var ia = new Uint8Array(aa);
var tmp = new Uint8Array(ia.subarray(0,512));
var bb = new BlobBuilder();
//これはOK
bb.append(tmp.buffer);
posted by 右京 | javascript
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。