def bass_note_tendency_score(candidate, beat): this_chord = chords.get(beat.start()) score = 0.0 candidate_is_this_chord_bass_note = pitches.same_species(candidate, this_chord.bass_note) # first bass note should definitely be the root if beat.start() == 0 and candidate_is_this_chord_bass_note: return vars.FIRST_BEAT_BASS_ROOT # If beat one, we want to hear the bass note if beat.first_beat() and candidate_is_this_chord_bass_note: score += vars.FIRST_BEAT_BASS_NOTE last_chord = chords.get(0 if beat.start() == 0 else beat.previous().start()) this_and_next_chord_are_same = chords.same(last_chord, this_chord) this_chord_root_in_bass = this_chord.root_in_bass() # Chord is the same as the last chord, and this is root note. Less important as root was likely # already established if this_and_next_chord_are_same and candidate_is_this_chord_bass_note and this_chord_root_in_bass: score += vars.BASS_ROOT_SAME_CHORD # Bass note does not equal root note, therefore it is especially important if pitches.same_species(candidate, this_chord.bass_note) and not this_chord_root_in_bass: score += vars.NON_ROOT_BASS_NOTE # new chord, we definitely want to hear the bass_note if not this_and_next_chord_are_same and candidate_is_this_chord_bass_note: score += vars.BASS_NOTE_NEW_CHORD return score
def preemption_penalty(candidate, beat): if beat.end() == config.song_length: return 0.0 this_chord = chords.get(beat.start()) next_chord = chords.get(beat.next().start()) if pitches.same_species(candidate, next_chord.root()) and this_chord != next_chord: return vars.PREEMPTION return 0.0
def get_all_transforms(start_position, end_position, max_subdivisions): satb = sequences.soprano(), sequences.alto(), sequences.tenor(), sequences.bass() pitches = [(sequence.pitch(start_position), sequence.pitch(end_position)) for sequence in satb] chord = chords.get(start_position) rhythm_set_groups = get_rhythm_sets(config.minimum_time_unit(), max_subdivisions, end_position - start_position) direction_set_groups = [direction_permutations(i) for i in range(1, max_subdivisions)] all_transforms = [] for i, (sequence, (start_pitch, end_pitch)) in enumerate(zip(satb[1:], pitches[1:])): # We can't (read: don't want to) transform to or from a rest; skip if the start or end pitch is a rest. if start_pitch == -1 or end_pitch == -1: all_transforms.append([[]]) continue high_thresh = min([p for p in pitches[i] if p != -1] + [sequence.part().max_high]) low_thresh = sequence.part().max_low if i == len(satb) - 1 else min(sequence.part().max_low, pitches[i - 1]) bounded_pitches = [pitch for pitch in chord.scale() if low_thresh <= pitch <= high_thresh] sequence_transforms = [] for i, direction_set_group in enumerate(direction_set_groups): pitch_sets = [group for direction_set in direction_set_group for group in pitch_sets_for_directions(bounded_pitches, start_pitch, end_pitch, direction_set)] trans = [StrongBeatPhrase(r, p) for p in pitch_sets for r in rhythm_set_groups[i]] sequence_transforms.extend(trans) all_transforms.append(sequence_transforms) product = list(itertools.product(*all_transforms)) return product
def third_preference_score(candidate, beat): chord = chords.get(beat.start()) if isinstance(chord, chords.SevenChord): if [pitch for pitch in candidate if pitches.same_species(pitch, chord.three())]: return vars.THIRD_PREFERENCE return 0.0
def get_candidate_matrix(beat, soprano_value): current_chord = chords.get(beat.start()) alto_candidates = sequences.alto().part().available_notes(current_chord) + [-1] tenor_candidates = sequences.tenor().part().available_notes(current_chord) + [-1] bass_candidates = sequences.bass().part().available_notes(current_chord) + [-1] return [g + [soprano_value] for g in combine_pitch_candidates(alto_candidates, tenor_candidates, bass_candidates) if parts_dont_cross(g, soprano_value)]
def unique_pitch_score(candidate, beat): chord = chords.get(beat.start()) unique_pitches = len(set([pitch % 12 for pitch in candidate if pitch in chord.all_octaves()])) return vars.unique_pitch_score(unique_pitches)