def test_minor_seconds(self): minors = { "C": "Db", "Db": "Ebb", "D#": "E", "C#": "D", "E": "F", "F": "Gb", "G": "Ab", "Gb": "Abb" } for x in minors.keys(): self.assertEqual(minors[x], intervals.minor_second(x),\ "The minor second of %s is not %s, expecting %s" % (x, intervals.minor_second(x), minors[x]))
def test_minor_seconds(self): minors = { 'C': 'Db', 'Db': 'Ebb', 'D#': 'E', 'C#': 'D', 'E': 'F', 'F': 'Gb', 'G': 'Ab', 'Gb': 'Abb', } for x in list(minors.keys()): self.assertEqual(minors[x], intervals.minor_second(x), 'The minor second of %s is not %s, expecting %s' % (x, intervals.minor_second(x), minors[x]))
def minor_seventh_flat_five_flat_nine_flat_thirteen(note): """ e.g. Bm7b5b9b13 = BDFA + CEG This arises as the diatonic extension of VIIm7b5 i.e. B diatonic thirteenth in C major """ return half_diminished_seventh(note) + major_triad( intervals.minor_second(note))
def ascending(self): notes = [self.tonic] for n in range(1, 7): if n in self.semitones: notes.append(intervals.minor_second(notes[-1])) else: notes.append(intervals.major_second(notes[-1])) return notes * self.octaves + [notes[0]]
def suspended_fourth_ninth(note): """Build a suspended fourth flat ninth chord on note. Example: >>> suspended_fourth_ninth('C') ['C', 'F', 'G', 'Db'] """ return suspended_fourth_triad(note) + [intervals.minor_second(note)]
def test_minor_seconds(self): minors = { "C": "Db", "Db": "Ebb", "D#": "E", "C#": "D", "E": "F", "F": "Gb", "G": "Ab", "Gb": "Abb", } for x in minors: self.assertEqual( minors[x], intervals.minor_second(x), "The minor second of %s is not %s, expecting %s" % (x, intervals.minor_second(x), minors[x]), )
def ascending(self): notes = [self.tonic] for i in range(3): notes.extend([ intervals.minor_second(notes[-1]), intervals.minor_third(notes[-1]) ]) notes.append(intervals.minor_seventh(notes[0])) notes[-2] = intervals.major_sixth(notes[0]) return notes * self.octaves + [notes[0]]
def dominant_flat_ninth(note): """Build a dominant flat ninth chord on note. Example: >>> dominant_ninth('C') ['C', 'E', 'G', 'Bb', 'Db'] """ res = dominant_ninth(note) res[4] = intervals.minor_second(note) return res
def create_interval_dissonant(start_note): start = start_note options = [ intervals.minor_second(start), intervals.major_second(start), intervals.minor_fifth(start), intervals.minor_seventh(start), intervals.major_seventh(start) ] end = options[(randint(0, len(options) - 1))] interval = intervals.determine(start, end) return interval
def get_diatonic_upper_chord_extension(chord, extension, key=None, mode='major'): ''' params: - chord is a (parsed) shorthand symbol e.g. 'Dm7' - extension is an integer representing the target extension (e.g. 3 to give the 3rd (major or minor)) ''' root, chord_type = chord_note_and_family(chord) extension_index = { 1: 0, 3: 1, 5: 2, 7: 3, 9: 4, 2: 4, 11: 5, 4: 5, 13: 6, 6: 6 } # we consider the thirteenth chords which arise from diatonic chord extensions only, # we then check if our chord is a subchord of any of these diatonic thirteenths; # if it is, then we assume that it plays the role of the chord (roman numeral) which is most likely to generate that thirteenth. # e.g. if we find a G13 then we assume it comes from G7 (V7 in C) # More details: # if key is not specified, then default to the most conventional extensions for a given chord type (https://en.wikipedia.org/wiki/Extended_chord#Chord_structure # Note: Would this be different in a different mode/tonality (e.g. extend me a IV chord while playing a locrian tune...)? Should probably factor this in... (TO-DO) # See also https://www.reddit.com/r/musictheory/comments/8becrf/when_to_apply_which_chord_extension/ # M7 -> M13 (M7, 9, #11*, 13) *by convention # m7 -> m13 (m7, 9, 11, 13) # 7 -> 13 (7, 9, 11, 13) # m7b5 -> m7b5b9b13 (7, b9, 11, b13) (e.g. B D F A -> B D F A C E G) # if key is specified then we can work out the degree of our chord (e.g. an FM7 in C is a IV chord) and be more clever with extensions # IM7 -> M13#11 # IIm7 -> m13 (e.g. DFACEGB) - note that this has a major 13th (https://music.stackexchange.com/questions/16932/why-does-a-cm13-chord-use-a-instead-of-a) # IIIm7 -> m13b9 # IVM7 -> M13#11 # V7 -> 13 # VIm7 -> m7b13 (e.g. ACEGBDF) # VIIm7b5 -> m7b5b9b13 def assume_key(root, chord_type, mode): if mode == 'harmonic_minor': if chord_type in ['7b9']: # assume V (C7b9 implies F harmonic minor, i.e. 7b9 is phyrgian dominant (V mode of HM)) TODO: refactor? return notes.int_to_note(notes.note_to_int(root) - 7) if chord_type in ['M7', 'M9', 'M13', 'M6']: return root elif chord_type in ['m7', 'm9', 'm11', 'm13']: # assume II, e.g. Dm7 -> return C return notes.int_to_note(notes.note_to_int(root) - 2) elif chord_type in ['m7b9', 'm11b9', 'm13b9']: # assume III return notes.int_to_note(notes.note_to_int(root) - 4) elif '#11' in chord_type: # assume IV return notes.int_to_note(notes.note_to_int(root) - 5) elif chord_type in ['7', '9', '11', '13']: # assume V return notes.int_to_note(notes.note_to_int(root) - 7) elif chord_type in ['m7b13']: # assume VI return notes.int_to_note(notes.note_to_int(root) - 9) elif ('b5' in chord_type) or ('dim' in chord_type): # assume VII return notes.int_to_note(notes.note_to_int(root) - 11) elif chord_type in [ '7b9' ]: # TODO: refactor so that this is not an ad hoc exception (given 7b9 is covered below) but instea maybe automatically check all hminor modes etc pass else: print( f'\nWarning: utilities.assume_key() does not know how to handle chord_type {chord_type}' ) pass if key is None: key = assume_key(root, chord_type, mode) # TODO: handle modes / alterations (also see above) # assume_key() is assuming major tonality (more precisely, diatonic_thirteen() is assuming major tonality and assume_key() provides accordingly) if key is None: # if assume_key didn't work e.g. for a 7b9 which does not arise on any 7th chord built from the major scale if chord_type == '7b9': diatonic_extended_chord = chords.dominant_flat_ninth( root) + chords.major_triad( intervals.minor_second(root))[1:] # 1 3 5 b7 b9 11 b13 return diatonic_extended_chord[extension_index[extension]] try: diatonic_extended_chord = diatonic_thirteenth(root, key) except NoteFormatError: try: diatonic_extended_chord = diatonic_thirteenth(root, synonyms[key]) except KeyError: print(f'Problem fetching diatonic_thirteenth({root},{key})') return diatonic_extended_chord[extension_index[extension]]