Generation

This commit is contained in:
khodowany
2026-09-26 18:00:51 -05:00
parent c8581ea51a
commit 83154b1a01
10 changed files with 263 additions and 90 deletions
+29
View File
@@ -1,11 +1,40 @@
from __future__ import annotations
import dataclasses
import fractions
import itertools
import generator.accompaniment
import generator.model
@dataclasses.dataclass
class HarmonySpan:
harmony: dict
location: str
notes: list[dict] = dataclasses.field(default_factory=list)
def harmony_spans(document: dict) -> list[HarmonySpan]:
"""Group attacks by continuous harmony, including changes during silence."""
spans, span, active = [], None, None
for measure in document['staves'][0]['measures']:
if {v['id'] for v in measure['voices']} != {'bass', 'upper'}:
span, active = None, None
continue
events = [(generator.model.fraction(h['onset']), 0, h) for h in measure['harmonies']]
events.extend((generator.model.fraction(n['onset']), 1, n) for v in measure['voices'] for n in v['notes'] if n.get('_guitar_profile') == 'acoustic')
for onset, kind, item in sorted(events, key=lambda event: event[:2]):
harmony = item if kind == 0 else item['_harmony']
if not generator.accompaniment.same_chord(active, harmony):
span = None
active = harmony
if kind == 0:
continue
if span is None:
span = HarmonySpan(harmony, f'measure {measure["number"]}, event {item["id"]}, onset {onset}')
spans.append(span)
span.notes.append(item)
return spans
def written_durations(length: fractions.Fraction):
while length:
written = generator.model.written_for(length)