太鼓さん次郎 Ver.2.92 の内部仕様雑記
フレーム数とか、バグとか、そういう細かい内部仕様について雑記します。太鼓さん次郎エキスパート向け。
判定
基本的なことは次郎本体についてるfaq.htmlに書いてある通りです。Badの2倍が最初怪しいなと思ったけど少なくともJudgeLevel=1まではその通りかなと思います。
同時押し
同時押しについて。キーボードから面と縁の同時押しの信号が送られると都合良い方1打(連打は両方)だけ反応します。
常に同時押しできれば後ろの音符を巻き込んで不可になることはありません。
キーボードやPCの性能によるとは思いますが、私の環境では少なくとも10msくらいまではズレても同時押しと受け取ってくれます。キーボードの信号と、config.iniのFramerate=の値の低い方が参照されているようです。
2打同時(見やすいものはARMA音符と呼ばれていますね)を叩く際は適度にズラして叩く必要があります。ほかにも密度の高いノーツを捌いていく際は要注意。
巻き込み
巻き込みについて。通常音符後も大音符後も連打後もJudgeRangeGood=の値に依存しているようです。音符の遅可判定が終わらなければ次の音符を入れることができません。
例:BPM250、16分間隔の「31221」を、JudgeLevel=1で右手から順に交互で「11221」と捌く
(JudgeLevel=1だとBPM240の16分音符間隔より早い場合はリズムピッタリに叩いても巻き込みが発生します)
右面の入力で大音符が入力され、大音符の入力を待つ状態になる(大音符の入力待ちは恐らく0.03~0.05秒くらい?→大音符の入力がない。右面の判定は片手良となる。
左面の入力。1.の大音符による巻き込みが発生。この入力は判定されない。
右縁の入力。2.の通常音符による巻き込みが発生。この入力は左面に対する判定となる。左面は判定されず、通り過ぎて不可。
左縁の入力。3.の通常音符による巻き込みが発生。この入力は右縁に対する判定となる。右縁は可。
右面の入力。4.の通常音符による巻き込みが発生。この入力は左縁に対する判定となる。左縁は判定されず、通り過ぎて不可。
右面に対する入力はない。右面は通り過ぎて不可。
2.で起きている大音符の巻き込みを回避する方法は、大音符を入力することです。今回の例の「31221」が「32221」になっても、2.までは同じように大音符による巻き込みが発生すると思われます。
連打に対しても基本的には同じような巻き込みの処理がかかっているようです。
連打頭
どこかのタイミングで調べたい。JudgeRangeGreat=依存だと思うのですが……。
GJA/GJH
10-10-200? / 10-100-200? だと思います。
フレーム数
太鼓さん次郎の内部フレーム事情についてです。
事前知識として「太鼓さん次郎の最小単位は1ms,1px」ということを頭に入れておいてください。
判定位置
譜面にBPMCHANGEを入れると判定位置が早ズレします。
1回につき0ms~2ms判定位置が早くなります。
これは、太鼓さん次郎が命令付近の小節の長さを計算するときに、ミリ秒未満を無視しているために起こっています。
#BPMCHANGE 220
3111,
1000100010001021,
22101010,
1000102010021012,
#BPMCHANGE 220
10401112,
100000000200100000200000100200000000100020002000,
1000102012221020,
100000000200100000102020100000100000400000000000,
#BPMCHANGE 220
このTJAの長さはどうやら「BPMCHANGEの掛かっている最初1小節の長さ」+「次にBPMCHANGEが来るまでの3小節の長さ」+「最初1小節の長さ」+「3小節の長さ」で計算されているようです。
BPM220の1小節の長さは1.090909…秒、ミリ秒にすると1090.91msなのですが、ミリ秒未満を切り捨てるため1090msとして計算されます。
残りも全て計算すると合計は8724msとなります。正しい楽曲の長さは8727.27msなので、約3.27ms早くなってしまっている、という計算です(要確認)
長さが変わってしまう問題を解決するために、DELAYを使用したり、BPM値を逆算したり(こちらの方が好みです)するのですが、多くの場合は「まあ数msくらい仕方ないよな」という空気だったりします。
描画位置
譜面にBPMCHANGEを入れると描画位置もズレます。
命令がかかったタイミングでサブピクセル単位でノーツが「戻る」ような挙動をします。(この挙動を以下の難しい日本語でWIZARD1さんに説明したら、すごく分かりやすい解釈が帰ってきたので、そのまま載せさせて頂きました)
原理的には、BPMCHANGEがかかる瞬間に、全ての音符がサブピクセルの一番左側に到着するようになっています。BPMCHANGEのタイミングでその音符があるべき場所(叩く音符は正しいサブピクセル、そうでない音符は次のBPMCHANGEでサブピクセルの一番左側に到着するような場所)に再配置されるという感じになっています。
HSの異なるダミーノーツを使用するときに何故か位置が合わなかったり、ダミーノーツを置くときに何故か1/256とかで細かい調節をしないといけない場合があるのですが、この描画位置のズレが原因です。
ちなみに、このズレの影響を受けにくそうなHSがあって、それが0.07625とその倍数です。倍にしていったら0.61とか1.22というHSになります。
Notedist=2のとき、HS0.07625は、32分音符1個分の長さに対して音符が1ピクセル進む速度になっています。そのため、当該HSがかかっている音符は、BPMCHANGEがかかる瞬間に必ずサブピクセルの一番左側にあります。これにより、BPMCHANGEから受ける影響が非常に少なくなります。(ただしMEASURE 1/400とかやるなら話は別)
余談ですが、HS1.22で512px/小節なので、HS1なら419.672px/小節という計算になります。HS1とかいうの、何も美しくないですすみません思想が勝手に更に余談ですが、Notedist=を2以外にするとこの辺の挙動は変わったりします。Notedist=0がHS1の512px/小節なんじゃないかなとおもっています(要検証)
Framerate=の値について
太鼓さん次郎の入力や出力のフレーム数を決めると同時に、命令の処理速度
・小節線の処理速度・オートの風船の入力速度の3つがこのFramerateで定められていると思われます。
命令の処理は、1フレームにつき1回しかできません。命令の処理速度に関係する命令は、前もって描画されているSCROLLやBARLINEONといったものではなく、主にGOGOSTARTなどのゴーゴー系の命令は確実で、ほかにはDELAY(要検証)とSECTION(どう検証すればいいんだ)が怪しいです。GOGOをフレームレート以上に点滅させるときに、処理が追い付かなくなる、というのはありがちかもしれません。
小節線の処理は、1本の小節線が消えて、新たな小節線が出現する(消えた小節線の8本先です)ことを指します。その処理は、1フレームにつき1本しかできません。昨今の譜面大会シーンでは小節線を出現させるギミックが流行っているのですが、フレームレートが小さいと一気に出現するタイプのギミックの見栄えが悪くなるかもしれません。
オートは1フレームにつき1打しか風船を入れないので、「オートでも割れない風船」ということをしたくても、各人の環境によってまちまちになってしまうということになります。ちなみにFramerate=に1000以上だか超過した数を入れると風船処理がバグり、非常に大きな値の風船でも割ってしまうオートが完成します。把握していないバグが出る可能性も多いので、ほどほどにしておいた方がよいかもしれません。
トピック募集
書きたかったことがまだまだたくさんあるのですが(分岐のこととかゲージのこととか)文章化が面倒なのでこの辺で一度投稿してみます。
もし内部処理のことで聞きたいことがあったら、Twitterにて意見をお寄せください。