RSS Twitter Facebook


« 2012年09月 | 2012年10月のアーカイブ | 2012年11月 »

2012/10/31

Web Audio API のオシレーターでFMシンセサイズ


Web Audio APIのオシレーターを組み合わせてFM合成で音を作る実験。ものすごく適当ですけどとりあえず試してみた。


Chrome必須

オペレーター3段重ねでFMぽい音が作れそうではあるのですが、どうもSafariのWebAudioAPIだと全然違う音になってしまう模様。こういう使い方は想定してないのかなあ。

http://www.g200kg.com/shotit/

posted by g200kg : 11:44 PM : PermaLink

KVR DC'12 締め切り延長


KVR Developer Challenge のエントリー締め切りがちょっとだけ延長されました。
11月6日(火) AM10:00 (GMT) がエントリーの最終締め切りになり、各エントリーの公開と投票開始もそれ以降になります。

まあありがちな事なんでしょうがないけど、さっさと公開状態になってくれないとどうも落ち着かんなあ。
http://www.kvraudio.com/news/kvr-developer-challenge-2012-closing-date-looms---announcing-a-one-week-extension-20411

posted by g200kg : 7:16 AM : PermaLink

2012/10/26

BLITのお話


BLITって知ってますか? シンセを作ってる人じゃないとあまりなじみが無い言葉だとは思うのですが、時々ソフトシンセで、BLITを使ってます、とかいう売り文句があったりしますよね。ちょっとこのBLITについて書いてみたいと思います。

詳しくはこのあたりにあります
https://ccrma.stanford.edu/~stilti/papers/blit.pdf
後はTALさんが書いているこのページなんかは読みやすいです。
http://www.kunz.corrupt.ch/?DSP:Blit

BLIT は 「Band Limited Impulse Train」の略です。 Impulse Trainはインパルスがずらっと並んだ事を表しています。つまり、下の赤い線みたいにひげのようなパルスが一定間隔で並んだ波形です。Band Limited というのは帯域制限されているという事で、このインパルスが並んだ波形を理想的なローパスフィルターでナイキスト周波数より上をばっさりと切り落とした状態です。するとどうなるかというと、下の青い線の図みたいな波形になります。

数式的には
y(n) = (M/P) * SincM ((M/P) * n)
ただし
SincM(x)= sin(PI * x) / (M * sin(PI * x / M) )
て感じで表されます。

もうちょっとまとめると
y(n) = sin( PI * M / P * n) / (sin(PI / P * n) * P)
ここで、Pは1周期のサンプル数。MはPを超えない奇数で、帯域制限の上限を表しています。つまりMが大きいほど青線のうねうねが細かくなって本来のインパルスの形に近づいて行きます。

で、これが何の役に立つのでしょうか?

ここで話変わってオシレーターの作り方

例えばのこぎり波を作りたいとします。出したい周波数とサンプリング周波数の比から1サンプルあたりの差分 delta を作って、

phase += delta
if(phase >=1.0)
  phase -= 1.0

てやれば振幅が0.0 から 1.0 の範囲で変化するのこぎり波になりますが、実はこれだけだとエイリアスノイズが発生するという問題があります。これの何が悪いのさ、出したい理想波形上の点に一致してるでしょ、嫌なら後でフィルターでもかませば、て思うかも知れませんが、オシレーターの出力としてこういう波形を出した時点で駄目なんです。

例えばこの要領で矩形波を作ると、

if(phase >=0.5)
  out=1.0
else
  out=0.0

矩形波なんて0と1しかないんだからこんなんで良いんじゃね? と思いますが、44.1KHzのサンプリングレートで440Hzの音なら1周期が100.227ですから、100サンプルのサイクルと101サンプルのサイクルが周期的に混じったものになります、と言えば少なくともこれではまずいというのが直感的にわかりやすいですね。この周期のブレは音の濁りになり、これは後でフィルター掛けても既にノイズは折り返されて低い周波数になってますので取り除けません。

じゃあどうなんなきゃいけないのさ、と言うと、答えの1つが加算合成、アディティブシンセシスです。どんな波形でもサイン波を足していけば作れます、て言うのはフーリエ変換の説明の頭とかに出てきますけど、

sin(p) + sin(p*2)/2 + sin(p*3)/3 + sin(p*4)/4 +.....

て感じでナイキスト周波数以下の範囲で足して行けばエイリアスノイズのないのこぎり波が合成できます。こうやって加算合成で波形を作るのは DSF (Discrete-Summation Formulae) とも呼ばれます。 でもこれはさすがに計算が大変すぎます。1サンプル決めるのにどんだけ計算するんだよ、て感じですね。

て所で、BLITを使うわけです。エイリアスの発生しないBLIT波形にちょいと細工をしていろんな波形をつくってしまおうというもくろみですね。BLIT波形の性質は基本的にはインパルス列と同じようなもので、積分すると(積算してゆけば)段差が1の階段状の波形になるので、積算しながら1/Pを引く事でのこぎり波ができます。極性とかは後でなんとかしてください。

y(n+1) = y(n) + sin( PI * M / P * n) / (sin(PI / P * n) * P) - 1/P

て事ですね。sin()関数がいっぱいあったのがこれだと2つですみます。おー。

他のパターンとして、矩形波を作りたい場合はバイポーラBLITと言う波形を使います。バイポーラBLITというのは上下に順番にパルスが出るBLIT波形なんですが、実はBLITの式

y(n) = sin( PI * M / P * n) / (sin(PI / P * n) * P)

でMを偶数にするだけでできます。バイポーラBLITの積分は段差1を上がったり下がったりしますので、矩形波を作るのならこれを加算してゆくだけです。周波数は1/2になりますけど。

とまあ、これがBLIT方式による波形の発生の基本的な原理です。

しかしですね。2回とは言え1サンプル毎にsin()の計算が必要なんで、実際のシンセの実装としては、BLITを売り物にするんでなければ、あらかじめ作っておいた波形テーブルとかでやる方が一般的ですね。ただ、BLITもそうだけどナイキスト周波数ぎりぎりまで使ったエイリアスの出ない波形は出そうとしている周波数が変わると変わっちゃいますので、周波数範囲を幾つかに分けてテーブルを切り替えるとか色々このあたりはみなさん工夫しているようですよ。

まあ、ものが楽器ですのでエイリアスが全くない波形が唯一素晴らしいのか、という問題もありますし。どんなノイズが含まれているかも含めて、その楽器の音ですからね。

posted by g200kg : 2:03 PM : PermaLink

Windows8の日か・・・


どうしたもんかね。音楽関係の人の意見としては今の所

年末か来年あたりにアップデートするかな 21%
Win7/XPでいけるとこまで行くぜ 39%
わからん 21%
俺Win関係ねーし 6%
その他...

みたいな感じ。ふむ、まあそんなもんかな。
http://www.kvraudio.com/forum/viewtopic.php?t=363594&postdays=0&postorder=asc&start=0

posted by g200kg : 9:19 AM : PermaLink

2012/10/22

アナログシンセビルダーズサミット


アナログシンセビルダーズサミットにPolyphonic Full-Modular Software Synth 「Kamioooka (上大岡)」を展示します。

日時 : 2012年11月10日(土)
場所 : 東京都千代田区 科学技術館 第3会議室

なお、参加には事前登録が必要です。

http://analog-synth.jp/summit12entry/j_index.html

posted by g200kg : 2:38 PM : PermaLink

2012/10/18

プラグイン開発の開発プロセス


KVR のフォーラムでちょっと興味深いポストがあった。
この人は学生で、オーディオプラグイン開発における開発プロセスについて論文を書こうとしているらしいのだが・・・。

http://www.kvraudio.com/forum/viewtopic.php?t=362683

ある程度の規模のソフトウェア開発になればいやでもウォーターフォールだのアジャイルだのと、どういう開発プロセスを取るかが問題になるわけですが、オーディオプラグインってのはソフトウェアとしては非常に小規模ですからねえ。1人で完全にコントロールできる程度に小さくて、工業製品というより工芸品的な職人の世界ぽい。 ハードのエフェクターなんかも同じかも知れないけど。

まあ、普通のソフト開発だって昔はそんな感じでやってたのだけど規模が大きくなって立ち行かなくなったので、いやいやながら(?) ウォーターフォールにしてみたりやっぱりアジャイルにしてみたりしてるのだよね。製品を作るには避けては通れないけど、本当は開発プロセスがどうとかではなくて、ただアルゴ考えてコード書いていたい、とか本音では思ってる人が多いんじゃないかな。

その点、オーディオプラグインて奴は製品の特質上、機能をどんどん上乗せしていくようなものではなく、ソフトウェア規模が肥大しにくいので、今では数少ない楽園なのかも知れない。

アンケート取ってるようだけど、どんな結果なのか興味があるなあ。

posted by g200kg : 8:15 AM : PermaLink

2012/10/16

KVR DEVELOPER CHALLENGE remembered


2009/2007/2006 年に開催された KVR Developer Challenge 参加作品一覧
懐かしい人には懐かしいのだ

今年は3年ぶり4回目の開催。10月末エントリー締め切り。11/1から投票です。
http://www.kvraudio.com/kvr-developer-challenge/2012/

posted by g200kg : 7:45 AM : PermaLink

2012/10/14

Harmonic Shells



コーネル大学のHarmonic Shells。

たまたま見つけたのだが、これは凄く面白いな。薄板の振動をオーディオレートで物理シミュレーションしながら音としてレンダリングするというもの。いわゆる物理モデリング音源て事になるのだろうけど、色々がらくたっぽいものがぶつかる音をアニメーションと一緒に見せるというのはなんか面白い。

ピッチのグライド感が妙に不自然な感じがするけど、このあたりはなにやら苦労しているらしい。3年前のビデオみたいなので今はどうなっているのだろうか?

http://www.cs.cornell.edu/projects/harmonicshells/

posted by g200kg : 7:29 PM : PermaLink

2012/10/12

鍵盤どうやって描いてますか?



鍵盤の絵を描く必要にせまられている人がどれくらいいるのかは謎ですが・・・
とりあえずあまり考えずにこんな感じで描いてるケースが多いのではないでしょうか。黒鍵はちょうど白鍵の境界に中心を合わせて配置する、と。

1オクターブ並べると右の図のようになります。これでもマウスでクリックすると音が出るようなアプリの場合、位置からキーを判定するのが面倒ですね。計算で出すのは面倒だから各キーの矩形情報をテーブルで持って内部かどうか、みたいなやり方ですかね。

メジャーなソフトシンセなんかでも、このように描かれているものも多くありますので、別に気にする事でもないのですが、これは実際の鍵盤を見ると微妙に違ってますよね。実際は黒鍵の位置は中心からずれた場所に配置されて結構やっかいな事になっています。


これをどう考えるべきかというと、つまりC~Eの範囲を5分割、F~Bの範囲を7分割すると考えて、白鍵の幅を1とすると黒鍵側の配置はC~Eで3/5=0.6 、F~Bは4/7=0.5714..の幅を並べたような感じになります。更に言えば黒鍵の幅は一定でもう少し幅が狭い(白鍵23mmに対して黒鍵底面11mm) ので、この位置に中心を合わせてもう少し痩せた状態になります。どうせ矩形テーブルで位置を判定するなら中心合わせじゃなくて黒鍵の位置を微修正した方が良いかもですね。

そして・・・

逆に考えると、ソフト的に手抜きする方法もあります。実際の鍵盤とは若干ずれるのですが、1オクターブを白鍵側を7分割、黒鍵側を12分割すると考えてしまえば、ソフト的には白鍵側か黒鍵側かを判断した後、X座標を分割幅で割ってキーの位置を直接計算できます。

鍵盤の絵が小さい時なんかはもうこれで良いんじゃないかなと思うのです。F#の右端なんかがちょっと気になるので絵としてはもう少しごまかした方が良いかも知れませんが、ソフト的に単純になるのは魅力なのですよ。黒鍵のあたりをグリッサンドした時に等間隔でセミトーンが並んでいるのでなんとなく気分が落ち着くという効果もあるかも知れません。

posted by g200kg : 11:00 AM : PermaLink

2012/10/11

Web Music Meetup


昨晩はWeb Audio APIやらWeb楽器やらについて語り合うなかなかディープな会合がありまして、ついつい熱くなっておりました。このあたりの分野は今まさに発展途上でまだまだ取り組んでる人口が少ないですから、参入するなら今がチャンスですよ! ちょっと目を離しているとおいていかれちゃいそうでもありますが!!

--------------------------

と思ったら既に「Web Music Developers JP」というグループができていた。これは動きが加速する予感
https://groups.google.com/forum/?hl=ja&fromgroups#!forum/web-music-developers-jp

posted by g200kg : 2:28 PM : PermaLink

2012/10/10

CygwinでVSTを作るチュートリアル


lvlaudioさんがCygwin上でVSTのサンプルコードをコンパイルする環境をセットアップするビデオチュートリアルを公開しています。
https://www.youtube.com/watch?v=6_o1Kcpj7s8

まあ正直、VC++を使った方が色々と面倒くさくないんですけど、どうしてもCygwinでやりたいという人には役立つかな。


posted by g200kg : 4:22 PM : PermaLink

2012/10/09

マーシャルは何を作ろうとしているの?


マーシャルもソフトエンジニアを探しているらしい。
USBとかWindowsとかOSXとか書いてるけど、そっち方面に手を伸ばすのか?

http://www.marshallamps.com/support/support_job.asp?vacancyId=1

まあ流れ的にはそういう方向に行くのかね。フェンダーのアンプには既にUSBが付いているし不思議ではないはずなのだけど、積み上げられたスタックの横からUSBケーブルが・・・なんて事になったらちょっとシュールで面白そうではあるけど。
http://www.fender.jp/gdec3/products/

posted by g200kg : 5:07 AM : PermaLink

2012/10/04

続・ADSRの実装


ADSRの実装について書いたら超ニッチな話題にもかかわらず、結構いろんな人が反応してくれたので、調子に乗ってもう少し突っ込んだ解説もしてみます。

さて、ADSRはハードウェア回路としてはコンデンサの充放電によるカーブでできていて、それをソフトウェアで実現するために

現在値=目標値 + (現在値 - 目標値) × 係数

という計算でいけるよと説明しましたけど、まずこのあたりについて。

式の説明

話を簡単にするために0に向かって減少するリリースの場合だと、この式は単に

現在値 = 現在値 × 係数(例えば0.99とか)

になるわけですが、こんな単純でいいんでしょうか? という話。
コンデンサの充放電って要するにRC回路の過渡応答なわけで、電気回路の教科書を探せば

V(t)=V×(1-exp(-t/RC))

なんてゆう公式が見つかるかと思います。これはRC回路に電圧Vをかけた時のコンデンサの電圧の上がり方を表しています。リリースのカーブを想定して現在値1Vで0Vに向かって減少するという場合なら、1Vを基準点(=0)と置いて-1Vで充電すると考えればよいです。つまり

V(t) = 1 + (-1× (1-exp(-t/RC))) = exp(-t/RC)

なんだ結局指数関数 exp(-t/RC) で減少してるだけじゃん、て事ですね。指数の符号がマイナスですから指数曲線の0から左に向かって動いています。

さてこれを一定周期毎に計算するわけです。つまり単位時間あたりの差分を計算するのですが、「指数の微分は指数」ですからね。言い換えれば、「今の地点の傾きは今の地点の大きさ」って事です。

つまり現在値に比例した差分を差っぴいていけば良いだけの話なので
現在値 = 現在値 × 係数
で良いのです。この式って指数関数なのですよ。

電荷がコンデンサから抜けて行くのは水の溜まった水槽の一番下に穴を開けたみたいな感じで、最初は圧があるので勢い良く減りますがだんだんゆっくりになるのをイメージすれば直感的に理解できるかも知れません。水槽に残っている水の量に比例した速さで抜けて行くわけです。

係数の話

さてじゃあ、この係数はどうやって決めれば良いの? という話。

結構な頻度で繰り返し掛け算していくので 0.99... みたいな1に近い値が必要である事はわかると思います。
Attack Time とか Release Timeとか時間で指定したい所ですが、漸近してゆくだけでいつまで経っても目標値にはなりませんので、例えば「目標値の95%に近づくまでの時間」のような決め方をします。

つまり 1.0 => 0.05 になるまでの時間。仮に1mSec周期で計算してReleaseTime を1秒にしたいなら 1000回掛け算をして 0.05になるわけですから、これは

「0.05 の1000乗根」

です。C言語なら pow(0.05, 1.0/1000) とかいう感じで計算できますね。

更に更に、この辺の人間の感覚は対数的なのでツマミの反応カーブ自体が指数的(対数目盛り)であって欲しいですね。ハードウェアで作るならボリュームにAカーブを使う所です。ツマミのx=0.0~1.0に対して、最速10mSec~最長10Secとか。これは pow(1000,x)*0.01 (sec) という感じですね。

毎秒n回計算するとしてこれを上の式と一緒にすると

係数=pow(0.05, 1.0 / (pow(1000, x) * 0.01 * n))

こんな感じになります。 結構重そうだけど、係数を計算するのはツマミをいじった時だけですのであまり問題にはならないですね。

でましたデノーマル

こんな感じでADSRは実装できるのですが・・・ただし!! ここで1つだけ気をつけなければいけない事があります。それが「デノーマルの罠」です。 「現在値 = 現在値 × 係数」 で計算を繰り返していくと、だんだん0に近づいていって、これを放置しておくと「デノーマル数」という厄介な問題に突入してパフォーマンスがガタ落ちになります。

詳しくは「VSTiの作り方」の方にも書いてますので参照して欲しいのですが、ほぼ0になったらどこかで計算を打ち切ってやる必要があります。
http://www.g200kg.com/jp/docs/makingvst/03.html#3.3

Javascriptで書いてると見落とし勝ちですが、先日確認した所ではこの問題はNativeだけじゃなくてJavascriptでも同じように発生するので要注意です。

posted by g200kg : 6:57 AM : PermaLink

2012/10/02

ADSRの実装


ADSRと言えばシンセを扱う人なら誰でも知っている音の音量カーブを決めるパラメータですが...

Twitterの方でモハヨナオさんの発言「ADSRエンベロープの実装って真面目にやるとキーオフのタイミングをめぐってややこしくなるけど、キーオンとキーオフ、二つのエンベロープに分割するとすごく楽になる 」というのがあって、なんか面白かったので自分のコードを眺めなおしたりしてたのだけど、なんか毎回ちょっとずつ違う実装してたりしてまとまりがないのだ。

正直ADSRのカーブを見ながらソフトで実装しようとすると変に複雑になりがちなんで、モハヨナオさんのアイデアとはまた違うのですが、この際、自分なりのADSRの実装について考察してみます。
ハードウェアとして一般的な回路がどうなってるかは武田さんのページなんかからたどれば色々でてきます。
http://www.aleph.co.jp/~takeda/radio/hms6.html
http://www.uni-bonn.de/~uzs159/adsr2.png

単純に書くとこんな構造です。

基本的にはこれをシミュレートする方向で考えると、回路的にはタイマーIC(NE555)一個だけでできているのですね。つまりADSR内部で必要なのはTimerOnのフラグ1つあれば良くて、出力される電圧は結局の所、タイマーICに繋がっている1つのコンデンサに対する充放電のカーブになっています。

ダイオードで充放電の方向が決まるのですが、動作を言葉で説明するとこうなります。出力するレベルは 0.0-1.0 の範囲で、Key信号はオン=1.0、オフ=0.0です。

■TimerはKeyの立ち上がりでOnして出力が1.0になったらOff (途中でKeyが下がっても強制Off)
■Timer On期間はAttackレートでピークに向かって充電
■Timer Off期間は出力がSustain Levelより大きいければSustain Levelに向かってDecayレートで放電
■出力がKey Levelより高ければKey Levelに向かって放電
これだけです。これは言葉で書いたほうがすっきりしてプログラムに落とすのも簡単な気がしますね。

ちなみに「xxに向かって充電(放電)」て言うのは、一定の周期で
現在値=目標値 + (現在値 - 目標値)×係数
を繰り返して目標値に漸近するカーブになります。

で、まあ、実は音の性格を決める所でアタックのカーブの取り方が結構重要な気がします。「ピークに向かって充電」と書きましたけど、1.0に漸近する曲線ではいつまでたっても1.0にならないわけで、このピーク付近のカーブの違いでアタック部分の音の図太さが変わっちゃいます。もう1つパラメータを追加するならAHDSRの「Hold」に相当する部分ですね。


NE555の仕様に忠実に行くならば、タイマーのスレッショルドは電源の1/3の所ですので、正確には「3.0に向かって充電して1.0を超えたらリセット」電源の2/3の所ですので、正確には「1.5に向かって充電して1.0を超えたらリセット」って感じになります。他の方法としてはアタックは直線で上らせるというやりかたもありますね。これだとちょっとピークが細い感じになります。

posted by g200kg : 8:12 PM : PermaLink

« 2012年09月 | 2012年10月のアーカイブ | 2012年11月 »


g200kg