- Python 100%
| .gitignore | ||
| generate_notes.py | ||
| generate_patterns.py | ||
| README.md | ||
| requirements.txt | ||
| tjaf.py | ||
tjaf-generator
TJA譜面と対応する音声を教師データとして、譜面生成に使う2種類のTensorFlow/Kerasモデルを学習するツールです。
generate_patterns.py: 前後の時系列をLSTMで見て、各時刻にノーツがあるかを判定する2値分類モデルgenerate_notes.py: ノーツ位置の音声からノーツ種別(0〜4)を分類するモデル
入力ディレクトリ以下の .tja を再帰的に検索し、音声から抽出したMFCC特徴量で学習します。学習結果は再利用できる .keras ファイルとして保存されます。
必要なもの
- Python
- TJA譜面
- 各TJAの
WAVEヘッダーに対応する音声ファイル
依存パッケージは requirements.txt に固定されています。仮想環境でのインストールを推奨します。
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
Windowsで仮想環境を有効化する場合は、次を実行してください。
.venv\Scripts\activate
入力データ
TJAと音声は、たとえば次のように配置します。
songs/
├── song-a/
│ ├── chart.tja
│ └── song.ogg
└── song-b/
├── chart.tja
└── song.wav
TJAの WAVE には、そのTJAからの相対パスまたは絶対パスで音声を指定します。
TITLE:サンプル曲
BPM:120
WAVE:song.ogg
OFFSET:0
COURSE:Oni
LEVEL:5
#START
0010,
1010,
#END
WAVE で指定したファイルが見つからない場合は、TJAと同じディレクトリの main.<WAVEの拡張子> も検索します。TJAの文字コードと改行コードは、読み込み時にUTF-8/LFへ変換されます。
使い方
1. ノーツ位置モデルを生成する
音声の各時間枠を「ノーツなし(0)」または「ノーツあり(1)」に分類するモデルです。MFCCを曲ごとの時系列として固定長シーケンスに分割し、LSTMで前後の文脈を見ながら各フレームを判定します。
python generate_patterns.py ./songs
既定では patterns.keras に保存されます。保存先や学習条件も指定できます。
python generate_patterns.py ./songs \
--output ./models/patterns.keras \
--course 3 \
--epochs 10 \
--batch-size 64
TJAの空打ち 0 はノーツなし、それ以外の数字はすべてノーツありとして扱います。音声全体の時間枠を学習対象とし、アンダーサンプリングは行いません。クラス重みには、譜面ごとに求めたノーツあり率の全譜面における中央値を使用します。
patterns.keras は (任意の時系列長, n-mfcc) の入力を受け取り、各時刻のノーツ有無を時系列で出力します。推論時も単発フレームではなく、学習時と同じMFCC列を時系列のまま渡してください。末尾の不足フレームは学習時にパディングされ、損失計算からは除外されます。
2. ノーツ種別モデルを生成する
譜面上の各ノーツ位置に対応する音声から、TJAのノーツ種別 0〜4 を分類するモデルです。
python generate_notes.py ./songs
既定では notes.keras に保存されます。オプションの指定方法は位置モデルと同じです。
python generate_notes.py ./songs \
--output ./models/notes.keras \
--course 3 \
--epochs 10 \
--batch-size 64
5〜9 のノーツは学習対象外です。また、空打ち 0 は入力データに含まれますが、損失計算からは除外されます。
オプション
主なオプションは次の通りです。
| オプション | 既定値 | 内容 |
|---|---|---|
input_dir |
必須 | TJAを再帰検索する入力ディレクトリ |
--output |
スクリプトごと | モデルの保存先 |
--course |
3 |
学習対象のコース番号 |
--epochs |
4 |
学習エポック数 |
--batch-size |
32 |
バッチサイズ |
--scale-ms |
10 |
MFCCの時間間隔(ミリ秒) |
--n-mfcc |
13 |
MFCCの次元数 |
--n-fft |
1024 |
FFTの窓幅 |
--sequence-length |
64 |
generate_patterns.py のLSTMへ渡す時系列フレーム数 |
--lstm-units |
64 |
generate_patterns.py のLSTMユニット数 |
--output の既定値は、generate_patterns.py が patterns.keras、generate_notes.py が notes.keras です。
コース番号は次の通りです。
| 番号 | コース |
|---|---|
0 |
Easy |
1 |
Normal |
2 |
Hard |
3 |
Oni |
4 |
Edit / Ura |
5 |
Tower |
6 |
Dan |
全引数は各スクリプトの --help でも確認できます。
python generate_patterns.py --help
python generate_notes.py --help
対応している譜面情報
ノーツ時刻の計算では、次の情報を反映します。
- 共通ヘッダーの
BPM(省略時は120) - 共通ヘッダーの
OFFSET(省略時は0) - 譜面中の
#BPMCHANGE - 譜面中の
#MEASURE
上記以外の分岐、スクロール、停止などの命令は、学習時刻の計算には反映されません。
注意事項
- 読み込めないTJAや音声は、理由を表示してスキップします。
- 指定したコースが存在しない譜面もスキップします。
- 同じモデルで推論するときは、学習時と同じ
scale-ms、n-mfcc、n-fftを使ってMFCCを生成してください。 - 譜面数や音声の長さに応じて、学習に必要なメモリと時間が増えます。まずは少数の曲と小さなエポック数で動作を確認してください。
- このリポジトリは学習モデルの生成までを扱います。音声からTJAを出力する推論処理は含まれていません。