Chord Families

This commit is contained in:
khodowany
2026-10-06 02:57:37 -05:00
parent df83cae38c
commit e71385dad1
16 changed files with 590 additions and 126 deletions
+5 -3
View File
@@ -137,7 +137,7 @@ def lane_candidates(measure, prior, lane, melody, policy, seed):
continue
if any(not any(a <= t < b for t in onsets) for a, b in required):
continue
if any(b - a < 1 for a, b in zip(onsets, onsets[1:])):
if any(b - a < fractions.Fraction(policy['attack_spacing']) for a, b in zip(onsets, onsets[1:])):
continue
for family in policy['layers'][lane]['families']:
durations = policy['families'][family]
@@ -147,12 +147,14 @@ def lane_candidates(measure, prior, lane, melody, policy, seed):
following = onsets[i + 1] if i + 1 < len(onsets) else length
duration = fractions.Fraction(durations[i % len(durations)])
events.append(Attack(lane, a, min(a + duration, following, end)))
if policy.get('allowed_durations') and any(e.end - e.start not in tuple(map(fractions.Fraction, policy['allowed_durations'])) for e in events):
continue
exceptions = ((lane, 'extra attack for harmonic changes'),) if count > high else ()
contributions = (*lane_score(events, lane, melody, harmony, length), ('extra_attacks', .5 * bool(exceptions)))
result.append(Rhythm(tuple(events), ((lane, family if count else 'space'),), contributions, exceptions))
if not result:
# A short partial bar can have fewer gestures, not invented subdivisions.
if length < 1:
if length < 1 and not policy.get('allowed_durations'):
a, b, _ = active[0]
return Rhythm((Attack(lane, a, b),), ((lane, 'partial'),), (('activity', 0.),)),
raise ValueError(f'measure {measure["number"]}: no {lane} rhythm within the bounded attack/spacing policy')
@@ -166,7 +168,7 @@ def crowding(events):
return cost + .5 * sum(z - x <= 1 for x, y, z in zip(times, times[1:], times[2:]))
def candidates(measure, prior, part, melody, seed):
policy = generator.vocabulary.data('accompaniment')
policy = generator.vocabulary.accompaniment(part)
if part == 'electric':
return lane_candidates(measure, prior, 'electric', melody, policy, seed)
bass = lane_candidates(measure, prior, 'bass', melody, policy, seed)