Generation
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user