@@ -130,7 +130,7 @@ def anchor_backbones(identifier, start, end, release, register, choices, bar, se
|
||||
if terminal_start <= opening + fractions.Fraction(1, 2):
|
||||
moments = []
|
||||
moments.append((terminal_start, 'terminal'))
|
||||
states = [(0.0, ())]
|
||||
states = [(0.0, (), intention) for intention in ('rising', 'falling', 'returning', 'repeated')]
|
||||
for index, (time, role) in enumerate(moments):
|
||||
choice = next(c for c in active if c.span.start <= time < c.span.end)
|
||||
chord_roles = generator.solo.harmonic.roles(choice.span.chord)
|
||||
@@ -141,17 +141,18 @@ def anchor_backbones(identifier, start, end, release, register, choices, bar, se
|
||||
pitches = [p for p in pitches if register[0] <= p.number() <= register[1] and p.number() % 12 in eligible and generator.fretboard.single_positions_for_pitch(fractions.Fraction(p.number()))]
|
||||
desired = register[0] + (5 if index == 0 else 8 if role == 'terminal' else 11)
|
||||
following = []
|
||||
for cost, anchors in states:
|
||||
for cost, anchors, intention in states:
|
||||
for pitch in pitches:
|
||||
jump = abs(pitch.number() - anchors[-1].pitch.number()) if anchors else 0
|
||||
direction = 1 if role != 'terminal' else -1
|
||||
direction = 1 if intention == 'rising' or intention == 'returning' and role != 'terminal' else -1 if intention != 'repeated' else 0
|
||||
wrong_way = bool(anchors and (pitch.number() - anchors[-1].pitch.number()) * direction < 0)
|
||||
preferred = target_pitches(choice.span.chord, role == 'terminal')
|
||||
score = cost + jump / 12 + 0.3 * wrong_way + abs(pitch.number() - desired) / 18 + 0.3 * (pitch.number() % 12 not in chord_roles.basic) + 0.2 * (role == 'terminal' and pitch.number() % 12 not in preferred)
|
||||
destination_motion = 0 if intention == 'repeated' else 4
|
||||
score = cost + abs(jump - destination_motion) / 12 + 0.8 * wrong_way + abs(pitch.number() - desired) / 36 + 0.3 * (pitch.number() % 12 not in chord_roles.basic) + 0.2 * (role == 'terminal' and pitch.number() % 12 not in preferred)
|
||||
anchor = generator.solo.types.Anchor(f'{identifier}_anchor_{index + 1}', time, latest, pitch, frozenset(eligible), register, duration, role, generator.harmony.symbol(choice.span.chord), False, finish if role == 'terminal' else None)
|
||||
following.append((score, (*anchors, anchor)))
|
||||
states = list(generator.solo.sequences.diverse(following, lambda item: (item[0], generator.solo.policy.stable_rank(seed, tuple(a.pitch for a in item[1]))), lambda item: (item[1][0].pitch.number(), item[1][-1].pitch.number()), generator.solo.policy.DEFAULT.alternatives))
|
||||
return tuple(anchors for _, anchors in states)
|
||||
following.append((score, (*anchors, anchor), intention))
|
||||
states = list(generator.solo.sequences.diverse(following, lambda item: (item[0], generator.solo.policy.stable_rank(seed, tuple(a.pitch for a in item[1]))), lambda item: (item[2], item[1][0].pitch.number()), generator.solo.policy.DEFAULT.anchor_lines))
|
||||
return tuple(dict.fromkeys(anchors for _, anchors, _ in states))
|
||||
|
||||
def plans(analysis: generator.solo.analysis.Analysis, measures: list[dict], choices, end: fractions.Fraction, part: str, sequences: generator.solo.sequences.Library) -> tuple[generator.solo.types.PhrasePlan, ...]:
|
||||
boundaries = [fractions.Fraction()]
|
||||
@@ -207,23 +208,13 @@ def plans(analysis: generator.solo.analysis.Analysis, measures: list[dict], choi
|
||||
if slot < 2 and slot not in inventions:
|
||||
inventions[slot] = new_motif(sequences, bar, choices=local, register=register, seed=passage_seed, variant=slot)
|
||||
motif = head if slot == 2 else inventions[slot]
|
||||
gestures, cursor = [], start
|
||||
while cursor < finish - release:
|
||||
gesture_end = min(cursor + bar, finish - release)
|
||||
closing = gesture_end == finish - release
|
||||
changed = any(c.span.start == cursor and c.scale and prior.scale and c.scale.pitches != prior.scale.pitches for prior, c in zip(choices, choices[1:]))
|
||||
relationship = 'statement' if not gestures else 'close' if closing else 'repeat_with_harmonic_adaptation' if changed else 'answer' if cursor >= start + (finish - start) / 2 else 'extend'
|
||||
treatment = 'opening_reference' if not gestures and motif.origin == 'melody' else 'invented' if not gestures else 'rhythmic_reference' if relationship == 'repeat_with_harmonic_adaptation' else 'answer' if relationship in ('answer', 'close') else 'contour_reference'
|
||||
gestures.append(generator.solo.types.Gesture(f'{passage_id}_gesture_{len(gestures) + 1}', cursor, gesture_end, relationship, treatment))
|
||||
cursor = gesture_end
|
||||
phrase_start = start
|
||||
for phrase_stop in phrase_stops:
|
||||
phrase_end = boundaries[phrase_stop]
|
||||
terminal = phrase_end == finish
|
||||
treatment = 'opening_reference' if motif.origin == 'melody' else 'invented'
|
||||
local_gestures = tuple(g for g in gestures if g.start < phrase_end and g.end > phrase_start)
|
||||
landmarks = tuple(generator.solo.types.Landmark(a.earliest, a.latest, min(v[i].pitch.number() for v in anchors), max(v[i].pitch.number() for v in anchors), 0, a.role) for i, a in enumerate(anchors[0])) if anchors and anchors[0] else ()
|
||||
result.append(generator.solo.types.PhrasePlan(f'{part}_phrase_{len(result) + 1}', phrase_start, phrase_end, motif, 'statement' if phrase_start == start else 'continue', treatment, None, register, activity, release if terminal else fractions.Fraction(), envelope, landmarks, 'breath' if terminal and release else 'sustain' if terminal else 'connected', 'closed' if terminal else 'open', passage_seed, passage_id, start, finish, anchors, local_gestures))
|
||||
result.append(generator.solo.types.PhrasePlan(f'{part}_phrase_{len(result) + 1}', phrase_start, phrase_end, motif, 'statement' if phrase_start == start else 'continue', treatment, None, register, activity, release if terminal else fractions.Fraction(), envelope, landmarks, 'breath' if terminal and release else 'sustain' if terminal else 'connected', 'closed' if terminal else 'open', passage_seed, passage_id, start, finish, anchors))
|
||||
phrase_start = phrase_end
|
||||
index = stop
|
||||
return tuple(result)
|
||||
|
||||
Reference in New Issue
Block a user