ノートをMMLに変換するスクリプト
- 注意点
- ノートの最小分解度は 64分音符までです
- 3連符、5連符、6連符といった連符は未実装です
- 和音は考慮されません
- 参考
スクリプト
以下のスクリプトを拡張子「.pyscript」で保存して "piano roll scripts" フォルダに配置します。
from flpianoroll import *
# 音階定数.
NOTES = ["c", "c+", "d", "d+", "e", "f", "f+", "g", "g+", "a", "a+", "b"]
def number_to_mml(number, prev):
"""
音階の文字列を返す
オクターブ移動がある場合はそれも合わせて文字列連結する
"""
ret = ""
octave = int(number / 12) - 1 # FLは標準より1オクターブ高い.
if prev is None:
# initial.
ret = "O%d "%octave
else:
# 前回からの差分を求める
octave_prev = int(prev / 12) - 1 # FLは標準より1オクターブ高い.
d = octave - octave_prev
if d != 0:
# shift octave
if d > 0:
ret += "> " * d
else:
ret += "< " * abs(d)
note = number % 12
return ret + NOTES[note]
def ticks_to_mml(ticks, ppq=96):
"""
MIDIティック数をMML音符長形式に変換する関数。
:param ticks: MIDIティック数 (例: 96, 48, 72など)
:param ppq: 分解能 (Pulse Per Quarter Note)。デフォルトは96。
:return: MML形式の音符長 (例: "4", "8.", "4.^16")。
"""
# 基本的な音符長のティック値
note_lengths = {
"1": ppq * 4, # 全音符
"2": ppq * 2, # 二分音符
"4": ppq, # 四分音符
"8": ppq // 2, # 八分音符
"16": ppq // 4, # 十六分音符
"32": ppq // 8, # 三十二分音符
"64": ppq // 16 # 六十四分音符
}
# 付点音符のティック値
dotted_lengths = {
"4.": ppq + ppq // 2, # 付点四分音符
"8.": (ppq // 2) + (ppq // 4), # 付点八分音符
"16.": (ppq // 4) + (ppq // 8), # 付点十六分音符
"32.": (ppq // 8) + (ppq // 16) # 付点三十二分音符
}
# 複合音符のティック値(例: "4.^16")
compound_lengths = {
"4.^16": ppq + (ppq // 4), # 付点四分音符 + 十六分音符
"8.^32": (ppq // 2) + (ppq // 8) # 付点八分音符 + 三十二分音符
}
# 最も近い一致を探す
closest_match = None
closest_difference = float("inf")
for mml, length in {**note_lengths, **dotted_lengths, **compound_lengths}.items():
difference = abs(ticks - length)
if difference < closest_difference:
closest_match = mml
closest_difference = difference
# ティック数が六十四分音符より短い場合は None を返す
if ticks < note_lengths["64"]:
return None
return closest_match
# -------------------------
# start program
# -------------------------
s = ""
note_prev = None
time_prev = 0
for i in range(score.noteCount):
# ノート情報を取得 (和音は考慮しない).
note = score.getNote(i)
# 音階を決める
pitch = number_to_mml(note.number, note_prev)
time = note.time
# 休符を入れる.
d = time - time_prev
if d > 0:
len2 = ticks_to_mml(d)
if not len2 is None:
s += "r%s "%len2
# next start time.
time_prev = time + note.length
# 音階と長さを決める
length = ticks_to_mml(note.length)
if not length is None:
s += "%s%s "%(pitch, length)
note_prev = note.number
# ダイアログでテキストを出力する
Utils.ShowMessage(s)
最終更新:2025年03月27日 08:25