mucom88のテンポ設定

mucom88でテンポが合わない(やたらと遅い)ことがあるので調べてみた。

途中までやってた曲が本来 ♩=122 くらいなんだけど、T122 では遅くて、テキトーに T132 とかにした方がマシだったというのが発端。

大きく二つ原因があって、一つは「Tコマンドの処理」、もう一つは「タイマの精度」。

Tコマンドの処理

テンポ設定の際、「Timer-B とかよくわからん」という理由で、t コマンドではなく T コマンドを使いたい(使っていた)ところだけれど、これがテンポの合わない原因のひとつ。

muc88.asm の SETTMP: をざっと眺めた感じだと、Tコマンドの数値は:
\[t = \left\lfloor \frac{25600-346\times \left( \left\lfloor \frac{60000}{ \left\lfloor \frac{C}{4}\right\rfloor\times T}\right\rfloor +1\right)}{100}\right\rfloor\]
のような計算をして t コマンドで指定する値 \((t)\) に置き換えている。

ただし:
\(C\): Cコマンドで指定した値(デフォルト128)
\(T\): Tコマンドで指定した値
\(\left\lfloor x \right\rfloor\) は \(x\) の端数切捨て

実際に与えるべき数値は(たぶん):
\[t = 256-\frac{60 \times 3993600}{\frac{C}{4}\times T\times 1152}=256-\frac{832000}{CT}\]
……の端数を適当に丸めたもの。3,993,600 [Hz] はマスタークロック(たぶん)。

Z80は除算命令がないので減算ループを使い、しかも計算途中で(16ビットで)オーバーフローしないようにした結果が(たぶん)上記 SETTMP: の処理なんだけれど、どうしても値がずれてしまう。

タイマの精度(というか分解能?)

上の式が正しいとすると、
\[T = \frac{832000}{(256-t)C}\]

C192 t220 でおよそ ♩=120.4 だけれど、1増やして t221 にするとおよそ ♩=123.8 となり、その間の ♩=121, 122, 123 のような細かい設定はできない。これは、テンポが速いほど、そしてCの値が大きいほど、顕著になる。

そして、これら二つが組み合わせられて、慣れ親しんだ ♩=… の値を T コマンドで指定しても、(特にC192などでは)全然違う速さになってしまうようです。

対策としては:

  • T ではなく t でテンポを指定する
  • C の指定はなるべく小さい値で済ませる

くらいですかね。

ただ、C の値を小さくすると短い音符が表現できないだけでなく、qコマンドやポルタメントやソフトLFOにも影響するので、結局96か192(あるいは三連符がないなら128)に落ち着くことが多いです……。

付録(t コマンドの値の目安)

テンポ(♩=)C96C128C192
100169191213
110177197217
120184202220
130189206223
140194210225
150198213227

間違いがあったら教えてください。

2021-12-05追記テンポ計算するやつ作った。