WebStorageクラスみたいなの作った(多分未完)
web storageなるものがあるんですよ(唐突)
これWeb Storage
要はグローバルオブジェクトが持ってるストレージです(適当)
やばい。フロントの人たちに刺される。
web storageには2種類、sessionStorageとlocalStorageがあります。
sessionStorageはブラウザを閉じるまで、localStorageは永続的に、保存したドメイン上で残り続けます。
web storageはKVSで、僕はてっきりObjectなのかと今日まで思ってたのですが、JSONとまるまる同じみたいです。NumberとかObjectをvalueに突っ込むとtoString()されちゃうので注意です。
ブラウザ対応状況としては、PCはIE8+、SPは大体どれでも大丈夫と、業務でも使えそうなレベルになってきています。で、どうやらcssとかjs等の外部ファイルの中身を突っ込んでおくと捗るとの話を聞き、今日早速クラスを作ってみました。まだ実用には程遠いですが、大体こんな感じになるだろうなー、って感じで。
実装する上で色々決まり事をしました。というかほとんど、教えてくれたTohlSMALLFIELD氏のパクリです。ごめんなさい
名前空間で管理する
逐一KVの組で管理してもいいのですが、値が多くなり過ぎると汚くなりそうなので、名前空間をkeyに、storeする値をvalueに入れることにしました。とは言え、書いた通りJSONみたいな形なので、Objectを入れ子にはできません。そこで
storeするときはJSON.stringify、loadするときはJSON.parseする
これも完全にTohl氏の受け売りなのですが、各名前空間のvalueにはObjectをしまいます。しかしObjectのまましまうとtoStringされておかしくなっちゃうので、JSON.stringifyとJSON.parseでstore、loadを管理します。
localStorageを使用し、expiresを設定できるようにする
これも完全にTo(ry
書いた通り、web storageには2種類あるのですが、ブラウザを閉じると初期化されてしまうsessionStorageを使うよりは、localStorageにexpiresを設定できるようにし、cookieの拡張のように使えるようにすると便利そうです(受け売り。
というわけで、storeするObjectの形は
item[key] = { val: val, expire: Date.now()+expire };
みたいな感じになり、loadするときにDate.now()がitem[key].expireよりも大きかったら、値を返さずitem[key]を削除すれば良いという実装にしました
- private
var LS = win.localStorage; function constructor(){ set({}); } function get(){ return JSON.parse(LS.getItem(ns)); } function set(obj){ LS.setItem(ns,JSON.stringify(obj)); }
getは、名前空間をkeyにしたvalueを取り出してパースして返す
setは、引数のObjectをstringifyしてlocalStrageに名前空間をkeyとしたvalueとしてstoreする
constructorは、空のObjectをsetする
- public
function save(key,val,expire,force){ var item = get(), f = force ? force : false; if(item[key]&&!force){return false;} item[key] = { val: val, expire: expire ? Date.now()+expire : 0 }; set(item); return true; } function load(key){ var item = get(); if(item[key]&&(!item[key].expire||item[key].expire>Date.now())){ return item[key].val; }else{ remove(key); return false; } } function remove(key){ var item = get(); if(item[key]){ delete item[key]; set(); return true; }else{return false;} } function clear(){ LS.clear(); }
save、ちょっと引数多くなってしまった。仕方ないかな
saveはkeyとvalueでlocalStorageにsetItemする。expireは任意で、単位はmsec。Date.now()に加算して保存する。forceはbooleanで、仮に既にkeyが存在していても、forceがtrueだったら上書きする。
loadは引数のkeyをstorageから探し、expireが指定されてない若しくは期限内である場合にvalueを返す。そうでなければ後述のremoveを呼び出し、storage内から値を削除する
removeはkeyを引数に、key-valueの組みが存在すればそれを削除してsetし直す。
clearはweb storageのメソッドをそのまま使い、storage全体をクリアする。
以上です。あーまた長くなってしまった。どうしたらもうちょい読みやすくできるんでしょ。
で、このクラス数十分で書いたので穴だらけだろうし、そもそも当初の目的である外部ファイルのキャッシュみたいな目的を達成するようには書かれていないので改良が当然必要です。
フロントエンドエンジニアの皆様、この穴だらけのゴミクラスを殴って蹴ってくださいお願いしますうううううううううううううう
ではまた
主要ブラウザのmousewheelイベントのスクロール量について
最近、スクロールアニメーションというか、スクロール量に応じてアニメーションが進むようなものを作りたい欲が高まっている(「カッコeK」新型eKカスタム - カッコいい方に、走ってしまえ | MITSUBISHI MOTORS JAPAN)←こういうの
で、html,bodyにoverflow: hiddenをかけてメインコンテンツをposition: fixedにし、mousewheelイベントの値によってアニメーションを進めればいいことはわかったのだが
どうやらブラウザによってmousewheelイベントの実装が違うらしい。なにゆえ
というわけで手っ取り早くchrome、firefox、IE9で調べてみた。safari?知らん
window.addEventListener('mousewheel',function(e){ console.log(e.wheelDelta); },false);
これで、下にマウスホイールすると-120が、上にマウスホイールすると120が出力される。勢い良くやろうが静かにやろうが、120が出力される回数が変わるだけで、値は変わらない。
document.attachEvent('onmousewheel',function(e){ console.log(e.wheelDelta); });
chromeとほぼ同じ実装でとれる。値もchromeと一緒で、静かにやろうが激しくやろうが、上で120、下で-120だった
window.addEventListener('DOMMouseScroll',function(e){ console.log(e.detail); },false);
問題はこいつ。まずmousewheelイベントがない。あると思ってたわ。なんだそのまどろっこしいイベント名は。プロパティ名も当然のように違うし。で、この状態で上にマウスホイールすると-3、下にマウスホイールすると3が出力される。すごい差。
まとめ
というわけで、マウスホイールをトリガーにアニメーションさせるようなページを実装する場合、Firefoxのe.detailを40倍してchrome、IE9に合わせるか、chrome、IE9を120で割り、Firefoxを3で割って1に正規化してやるかのどっちかがよさそう。後者の方が好き。safari?知らん。
たぶん世界最年少のクリエイティブディレクターと一緒にお仕事をしました
お久しぶりです。
デザイナーの佐藤ねじさんからサイト制作のお話をいただきましたシリーズです。
と言っても簡単なLPだけだったので今回は1時間程度でしたが。
ねじさんの息子さん(1歳)にクリエイティブディレクターをしてもらい、グラフィックから文言、リンク先管理などを全てやらせてみたらどうなるか、というものでした。
つくづくねじさんの「誰もいない土俵を探す」発想には毎度毎度驚かされます。
それと、今回すごく息子さんのライフログ的な意味合いが強いと思うんですが、クレジット乗せてもらって申し訳ないなぁとか思った。
断っておくべきだったろうか
あとこのクレジット、知らない人が見ると家族か何かだと思ってしまうんじゃないだろか。苗字一緒だし
あ、動画がすごくほっこりします。やばいです。ほっこり。
クリエイティブディレクターが自由過ぎて。
で、えーと、技術的な話はそんなにないんですが
1.背景に動画敷いたら素敵な表現になった
今回、キャプション部分(8a16df449dda796b0f57a9a2ff6f2b38.png)と、外側のコンテナ部分(0f403ef08b3f883c195c3749c5195570.png)に透過が仕込まれています。
さらに、ねじさんからの要望で、サイトに置いてあるyoutube動画と同様のものをその背景に敷いたら不思議な表現になりそう、との話をうかがってやってみたら、正に新しい、素敵な表現になってびっくりしました。
これを上手く応用すると、同様な一枚の画像の背景で上手い感じに動画を仕込めば、画像は一枚で、DOM操作をしなくても複数の見え方ができる、ということができたり、もしかしたらブラウン管テレビみたいなことができるんじゃねーかなーと思いました。
2.youtube player APIはスマホ対応していない?
1.に書いた演出は、実はPCでしか見ることができません。
経緯を話しますと、背景に敷いている動画はyoutubeが提供している通常の埋め込みではなく、前回佐藤フィルターで使ったyoutube player APIから動画を呼び出して埋め込んでいます。
youtube player APIを採用した理由として、背景の動画は音を鳴らしたくないという要望があったからで、通常の埋め込みパラメータの中にはvolumeやmuteといったものがありません。というわけで、youtube player APIを使い、onYouTubePlayerReadyのタイミングでplayer.mute();しているというわけです。
で、こっからはちゃんと調べてないんですが、youtube player APIで呼び出す動画は基本的にAS3のもので、flash非対応ブラウザにはHTML5のものを埋め込むわけ「ではない」可能性があります。
実際今回、出来上がったサイトをiPhoneから見てみたら、背景の動画は再生されず、かつonYouTubePlayerReadyも呼ばれていませんでした。
公式のドキュメントを読んで追記しますが、現時点ではyoutube player APIはスマホ未対応の可能性があります
3.youtube player APIによる埋め込みを行うとパラメータが一部無視される?
なんか長くなってきたからざっくり書こう
背景の動画、ループさせるという要望だったのでembedのパラメータにloop=1を仕込んだんですが、これが何故か無視されていました。他のも無視される可能性あります。ということで今回は
player.addEventListener('onStateChange','handleLoopVideo'); function handleLoopVideo(){ // 0は'終了'を示す if(player.getPlayerState()===0){ player.playVideo(); } }
として、playerの状態変化時にイベントハンドラを貼り、再生終了だったらまた頭出し再生する、という処理を追加しましたとさ、という話です。
結局長くなってしまいましたが今回も色々と学びの多い制作でした。ねじさん、ねじさんの息子さん、ありがとうございました!
jQueryのanimate関数を自作してみた(超未完、追記あり)
はい。以上です。
ではなく。解説します。
最近までjQueryでしかjs書けなくてほんとクソだなー早くフロントやめて死ねばいいのにって思ってたのでjQueryの代替品を作っているかるねです。
で、defferedとajaxとanimateとquerySelector以外は大体作り終えたので、んじゃanimateやるかーってなったとこです。って書いたけど残ってる奴らが強敵ばかりだな………
ま、まぁいいか。中途animateの説明しますね。
まず始めに、このanim関数はjQueryのanimate関数と比べてまだ色々不備を抱えています。そりゃあね。半日でべべべっと組んだわけですし。で、現時点で分かってる不備は以下の通り
- メソッドチェーンによるコールバック登録
- margin, paddingの複数値設定への対応
- easing(追記あり)
- 色を指定する16進のtransition(jQueryのanimateは非対応。プラグインあり)
こんな感じか。実用する上で致命的なのはeasing、次にmargin,padding、次いでコールバック登録で、色のtransitionかしら。今はlinearしかできないからほんと使い物にならん。早くeasing実装せねば
この関数を機能分割すると
- 引数で与えられたプロパティから接尾詞(今のところpxのみ)の有無を認識する
- 該当プロパティの初期値の設定
- forとsetTimeoutでstyleを書き換える
だけです。初期化付近は読めば分かるので、メイン部分の3.について
// main function function anim(el,prop,duration,easing,callback){ cnt = parseInt(duration/timerInterval,10), index = 0; // initialize (suffix,get value,...) for(var key in prop){ crnt[key] = setCrnt(el,key); obj = setSuffix(crnt[key],prop[key]); crnt[key] = obj.crnt; start[key] = obj.crnt; prop[key] = obj.goal; delta[key] = obj.delta; suffix[key] = obj.suffix; } // animate loop for(var i=0;i<cnt;i++){ window.setTimeout(function(){ for(var key in prop){ // set property crnt[key] += delta[key]/cnt; if(easing){ el.style[key] = calcEasing(index,cnt,start[key],crnt[key],prop[key]) + suffix[key]; }else{ el.style[key] = crnt[key] + suffix[key]; } } // when complete animate if(++index>=cnt){ for(key in prop){ el.style[key] = prop[key] + suffix[key]; } if(callback){callback();} } },timerInterval*i); } }
引数は
- el:対象となるDOM
- prop: 変化させるプロパティをkey、目標値をvalueとするobject。
{width: '100px',height: '300px',opacity: '0.5',fontSize: '30px'}
みたいに渡す
- duration: アニメーション時間(msec)
- easing: 今のところeasingは1種類しかないので、booleanで適用の有無を指定する。
- callback: アニメーション完了時に実行する関数を指定する。
処理の順番としては
- durationをtimerInterval(1000msecをリフレッシュレート(コードでは60)で割った値)で割り、ループの回数を計算する
- propの中を見て、接尾詞の有無や初期値の設定を行う
- cnt回のループ内でsetTimeoutを設定する
- 現在のプロパティ値(crnt)に、目標値との差分(delta)をループ回数(cnt)で割った値を加算し、styleに設定していく(easingの説明は一旦省きます)
- 4.を、prop内のkeyの数だけ実行する。これをループ内の処理としています
- forループの完了を観測したら、styleの値を目標値に強制的に設定する。これは、4.で計算したdeltaを加算していくだけでは正確に目標値に到達しないことがあるため。例えば、初期値0、目標値1、ループ回数3ではループ完了時の値は0.99999....となる。これを丸めるために最後は手動で値を設定する
- コールバック関数が存在していればそれを実行する
といった感じです。
メインループ周りは今のところシンプルな実装になっていると思っています、自分では。
ひとまずはこれで最低限の機能は満たしているように見えます。
とは言え、実用に至るにはやはりeasingがないと使えない。
けれども僕は数学に滅法弱いので、jQuery.easingを流用する方法をさぐりながら今週を過ごそうと思います。色々説明不足ですが何かあったらコメントなりjsdo.itの方でお願いします。
お腹減ったー
追記(2013/04/09 16:55)
jQuery.easingを移行できました。引数easingにjQuery.easingのような種類を表すstringを入れると変化量が変わるように実装しました。ただ、bounce系だけ上手く実装できず、調査中です
Youtube Player APIの使い方とか、使ってみての感想とか(佐藤フィルター解説その2)
はい、かるねです。
一応佐藤フィルターで使ったあれこれの話(Youtube Player API その1) - 女子小学生と××したいの続きという意味付けで書いているこの記事なのですが、佐藤フィルターで使ったAPIの説明だけだとあんまり面白くないので、色々調べながら書いてみた
YouTube JavaScript Player API リファレンス - YouTube — Google Developers
↑このコードでは
- 現時点でYoutube側で仕様が固まりきっていないのか、使用を非推奨としているもの
- キュー関数(動画のリクエストを行う関連のメソッド、参考:YouTube JavaScript Player API リファレンス - YouTube — Google Developers)
- 使ってみたけどいまいち上手く動作しなかったもの
以外についてはほぼ、APIで用意されているものを網羅できていると思うです
なんかブログ内での口調が定まらなくてアレだな
で、↑のjsdo.itでやっていることとしては
1. 動画の再生(player.playVideo())
2. 一時停止(player.pauseVideo())
3. 指定位置へのシーク(player.seekTo(sec)
4. ミュート/非ミュートの切り替え(player.mute(),player.unMute())
5. 音量の設定(player.setVolume(percentage))
6. 音量の取得(player.getVolume())
7. 現在の動画の再生ステータス(再生中、一時停止中、終了、再生開始待ち等)の取得(player.getState())
8. 動画の長さ(sec)の取得(player.getDuration())
9. 動画URLの取得(player.getVideoUrl())
10. 動画の再生画質の取得(player.getPlaybackQuality())
11. 現在ロードされているバイト数、全体のバイト数の取得(player.getVideoBytesLoaded(),player.getVideoBytesTotal())
12. 現在の経過時間の取得(player.getCurrentTime())
です。上手く使えば、複数の「演奏してみた」動画をセッションさせるとか、ボリュームを線形に推移させて特殊な演出とか、setTimeoutでseekToをがちゃがちゃやってMAD動画風にするとか、色々できそうですね。まずはセッションからやってみようかなー。
ちなみに前述している12項目に関しては特に問題なく使えると思います。そんなに難しいことしてないので。なので本当は1ネタ仕込んでからこのブログ書きたかったんですが、
が
が
まぁ、めんどくさくなったんですねwwwwwwwwwwwwww
なんか作ったら紹介します。アイデア募集です。可能そうなら作ります。
今回検証しなかったキュー関数に関しても後々検証して記事書こうと思います。
検証していていまいち分からなかったメソッドが1つだけありまして
player.setPlaybackQuality(suggestedQuality:String):Void
です。
getPlaybackQualityのsetterバージョンで、引数として有効な値はsmall、medium、large、hd720、defaultとリファレンスに書かれています。なんですがいまいち画質が変わらんのです。
「変わってるんだけど気付いてないだけなんじゃないのー?」と最初は思ったんですが、このAPIにはonPlaybackQualityChangeというイベントがあり、このsetPlaybackQualityで画質を変更する、もしくはユーザアクションで動画ウインドウのコントローラから画質を変更した際に発火するという説明がされています。
このイベントにリスナを登録して色々試してみたのですが、ユーザアクションによる変更ではイベントが発火するのにsetPlaybackQualityでは発火しませんでした。
色々調べてみると、player.getAvailableQualityLevels():Arrayというメソッドが用意されており、当該動画で再生可能な画質のリストを配列にして返してくれるというものです。↑のjsdo.itのコードで試すと、返り値は
["hd720", "large", "medium", "small"]
でした。なのでこの4つに関してはsetPlaybackQualityで設定できると思ったんですが………んー。
リファレンスには
この関数を呼び出しても、再生画質が実際に変更されるとは限りません。
ってあるし、もしかすると埋め込み時に設定された推奨画質以外には、基本的には変えて欲しくないっていうスタンスなのかも知れない。それはちょっと都合の良すぎる解釈だけど。というわけで再度調査します
「後で調べる」ばかり先行してしまってよくないとは言え、記事も長くなってきたしこのくらいかなー。嵐が来てるし、こないだみなみけの最終回で保坂が「そら豆とキャベツのクリームパスタ」の話をしていたので、昼飯はそれにしようと思います
ではー
web audio APIのpannerNodeのsetPositionについて思うこと
この話題、まだ続きます。ごめんなさい。
この記事は少し前の記事をちょこちょこ読まないとわからない感じになっています。
ざっくり要旨を語りますと、「web audio APIのpannerNodeのsetPositionは恐らく様々な角度からの音のインパルス応答を対象音の音源に畳み込み演算して出力しているが、補間を行なっていないので測定データの無い角度からの音を完全に再現はできない」ということです。
あれ?
大体説明し終えたぞ?ま、まぁ、ちゃんと書くか。
web audio APIってのは「ノード」と呼ばれる、各機能を持ったモジュールをつないで、色んな効果や音色を持った音を出力します。
その中に、Pan(パン。「定位」つまり音源の位置を定めること)に関するpannerNodeというものがあります。
ざっくり読むと、音源の位置変えたり、音源の方向、音源自体が向いている方向を変えたりできるようですね(適当)。で、何回か紹介しているiOS6 safari対応 擬似立体音響 - jsdo.it - Share JavaScript, HTML5 and CSSではこのpannerNodeのsetPositionというメソッドで仮想音源の座標を決定しています。
で、↑のjsdo.itを走らせていて分かったのですが、仮想音源位置を上下に動かしていくと、なんか境界があるというか、段階的に音が変わるのが分かってしまいます。最初は僕の実装の問題かと思い、setPositionを行なっているタイマーのインターバルを10msにしたんですが結果変わらずでした。
で、この挙動に対する素人目線な仮説を書こうって話です
このメソッドの内部処理までしっかり読んだわけではないんですが、この手の処理は大体、「インパルス応答の畳み込み演算」というもので行なっています。この辺の詳しい話をし始めると厳密なところで間違ってて、空間音響の方々から刺されかねないのでざっくり説明します。
ざっくり説明しますと、ダミーヘッドと呼ばれる人型マネキンみたいな人形の鼓膜付近にマイクロホンを仕込み、ある角度から出力したインパルス音という非常に短い音をそのマイクで録音したものをインパルス応答と呼びます。
これを様々な角度から同様に測定していきます
ちなみにこんな機械で測定します
http://www.ais.riec.tohoku.ac.jp/Lab2/sp-array/newimg/speaker_array_small.jpg
こうして測定したインパルス応答を、「畳み込み演算」という方法でごにょごにょ(参考:FIR型とインパルス応答の畳み込み : ソフトウェアと音響のデジタル信号処理)すると、↑のjsdo.itでやっているような様々な角度からの仮想音源を再現することができます。
さて、では上下に音源を徐々に移動させた場合に起きている途切れの原因の予想についてなのですが
↑の画像を見ていただくと分かる通り、当然スピーカーとスピーカーには間隔が空いており、測定できない角度というのが出現してきます。
これが原因、と言ってしまえばまぁ、そういうことです。例えば測定が10°おきに行われたインパルス応答を用いれば、45°方向のインパルス応答はないので、例えば40°から50°の間は40°のインパルス応答で代用しているような実装になっているとすれば、今回起きているような途切れの原因として十分考えられると思います。
ちなみに、このようにならない方法として、インパルス応答を補間するという手法が考えられます。ざっくり言えば、40°のインパルス応答の特徴と50°のインパルス応答の特徴から45°のインパルス応答を近似する手法です。この手法がどの程度精度が高く、どの程度実用段階かというのはちょっと失念してしまいましたが、少なくとも現在も研究が行われ続けているというのは事実です。
というわけでまとめますと
- web audio APIのpannerNodeのsetPositionメソッドには、仮想音源位置を上下(前後)をなめらかに移動させた場合に途切れが発生する
- このメソッドは恐らく、室インパルス応答の畳み込み演算によって実装されている
- そして、データの存在しない角度のインパルス応答については補間を行わず、不完全な実装となっている可能性がある
ってことです。あくまで予想に過ぎませんし、ちゃんと実装読んでから書けやクソがぁああって意見も大募集なのですが、間違ってたら消しますので、ご勘弁を。それでは~
iOS6 safari向けにweb audio APIのアプリケーションを作るときにつまずきそうなこと
web audio APIを用いたiOS6 safari対応の仮想音源位置の移動があんまり上手くいかなかった話 - 女子小学生と××したいの追記、というかスマホ対応のときに思ったことです。
そもそもなんであのコード書こうと思ったかという話が絡んでくるのですが
音が好きで、かつフロントエンドエンジニアを始めたのでまぁ、この2つを絡めたものは作りたいなぁと思っていて
web audio APIっつう、新しくて未開拓で面白そうなもんが転がってるなーってのは知ってて
でも、手っ取り早く始めるならflashで良かったんすよね、基盤が出来上がってるし色んなことできるし
ただ、「音が好き」「ブラウザの中が好き」ともう1つ「スマホがこれからすげー面白くなる」ってのがあって
正直PCブラウザの中はやり尽くされた感があるって勝手に感じてます
PCブラウザの中でリッチな表現するのにわざわざjsを選ぶ理由ってそんなになくて、flashでいいじゃんって話になるけど
去年からフロントを始めた僕が「今から」flashを勉強するのはいかがなんかなぁ、と思いました
flashエンジニアのみなさんごめんなさい
まとめますと、「音が好き」「ブラウザの中が好き」「スマホにリッチなコンテンツを」「flashをガッツリ勉強するには遅すぎた」という4つの理由から、web audio APIで遊ぶことを選びました。
「音が好き」とざっくり言いましたが、もっと言うと空間音響と音楽音響です。好きとは言ったもののそこまで物を知ってるわけでもないです。
あのjsdo.itのコードも特に発展性や、これから爆発するアイデアがあるわけでもなくただの練習用なのですよ。
というわけで長くなってしまいましたが解説に入ります。
iOSのバージョンが6系に上がり、safariがweb audio APIに対応したという話を聞いてそれはそれは喜んだわけですが。
僕の調査から得られた主観的な意見なので本当かどうかを確かめる手段もないと思いますが、iOS6 safariはweb audio APIに完全対応はできていない感じだと思います。「んなもん当たり前だろなんだこいつ」と思われたら机で殴りに来てください。
web audio APIにはcreateBufferSourceというメソッドが用意されており、wav、mp3、ogg等から作ったarraybufferをAudioBufferSourceNode.bufferに突っ込んで再生することができます(参考:Web Audio APIで立体音響 - jsdo.it - Share JavaScript, HTML5 and CSS)。
で、ここからは完全に僕の予想になるのですが、このAudioBufferSourceNodeがiOS6 safariに未対応なのではないかと感じています。ちなみに↑のryoheyccさんのコードはiOS6 safariでは動作しません。具体的には、音が鳴りません。
僕が投稿したコードなんですが、当初はAudioBufferSourceNodeを使ってSVG女子のテーマ曲の仮想音源位置をぐりぐり回そうと思っていました。
が、この問題に当たってしまいました。iOS6 safariで音が鳴るコードはいくつか公開されています
iOS6 の Web Audio API を使う - 音の鳴るブログ
The Rise of the Mobile Web (and Web Audio on iOS 6)他
しかしAudioBufferSourceNodeを使ってiOS6 safari対応のアプリケーションを作った例が見つからなかったため、今回はcreateJavaScriptNodeで作ったnodeに乱数配列を突っ込んで白色雑音を再生するという手法を取っています。
今回作ってみて色々なものを色々試したんですが、どうにもまだiOS端末に対応し切れていないweb audio APIのnodeはありそうな感じがしています。
というわけで、iOS6 safariでweb audio APIを用いて音の表現を入れたいけど上手くいかないなぁ、という問題に当たった方は「そもそも対応していない」という選択肢を持ってみるのもいいんじゃないかなぁ、というなんだこれ酷い記事だなこれ。まぁいいや。
ファイルから作ったarraybufferをjavascriptNodeになんとか突っ込めればそれも解決すると思うので、それはこれから作ります。
長くなってしまったので今回はこのぐらいで。このコードについてはまだ書きたいことが2、3個あるのでだらだら書いていこうと思います。それでは失礼します