def blend_chords(pc1, pc2): spec1 = get_chord_spec(pc1) spec2 = get_chord_spec(pc2) generic_space = set.intersection(spec1, spec2) path1 = get_generalization_path(spec1, generic_space) path2 = get_generalization_path(spec2, generic_space) solutions = [] for i, _ in enumerate(path1): for j, _ in enumerate(path2): colimit = set.union(generalized(spec1, path1, i), generalized(spec2, path2, j)) deduced = Chord.classify_uniquely( pitch_class(axiom) for axiom in colimit if type(axiom) is AbsNote) blendoid = { *deduced, *(pitch_class(axiom + deduced.root) for axiom in colimit if type(axiom) is RelNote) } if check_for_consistency(blendoid): # TODO: account for deviations from priority ordering cost = max(i, j)**2 + min(i, j) solutions.append((blendoid, cost)) return min(solutions, key=itemgetter(1))[0]
def get_chord_spec(notes): chord = Chord.classify_uniquely(notes) return { *map(AbsNote, chord), *map(RelNote, relative_intervals(chord, chord.root)) }