2016年10月18日火曜日

MDX解析で色々1:タイマーB

というわけでMDX一区切り。

2016年に一生懸命MDXの解析とかやってる人は世界に俺だけかと思う位情報が無かった。
ググっても大体2000年代が最新情報。フォーマットに関しては2つほど資料が落ちてたので
それを使って1バイトづつ読み込んで解析していきました。

■タイマーBって何や
MDXはBPMやTEMPOで制御するのではなく、X68の割り込みタイマー、通称タイマーBという
割り込みを使うのだ。この辺も未だあやふやなままだが、このタイマーBの数値でカウンタを
回して、カウンタの数字を見ながら音を鳴らすというのが大きな流れだ。

まあ当然ながら、このタイマーBでハマった・・。

テンポとタイマーBの1対1の数式は2~3個あったソースコードから引用できたので問題無い
のだけど、ZMSは最初に曲全体を絶対的な時間にどんと割り振ってから演奏するやり方を
採用していて、まあ理由はWindowsの割り込みタイマが信用ならんからなんだけど、その方法
をまずは採用して計算してみた。

でも途中でテンポが変わる時にもう計算がレロレロに・・。

しばらくそのやり方で作っていって、だいぶ鳴るトコまで来たのだけど、どうにもダメなトコに
ブチ当たって、完成間近と思われていたMDXを一度リセット!!

これが当ブログ9月5日の事でありました・・。

■絶対時間を止める
カウンタを厳密に回す方法が中々見つからず、色々やってたら、ナイスな方法をようやく
見つけた。それがこれ。この計算を、10msとかの間隔で呼び出す。

// 経過時間取得
LONGLONG llNow = GetNowHiPerformanceCount();
LONGLONG llPassTime = llNow - g_llPreTime;
g_llPreTime = llNow;

// 1クロックの計算はテンポチェンジに備えて毎回やっておく
double dWholeNote = (6.0 * 2048.0 * (256.0 - (double)g_fTimerB)) * 4.0;
g_dOneClock = (dWholeNote / 192.0);

// 経過時間が1クロックの時間のどれくらいかを計算してクロックに足す
g_dClock += ((double)llPassTime / g_dOneClock);

カウンタ計算の度に、クロックがどのくらい進んだかをdoubleで計算する事に。そして
使うときにはintでキャストするというやり方。

これでどのくらいちゃんと厳密にできてるか調査してみたら、ほぼ想定通りの数字が出た。
良かった!!これでクロックが増える度に命令を取り出してきて実行するといういきあたり
ばったりのやり方で行ける!

■いきあたりばったり
そういう意味でも、いきあたりばったり方式はX68時代のやり方とほぼ同じであり、再現という
意味でもいい感じになってしまいました。このクロックカウンタ計算をベースとして作り出したら
割とトントンっと進みだしたのでした。

つづく~

0 件のコメント:

コメントを投稿