hello_ymfm_wasm

YM2612 で Beep を鳴らす

このメモは ex03_beep.cpp のためのものです。

目的は、まだ豊かな楽器音を作ることではありません。 まずは 1 つの単純な YM2612 beep を、完成した音から逆にたどって理解することです。

まず browser demo を見る

コードを読む前に、まずは次のページで目標の音を聞いてみてください。

この demo は ex03_beep.cpp と同じ YM2612 設定を使っています。

この tutorial の問いは、次の 2 つです。

まず FM の考え方で beep を説明する

最初から register 番号を見るより先に、この beep を FM 的に言い直すと分かりやすいです。

これが、この beep の本当の内容です。 register write は、この内容を chip 固有の形式で表現しているだけです。

channel と operator の考え方

YM2612 には 6 個の FM channel があります。 各 channel には 4 個の operator があります。

operator は小さな音の発生器です。 operator 同士を変調に使うこともできるし、そのまま最終出力に混ぜることもできます。

ex03_beep.cpp では channel 1 を使っています。

FM 音源では、基本的に 1 つの channel を 4 つの operator で構成します。 そのため、0x30-0x3c のようにアドレス範囲に幅があるのは、 4 個の operator 分の設定が並んでいるためです。

なぜ Algorithm 7 なのか

Algorithm 7 では、4 個の operator がすべて carrier として動きます。 すべてが直接出力に行くので、最初の理解用として分かりやすいです。

唯一の方法ではありませんが、最初の beep には向いています。

この beep の目標設定

この beep を設定の意図として書くと、だいたい次のようになります。

Channel

Operators

もう少し具体的には:

Pitch

Trigger

Key ON を送らないと、chip の設定は終わっていても音は始まりません。

その考え方を YM2612 write に変換する

FM 側の考え方が見えたら、次に chip 側の表現を見ます。

各レジスタ書き込みは、次の 2 段階です。

  1. address port にレジスタ番号を書く
  2. data port に値を書く

例:

chip.write(0, 0x30);
chip.write(1, 0x01);

これは、

  1. レジスタ 0x30 を選ぶ
  2. レジスタ 0x30 に 0x01 を書く

という意味です。

つまり ex03_beep.cpp では、同時に 2 つのことをしています。

ex03_beep.cpp で使うレジスタ

全体の見取り図

1. DT / MULTI

これらのレジスタは、各 operator の detune と frequency multiple を設定します。

ex03_beep.cpp では、すべて 0x01 を設定しています。

何が起きるか:

補足:

2. Total Level

これらのレジスタは、各 operator の出力レベルを設定します。

ex03_beep.cpp では、operator 4 だけを大きくしています。

何が起きるか:

補足:

3. Attack Rate

これらのレジスタは、音がどれだけ速く立ち上がるかを設定します。

ex03_beep.cpp では、すべて 0x1f です。

何が起きるか:

補足:

4. Sustain / Release 周辺

これらのレジスタは、エンベロープ設定の一部です。

ex03_beep.cpp では、すべて 0x0f です。

何が起きるか:

補足:

5. Algorithm

これは channel 1 に Algorithm 7 を設定しています。

何が起きるか:

補足:

6. 左右出力

これは left と right の両方の出力を有効にしています。

何が起きるか:

補足:

7. Frequency

この 2 つのレジスタで音程を設定します。

何が起きるか:

補足:

8. Key ON

これは channel 1 の operator 1-4 を ON にしています。

何が起きるか:

補足:

コードをレジスタ辞書として読む

YM2612 をもう一段深く理解して、自分で設定を書けるようになりたい場合は、 ymfm のソースコードをそのまま読むのがかなり有効です。

このリポジトリでは、src/ymfm_opn.h:209 がレジスタ辞書としてとても役に立ちます。

特に次の行が分かりやすいです。

0x28 の key on / key off の扱いは、src/ymfm_opn.cpp:176 を読むと追えます。

ex03_beep.cpp の write() と、ここでの定義が頭の中でつながるようになると、 かなり自力で YM2612 の beep 設定を書ける段階に近づいています。

大事な考え方

beep は特別な 1 命令で出るわけではありません。

次の積み重ねで音になります。