This commit is contained in:
khodowany
2026-10-04 12:27:43 -05:00
parent 8fdd736e13
commit 405066eb43
18 changed files with 810 additions and 71 deletions
+9 -5
View File
@@ -104,7 +104,7 @@ def write_harmony(parent, value: dict, divisions: int) -> None:
element(item, 'degree-type', degree['type'])
element(node, 'offset', int(generator.model.fraction(value['onset']) * divisions))
def write_note(parent, event: dict, voice: str, divisions: int, tuplets: list[dict]) -> None:
def write_note(parent, event: dict, voice: str, divisions: int, tuplets: list[dict], tablature=False) -> None:
if event['kind'] == 'spacer':
item = element(parent, 'forward')
element(item, 'duration', int(generator.model.fraction(event['duration']) * divisions))
@@ -170,6 +170,10 @@ def write_note(parent, event: dict, voice: str, divisions: int, tuplets: list[di
for beam in event.get('beams', []):
element(node, 'beam', beam['type'], number=beam['level'])
notations = element(node, 'notations')
if tablature and pitch and pitch.get('tablature'):
technical = element(notations, 'technical')
element(technical, 'string', pitch['tablature']['string'])
element(technical, 'fret', pitch['tablature']['fret'])
for field, action in (('tie_from', 'stop'), ('tie_to', 'start')):
if pitch and pitch.get(field):
element(notations, 'tied', type=action)
@@ -204,7 +208,7 @@ def write_barline(bar, measure, location):
node = element(bar, 'barline', location=location)
element(node, 'bar-style', measure.get('barlines', {}).get(location, 'regular'))
def musicxml_tree(document: dict) -> xml.etree.ElementTree.ElementTree:
def musicxml_tree(document: dict, *, tablature=False) -> xml.etree.ElementTree.ElementTree:
generator.model.validate_document(document)
root = xml.etree.ElementTree.Element('score-partwise', {'version': '4.0'})
metadata, staff = document['metadata'], document['staves'][0]
@@ -296,7 +300,7 @@ def musicxml_tree(document: dict) -> xml.etree.ElementTree.ElementTree:
onset = generator.model.fraction(event['onset'])
if onset > cursor:
element(element(bar, 'forward'), 'duration', int((onset - cursor) * divisions))
write_note(bar, event, voice['id'], divisions, staff.get('tuplets', []))
write_note(bar, event, voice['id'], divisions, staff.get('tuplets', []), tablature)
cursor = onset + generator.model.fraction(event['duration'])
if cursor < generator.model.fraction(measure['duration']):
element(element(bar, 'forward'), 'duration', int((generator.model.fraction(measure['duration']) - cursor) * divisions))
@@ -305,7 +309,7 @@ def musicxml_tree(document: dict) -> xml.etree.ElementTree.ElementTree:
absolute += generator.model.fraction(measure['duration'])
return xml.etree.ElementTree.ElementTree(root)
def write_musicxml(path: pathlib.Path, document: dict) -> None:
tree = musicxml_tree(document)
def write_musicxml(path: pathlib.Path, document: dict, *, tablature=False) -> None:
tree = musicxml_tree(document, tablature=tablature)
xml.etree.ElementTree.indent(tree, space=' ')
tree.write(path, encoding='utf-8', xml_declaration=True)