Accompaniment
ci / checks (push) Successful in 49m53s

This commit is contained in:
khodowany
2026-10-06 01:59:55 -05:00
parent 04bb44b9d0
commit df83cae38c
14 changed files with 916 additions and 156 deletions
+8
View File
@@ -66,6 +66,7 @@ def validate_document(document: dict) -> None:
if not staff.get('tablature'):
continue
for measure in staff['measures']:
sounding = []
for voice in measure['voices']:
for note in voice['notes']:
tones = []
@@ -73,8 +74,15 @@ def validate_document(document: dict) -> None:
tab = pitch['tablature']
position = TabPosition(tab['string'], tab['fret'], dict(STANDARD_TUNING)[tab['string']] + tab['fret'])
tones.append((position, generator.model.fraction(pitch['duration'])))
start = generator.model.fraction(note['onset'])
sounding.append((start, start + generator.model.fraction(pitch['duration']), position))
if not playable_attack(tones):
raise ValueError(f'{measure["id"]}, event {note["id"]}: single notes require frets {MIN_FRET}-{MAX_SINGLE_FRET}; each sounding chord requires an anchor in {MIN_FRET}-{MAX_ANCHOR_FRET} and at most {MAX_FRET_SPAN} consecutive fret positions, including held/tied tails')
if len(measure['voices']) > 1:
for time in sorted({t for a, b, _ in sounding for t in (a, b)}):
held = [(p, b - time) for a, b, p in sounding if a <= time < b]
if not playable_attack(held):
raise ValueError(f'{measure["id"]}, beat {time + 1}: overlapping guitar voices conflict in string, fret span or sounding anchor')
def validate_tuning(state: dict, location: str) -> None:
details = state['staff_details']