This commit is contained in:
khodowany
2026-10-01 16:41:18 -05:00
parent 28fc67fba1
commit f5861fcdf6
22 changed files with 1473 additions and 122 deletions
+16 -4
View File
@@ -52,13 +52,25 @@ class Harmony:
def __init__(self, choices):
self.choices = choices
self.spans = tuple(Span(c.span.start, c.span.end, roles(c.span.chord), c.scale, generator.harmony.symbol(c.span.chord) if c.span.chord else 'N.C.') for c in choices)
self._at = {}
self._segments = {}
self._members = {}
self.evaluations = {}
def at(self, time):
return next((s for s in self.spans if s.start <= time < s.end), None)
if time not in self._at:
self._at[time] = next((s for s in self.spans if s.start <= time < s.end), None)
return self._at[time]
def segments(self, note):
return tuple((s, max(note.start, s.start), min(note.end, s.end)) for s in self.spans if s.start < note.end and s.end > note.start)
key = (note.start, note.end)
if key not in self._segments:
self._segments[key] = tuple((s, max(note.start, s.start), min(note.end, s.end)) for s in self.spans if s.start < note.end and s.end > note.start)
return self._segments[key]
def members(self, start, end):
spans = [s for s in self.spans if s.start < end and s.end > start]
return frozenset.intersection(*(s.roles.basic for s in spans)) if spans else frozenset()
key = (start, end)
if key not in self._members:
spans = [s for s in self.spans if s.start < end and s.end > start]
self._members[key] = frozenset.intersection(*(s.roles.basic for s in spans)) if spans else frozenset()
return self._members[key]
def function(self, number, span):
pitch = number % 12
return 'basic' if pitch in span.roles.basic else 'specified_extension' if pitch in span.roles.specified else 'mapped_motion' if span.scale and pitch in span.scale.pitches else 'outside_collection'