以前ソフトウェアFM音源(ソフトシンセ)について投稿しました。
このままだと作っただけで終わるので、技術的なところを書いてみたいと思います。
まずは思い出話から。
FM音源といえば、それまでピコピコしたビープ音しか鳴らなかったパソコンなどに、豊かな音色と多くの和音をもたらしてくれる音源として普及しました。晩年は携帯電話(ガラケー)の着メロなどで使われていましたが、その後は録音した音を再生するサンプリング方式の音源が普及して2025年現在に至ります。
FM音源が普及するまでは、ファミコンではメロディー演奏は矩形波と三角波による3和音のみでしたし、我が家で最初に導入した貰い物のPC-9801VMでは1音のビープ音(矩形波)しか鳴りませんでした。音色もピーとかプーといった単調なもので、その中で生まれた名曲もあるかと思いますが、ピコピコサウンドと評されるように、表現性の高い音楽を演奏するには向いていませんでした。
ファミコンはその後スーパーファミコンに進化し、サンプリング方式の音源に移行しました。以降、ゲーム機ではサンプリング音源が主流です。
PC-98などのパソコン界隈では、YAMAHAのFM音源チップを搭載した機種、または26ボード(OPN)や86ボード(OPNA)といったそれらを搭載した拡張ボードなどでFM音源が普及しました。当時、パソコン通信のnifty serveでは、RayというFM音源を活用して音楽を奏でるソフトおよびそのコンテンツが配布されていました。私は、友人からもらったrayファイルを再生してよく聞いており、そのノスタルジーに浸る目的もあり、作ったソフトシンセでrayファイルも演奏できるようにしてます。その後時代はGSやXGなどのサンプリング方式音源を搭載しているMIDI音源へとシフトしていきました。
閑話休題。
シンセサイザーとは音を合成(シンセサイズ)する機器・機能のことです。これをソフトウェアで実現するものがソフトウェアシンセサイザー(ソフトシンセ)です。録音したものを再生するサンプリング方式と異なり、シンセサイザーは何もないところから正弦波や三角波など信号を合成することで全く新しい音を作り出すものです。
音は、波形・波形の繰り返し周期(周波数)・波形の高さ(音量)の3要素で決まります。ピコピコ音源(正式な言葉ではありませんが)は周波数を変更できますが、音量は基本的に変更できません。波形も矩形波や三角波などのいくつかの固定波形のみです。PSG音源というものがあり、これはピコピコ音源にエンベロープ(1音内での音量の推移)が付いたシンセサイザーになります。FM音源とは、波形と周波数と音量が変更できるシンセサイザーです。波形を変更できると言っても、多数のパラメーターを使って間接的に変更することになり、「こんな形にしたい」と思った形を作り出すことは至難の業です。さらに波形も思った通りに変更できるものがサンプリング方式の音源となります。
FM音源は複数のオペレーターを組み合わせて音を合成します。OPNAやOPNでは4個のオペレーター、DX7では6個のオペレーターを組み合わせます。組み合わせ方をアルゴリズムといい、アルゴリズムによって全く異なる音が出ます。オペレーターにはキャリアとモジュレーターという役割があり、モジュレータは他のオペレーターに入力して変調するもの、キャリアは他のオペレーターから入力を受けて変調されるものと定義され、アルゴリズムによって各オペレーターはどちらかの役割に属します。FM音源のFMとはFrequency Modulation(周波数変調)の略でFMラジオのFMと同じですが、実際の仕組みはFMとは異なり、モジュレータの出力が次のキャリアの位相に入力されるPM(Phase Modulation(位相変調))として働きます。
オペレーターは発信器とエンベロープジェネレーターからなり、発信器はサイン波だけのものから、ソフトシンセなど、複雑な波形を指定できるものまであります。エンベロープジェネレーターとは音量推移を司るもので、例えばピアノの鍵盤を押した場合など、発声したあとに音が消えるまでの一連の音量推移を制御します。よくあるものとしてはアタック、ディケイ、サスティン、リリース(ADSR)の4つのパラメーターになります。また、オペレーターの出力レベルと、自己への再入力(フィードバック)レベルを変更することができます。
これらを踏まえ、一つのオペレーターを数式で表すと、
OPoutput(t,f,a,d,s,r)=L×EG(t,a,d,s,r)×sin(2πf×t+FB(t-1)+OPother)
FB(t+1)=OPoutput(t,f)×FBL
ただし、tは発声開始からの時間、fはオペレーター発振器の周波数、OPoutput(t)は時刻tにおけるオペレーターの出力、Lはオペレーターの出力レベル、EG(t,a,d,s,r)は時刻tにおけるadsrパラメーターで決まるエンベロープ、FBLはフィードバックレベルです。FB(t+1)や(t-1)と±1が付くのはソフトウェアならではですが、影響は無視できるレベルと思われます。OPotherは他のオペレーターからの出力です。このOPoutputを4つ組み合わせて一つの音を作るのがOPNA、6つ組み合わすのがDX7ということです。
AとB、2つのオペレーターをそれぞれキャリア、モジュレータとして数式で表すならば、
outputa(t,f,a,d,s,r)=La×EGa(t,a,d,s,r)×sin(2πfat+FBat+outputb(…))
FBx(t+1)=FBLx×outputx
となります。
FBxの初期値は0で、計算して得たそれぞれのオペレーターの出力レベルを保存しておき、次の計算時に組み込む事で実現します。フィードバックは適切に行わなければうまく音が鳴りません。このあたりは特許技術も関係してきます。
OPNAでは、このほかにdetuneなどのパラメーターもありますが、fに揺らぎを与えるものであって、基本的な考え方は同じです。
オペレーターをプログラム化できれば、次はアルゴリズムです。OPNA互換音源を作るのであれば、OPNAのアルゴリズムを実装してください。完全にフリーなFM音源を作るなら、好きなようにオペレーターをつないでください。
最後に、出てきたoutputを足し合わせて音量を調整すればFM音源の完成です。
オペレーターのプログラムだけなら数百行くらいで作れます。
ね、簡単でしょ?