textage.cc/score 譜面解析バグ修正

うまくチャージノーツが展開できない件について、そろそろ調査はじめよう……

lmtak.hateblo.jp


チャージノーツ展開部のスクリプト

# CN / BSS / MSS の始端
if flag & 1 == 1:
    if start not in notes[notes_idx][measure]:
        notes[notes_idx][measure][start] = [0, 0, 0, 0, 0, 0, 0, 0]
    if dbg:
        print('CN: notes_idx=' + str(notes_idx) + ' start=' + str(start) + ' note=' + str(note))
    if note < 7:
        notes[notes_idx][measure][start][note] = 1
    while note >= 10:
        note1 = note % 10
        notes[notes_idx][measure][start][note1] = 1
        note = math.floor(note / 10)

# BSS / MSS の終端
if note == 0 and flag & 2 == 2:
    end = start + length
    if end not in notes[notes_idx][measure]:
        notes[notes_idx][measure][end] = [0, 0, 0, 0, 0, 0, 0, 0]
    notes[notes_idx][measure][end][note] = 1

notes辞書は、notes[1P or 2P][小節番号][小節内の位置][レーン番号]というネストしまくり辞書で、レーン番号は 0 がターンテーブルで 1 ~ 7 がキーにあたる。
よく見ると、

    if note < 7:
        notes[notes_idx][measure][start][note] = 1

noteが 7 未満のとき、1 を設定する……? この境界条件が間違っているな?
つまりc1またはc2の定義で、7 鍵盤の単発チャージノーツ開始部がうまく配置されない。

    if note <= 7:
        notes[notes_idx][measure][start][note] = 1

条件式にイコール付けて、スクリプト保存して、もういっかい db ファイル作りましょう。


$ sqlite3 notes-8.db "select * from NOTES where MUSIC_ID='poodle' and DIFFICULT='L' and MEASURE in (23, 24) and SIDE=1"
poodle|DP|L|23|1|160|2251|8|13 1 5 1 7 135 157 135|57 7 3 7 1 357 137 357|13 1 5 1 7 135 157 135|57 7 3 7 1 357 137 357
(以下略)

13 1 5 1 7 135 157 135の 7 が表れているので、条件式修正はうまくいったっぽい。1 と 7 は画像で同時押しのように見えて、

// (注釈)チャージノーツ (1P側 23 小節目)
c1[23]=c2[25]=c1[53]=[[3,0],[5,48],[7,96]];
// (注釈)鍵盤定義(1P側 23 小節目)
sp[21]="02020202";
sp[22]="0a222222";
sp[23]=sp[21];

[7,96]は 4 つ押し 4 つ目で、sp[23]=sp[21]="02020202"も、1 鍵を 4 分音符で 4 つ押ししてるだけだから、タイミングは一緒のはずだな……

もう少し追ってみると、1 鍵の 4 分音符 4 つ目が展開されていないことが分かった。

GN:M23:0 div= 0 , sft= 0 , len(sdd)= 8 , sdd= 02020202
# (中略)
GN:M23:7 notes[location]=note // location= 0 , note= [0, 1, 0, 0, 0, 0, 0, 0]
GN:M23:8 sft= 2 , div= 2
GN:M23:0 div= 2 , sft= 2 , len(sdd)= 8 , sdd= 02020202
# (中略)
GN:M23:7 notes[location]=note // location= 32 , note= [0, 1, 0, 0, 0, 0, 0, 0]
GN:M23:8 sft= 4 , div= 4
GN:M23:0 div= 4 , sft= 4 , len(sdd)= 8 , sdd= 02020202
# (中略)
GN:M23:7 notes[location]=note // location= 64 , note= [0, 1, 0, 0, 0, 0, 0, 0]
GN:M23:8 sft= 6 , div= 6
GN:M23:0 div= 6 , sft= 6 , len(sdd)= 8 , sdd= 02020202
GN:M23:2 y= 0
GN:M23:4 location= 96 , nbar= 128 , div= 6 , len_sdd= 8
GN:M23:5 note_cnt= 0 , y= 0 , j= 0 , (y >> j)= 0
GN:M23:8 sft= 8 , div= 8
GN:M23:9 notes= {0: [0, 1, 0, 0, 0, 0, 0, 0], 32: [0, 1, 0, 0, 0, 0, 0, 0], 64: [0, 1, 0, 0, 0, 0, 0, 0]}

本来ならば、96: [0, 1, 0, 0, 0, 0, 0, 0]notes辞書に登録されているはずだ。
スクリプトで怪しいところは、

y = 0

if sft + 2 < len(sdd):
	y = int(sdd[sft:sft + 2], 16)

note = [0, 0, 0, 0, 0, 0, 0, 0]
location = math.floor(nbar * div / len_sdd)

note_cnt = 0
for j in range(0, 8):
	if y >> j == 0:
		break
	if y >> j & 1 == 1:
		note[j] = 1
		note_cnt += 1

sdd[sft:sft + 2]を参照したいのに、if 条件式でif sft + 2 < len(sdd):を満たせずにyが 0 のまま推移するのがダメそう。
ここを修正すると、前述のnotes辞書が 0, 32, 64, 96 の 4 キーで構成されるようになった。

再確認。

$ sqlite3 notes-8.db "select * from NOTES where MUSIC_ID='poodle' and DIFFICULT='L' and MEASURE in (23, 24) and SIDE=1"
poodle|DP|L|23|1|177|2251|8|13 1 5 1 17 135 157 135|57 7 3 7 17 357 137 357|13 1 5 1 17 135 157 135|57 7 3 7 17 357 137 357
(以下略)

1 鍵と 7 鍵が同時押し認識してくれたのでヨシ!

もちろん検索結果にも出てくる。