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 __eq__(self, other): if not isinstance(other, self.__class__): return False return pitches.same_species(other.bass_note, self.bass_note) and pitches.same_species( other._root, self._root)
def functional_relevance(self, c1, c2): score = _KeySignature.functional_relevance(self, c1, c2) if self.is_functional(c1) and self.is_functional(c2) and \ pitches.same_species(c1.root(), self.five()) and pitches.same_species(c2.root(), self.flat_six()): score += vars.FIVE_SIX_FUNCTIONALITY return score
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 __contains_one_or_five_seven(key_signature, chord_progression_stub): for key in chord_progression_stub.keys(): chord = chord_progression_stub[key] if key_signature.is_functional(chord) and pitches.same_species( key_signature.one(), chord.root()): return True return False
def harmonic_relevance(self, chord): if pitches.same_species(chord.root(), self.one()) and \ isinstance(chord, chords.MinorChord): return vars.ONE_CHORD_HARMONY elif pitches.same_species(chord.root(), self.two()) and \ isinstance(chord, chords.DiminishedChord): return vars.TWO_CHORD_HARMONY elif pitches.same_species(chord.root(), self.three()) and \ isinstance(chord, chords.MajorChord): return vars.THREE_CHORD_HARMONY elif pitches.same_species(chord.root(), self.four()) and \ isinstance(chord, chords.MinorChord): return vars.FOUR_CHORD_HARMONY elif pitches.same_species(chord.root(), self.flat_six()) and \ isinstance(chord, chords.MajorChord): return vars.SIX_CHORD_HARMONY return _KeySignature.harmonic_relevance(self, chord)
def harmonic_relevance(self, chord): """ Some chords are more indicative of a certain key than other. E.g. in C, the chords C and G7 strongly indicate that we're in the key of C. Returns a score based on harmonic relevance to the key :param chord: chords.Chords object :return: Harmony relevance score """ if pitches.same_species(chord.root(), self.five()) and \ isinstance(chord, chords.SevenChord): return vars.FIVE_DOMINANT_HARMONY elif pitches.same_species(chord.root(), self.five()) and \ isinstance(chord, chords.MajorChord): return vars.FIVE_MAJOR_HARMONY elif pitches.same_species(chord.root(), self.seven()) and \ isinstance(chord, chords.DiminishedChord): return vars.MAJOR_SEVEN_DIMINISHED_HARMONY return 0.0
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_musicality(self): score = 0.0 next_pitch = self.sequence[self.position + config.resolution].midi() next_chord = config.chord_progression[self.position + config.resolution] next_key = config.key_signatures[self.position + config.resolution] this_key = config.key_signatures[self.position] if pitches.same_species(next_pitch, next_chord.root()): y = this_key != next_key s = next_chord.root() e = next_key.one() t = pitches.same_species(next_chord.root(), next_key.one()) score += vars.APPROACH_KEY_CHANGE \ if pitches.same_species(next_chord.root(), next_key.one()) and this_key != next_key \ else vars.APPROACH_NEW_CHORD_ROOT else: score += vars.APPROACH_DEFAULT_MUSICALITY score += vars.FLICKER_COEF if self.causes_flickering() else 0.0 return score
def is_functional(self, chord): chord_root = chord.root() if (pitches.same_species(chord_root, self.three()) or pitches.same_species(chord_root, self.flat_six()) or pitches.same_species(chord_root, self.five())) and \ isinstance(chord, chords.MajorChord): return True elif (pitches.same_species(chord_root, self.five())) \ and isinstance(chord, chords.SevenChord): return True elif (pitches.same_species(chord_root, self.one()) or pitches.same_species(chord_root, self.four())) and \ isinstance(chord, chords.MinorChord): return True elif (pitches.same_species(chord_root, self.seven() or pitches.same_species(chord_root, self.two())) and isinstance(chord_root, chords.DiminishedChord)): return True return False
def root_in_bass(self): return pitches.same_species(self._root, self.bass_note)
def functional_relevance(self, c1, c2): """ Some functional relationships are more indicative of some key sigantures. E.g. A7 -> D is strongly indicative of the key of D. Returns a score based on how functionally relevant the two chords are in this key. * Not currently implemented: The dimension of time needs to be included within the scoring mechanism. The following example illustrates why. Assume we're in 4/4 and the actual key signature is A | A | | | || D | | | || F- | | | || Why humans can deduce that this relationship is indicative of A, the computer just see A -> D, which is more indicative of the key of D. The F- could be any chord that would force a key change to be registered. :param c1: first chord :param c2: second chord :return: functionality score based on the chords """ score = 0.0 if self.is_functional(c1) and self.is_functional(c2): # Dominant five chords in functional relationship are more valuable than just major fives if (pitches.same_species(c1.root(), self.five()) and isinstance(c1, chords.SevenChord)) or \ (pitches.same_species(c2.root(), self.five()) and isinstance(c2, chords.SevenChord)): score += vars.DOMINANT_FIVE_IN_FUNCTIONAL_RELEVANCE elif (pitches.same_species(c1.root(), self.five()) and isinstance(c1, chords.MajorChord)) or \ (pitches.same_species(c2.root(), self.five()) and isinstance(c2, chords.MajorChord)): score += vars.MAJOR_FIVE_IN_FUNCTIONAL_RELEVANCE if pitches.same_species(c1._root, self.five()) and pitches.same_species(c2._root, self.one()): score += vars.FIVE_ONE_FUNCTIONALITY elif pitches.same_species(c1._root, self.seven()) and pitches.same_species(c2._root, self.one()): score += vars.SEVEN_ONE_FUNCTIONALITY elif pitches.same_species(c1._root, self.two()) and pitches.same_species(c2._root, self.five()): score += vars.TWO_FIVE_FUNCTIONALITY elif pitches.same_species(c1._root, self.four()) and pitches.same_species(c2._root, self.five()): score += vars.FOUR_FIVE_FUNCTIONALITY return score