第7章 時間軸シミュレーションエンジンとプレイアビリティ保存¶
本章では、冗長な音声定義を単一の代表元へと統合した結果、ゲームプレイ時に「音が不自然に重なる」「発音タイミングが変わる」といったプレイフィール上の破綻が絶対に発生しないことを数学的・論理的に保証するためのシステムシミュレーション理論を解説する。 単なる静的な定義置換が引き起こす干渉問題を排除し、楽譜時間から実時間への非線形写像、および Sweep-Line アルゴリズムを用いた区間代数によって、重複発音の検証計算量を \(O(M^2)\) から \(O(M \log M)\) へと削減する過程を証明する。
Note
本章における主要な略称・用語
- BPM: Beats Per Minute
- JND: 最小可聴差異
- Sweep-Line: 走査線アルゴリズム
7.1 楽譜時間(パルス)と実時間(秒)の非線形写像の定式化¶
BMSにおけるノート(音符)の配置は、一定のリズム間隔を示す「パルス」と呼ばれる離散的な座標系で行われる。これを物理的な音響波形のオーバーラップ検証に用いるためには、パルスから実時間(秒)への厳密な写像を構築する必要がある。
定義 7.1 (Pulse-Time 写像)¶
BMSのタイムライン上に存在するBPM変更イベントおよびSTOPイベントの全集合を考慮する。 パルス座標 \(p \in \mathbb{R}_{\ge 0}\) から実時間座標 \(t \in \mathbb{R}_{\ge 0}\) への変換を、非線形な連続関数(または区間的に連続な関数) \(T: p \mapsto t\) として定義する。
あるパルス区間 \([p_k, p_{k+1})\) においてBPMが定数 \(B_k > 0\) であるとき、パルスの基本分解能を \(R\)(通常 \(R=96\) または \(192\))とすると、その区間における実時間の増分 \(\Delta t\) はパルスの増分 \(\Delta p\) に対して以下の線形関係を持つ。
定義 7.2 (発音イベントとエネルギー密度)¶
タイムライン上の \(i\) 番目の発音イベント \(e_i\) を、タプル \((p_i, w_i, L_i)\) として定義する。 ここで \(p_i\) は発音開始パルス、\(w_i \in V\) は再生される音声定義、\(L_i\) は音声波形の実時間長である。写像 \(T\) により、実時間における発音区間は \(I_i = [T(p_i), T(p_i) + L_i]\) となる。
7.2 課題:静的解析の限界と波形干渉のジレンマ¶
最適化の目的は、類似した音声定義群(同値類 \([w]\))を代表元 \(w_{\text{rep}}\) にすべて置換することである。しかし、タイムラインを考慮せずに静的置換を強行すると、以下の物理的・音響的破綻を引き起こす。
1. 位相干渉とコムフィルタ効果の発生 もし異なるレーンに配置されたノート \(e_1, e_2\) が同一の実時間 \(t\) に極めて近いタイミングで発音され、それらが同じ代表元 \(w_{\text{rep}}\) に置換されたとする。二つの同一波形が微小な時間差 \(\Delta t\) で重ね合わされると、周波数領域においてコムフィルタ効果が発生する。これにより、元の音響的性質が著しく歪む(フランジャーのような音質劣化を招く)。
2. 同時発音数制限による音抜け 多くの再生エンジンは、全く同一のバッファへの同時アクセスや多重再生に対してハードウェア的またはソフトウェア的な発音数上限を持つ。同一時刻付近に多数の \(w_{\text{rep}}\) が密集すると、後着のノートが再生をキャンセルされる(音抜けが発生する)。
3. \(O(M^2)\) の素朴な区間衝突判定の爆発 上記の破綻を防ぐには、「置換対象のノート群の実時間区間 \(I_i\) と \(I_j\) がオーバーラップしているか否か」を全イベントについてシミュレーションする必要がある。総ノート数を \(M\) としたとき、すべてのペアを素朴に比較すると時間計算量は \(O(M^2)\) となる。高難易度の譜面(\(M > 10^5\))では数分間の計算ブロックが発生し、パイプラインのリアルタイム性を損なう。
7.3 定理の提示とSweep-Lineアルゴリズムによる証明 (Proof)¶
Pulse-Time写像の単調性と、区間代数における Sweep-Line アルゴリズムを導入することで、シミュレーション計算量を劇的に削減する。
Important
定理 7.1 (Pulse-Time 写像の広義単調増加性と逆関数) STOPイベントによる停留区間を除き、関数 \(T(p)\) は広義単調増加である。 すなわち、任意の \(p_1 < p_2\) に対して \(T(p_1) \le T(p_2)\) が成り立つ。これにより、\(B\) 個のBPM/STOP変化点を持つ区分線形関数 \(T(p)\) の評価は、変化点の配列に対する二分探索を用いることで、任意の \(p\) に対して \(O(\log B)\) 時間で一意に計算可能である。
Important
定理 7.2 (Sweep-Lineによる区間オーバーラップの高速検出) 総数 \(M\) 個の発音イベント集合 \(E\) におけるすべての区間交差(オーバーラップ)の検出は、時間計算量 \(O(M \log M)\) で完了する。
Note
証明
各発音イベント \(e_i\) の実時間区間 \(I_i = [t_{\text{start}}^{(i)}, t_{\text{end}}^{(i)}]\) に対して、2つの端点を生成する。
- 始点イベント: \((t_{\text{start}}^{(i)}, \text{type: START}, \text{id}: i)\)
- 終点イベント: \((t_{\text{end}}^{(i)}, \text{type: END}, \text{id}: i)\)
これら \(2M\) 個の端点を、時間 \(t\) の順にソートする(ソートの時間計算量は \(O(M \log M)\))。 Sweep-Line を時間 \(t=0\) から順に進めながら、以下の状態遷移を行う。
STARTイベントに遭遇した場合:現在の「発音中リスト」にノート \(i\) を追加する。このとき、リスト内に既に存在するノート群が、ノート \(i\) と確実に交差(オーバーラップ)している区間である。ENDイベントに遭遇した場合:「発音中リスト」からノート \(i\) を削除する。
この走査処理において、各イベントのリストへの追加・削除がそれぞれ1回ずつ行われるため、走査自体の時間計算量は \(O(M)\) である。交差の列挙を含めても、ソートの計算量が支配的となるため、全体の時間計算量は \(O(M \log M)\) となることが示された。\(\blacksquare\)
7.4 計算量削減の定量的評価と疑似コード¶
前述の証明により、譜面の全ノートのペアを検証する \(O(M^2)\) の力技探索は排除され、ソートに基づいた \(O(M \log M)\) 空間へと最適化された。
実装への射影:PulseToRealTimeCalculator と SimulationEngine¶
C# 実装においては、PulseToRealTimeCalculator が前計算による変化点配列の二分探索を担保し、SimulationEngine が走査線アルゴリズムを実行する。
// 【疑似コード】PulseToRealTimeCalculator.cs における O(log B) 時間変換
public double ConvertPulseToSeconds(double pulse) {
// _timeEvents はパルス順にソート済みの BPM/STOP 変化点配列
// 二分探索により、O(log B) で対象区間を特定
int idx = BinarySearch(_timeEvents, pulse);
var ev = _timeEvents[idx];
// 式(7.1)に基づく線形補間
double deltaP = pulse - ev.Pulse;
return ev.RealTime + (deltaP * (60.0 / (ev.Bpm * Resolution)));
}
// 【疑似コード】SimulationEngine.cs における Sweep-Line オーバーラップ検出
public void SimulateAndOptimize(List<NoteEvent> notes) {
var endpoints = new List<TimePoint>(notes.Count * 2);
foreach (var note in notes) {
endpoints.Add(new TimePoint(note.StartTime, START, note));
endpoints.Add(new TimePoint(note.EndTime, END, note));
}
// O(M log M): タイムライン順にソート
endpoints.Sort((a, b) => a.Time.CompareTo(b.Time));
var activeNotes = new HashSet<NoteEvent>();
// O(M): 走査線によるシミュレーション
foreach (var pt in endpoints) {
if (pt.Type == START) {
// 現在発音中のノートとの衝突判定
foreach (var active in activeNotes) {
if (AreInSameEquivalenceClass(pt.Note.Audio, active.Audio)) {
MarkAsNonOptimizable(pt.Note); // 同時発音による破綻を回避するため最適化から除外
}
}
activeNotes.Add(pt.Note);
} else {
activeNotes.Remove(pt.Note);
}
}
}
このシミュレーションにより、置換対象となる音声が「タイムライン上でオーバーラップする」場合は安全のために最適化から除外される。
7.5 プレイアビリティ等価定理と許容限界¶
最終的に、このシミュレーションエンジンが保証する「ゲームプレイの不変性」を数学的に定義する。
Important
定理 7.3 (プレイアビリティ等価定理) 最適化前の譜面における時刻 \(t\) での全発音エネルギー密度関数を \(\Phi_{\text{orig}}(t)\)、最適化後のそれを \(\Phi_{\text{opt}}(t)\) とする。 SimulationEngine によって「干渉する同値類ノートを統合しない」という境界条件が守られる限り、任意の時刻 \(t\) において以下の不等式が成立する。
ここで \(\delta\) は人間の聴覚におけるJNDに基づく極微小な許容限界値である。
この定理により、BMS Part Tuner が行う最適化は単なるファイルサイズの削減に留まらず、「プレイヤーが体感する音響的エネルギーの総量と位相分布を数学的に完全保存している」ことが論理的に証明される。
7.6 参考文献 (References)¶
- Shamos, M. I., & Hoey, D. (1976). "Geometric intersection problems". 17th Annual Symposium on Foundations of Computer Science (sfcs 1976). IEEE.