作ればわかる、FM音源

この記事はSpeee Advent Calendar 2017 15日目の記事です。

前日は@cho3による「サンタクロースの正体を暴く」でした。

動機

昔からFM音源の音は好きだったが、どういう原理で音作りをしているのか詳しくは知らなかった。

FM音源がどんな音色を出すかについては、ここに貼った動画を見てほしい。

www.youtube.com

一言で言うと80年代の音。
とはいえ90年代以降も多用されていて、メガドライブの内蔵音源や、ガラケーの着メロを鳴らしていたのもFM音源だ。

とある記事(アナログシンセとはまったく違う、“誰でもわかるFM音源”講座 : 藤本健の“DTMステーション”)を読んでいたら、仕組みについてはなんとなく理解できたので、実際に動くものをWebAudioとReactで作ってみることにした。

そうFM音源とは周波数変調をかける音源であり、OP2でOP1にビブラートをかけるというか、くすぐるんです。OP1はもともとポーっと鳴っていた音が、くすぐったいのでピーとかジーとがギャーって鳴るんです

本稿では一般的なFM音源の原理については詳しく触れないので、気になる方は記事を読んでみてほしい。

記事中に出てくるReface DXのUIはグラフィカルでFM音源の音作りも直感的にできそうだ(欲しい)。
以前、DX7の実機でパラメータをいじったときは全然理解できなかった。

オペレータを作る

FM音源において音を構成する最小要素、オペレータから作っていく。
OscillatorNodeとGainNodeをまとめたものにEG(ADSR)を追加してOperator classを作った。

f:id:nishaya:20171214181637p:plain

ADSRは数値だけだと直感的にエディットしづらいので可視化した。
SVGを使ったのは、DOMで記述できReactとの相性が良いため。

オペレータのルーティングをする

Operatorには変調をかけられる側(キャリア)とかける側(モジュレータ)があり、それぞれノードを接続する先が違う。
キャリアは音を出すので出力に直結するGainNodeに、モジュレータは変調をかけるのでキャリアのOscillatorNode(のfrequency)に接続する。

例えば、後述するElectric Pianoのルーティングは以下のようになる。

f:id:nishaya:20171214165523p:plain

※ nodeの可視化にはFirefoxWeb Audio エディターを使った

勘のいい読者ならお気づきと思うが、このルーティングはFM音源シンセサイザーにおけるアルゴリズムとほぼ同じだ。

音(ノート)を鳴らす

キーを押すとOscillatorNodeの発振が開始されて音が出る。 今回作ったFM音源は4OPなので1音発音するのに4つのOscillatorNodeのstart()を呼ぶ。

このとき、各オペレータに内包されているGainNodeに対し、ADSRのパラメータによるレベルの時間的変化をスケジュールする。 これによって、ゆっくり立ち上がる(長いattack)音や、鋭さを伴った(短いdecayと低いsustain)変調、キーを話したときの余韻(長いsustain)といった表現が可能になる。

WebAudio APIのOscillatorNodeは1回鳴らすごとに使い捨てなので、発音のたびに4つのOperatorを内包するNoteオブジェクトを生成し、アルゴリズムに沿ってNodeの接続をした後にOscillatorNodeの再生を行っている。

音色を作る

FM音源の音色作りは変調による波形の変化が極端なため、一般的には難解とされるが「くすぐり」を意識しながら作っていくとそれらしい音ができあがる。

1. Electric Piano

いかにもFM音源といった感じのエレクトリックピアノ
バリエーションとして 4. Toy Piano も作った

  • carrier #0 に 減衰の速い(decayを短めにした) modulator #1 をかけて「コツン」という感じの立ち上がりを与える
  • 音に厚みを出すため、デチューンした carrier #2 を用意し、金属的な響きを加えるためにfreq. ratioを大きめにとった modulator #3 をかける

2. Organ

オーソドックスなオルガン。

  • carrier #0 ~ #3を並列に並べ、それぞれを別のfreq. ratioで鳴らす

3. Synth Bass

クセの強いシンセベース。

  • carrier #0 に modulator #1~3 をかける。modulatorごとに異なるADSRを設定し、音色に時間的な変化を与えている

別途LPFをかけるとそれらしくなりそう

DEMO

My first FM synth

f:id:nishaya:20171214193716p:plain

※ A~Lのキーを鍵盤に見立てて演奏ができます

Chrome(63以降)推奨。 FirefoxだとAudioParam.cancelAndHoldAtTime()が使えないのでリリースが不自然になる問題が残っている。

Source Code

今回のdemoのビルドにはParcelを使った。
production buildするときにこのバグを踏んだのだけれど、翌日にリリースされた1.2.0で修正されていた。

Unable to `build` index.html · Issue #8 · parcel-bundler/parcel

TODO

  • とりあえず音が出るよう作ったのでリソースの管理が雑なのをなんとかする
  • オペレータにフィードバックを追加する
  • フィルタを追加する
  • アルゴリズムをグラフで可視化する

所感

難解だと思っていたFM音源も、自分で作ることによって理解が進み、ある程度までは思い通りの音を作れるようになった。

D-50のLA音源や物理モデル音源など、原理が気になる音源方式は無数にあるので、機会があればそれらも挑戦してみたい。


明日は@yoppiによる「GoとECSの格闘技について」 お楽しみに!