Construction

This commit is contained in:
khodowany
2026-10-07 23:45:17 -05:00
parent 3a01b4b6bd
commit 841a3f974e
8 changed files with 236 additions and 80 deletions
+13 -32
View File
@@ -208,10 +208,6 @@ class Canonical:
size = 2
self.groups.append(tuple((self.measures[i], carried[i], i) for i in range(index, index + size)))
index += size
choices, locations, self.groove_report = generator.comping_rhythm.choose_cycles(self.groups, part, self.melody, seed)
self.patterns = {g[0][2]: (p, a) for g, (p, a, _) in zip(self.groups, choices)}
self.locations = {g[0][2]: location for g, location in zip(self.groups, locations)}
selected = [r for _, _, r in choices]
self.acoustic_cache = {}
self.pair_breaks = {self.first, len(self.measures)}
self.pair_stops = []
@@ -229,13 +225,11 @@ class Canonical:
attacks = [generator.model.fraction(n['onset']) for n in generator.score.measure_notes(self.measures[0]) if n['pitches']]
if attacks:
self.pair_stops.append((last, pad + min(attacks)))
if part == 'acoustic':
assigned = self.acoustic_realizations(self.measures)
selected = [assigned[g[0][2]] for g in self.groups]
for report in self.groove_report:
report['retrieval_cost'] = report['cost']
report['cost'] = sum(r.cost * len(g) for g, r in zip(self.groups, selected) if report['source_start'] <= g[0][2] <= report['source_end'])
report['attack_assignment'] = 'combined_except_eighth_pairs'
breaks = [(i, fractions.Fraction()) for i in self.pair_breaks] + self.pair_stops
choices, locations, self.groove_report = generator.comping_rhythm.choose_cycles(self.groups, part, self.melody, seed, breaks=breaks)
self.patterns = {g[0][2]: (p, a) for g, (p, a, _) in zip(self.groups, choices)}
self.locations = {g[0][2]: location for g, location in zip(self.groups, locations)}
selected = [r for _, _, r in choices]
self.block_rhythms = {group[0][2]: rhythm for group, rhythm in zip(self.groups, selected)}
prepared = [self.prepare(group, rhythm) for group, rhythm in zip(self.groups, selected)]
active = tuple(span for spans in prepared for span in spans if span.events)
@@ -287,11 +281,10 @@ class Canonical:
starts = [fractions.Fraction()]
for m in sources:
starts.append(starts[-1] + generator.model.fraction(m['duration']))
breaks = {starts[i] for i in self.pair_breaks | set(bounds or ())}
breaks.update(starts[i] + t for i, t in self.pair_stops)
breaks = [(i, fractions.Fraction()) for i in self.pair_breaks | set(bounds or ())] + self.pair_stops
if stop:
breaks.add(starts[stop[0]] + stop[1])
events, raw = [], {}
breaks.append(stop)
groups, raw = [], []
for original in self.groups:
group = tuple(full[i] for _, _, i in original)
index = group[0][2]
@@ -300,23 +293,11 @@ class Canonical:
rhythm = generator.comping_rhythm.realize(pattern, group, 'acoustic', self.melody, anticipate=anticipate, limit=limit, boundary=True, assign=False)
if rhythm is None:
raise ValueError(f'source measure {sources[index]["number"]}: selected acoustic rhythm cannot fit written harmony')
raw[index] = rhythm
events.extend(dataclasses.replace(e, start=e.start + starts[index], end=e.end + starts[index],
harmonic_time=e.harmonic_time + starts[index] if e.harmonic_time is not None else None) for e in rhythm.events)
harmony = generator.comping_rhythm.spans(generator.comping_rhythm.flatten(full), None)
assigned = generator.comping_rhythm.assign_acoustic(events, harmony, breaks)
result = {}
for original in self.groups:
group = tuple(full[i] for _, _, i in original)
index, end = group[0][2], group[-1][2] + 1
local = tuple(dataclasses.replace(e, start=e.start - starts[index], end=e.end - starts[index],
harmonic_time=e.harmonic_time - starts[index] if e.harmonic_time is not None else None)
for e in assigned if starts[index] <= e.start < starts[end])
melody = tuple((a + starts[i] - starts[index], b + starts[i] - starts[index]) for _, _, i in group for a, b in self.melody[i])
flat = generator.comping_rhythm.flatten(group)
contributions = generator.comping_rhythm.evaluate(local, 'acoustic', melody, generator.comping_rhythm.spans(flat, None), tuple(starts[i + 1] - starts[i] for _, _, i in group))
result[index] = dataclasses.replace(raw[index], events=local, contributions=contributions,
exceptions=(*raw[index].exceptions, ('layer_assignment', 'source-form combined attacks with non-overlapping same-harmony eighth pairs')))
raw.append(rhythm)
groups.append(group)
context = generator.comping_rhythm.acoustic_context(groups, self.melody, breaks)
realized = generator.comping_rhythm.realize_acoustic_form(raw, context)
result = {g[0][2]: r for g, r in zip(groups, realized)}
self.acoustic_cache[key] = result
return result
def prepare(self, inputs, rhythm):