33 lines
1.6 KiB
Python
33 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import generator.harmony
|
|
import generator.model
|
|
import generator.scales.library
|
|
import generator.scales.report
|
|
import generator.scales.selection
|
|
import generator.scales.timeline
|
|
|
|
def annotate(document: dict, solos: list[generator.scales.timeline.Solo], library: generator.scales.library.Library, source: str) -> str:
|
|
staff = document['staves'][0]
|
|
timeline = generator.scales.timeline.read(staff)
|
|
spans, reports = [], []
|
|
for solo in solos:
|
|
choices = generator.scales.selection.select(timeline, solo, library)
|
|
previous = None
|
|
for choice in choices:
|
|
if choice.span.chord is None:
|
|
previous = None
|
|
continue
|
|
label = choice.scale.label() if choice.scale else 'No exact scale match'
|
|
if previous is not None and previous['label'] == label and generator.model.fraction(previous['end']) == choice.span.start:
|
|
previous['end'] = generator.model.rational(choice.span.end)
|
|
else:
|
|
previous = {'id': f'scale-{len(spans) + 1}', 'start': generator.model.rational(choice.span.start), 'end': generator.model.rational(choice.span.end), 'label': label, 'matched': choice.scale is not None}
|
|
spans.append(previous)
|
|
if choice.scale is None:
|
|
print(f'{source}, {staff["name"]}, source measure {choice.span.source_measure}, beat {choice.span.beat}: {choice.reason} Chord: {generator.harmony.symbol(choice.span.chord)}', flush=True)
|
|
reports.append(generator.scales.report.passage(staff['arrangement_part_type'], solo, choices, library))
|
|
if spans:
|
|
staff['scale_spans'] = spans
|
|
return '\n'.join(reports)
|