slay-micro-models / src /core /abc_to_midi.py
Maggio33's picture
Re-sync: warstwowy src/ (core/data/train/generate/compose/tools) + wagi + karta
ab7c6e3 verified
Raw
History Blame Contribute Delete
2.19 kB
"""Konwersja wygenerowanych melodii ABC -> MIDI (fortepian) przez music21.
Każda melodia osobno; błędy parsowania nie wywalają całości.
"""
import sys, re
from music21 import converter, instrument
def sanitize(abc: str) -> str:
"""Usuwa powtórzenia/volty z ciała, ALE ZOSTAWIA akordy [ace]. Nagłówki nietknięte."""
out = []
for ln in abc.split("\n"):
if re.match(r"^[A-Za-z]:", ln): # nagłówek
out.append(ln); continue
b = re.sub(r"\[[12]", "", ln) # volty [1 [2 (akordy [ace] ZOSTAJĄ!)
b = b.replace(":", "") # dwukropki powtórzeń (|: :| ::)
b = re.sub(r"\|\s*[12]", "|", b) # numery volt po kresce |1 |2
b = re.sub(r"\|+", "|", b) # scal wielokrotne kreski
b = re.sub(r"\^=|=\^|_=|=_", lambda m: m.group(0).replace("=", ""), b) # zepsute akcydencje (^=)
out.append(b)
return "\n".join(out)
def to_midi(abc: str, out_path: str, inst=None) -> bool:
try:
score = converter.parse(sanitize(abc), format="abc")
# spłaszcz do samych nut/pauz (omija konflikt TimeSignature przy budowie taktów)
notes = score.flatten().notesAndRests.stream()
if inst is not None: # ustaw instrument (np. Violin); domyślnie fortepian (GM 0)
notes.insert(0, inst)
notes.write("midi", fp=out_path)
return True
except Exception as e:
print(f" [pominięto] {out_path}: {type(e).__name__}: {e}")
return False
def main():
sys.stdout.reconfigure(encoding="utf-8")
infile = sys.argv[1] if len(sys.argv) > 1 else "data/generated.abc"
prefix = sys.argv[2] if len(sys.argv) > 2 else "data/jig"
text = open(infile, encoding="utf-8").read()
tunes = [t.strip() for t in text.split("\n\n") if "X:" in t]
print(f"melodii do konwersji: {len(tunes)} (z {infile})")
ok = 0
for i, tune in enumerate(tunes, 1):
path = f"{prefix}_{i}.mid"
if to_midi(tune, path):
print(f" OK -> {path}")
ok += 1
print(f"\ngotowe: {ok}/{len(tunes)} plików MIDI (fortepian) w data/")
if __name__ == "__main__":
main()