shingoushori's dialy

音信号処理を専ら研究していた元博士後期課程の学生によるメモ

Web Audio API で、Multi-tap Delay (3 tap feedforward and 3 tap feedback)

Web Audio APIで、ディレイを組んでみました。
ただ、1本だけディレイのラインを出すだけならば、Web Audio APIにあったはず。
マルチタップで混沌とするには、1本だけのを組み合わせるのはメモリが勿体無い。
ちょっとだけ頭を捻って、1本だけのを組み合わせるよりはエコなものを組みました。

図などは、また時間があるときに描くことにいたしまして ... 

核心は、Web Audio API のフレームの倍サイズのメモリを1本用意し、
各サンプルでの数値をそのメモリ内の2箇所ずつに書き込んでいくこと。
リングバッファの実装で行われている技法です。
さっと探して参考文献が見当たらなかったので、こちらも後日。

計算量を検討したわけじゃないですが、
Web Audio APIのようにザクザクとブロック処理する場合は、
毎サンプルごとにリードライトを繰り返すくらいなら、
2箇所に書いてしまって、ポインタだけを動かした方が、たぶんシンプルです。

 

そんなMulti-tapなDelayを、feedforwardを3 tap と feedbackを3 tap 持たせまして、
前回( Web Audio API で、内蔵マイクで録音、ただしFirefox - shingoushori's dialy )
... のやつに繋いでみました。
内蔵マイクにDelay, wavを2つ同時再生してそちらにもDelay、ただしFirefox

 

実装してみて気づいたのが、3 tapのfeedbackのゲイン係数の発振条件。
1本だけなら、絶対値を1未満にしておけばいいわけです。
今回は3 tapが並列になるわけで、
遅延量が整数比の時には、倍数の経路でのゲイン係数が、
実際には約数の経路のゲイン係数との和になるわけですな。
条件を計算するのは後回しとしまして、
今回はとりあえず絶対値を0.33以下にしておきました。

Canvasで、はてなブログに回路図を直接描いてみるテスト(Diode Clipping)

はてなブログにできるだけ写真を投稿したくない!容量が気になるから.
でも、図やグラフを貼り付けたい!わかりやすいし、格好いいから.
この相反する気持ちの矛先として、Canvasに目をつけたわけです.

とりあえず最近のマイブーム、Diode clipperを描いてみました.

CanvasJavaScriptで関数化できるので、
巧くやればSVGファイルを頑張って貼るより色々楽しい予感がします.
Canvas要素の英語版wikiには、SVGとの比較が言及されていますな.

Web Audio API で、内蔵マイクで録音、ただしFirefox

前回、Web Audio API で、WAVファイルに書き出ししました.
今度はマイクの入力に手を出してみました.
ただし、録音はwavファイルの再生中のみで、
出力はwavファイルとの加算結果です.
さらに、どうにもFirefoxだけでしか動かない.

Google Chromeで動かないのが苦しいところ.
探してみると2013年あたりの文献が多く、しかもなにやら設定を変更せよとのこと.
http://www.html5rocks.com/ja/tutorials/getusermedia/intro/
http://slowquery.hatenablog.com/entry/2013/02/20/020321
https://developers.google.com/web/updates/2012/09/Live-Web-Audio-Input-Enabled
しかし、2016年3月現在の私のChromeでは記載の設定は見当たりませんでした.

Google Chromeで動くものもあり、
Simple microphone Web Audio API / WebRTC example – Nic Does Code
Pitch Detector
動かないものもあり...その違いが今の所わかりません.

Web Audio API で、WAVファイルに書き出してみる、再生終了後にダウンロード

これまでちまちまとWeb Audio APIで実装を試みてきました.
このあたりでWAVファイルへの書き出しに手を出してみました.

今回は、2つのファイルを同時再生し、
2つとも再生終了後に同時再生の結果をWAVファイルに書き出します.

書き出し可能になった時点で、"ダウンロード"にリンクが発生します.

怪しかったところが、再生終了のタイミングです.
onendedのタイミングで再生終了とすると、尻切れになってしまいました.
今回は乱暴に、onendedのタイミングからsetTimeoutによって遅らせました.

↓頼りきりになってしまった引用文献↓
http://qiita.com/HirokiTanaka/items/56f80844f9a32020ee3b
http://www.cyokodog.net/blog/media-capture-and-streams-web-audio-api/

Web Audio API で、the sliding Goertzel DFT filter のパラメータを弄ってみる、とりあえずNaN

前回、Web Audio API でthe sliding Goertzel DFT filterを実装し、
パラメータをいじりました.
しかし、入力された文字列によっては発散する恐れがありました.

今回は、入力された文字列に関門を設け、
想定外の数値となる場合は反映しないようにしました.

そこで一癖あったのが、NaNでした.
参考にしたページがこちら→NaNの判定について
JavaScriptの関数の癖だけでなく、主観的なNaNとプログラム上でのNaNは違うわけです.
数字でなくも文字列は、文字コードでもってNumberであり、NaNではない.
賢い関数がありそうなものですが、とりあえず単純に組んでみました.

Web Audio API で、the sliding Goertzel DFT filter のパラメータを弄ってみる、とりあえず

↓前回、the sliding Goertzel DFT filterを組みました. ↓
Web Audio API で、the sliding Goertzel DFT filter を試作 (1帯域) - shingoushori's dialy

今回は、パラメータを弄ってみました. とりあえず、です.
とりあえずポイント1: inputフォームを使う
とりあえずポイント2: 数値および数値の変更手順によっては、発散する
"ぷちっ"とノイズが出て、以後可聴な音が出なくなるわけです.
危険です. パラメータ変更に関しては、安全策を考える必要が有ります.
このサンプルをお使いになられてのトラブルについては、一切の責任を負いかねます...

 


fが中心周波数,rがdamping factor.
rについては,1以上の数値を入れると発散します.入れないでください!
fについては,DFTであるからk=f/(Fs/NDFT)が整数であるべきです.
ここで,k:周波数ビン番号,Fs:サンプリング周波数, NDFT:DFT点数です.
従って,k=round(f/(Fs/NDFT))とでもして整数化する実装が普通でしょう.
ところが,roundせずともフィルタリング自体はできているようです.
興味深い...

Web Audio API で、the sliding Goertzel DFT filter を試作 (1帯域)

Web Audio APIでのSTFTによる帯域分割がうまくいかないので,
the sliding Goertzel DFT filterに抜け道を求めました.

↓the sliding Goertzel DFT filterの素敵な文献↓
The Sliding DFT
SLIDING IS SMOOTHER THAN JUMPING

DFTの1帯域分に着目すれば,IIRフィルタで実装できるわけです.
しかも, フィルタだから毎サンプルでの算出結果が得られる.

 

とりあえず, DFT点数を1024, 着目する周波数ビン番号を20としてみました.
ただし, 負の周波数ビンとカップリングし,虚数が出ないようにしています.
さらに,発散しないように damping factor : r = 0.995で, 極を単位円から離しました.
数値は耳で聞いて設定しました.
damping factorがあるのでDFTと完全に一緒でもない.

 

今回, IIRフィルタをScriptProcessorNodeで組みました.
Web Audio APIにはIIRFilterNodeもありそうですが,私の環境では見つかりませんでした.
ScriptProcessorNodeも廃止が告知されており,
AudioWorkerNodeに置き換えられるそうで.
しかし,AudioWorkerNodeも私の環境にはまだ無い.
儚いものです...

 

最後に,ScriptProcessorNodeに引数とバッファを持たせる方法について.
JavaScriptでは, こんな感じにほいほい追加できる↓
オブジェクトを利用する
気づくまでに時間がかかり,
チャネル数を偽装して引数を渡そうとするなど,悪戦苦闘しました.