Added basic music21 converter

This commit is contained in:
2023-02-13 17:28:42 +02:00
parent 7cc89d3333
commit e240c45693
5 changed files with 75 additions and 5 deletions

3
.gitignore vendored
View File

@ -165,6 +165,7 @@ cython_debug/
# VSCode
.vscode
# Debugging file
# Debugging files
debug.py
test.py

10
test.py
View File

@ -1,4 +1,8 @@
from ziffers import *
# a = z1("q e 1 ^ ^ 2 _ 3 4 <3> 3")
a = z1("1 2")
print(a.take(3))
from music21 import *
z = z('e (1 2 3)+(4 2 1)*2')
s = to_music21(z,octave=-2,time="3/4")
s.show()
s.show('midi')

View File

@ -4,3 +4,4 @@ from .classes import *
from .common import *
from .defaults import *
from .scale import *
from .converters import *

View File

@ -1,5 +1,5 @@
""" Ziffers classes for the parsed notation """
from dataclasses import dataclass, field, replace
from dataclasses import dataclass, field, replace, asdict
from itertools import product, islice, cycle
import operator
import random
@ -31,6 +31,9 @@ class Meta:
if getattr(self, key) is None:
setattr(self, key, value)
def dict(self):
return {k: str(v) for k, v in asdict(self).items()}
@dataclass(kw_only=True)
class Item(Meta):

61
ziffers/converters.py Normal file
View File

@ -0,0 +1,61 @@
"""Collection of converters"""
from music21 import converter, note, stream, meter
from ziffers import zparse, Ziffers
def to_music21(strData: str|Ziffers, **options):
"""Helper for passing options to the parser"""
converter.registerSubconverter(ZiffersMusic21)
if isinstance(strData,Ziffers):
if options:
options["preparsed"] = strData
else:
options = {"preparsed": strData}
options = {"ziffers": options}
return converter.parse("PREPARSED", format="ziffers", keywords=options)
if options:
options = {"ziffers": options}
return converter.parse(strData, format="ziffers", keywords=options)
else:
test = converter.parse(strData, format="ziffers")
return test
def set_musescore_path(path: str):
"""Helper for setting the Musescore path"""
us = environment.UserSettings()
# Default windows path:
# 'C:\\Program Files\\MuseScore 3\\bin\\MuseScore3.exe'
us['musicxmlPath'] = path
us['musescoreDirectPNGPath'] = path
class ZiffersMusic21(converter.subConverters.SubConverter):
"""Ziffers converter to Music21"""
registerFormats = ("ziffers",)
registerInputExtensions = ("zf",)
def parseData(self, strData, number=None):
"""Parses Ziffers string to Music21 object"""
# Look for options in keywords object
keywords = self.keywords["keywords"]
if "ziffers" in keywords:
options = keywords["ziffers"]
if "preparsed" in options:
parsed = options["preparsed"]
else:
parsed = zparse(strData, **options)
else:
parsed = zparse(strData)
s = stream.Part()
if "time" in options:
m = meter.TimeSignature(options["time"]) # Common time
else:
m = meter.TimeSignature("c") # Common time
s.insert(0, m)
for z in parsed:
m_note = note.Note(z.note)
m_note.duration.quarterLength = z.duration * 4
s.append(m_note)
self.stream = s.makeMeasures()