# 特徴量について Gemini で生成しました。 ## 1. 概要 本プログラムは、JPypeを経由してJava製のBMS解析ライブラリを呼び出し、BMS/BMSONファイルをパースする。パースされたオブジェクトからノーツの配置時間を取得し、NumPyの2次元配列(タイムライン)に変換した上で、スライディングウィンドウによる区間ごとの譜面特徴量を高速に算出する。 ## 2. タイムラインの生成 (set_timeline_master) jpype を用いて Java クラス (bms.model.BMSDecoder または BMSONDecoder) を呼び出し、java.nio.file.Paths で指定したファイルパスから BMSModel オブジェクトを生成する。その後、getAllTimeLines() メソッドで取得したタイムラインオブジェクトのリストを走査し、NumPy配列に変換する。 - データ抽出: 各タイムラインから getMilliTime() でイベント時間を、getLaneCount() と getNote(lane) で各レーンのノーツオブジェクトを取得する。 - データ構造: 1イベントにつき9要素の配列 [time_ms, k1, k2, k3, k4, k5, k6, k7, scratch] を生成する。 - ノーツの扱い: 取得したノーツが NormalNote のインスタンス、または LongNote のインスタンスかつ isEnd() が偽(始点)である場合に対象レーンへ 1 を立てる。ロングノーツの終点は無視される。 - レーン補正: 5鍵譜面 (getLaneCount() == 6) の場合は、スクラッチのインデックスを配列の末尾にシフトし、7鍵+1皿の標準フォーマットに正規化する。 ## 3. 特徴量の高速計算アーキテクチャ (set_meta_master) 任意の時間区間(開始から終了までのミリ秒)の特徴量を高速に取得するため、事前に楽曲全体の累積和(Cumulative Sum)配列を計算しておく。 区間ごとの集計時は、Look Up Table (LUT) を用いて指定時間のインデックスを $O(1)$ で特定し、「終点の累積和 - 始点の累積和」を計算することで、集計処理の計算コストを削減している。 ## 4. 抽出される特徴量の解説 get_window_meta メソッドにて取得できる各特徴量の意味と、計算方法・導出式の解説である。 ### 基本統計と回復量 - button_count, scratch_count: 区間内の鍵盤ノーツ数とスクラッチノーツ数の総和。 - simul_count: 区間内で1つ以上のノーツが配置されている時間軸(イベント)の総数。 - recovery: 楽曲全体のTOTAL値と総ノーツ数から、対象区間内のノーツをすべてPerfectで取得した場合のゲージ回復量を推定する。 計算式: $TOTAL \times \frac{button\_count + scratch\_count}{total\_notes}$ - button_scratch_interaction: 直近の前後25ミリ秒(計50ミリ秒窓)における鍵盤の移動量と、スクラッチ発生数の積の合計。鍵盤と皿の複合(いわゆる皿複合)の負荷を評価する。 ### 同時押しとリズム - chord_mean: 1イベントあたりの平均ノーツ数(平均同時押し数)。 計算式: $\frac{button\_count + scratch\_count}{simul\_count}$ - chord_size_delta: 直前のイベントとの同時押し数の差分の絶対値を累積し、simul_count で割った平均変化量。時間間隔が400ミリ秒以内のイベント間のみを対象とする。 - rhythm_jitter: ノーツの配置間隔(ミリ秒)が、1つ前の配置間隔からどれだけ変化したかの絶対値の合計。リズムの不規則な変化を評価し、対数スケールで正規化される。時間間隔が400ミリ秒以内のイベントのみを評価対象とする。 計算式: $\ln(1 + \frac{rhythm\_jitter\_cum}{simul\_count})$ - delay_persistence: ノーツ間隔が 40ms 以下となる配置が連続して発生した際の、その間隔(ミリ秒)の合計値。 - ratio_mean, ratio_cv: 直近5秒間のノーツ間隔から、5ms より大きく 400ms 以下のものを抽出し、その最頻値を「基準リズム」とする。対象区間の各ノーツ間隔が基準リズムの何倍にあたるかの平均 (ratio_mean) と、その変動係数 (ratio_cv) を計算する。 - chord_q1, chord_q2, chord_q3: 区間内の同時押し数の25パーセンタイル、中央値(50パーセンタイル)、75パーセンタイル。 - chord_pattern_count_per_simul: 区間内に出現した同時押しの配置パターン(レーンの組み合わせ)の種類数を、simul_count で割った値。配置パターンの多様性・認識負荷を示す。 - oscillation: 同時押し数の増減が反転した(増加から減少、または減少から増加)際の変化速度の積の絶対値の平均。同時押し密度の波打ち(オシレーション)を評価する。間隔が400ミリ秒以内のものを対象とする。 - heavy_hit_jitter: 直前の同時押し数と、現在のリズムの揺れ(rhythm_jitter_step)の積の平均を対数化した値。重い同時押しの直後に発生するリズム難(打鍵後の硬直によるズレ)の負荷を評価する。 - shape_flux: 同時押し数の変化量に、局所的なBPM換算密度を掛け合わせた値の平均。高密度地帯における配置形状の激しい変化を評価する。 ### 配置と幾何学(ジオメトリ)依存 - lane_bias_entropy: 各レーンに降るノーツ割合 $p_i$ の情報量(エントロピー)。レーン配置の偏りを評価する。 計算式: $-\sum p_i \ln(p_i)$ - drift_velocity: 直近4回のイベントの配置レーンの平均位置を重心とし、現在の配置が重心からどれだけ離れているかをL1距離で計算したものの平均。イベント間隔が400ミリ秒以内の配置のみを重心計算の対象とする。 - triangle_gap_rate: 1歩前からの距離と2歩前からの距離の和から、2歩前からの直線距離を引いた値(反転ギャップ)の合計を、総移動量で割った値。指や腕の無駄な往復を評価する。各歩の間隔が400ミリ秒以内の接続のみを計算対象とする。 - radius_gyration: 各レーンの打鍵確率 $p$ を用い、ハミング空間上での打鍵の散らばり具合を算出する。 計算式: $\sum 2p(1-p)$ ### 運指・移動量と縦連(Jack) - movement: 1つ前のイベントとの配置の差分(ハミング距離)の総和を simul_count で割った平均移動量。間隔が400ミリ秒以内のイベント間のみを移動量として加算する。 - movement_interaction: イベント間の移動量(ハミング距離)と、現在の同時押し数の積の平均。移動と多重押しの複合負荷を示す。 - movement_stayed: 1つ前のイベントと同じレーンを叩き続けている(ホールドしている)指の数に、その時点の移動量(400ミリ秒以内)を掛け合わせた値の平均。拘束による押しにくさを評価する。 - stayed_count: 直前のイベントと同じレーンを叩き続けている(ホールドしている)指の数の平均。 - movement_lag2, movement_lag3, movement_lag4: それぞれ2つ前、3つ前、4つ前のイベントの配置とのハミング距離の平均。間隔が400ミリ秒以内のもののみを対象とし、直前以外の過去の配置からの指の移動軌跡や反復を評価する。 - jack: 同じレーンに連続して降るノーツの評価値。間隔が 140ms 以下から重みが発生し、130ms 以下で最大(重み1.0)となるよう線形補間され、全レーンの合計が算出される。 - jack_mean: 区間内で発生した縦連スコア(0より大きい値)の平均値。 - jack_chord_conflict_delay: 縦連による指の拘束が発生している最中の、50ミリ秒窓での全体移動量(鍵盤+皿)の合計。縦連を処理しながら他のノーツを捌く複合負荷を評価する。 - chord_jack_size_mean, chord_jack_size_cv: 縦連(スコアが0より大きい配置)が発生した瞬間の、同時押しサイズの平均と変動係数。 計算式 (CV): $\frac{\sqrt{E[X^2] - (E[X])^2}}{E[X]}$ ### クラスタ化(疑似同時押し) 40ms 以内に近接して配置されたノーツ同士をクラスタ化し、1つのストライク(打鍵の塊)として結合して評価する。 - strike_count_40: クラスタ化された結果のイベント数。 - strike_jitter_40: ストライク間の時間間隔の揺らぎを対数スケールで評価した値。 - stagger_mean_40: 40ミリ秒以内でクラスタ化されたストライク(打鍵の塊)の実質的なサイズの平均。 - drift_velocity_strike_40, triangle_gap_rate_strike_40, radius_gyration_strike_40: クラスタ化されたストライク単位で再計算された、重心漂流速度、反転ギャップ率、および空間占有率(それぞれイベント間隔400ミリ秒以内の制約を適用)。ズレ押しを同時押しとみなした際の実質的な手の動きを評価する。 ### ディレイとストリームトラッキング 時間・距離ペナルティに基づく貪欲法を用いて、譜面全体を複数の流れ(ストリーム)に分解する。接続を許容する最大時間を 100ms、最大レーン距離を 4.0 として計算する。 この指標は主にディレイ(40ms以下で連続する密な配置)の質と複雑さを評価する。 - stream_active: 区間内における追跡中のストリーム(物理的な指・腕の繋がり)の絶対数。 - stream_strokes: 区間内において各ストリームが左右への進行方向を反転させた回数の合計。 - stream_crossings: 区間内においてストリーム同士の軌跡(時間とレーンを軸とした線分)が交差した回数の合計。 - stream_active_mean: 追跡中のストリームの数を、strike_count_40 で割った平均値。 - stream_strokes_rate: 各ストリームが左右への進行方向を反転させた回数の合計を、strike_count_40 で割った発生率。 - stream_crossings_rate: ストリーム同士の軌跡が交差した回数の合計を、strike_count_40 で割った発生率。ディレイ中に運指がクロスする複雑な配置を評価する。