FM音源プログラム (6) -- EG (6)
「YMF715x(OPL3-SA3) -Register Description Document-」(以降「rege」と省略) のエンベロープ・レートと時間との対応表について、詳細に検討してみました。
現在のFM音源プログラムは、テーブルを使ってエンベロープ・レートからアキュムレータの増分値を得ています。 このテーブルは、 に比例する値をプログラムで計算して作成しています。
「rege」の表と、なるべく一致するような値を選んでいるのですが、微妙に違っているのが気にはなっていました。
深く追求しないで放っておいたのですが、今回、詳細に検討してみて、ハードウェアでの実現方法の片鱗が見えてきたような気がします。
まずは、アタック・レートの 0-100 % の時間の表について調べます。
実ARの値が 4 増えると時間が 1/2 になるのは自明ですから、4 以内の差について、アタック時間の比を求めます。
AR | アタック時間 | (AR-1)の値との比 | AR=4の値との比 |
---|---|---|---|
4 | 2826.24 | --- | 1.00000 = 69/69 |
5 | 2252.80 | 0.79710 = 55/69 | 0.79710 = 55/69 |
6 | 1884.16 | 0.83636 = 46/55 | 0.66667 = 46/69 |
7 | 1597.44 | 0.84783 = 39/46 | 0.56522 = 39/69 |
8 | 1413.12 | 0.88462 = 69/78 | 0.50000 = 69/138 |
ちなみに、プログラムで作成したテーブルでは、隣との比はすべて等しく、 です。
クロックの分周比が大きければ、分周後のクロックは遅くなり、そのクロックで駆動される回路の時間は長くなります。 同様に、分周比が小さければ、分周後のクロックは速くなり、時間は短くなります。
したがって、この表から、
- (AR mod 4) = 0 のとき 69 分周
- (AR mod 4) = 1 のとき 55 分周
- (AR mod 4) = 2 のとき 46 分周
- (AR mod 4) = 3 のとき 39 分周
したクロックを EG ハードウェア回路のクロックとして使用すれば、上の表の時間の比率を実現できることになります。
(AR div 4)、つまり、元の音色パラメータの AR 値は、EG アキュムレータをインクリメントするビット位置の選択に使います。
この考えで、「rege」の表と同等の表を出力する C プログラムを下に示します。
#include <stdio.h> #define fs (400e3) #define EGACC_MAX (0x4000L) int ardiv[] = { 69, 55, 46, 39 }; double calc_attacktime(int rate) { double fclk; fclk = fs / ardiv[(rate & 0x03)]; return((EGACC_MAX >> ((rate>>2) - 1))/ fclk); } void main() { int i; double t; printf("Rate Time [ms]\n"); for (i = 4; i < 60; i++) { t = 1e3 * calc_attacktime(i); printf("%3d %9.2f\n", i, t); } // for (i }
AR=0〜3 はエンベロープ変化なし、AR=60〜63 はアタック・タイム=0 となる特別な場合なので、上のプログラムでは除外しています。
このプログラムでは、400 kHz のメインクロックを 1/69, 1/55, 1/46, あるいは 1/39 の周波数に分周して、約 5.8 〜 10.3 kHz の EG クロックとし、重み のビットだけが立っているビットパターンで 14 ビット・アキュムレータに加算するというイメージです。
このプログラムの出力と「rege」の表を比べて、下のような誤りを発見しました。
AR | 誤 | 正 |
---|---|---|
20 | 176.76 | 176.64 |
多分、これは、データを人手で入力した時の誤りだと思います。
「rege」の同じ表の 10-90 % の立ち上がり時間については、単に 0-100 % の値と比例関係にあると思っていましたが、実際に詳しく調べてみると、
AR | 時間 | (AR-1)の値との比 | AR=4の値との比 |
---|---|---|---|
4 | 1482.75 | --- | 1.00000 = 181/181 |
5 | 1155.07 | 0.77901 = 141/181 | 0.77901 = 141/181 |
6 | 991.23 | 0.85816 = 121/141 | 0.66851 = 121/181 |
7 | 868.35 | 0.87603 = 106/121 | 0.58564 = 106/181 |
8 | 741.38 | 0.85378 = 181/212 | 0.50000 = 181/362 |
となり、0-100 % の場合と結果が違います。
これは、なぜなのか、良く分かりません。