NicoNico Audio Extractor 0.4.0

tile1.png

* TypeScriptで作り直した
* UIを変更した
* ダウンロード手順を変更した
* 動画もダウンロードできるようにした
* 結果的にけっこう安定した

利用規約をきちんと読んで法的なルールを守ってご利用ください。
そもそも、音源のダウンロードできる動画も増えてきたので可能ならばそちらをご利用していただきたいですね。
posted by 右京 | javascript

jsziptools 2.3.0 変更点

Repo:
https://github.com/ukyo/jsziptools

Tests:
http://ukyo.github.com/jsziptools/test/
http://ukyo.github.com/jsziptools/test/minified.html

Examples:
http://ukyo.github.com/jsziptools/examples/deflate_text.html
http://ukyo.github.com/jsziptools/examples/zip_viewer.html

変更点:
* jQueryライクな簡単なDeferredを追加(then, done, fail)
* async系はこれに統一
* jz.utils.waterfall, jz.utils.parallelとか追加
* jz.zip.unpackをBlob(File)にも対応
* Blob対応したからほとんどasyncになった(正直すまん)
* deflate,inflateを全面的にzlibをemscriptenで変換したものを使用(なんかよくわからんバグ対策)
* emscriptenのIOの最適化(数倍は速いはず)
* testとexampleを見れるようにした

TODO:
* API Referenceを・・・

個人的にはBlob(File)対応がけっこう大きいです。jz.zip.unpackからFileを直接読み込んだときのメモリ使用量がめっちゃ減ってるし、相当巨大なzipを読み込んでも平気でしょう。ただし、zip内のファイル一個一個が大きいとやっぱり重いんですが。まぁ、そこらへんはExamplesのZip viewerで試してください。

手前味噌ですが、今回の変更で最強のzipライブラリになった感があります。
posted by 右京 | javascript

expand for loop

2のn乗ごとにfor文を展開したら汎用的で速いloopが作れるかと思ったらそうでもなかった(V8でちょっとだけ効果があるかな)。
でも、オブジェクトが要素である配列を二重loopで走査するのにevalで内側のオブジェクトの走査を展開するってのは効果があります(node.jsのMySQLドライバーでの話)。

以下はArrayBufferから指定のエンディアン、タイプの配列を読み出す関数を作成する関数の例。
http://jsperf.com/test-expand-for-loop

たまにevalすげーって思うこともあるけど、やっぱり圧縮系のライブラリとの相性が最悪すぎてダメかーみたいなことはありがちですよね。でもまぁ、例えば、angular.jsって明らかにeval使っているのだけど、そういう(圧縮するやつ)の使わないって割り切ってんでしょう。
posted by 右京 | javascript

jsziptools 2.2.1

https://github.com/ukyo/jsziptools

変更点:

* DataViewUtilsへの依存をなくした
* inflateがちょっとだけ速くなった
* 流行りのdone,fail方式を取り入れた
* errorのハンドリング
* jz.zip.pack, jz.zip.unpackを完全に非同期化。同期のほうはもう使えないよ!
* jz.zip.pack, jz.zip.unpackでマルチバイト文字が使われているファイル名に対応(win, linux, macでいけるのでは)

ちなみにdone, fail方式とはjQueryのアレで使われているようなやつです。と言っても簡易的なもので、done(またはfail)に登録できる関数はそれぞれ一つだけです(一つでいいよね)。

jz.zip.pack({
files: files,
level: 5
})
.done(function(buffer){})
.fail(function(err){});

jz.zip.unpack({
buffer: buffer,
encoding: 'cp932'
})
.done(function(reader){})
.fail(function(err){});

TODO:
API Referenceを直す。
posted by 右京 | javascript

ACEのCoffeeScriptのシンタックスハイライトがパワーアップ!

プルリクエストが通りました。意外と苦労しましたよ。でも、納得のできじゃないでしょうか。

ダウンロード
https://github.com/ajaxorg/ace

キャプチャ

monokai
Ace Kitchen Sink-172244.png

ambiance
Ace Kitchen Sink-172323.png
posted by 右京 | javascript

node.jsでexpress使うんだったらcoffeescriptでもいいかなと思った瞬間

この書き方だとyaml(設定ファイル)っぽくて読みやすいですね。※簡単なブログを想定。
setRoutes = (routes) ->
for own routeName, route of routes
for own method of route
app[method] routeName, route[method]


setRoutes
'/admin*':
all: auth.ensureAuthenticated(failureRedirect: '/login')


setRoutes
'/':
get: (req, res) ->
res.send req.query.page

'/entry/:name':
get: (req, res) ->
res.send req.params.name

'/tag/:name':
get: (req, res) ->
res.send req.params.name

'/login':
get: (req, res) ->
res.render 'login'

post: auth.authenticate
successRedirect: '/admin'
failureRedirect: '/login'

'/logout':
get: (req, res) ->
req.logout()
res.redirect '/login'

'/admin':
get: (req, res) ->
res.send 'admin page!'


'/admin/entries':
get: (req, res) ->
res.send 'admin entries page!'

'/admin/entry/:id':
get: (req, res) ->
res.send 'hello'

post: (req, res) ->
res.send 'hello'

put: (req, res) ->
res.send 'hello'

delete: (req, res) ->
res.send 'hello'
posted by 右京 | javascript

CloudFoundryでnode.jsを使ってみる(とりあえずexpress)

http://www.cloudfoundry.com/

Cloud FoundryとはVMWareが作っているオープンソースのPaasで、ついでにホスティングサービス(β版)もやっているよ、というかんじのもの。

後者のホスティングサービスというものが意外と遊べそうなので紹介。今回はとりあえずnode.jsのexpressをセッティングするまでのチュートリアルということで。

1. サインアップ


http://www.cloudfoundry.com/ にいってサインアップする。ここは特に問題ないね。

2. コマンドラインツール等を入れる


返ってきたメールに初期パスワードとコマンドラインツールを入れてね,みたいなことが書いてある。
http://docs.cloudfoundry.com/tools/vmc/installing-vmc.htmlに書いてあることを上から順番に実行していくだけでなので、ここも問題ないね。

3. node.js version 0.8.2とexpressを入れる


cloudfoundry.comではnode.jsの0.6.8と0.8.2に対応しているので、nvmあたりでそのバージョンを入れる必要がある。今回は0.8.2にしてみた。
nvm install v0.8.2

ついでにexpressもインストール。
npm install -g express


4. アプリケーションを作ってデプロイ


これもすごく簡単。まずはexpressコマンドでアプリを作る。
express myapp
cd myapp && npm install

※package.jsonのnameは一意なものになるように変えておいたほうがいいです。
次に、vmc pushでカレントディレクトリのファイルをデプロイする。
vmc push --runtime=node08

何やら質問されるが適当に答えておけばok。

ちゃんとできればexpressの初期の画面が出るはず。
http://ukyo-myapp.cloudfoundry.com/
posted by 右京 | javascript

頭がとろけそうになる

こんな短いのにかなりのJSの知識を要求するコード。

(function() {

var Class = function() {},
slice = Array.prototype.slice,
include;


Class.include = Class.prototype.include = include = function() {
var self = this;

slice.call(arguments).forEach(function(object) {
Object.getOwnPropertyNames(object).forEach(function(name) {
self[name] = object[name];
});
});
};

Class.prototype.hook = function() {};

Class.extend = function(params, scope) {
var parent = this.prototype,
proto = Object.create(parent),
cls = {},
ctor;

include.call(cls, this);

if(arguments.length === 1 && typeof params === 'function') scope = params;
if(typeof scope === 'function') scope.call(proto, parent, cls);

ctor = proto.hasOwnProperty('init') ?
proto.init :
function() { parent.constructor.apply(this, slice.call(arguments)); };

if(typeof params !== 'function') proto.hook(params, parent, cls);

include.call(ctor, cls);
ctor.prototype = proto;
proto.constructor = ctor;

return ctor;
};


if(typeof module !== 'undefined' && module.exports) {
module.exports = Class;
} else {
this.Class = Class;
}

}).call(this);

使い方:
var Box = Class.extend(function(parent, cls) {
// クラス生成時にhookされる
this.hook = function(boxType, parent, cls) { cls.BOXTYPE = boxType; };
});

var FileTypeBox = Box.extend('ftyp', function(parent, cls) {
// body
});

console.log(FileTypeBox.BOXTYPE); // ちゃんと'ftyp'と表示される。

JavaScriptがどれだけ強力な言語かわかりますね。ほんと、頭がとろけそうになります。
posted by 右京 | javascript

TYPED ARRAYS: BINARY DATA IN THE BROWSERの翻訳記事

http://www.html5rocks.com/ja/tutorials/webgl/typed_arrays/

翻訳した記事がうpされました。さぁ、みんなも恐れずプルリクエスト!
内容はWebGLなどで使われている型付き配列についてのものです。まぁ、最後のほうグダグダになってますが、ご容赦を。
posted by 右京 | javascript

bytes of utf8 to unicode速度比較

TypedArray#subarrayはコピーが発生しないのでとにかく速い!今後、効率的な実装を行うときの強力な武器になりそう。まぁ、今回の場合はFileReader#readAsTextという万能の願望器があるので素直にそれを使ったほうが良さそう(特にセキュリティ的なこと含めると)。

http://jsperf.com/test-utf8-to-unicode

bytesToString = function(bytes, bufferSize){
bufferSize = bufferSize || 8192

var buffer = new Uint32Array(bufferSize),
n = bytes.length,
i = 0,
result = '',
j, head;

while(i < n) {
for(j = 0; j < bufferSize && i < n; ++i, ++j) {
head = bytes[i];
if((head >>> 7) === 0) {
buffer[j] = head;
} else if((head >>> 5) === 0x05) {
buffer[j] = ((head & 0x1F) << 6) | (bytes[++i] & 0x3F);
} else if((head >>> 4) === 0x0E) {
buffer[j] =
((head & 0x0F) << 12) |
((bytes[++i] & 0x3F) << 6) |
(bytes[++i] & 0x3F);
} else {
buffer[j] =
((head & 0x07) << 20) |
((bytes[++i] & 0x3F) << 12) |
((bytes[++i] & 0x3F) << 6) |
(bytes[++i] & 0x3F);
}
}
result += String.fromCharCode.apply(void 0, buffer.subarray(0, j));
}
return result;
};

bytesToString2 = function(bytes, bufferSize){
bufferSize = bufferSize || 8192

var buffer = new Uint32Array(bufferSize),
n = bytes.length,
i = 0,
arr = [],
j, head;

while(i < n) {
for(j = 0; j < bufferSize && i < n; ++i, ++j) {
head = bytes[i];
if((head >>> 7) === 0) {
buffer[j] = head;
} else if((head >>> 5) === 0x05) {
buffer[j] = ((head & 0x1F) << 6) | (bytes[++i] & 0x3F);
} else if((head >>> 4) === 0x0E) {
buffer[j] =
((head & 0x0F) << 12) |
((bytes[++i] & 0x3F) << 6) |
(bytes[++i] & 0x3F);
} else {
buffer[j] =
((head & 0x07) << 20) |
((bytes[++i] & 0x3F) << 12) |
((bytes[++i] & 0x3F) << 6) |
(bytes[++i] & 0x3F);
}
}
arr[arr.length] = String.fromCharCode.apply(void 0, buffer.subarray(0, j));
}
return arr.join('');
};

bytesToStringLegacy = function(bytes){
var n = bytes.length,
i = 0,
result = '',
j, head, c;

while(i < n) {
head = bytes[i];
if((head >>> 7) === 0) {
c = head;
} else if((head >>> 5) === 0x05) {
c = ((head & 0x1F) << 6) | (bytes[++i] & 0x3F);
} else if((head >>> 4) === 0x0E) {
c =
((head & 0x0F) << 12) |
((bytes[++i] & 0x3F) << 6) |
(bytes[++i] & 0x3F);
} else {
c =
((head & 0x07) << 20) |
((bytes[++i] & 0x3F) << 12) |
((bytes[++i] & 0x3F) << 6) |
(bytes[++i] & 0x3F);
}
result += String.fromCharCode(c);
++i;
}
return result;
};
posted by 右京 | javascript

unicode to array of utf8速度比較

Uint8Arrayを使うのが正解。
実装が簡単(タイプ数が少ない)なのはFileReaderを使用した場合。

http://jsperf.com/test-unicode-to-utf8
http://jsperf.com/unicode-to-utf8-long

あー、uriにtestつけるの忘れてる。

function unicode2utf8_array(str){
var n = str.length,
idx = -1,
bytes = [],
i, j, c;

for(i = 0; i < n; ++i){
c = str.charCodeAt(i);
if(c <= 0x7F){
bytes[++idx] = c;
} else if(c <= 0x7FF){
bytes[++idx] = 0xC0 | (c >>> 6);
bytes[++idx] = 0x80 | (c & 0x3F);
} else if(c <= 0xFFFF){
bytes[++idx] = 0xE0 | (c >>> 12);
bytes[++idx] = 0x80 | ((c >>> 6) & 0x3F);
bytes[++idx] = 0x80 | (c & 0x3F);
} else {
bytes[++idx] = 0xF0 | (c >>> 18);
bytes[++idx] = 0x80 | ((c >>> 12) & 0x3F);
bytes[++idx] = 0x80 | ((c >>> 6) & 0x3F);
bytes[++idx] = 0x80 | (c & 0x3F);
}
}
return bytes;
}

function unicode2utf8_uint8array(str){
var n = str.length,
idx = -1,
byteLength = 512,
bytes = new Uint8Array(byteLength),
i, c, _bytes;

for(i = 0; i < n; ++i){
c = str.charCodeAt(i);
if(c <= 0x7F){
bytes[++idx] = c;
} else if(c <= 0x7FF){
bytes[++idx] = 0xC0 | (c >>> 6);
bytes[++idx] = 0x80 | (c & 0x3F);
} else if(c <= 0xFFFF){
bytes[++idx] = 0xE0 | (c >>> 12);
bytes[++idx] = 0x80 | ((c >>> 6) & 0x3F);
bytes[++idx] = 0x80 | (c & 0x3F);
} else {
bytes[++idx] = 0xF0 | (c >>> 18);
bytes[++idx] = 0x80 | ((c >>> 12) & 0x3F);
bytes[++idx] = 0x80 | ((c >>> 6) & 0x3F);
bytes[++idx] = 0x80 | (c & 0x3F);
}
if(byteLength - idx <= 4){
_bytes = bytes;
byteLength *= 2;
bytes = new Uint8Array(byteLength);
bytes.set(_bytes);
}
}
return bytes.subarray(0, ++idx);
}

function unicode2utf8_filereader(str, callback) {
var fr = new FileReader();
fr.onloadend = function() {
callback(new Uint8Array(fr.result));
};
fr.readAsArrayBuffer(new Blob([str]));
}

次はarray of utf8 to unicodeで。
文字列結合と関数呼び出しの勝負(すごい汚コードになる予感)。
一番素直なのはFileReader#readAsTextを使う方法かな。
posted by 右京 | javascript

Archive API

https://dev.mozilla.jp/2012/08/archive-api-experimental-implement/

Firefox 17で実験的ですがZipアーカイブを扱うAPIが実装されているそう。記事にも書いてあるとおり、夢が広がる。とは言ったもののもう少しレイヤーが低い感じのもの、たとえばなんだけどCompression APIみたいなのがあったら嬉しいな。compression.inflateみたいな感じで。けっこうな人が喜ぶに違いない。
posted by 右京 | javascript

b64decode:: String -> Uint8Array

canvas.toDataURLとかから使いたいなと。引数の文字列をいじらないのとループの中で条件分岐しないので多少速くなった気がする。まぁ、毎回Array.prototype.forEachを呼んでいるところに手抜き感が見えるけど用途的に無視できるくらいのもんでしょ。

function b64decode(str) {
var hash = {'=': 0},
i = 0,
j = 0,
n = str.length,
bytes = new Uint8Array(n * 6 / 8),
a1, a2, a3, a4;

Array.prototype.forEach.call(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
function(c, i){hash[c] = i});

for(;i < n; i += 4, j += 3) {
a1 = hash[str[i]];
a2 = hash[str[i + 1]];
a3 = hash[str[i + 2]];
a4 = hash[str[i + 3]];

bytes[j] = (a1 << 2) | (a2 >> 4);
bytes[j + 1] = (a2 << 4) | (a3 >> 2);
bytes[j + 2] = (a3 << 6) | a4;
}

return bytes.subarray(0, j - (str[n - 1] === '=' ? 1 : 0) - (str[n - 2] === '=' ? 1 : 0));
}

ご利用はご自由に。ただし、動作保証はしません(動画をcanvasでキャプチャしながらBlobに変換してimg.srcにセットするのが一番手っ取り早いかな)。

追記:
encode(Uint8Array -> String)も足しました。FileReader#readAsDataURLを使えばよいので楽ですね。どちらかというとWorker内で使ったほうが楽です(コールバックが要らないので)。

posted by 右京 | javascript

JavaScriptテクニックバイブル ~効率的な開発に役立つ150の技をチラ見して

JavaScriptテクニックバイブル ~効率的な開発に役立つ150の技
JSサポーターズ
技術評論社
売り上げランキング: 1158


個人的には、これは知らなかったとか、どうやって使うのかわからくて放置していたものについて書いてあって確かにこれは役に立つなと思った。ただ、一つ一つのTipsの解説が少ないような気もした。これは150もあるとしょうがないのかな。

あと、プロトタイプの解説は間違っている。prototypeプロパティを持っているのは関数オブジェクト(つまりtypeof hoge === 'function'なもの)だけ。多分、内部プロパティとしてのプロトタイプ(hoge.__proto__やObject.getPrototypeOf(hoge)で取得できるもの)と間違えてるんだと思う。
posted by 右京 | javascript

jsziptools 2.1.0

そこそこリファクタリング。
jz.utils.loadSyncがなくなりました(これ、そもそも非推奨なんだよ)。
jz.zip.packで同期的に実行したときにXMLHttpRequestでファイルを取得できなくしました(上の影響)。
jz.zip.packのfilesプロパティで{name: 'hoge.txt', str:'text'}って書いていたのが{name: 'hoge.txt', buffer:'text'}というふうに書けるようにした。ArrayBuffer, Uint8Array, stringのどれでも同じように扱う。
jz.zip.packでディレクトリ単位の圧縮レベルを設定できるようにした。
jz.utils.stringToArrayBuffer -> jz.utils.stringToBytes、ついでに返り値がUint8Arrayに。
jz.utils.stringToBytesはWorker内ではネイティブのAPIで変換するようにした。
DataView関係のライブラリをマージしてminifyするようにした。まぁ、FirefoxがDataViewをサポートしたので別々にしなくてもファイルサイズ的に無視できるだろうということで。
posted by 右京 | javascript

ボンバーマソ

Happy Elements Labs: websocket + HTML5(canvas)でのゲーム開発(ボンバーマン風)について少し。ピクセルデータとしてバイナリのwebsocketを使う方法もあるけど、転送量を減らす目的でバイナリを使うのもありかなと(というかリアルタイム系のゲームは将来こういう感じになる?)。

こんな感じで。

Element(type, x, y)
 type 4bit
  0: 平地
  1: 壁
  2: 壊せない壁
  3: プレイヤー
  4: 爆弾
  5: 爆風
  6: 敵
  7: アイテム1
  8: アイテム2
  9: ア(ry
 x 6bit
 y 6bit

Char(id, element)
 id 1byte
 Element element 2byte

転送されるデータ
flowLength 2byte
flowList flowLength * 2byte
charLength 2byte
charList charLength * 3byte

これを直でパースしたら結構速いんじゃないかな。

補足の図
bomb.png
posted by 右京 | javascript
×

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