FM音源 EGS/OPSのレジスタ解析

はじめに

シンセサイザーTX7のシステムROMを解析して、YM2128(OPS)およびYM2129(EGS)のレジスタの調査を行った。 (2013.12.31)

概略

第一世代の6オペレータFMチップは同時に1種類の音色しか設定することができず、16チャンネル全部が同じ音色となる。 チャンネル単位で設定できるレジスタにはピッチ、アウトプットレベル、キーオンがあった。

DX7のサービスマニュアルによると、EGSとOPSの2個のチップでFM処理を行い、EGSの後段にOPSが接続される構成となっている。EGSは各オペレータのエンベロープとピッチの処理を行う。OPSは各オペレータの位相の処理、サインテーブルの読み出し、オペレータの結合、フィードバックの処理を行う。6オペレータ×16チャンネル分のエンベロープの出力と周波数の処理結果がEGSからOPSに渡される。

EGSには、未使用も含めて256個のレジスタがあり、OPSには2個のレジスタがあることが判明した。

アウトプットレベルには、各オペレータをチャンネルごとに設定できるようレジスタが用意されていた。 キーレベルスケーリング、キーベロシティの機能、チャンネル間の音量バランスはソフトウェアによって実現されていた。

EGSにはAM,PMのLFOの機能はあるが、OPMなど他のFMチップとはだいぶ異なるものであった。 低周波の波形が自動生成される機能はなく、瞬時のレベルの増減量、位相(音程)の増減量を指定する、LFOの補助的なレジスタが用意されているのみであり、ソフトウェアで波形の演算を行う必要がある。

EGS,OPSのレジスタマップ

EGS

Rcontent*0*1*2*3*4*5*F
00Pitch H/LCh1 HCh1 LCh2 HCh2 LCh3 HCh3 LCh8 L
10Ch9 HCh9 LCh10 HCh10 LCh11 HCh11 LCh16 L
20Freq H/LOp6 HOp6 LOp5 HOp5 LOp4 HOp4 L
30DetuneOp6Op5Op4Op3Op2Op1
40EG RateOp6 R1Op6 R2Op6 R3Op6 R4Op5 R1Op5 R2Op3 R4
50Op2 R1Op2 R2Op2 R3Op2 R4Op1 R1Op1 R2
60EG LevelOp6 L1Op6 L2Op6 L3Op6 L4Op5 L1Op5 L2Op3 L4
70Op2 L1Op2 L2Op2 L3Op2 L4Op1 L1Op1 L2
80Op6 OLCh1Ch2Ch3Ch4Ch5Ch6Ch16
90Op5 OLCh1Ch2Ch3Ch4Ch5Ch6...Ch16
A0Op4 OLCh1Ch2Ch3Ch4Ch5Ch6...Ch16
B0Op3 OLCh1Ch2Ch3Ch4Ch5Ch6...Ch16
C0Op2 OLCh1Ch2Ch3Ch4Ch5Ch6...Ch16
D0Op1 OLCh1Ch2Ch3Ch4Ch5Ch6...Ch16
E0AMS/KRSOp6Op5Op4Op3Op2Op1
F0Misc.AMDKeyPMD HPMD L

OPS

Rcontent
00Oscillator Key Sync ($30:sync/$50:async)
01Algorithm/Feedback Level [AAAA_AFFF]

EGSのレジスタ

R00-R1F: ピッチ

Bit Format : PPPP_PPPP_PPPP_PP00

各チャンネルの音程を14bitの値で指定する。 上位8bitが半音単位、下位6bitがより細かい音程を指定する。

形式的にはOPM系のKC,KF(キーコード、キーフラクション)レジスタと同じであるが、 EGS/OPSではチップの内部設計に依存すると思われるレジスタ仕様となっている。 EGSではKCの値に応じてKFにオフセット値を加える必要がある。 KCの下位2bitの値{0,1,2}により、KFに値{$00,$55,$aa}(8bit表現として。実際は下位2bitをマスク)を加えている。

KFのオフセットは半音の1/3ずつ増えているため、KCの値4つ分で半音3つ分に相当する(KCの1=KFの64=半音の3/4)という見方もできる。
(OPMではKFにオフセットを加えずに済むように改良されていると言える。KCがとびとびの値をとることの起源はこれだったのだ。)

R20-R2B: 周波数の倍率/固定周波数

Bit Format : FFFF_FFFF_FFFF_FFFM
下位1bitの値によってモードを指定する。0が倍率のモード、1が固定周波数のモードを表す。 上位15bitの値によって、周波数の倍率または固定周波数を指定する。

(Ratioモード)

上位15bitの値によって周波数の倍率を指定する。
最終的には定数$232cが加算された値がレジスタに書かれるが、定数を加算される前の16bitの値は、上位4bitがオクターブ増分の整数部、下位12bitがオクターブ増分の小数部に相当する。周波数の倍率2^nのnを与える値である。

VCEDパラメータ値coarse, fineとレジスタ値Rの関係は次のとおりである。
R = coarse_table[coarse] + fine_table[fine] + $232c;

レジスタ値に変換する過程

Frequency Coarseの値は0〜31の範囲で与えられる。値0が倍率0.5倍を意味し、値1〜31は倍率1〜31倍を意味する。
テーブルによりCoarseの値が16bitの値に変換される。

0→$f000,
1→$0000,
2→$1000, 3→$195c,
4→$2000, 5→$2528, 6→$295c, 7→$2cec,
8→$3000, 9→$32b8, 10→$3528, 11→$375a, 12→$395c, ...
16→$4000, 17→$4168, 18→$42b8, ...
31→$4f44,
Coarseの定義を考えつつ、このテーブルを眺めると、上位4bitが周波数倍率の、2のn乗の指数部に相当することがわかる。残りの下位bitが指数の小数部になっていそうに見える。

Frequency Fineの値は0〜99の範囲で与えられる。
テーブルによりFineの値が16bitの値に変換される。

0→$0000, 1→$003a, 2→$0075, 3→$00ae, ...
50→$095c, … 99→$0fe2, 100→$1000

Coarseのテーブルから求めた値と、Fineのテーブルから求めた値が加算され、さらに定数$232cが加算された値がレジスタに書き込まれる。式で表すと次のようになる。
R = coarse_table[coarse] + fine_table[fine] + $232c;

Fineの意味

ここで、Fineの意味を考える。
f(coarse,fine) = coarse_table[coarse] + fine_table[fine] とおくと、

f(1, 50) = $0000 + $095c = $095c
f(2, 50) = $1000 + $095c = $195c = f(3, 0)
f(4, 50) = $2000 + $095c = $295c = f(6, 0)
f(6, 50) = $295c + $095c = $32b8 = f(9, 0)
f(8, 50) = $3000 + $095c = $395c = f(12, 0)
この例より、fine=50は、coarseによる倍率を1.5倍する働きがあると言える。

fine=25の場合も見てみると、

f(4, 25) = $2000 + $0526 = $2526 = f(5, 0)
f(8, 25) = $3000 + $0526 = $3526 = f(10, 0)
となり、coarseによる倍率を1.25倍している。
よって、fine=nは、coarseによる倍率を(1+0.01*n)倍する、と考えてよさそうである。

また、coarseによる倍率はパラメータの定義より、2^(Coarse - 1)と表すことができる。
したがって、周波数の倍率は次式で表される。

Frequency Ratio = 2 ^ (Coarse - 1 + Fine / 100);

(Fixedモード)

上位15bitの値によって固定周波数を指定する。 VCEDパラメータ値とレジスタ値の関係は次のとおりである。

Frequency Coarseの値は下位2bitのみ有効である。パラメータ値{0, 1, 2, 3}に対して周波数{1, 10, 100, 1000}[Hz]が対応する。これらに対応するレジスタの値は{$0000, $3526, $6a4c, $9f74}である。テーブルにより変換される。

Frequency Fineの値は0〜99の範囲で与えられる。パラメータ値を136倍した値が先ほどのレジスタ値に加算される。 さらに、定数$5804が加算され、Fixedモードを表す下位bitの1が付いた値が、レジスタに書き込まれる。

まとめると、次式で求めた値Rがレジスタに書き込まれる。

R = coarse_table[coarse] + fine * 136 + $5804 + 1;

100を136倍すると、$3520となる。$6a4c,$9f74はその(約)2倍,3倍の値である。 このことから、fineの値はcoarse値の0.01倍に相当することがわかる。すなわち、固定周波数は次式で表される。

Fixed Frequency = 10 ^ (coarse + fine / 100);

R30-R35: Detune

Bit Format : ****_DDDD
各オペレータの入力ピッチの微調整を行う。
VCEDのパラメータでは、値7が中央値"0"を意味し、値0が"-7"、値14が"+7"を意味する。
レジスタの値では、値0〜7が"0"〜"+7"を意味し、値9〜14が"-1"〜"-7"を意味する。 すなわち、bit0-2が深さ、bit3が符号を意味する。
テーブルにより変換した値がレジスタに書き込まれる。

第二世代のチップが使われたDX7II、DX7sのユーザーマニュアルには、固定周波数モードの場合、プラス側の値のみ機能すると書かれている。第一世代のチップでも同じ仕様であると考えられる。

R40-R57: EG Rate

各オペレータのエンベロープの4つのレートR1,R2,R3,R4を0〜$3fの範囲で指定する。 値が大きいほど変化の速度が速い。

EG RateのVCEDパラメータは0〜99の100段階の値であるが、レジスタでは0〜$3fの64段階の値である。次式により100段階の値が64段階の値に変換される。

V' = (V * 164) / 256;   (割り算は切り捨て)

VCEDパラメータからレジスタ値への変換は次のようになる。

{0, 1, 2, 3, … 98, 99} → {$00, $00, $01, $01, … $3e, $3f}

R60-R77: EG Level

各オペレータのエンベロープの4点のレベルL1,L2,L3,L4を0〜$3fの範囲で指定する。 0が最大レベルを表し、$3fが最小のレベルを表す。

VCEDパラメータからレジスタの値への変換: 非線形テーブルを参照して、0〜99を$7f〜0へ変換し、さらに2で割った商をレジスタの値とする。
20〜99の範囲では次式により変換される。

V' = (99 - V) / 2;

R80-RDF: Output Level

チャンネルごとに、各オペレータの出力レベルを0〜$ffの範囲で指定する。 値0が最大のレベルを意味するが、ソフトウェアによって値が0〜3の範囲にある場合は4にクリップされていた。

キーボード・レベル・スケーリング、キー・ベロシティ、コントローラーによるEGバイアス/出力のコントロール、チャンネルの音量がソフトウェアで処理された結果がレジスタに書き込まれる。

VCEDパラメータは0-99の100段階の値であるが、レジスタでは0~$ffの256段階の値である。EG Levelと共通の非線形のテーブルによって、0〜99(99が最大)が$7f〜0(0が最大)へと変換される。
20〜99の範囲では次式により単純に$4f〜$00へと変換される。

V' = 99 - V;

RE0-RE5: AMS/KRS

Bit Format : ***A_AKKK
各オペレータの、音量モジュレーションの感度と、キーボード・レート・スケーリングを指定する。 音量モジュレーション感度は0〜3、キーボード・レート・スケーリングは0〜7の範囲で指定する。 キーボード・レート・スケーリングの値が大きいほど高い音程でのエンベロープの速度が速くなる。

RF1: key

Bit Format : **CC_CCSS
各チャンネルのキーオン/キーオフを指定する。 bit5-2によりチャンネル番号を指定し、bit1,0でキーの状態を指定する。 キーオンを指定するときは下位2bitの値に1が、キーオフを指定するときは2が指定されていた。

RF0: AMD

音量モジュレーションの量を指定する。
LFOのパラメータから波形の演算をソフトウェアで行い、瞬間の波形の値を0〜$ffの範囲で指定する。

RF2-RF3: PMD

音程モジュレーションの量を16bitの値により指定する。

OPSのレジスタ

R00: Oscillator Key Sync

キーオン時に各オペレータの位相をリセットするかどうかを指定する。 リセットする場合は$30が、リセットしない場合は$50がレジスタに書き込まれていた。

R01: Algorithm / Feedback Level

Bit Format : AAAA_AFFF
bit7-3によりアルゴリズムを指定し、bit2-0によりフィードバックレベルを指定する。