n2kd のタイマ(テンポ管理)
注意:当初 Sound Blaster の PCM 再生機能の割込をもとにテンポ管理する機能がありましたが、テンポ変更などをうまく動かすことができず現在は廃止されています。
n2kd の演奏処理は、外部ハードウェアからの定期的な割込により実行されます。 v1.0a 時点で対応している割込源となるハードウェアは以下の通りです。
- PC-98 版
- OPN(A) の timer_b
- PIT(システムタイマ)の ch.0
- PC/AT 互換機版
- PIT(システムタイマ)の ch.0
当初 PC-98 のみをサポートする FM 音源ドライバとして開発が始まった関係で、演奏のテンポは BPM ではなく OPN(A) の timer_b が基準となるよう実装されています。 PIT でテンポ管理を行う場合は、割込頻度を timer_b に近づけなくてはなりません。
まず、PIT を 16bit 2 進カウントモードで最大のカウント数である65536回カウントさせても、割込間隔がtimer_b の最も広い場合よりも短くなってしまう問題があります。 これは、与えられているクロックが決まっているので仕方ありませんが、PIT のカウンタの更新が timer_b より結構速いためです。
これに対処するため、より速い頻度で割込を受けて演奏処理はそのうち数回に1回だけ行う機能を足しました。 これにより、timer_b の遅い割込頻度を PIT でも取り扱うことができます。 PIT に設定する値と演奏を行わず待機する回数は、割込間隔があまり短くならない範囲で総当たりで求めました。
また、PC/AT 互換機の PIT の ch.0 は IRQ0 の発生源であり、時計を進めたりするのに必要なので、完全に乗っ取ってしまうとシステムの動作に影響があります。 そのため、PC/AT 互換機で PIT の ch.0 に常駐した際には、割込毎にカウント量を積算して適当なタイミングで元の IRQ0 を呼ぶことで、長期的に見た IRQ0 の元の割込ハンドラの実行頻度が保たれるようにしています。
冒頭にも書きましたが、当初 Sound Blaster の PCM 再生機能の割込をもとにテンポ管理する機能の実装を試みていましたが最終的に諦めました。 どうして AdLib カードは OPL2 の割込信号をバスに結線してくれなかったんですかね……。