def test_determine(self): for x in chords.chord_shorthand: self.assertEqual( True, chords.determine(chords.from_shorthand("C" + x)) != [], "'C%s' should return a value" % x, ) for x in (x for x in chords.chord_shorthand if x != "5"): self.assertEqual( "C" + chords.chord_shorthand_meaning[x], chords.determine(chords.from_shorthand("C" + x))[0], "The proper naming of '%s' is not '%s',expecting '%s'" % ( "C" + x, chords.determine(chords.from_shorthand("C" + x)), "C" + chords.chord_shorthand_meaning[x], ), ) self.chordsTest( [ [["A13"], ["A", "C#", "E", "G", "B", "D", "F#",]], [["Am13"], ["A", "C", "E", "G", "B", "D", "F#",]], [["AM13"], ["A", "C#", "E", "G#", "B", "D", "F#",]], ], lambda x: chords.determine(x, True), "chord name", )
def test_determine(self): map(lambda x: self.assertEqual(True, chords.determine(chords.from_shorthand('C' + x)) != [], "'C%s' should return a value" % x), chords.chord_shorthand.keys()) map(lambda x: self.assertEqual('C' + chords.chord_shorthand_meaning[x], chords.determine(chords.from_shorthand('C' + x))[0], "The proper naming of '%s' is not '%s',expecting '%s'" % ('C' + x, chords.determine(chords.from_shorthand('C' + x)), 'C' + chords.chord_shorthand_meaning[x])), [x for x in chords.chord_shorthand.keys() if x != '5']) self.chordsTest([[['A13'], [ 'A', 'C#', 'E', 'G', 'B', 'D', 'F#', ]], [['Am13'], [ 'A', 'C', 'E', 'G', 'B', 'D', 'F#', ]], [['AM13'], [ 'A', 'C#', 'E', 'G#', 'B', 'D', 'F#', ]]], lambda x: chords.determine(x, True), 'chord name')
def play_basic_chord(chord): c = NoteContainer(chord) l = Note(c[0].name) l.octave_down() print ch.determine(chord)[0] # Play chord and lowered first note fluidsynth.play_NoteContainer(c) fluidsynth.play_Note(l) time.sleep(1.0) return c
def playProgression(): progression = ["I", "vi", "ii", "iii7", "I7", "viidom7", "iii7", "V7"] key = "C" chords = progressions.to_chords(progression, key) if not fluidsynth.init(SF2): print "Couldn't load soundfont", SF2 sys.exit(1) while 1: i = 0 for chord in chords: c = NoteContainer(chords[i]) l = Note(c[0].name) p = c[1] l.octave_down() print ch.determine(chords[i])[0] # Play chord and lowered first note fluidsynth.play_NoteContainer(c) fluidsynth.play_Note(l) time.sleep(1.0) # Play highest note in chord fluidsynth.play_Note(c[-1]) # 50% chance on a bass note if random() > 0.5: p = Note(c[1].name) p.octave_down() fluidsynth.play_Note(p) time.sleep(0.50) # 50% chance on a ninth if random() > 0.5: l = Note(intervals.second(c[0].name, key)) l.octave_up() fluidsynth.play_Note(l) time.sleep(0.25) # 50% chance on the second highest note if random() > 0.5: fluidsynth.play_Note(c[-2]) time.sleep(0.25) fluidsynth.stop_NoteContainer(c) fluidsynth.stop_Note(l) fluidsynth.stop_Note(p) i += 1 print "-" * 20
def respell_and_determine(chord): named_chords = [chords.determine(chord)] if len(named_chords[0]) == 0: named_chords = [] candidates = list(set(chord) & set(list(synonyms.keys()) + list(synonyms.values()))) for i in range(0, len(candidates)): combs = combinations(candidates, i+1) for comb in combs: respelling = chord.copy() for to_syn in comb: respelling[respelling.index(to_syn)] = synonyms[to_syn] if chords.determine(respelling) != []: named_chords.append(chords.determine(respelling)) return named_chords
def chordname(chord, numeral=None): s = "" if numeral: s = numeral + " - " s += " :: ".join(ch.determine([x.name for x in chord], True)) s += " -- " + " ".join([x.name for x in chord]) return s
def play_note(note): """play_note determines the coordinates of a note on the keyboard image and sends a request to play the note to the fluidsynth server""" global text octave_offset = (note.octave - LOWEST) * width if note.name in WHITE_KEYS: # Getting the x coordinate of a white key can be done automatically w = WHITE_KEYS.index(note.name) * white_key_width w = w + octave_offset # Add a list containing the x coordinate, the tick at the current time # and of course the note itself to playing_w playing_w.append([w, tick, note]) else: # For black keys I hard coded the x coordinates. It's ugly. i = BLACK_KEYS.index(note.name) if i == 0: w = 18 elif i == 1: w = 58 elif i == 2: w = 115 elif i == 3: w = 151 else: w = 187 w = w + octave_offset playing_b.append([w, tick, note]) # To find out what sort of chord is being played we have to look at both the # white and black keys, obviously: notes = playing_w + playing_b notes.sort() notenames = [] for n in notes: notenames.append(n[2].name) # Determine the chord det = chords.determine(notenames) if det != []: det = det[0] else: det = '' # And render it onto the text surface t = font.render(det, 2, (0, 0, 0)) text.fill((255, 255, 255)) text.blit(t, (0, 0))
def test_determine(self): map(lambda x: self.assertEqual(True, \ chords.determine(chords.from_shorthand("C" + x)) != [],\ "'C%s' should return a value" % x), \ chords.chord_shorthand.keys()) map(lambda x: self.assertEqual("C" + \ chords.chord_shorthand_meaning[x],\ chords.determine(chords.from_shorthand("C" + x))[0], \ "The proper naming of '%s' is not '%s',"\ "expecting '%s'" % ("C" + x, \ chords.determine(chords.from_shorthand("C" + x)), \ "C" + chords.chord_shorthand_meaning[x])),\ [x for x in chords.chord_shorthand.keys() if \ x != '5']) self.chordsTest([ [['A13'], ['A', 'C#', 'E', 'G', 'B', 'D', 'F#']],\ [['Am13'], ['A', 'C', 'E', 'G', 'B', 'D', 'F#']],\ [['AM13'], ['A', 'C#', 'E', 'G#', 'B', 'D', 'F#']]],\ lambda x: chords.determine(x, True), "chord name")
def play_note(note): """play_note determines the coordinates of a note on the keyboard image and sends a request to play the note to the fluidsynth server""" global text octave_offset = (note.octave - LOWEST) * width if note.name in WHITE_KEYS: # Getting the x coordinate of a white key can be done automatically w = WHITE_KEYS.index(note.name) * white_key_width w = w + octave_offset # Add a list containing the x coordinate, the tick at the current time and # of course the note itself to playing_w playing_w.append([w, tick, note]) else: # For black keys I hard coded the x coordinates. It's ugly. i = BLACK_KEYS.index(note.name) if i == 0: w = 18 elif i == 1: w = 58 elif i == 2: w = 115 elif i == 3: w = 151 else: w = 187 w = w + octave_offset playing_b.append([w, tick, note]) # To find out what sort of chord is being played we have to look # at both the white and black keys, obviously: notes = playing_w + playing_b notes.sort() notenames = [] for n in notes: notenames.append(n[2].name) # Determine the chord det = chords.determine(notenames) if det != []: det = det[0] else: det = "" # And render it onto the text surface t = font.render(det, 2, (0,0,0)) text.fill((255,255,255)) text.blit(t, (0,0)) # Play the note fluidsynth.play_Note(note, channel, 100)
def numerals_list_to_shorthand_list(numerals, key='C'): ''' Convert numerals (e.g. ['IIm7', 'V7', 'IM7']) to shorthand (e.g. ['Dm7', 'Gdom7', 'CM7']) with optional choice of key (default is C) ''' chord_notes = [ progressions.to_chords(chord, key=key)[0] for chord in numerals ] # chords as individual Notes like [['C','E','G','B'],...] return [ chords.determine(chord, shorthand=True)[0] for chord in chord_notes ] # shorthand e.g. ['CM7',...]
def test_determine(self): list( map( lambda x: self.assertEqual( True, chords.determine(chords.from_shorthand('C' + x)) != [], "'C%s' should return a value" % x), list(chords.chord_shorthand.keys()))) list( map( lambda x: self.assertEqual( 'C' + chords.chord_shorthand_meaning[x], chords.determine(chords.from_shorthand('C' + x))[0], "The proper naming of '%s' is not '%s',expecting '%s'" % ('C' + x, chords.determine(chords.from_shorthand('C' + x)), 'C' + chords.chord_shorthand_meaning[x])), [x for x in list(chords.chord_shorthand.keys()) if x != '5'])) self.chordsTest([[['A13'], [ 'A', 'C#', 'E', 'G', 'B', 'D', 'F#', ]], [['Am13'], [ 'A', 'C', 'E', 'G', 'B', 'D', 'F#', ]], [['AM13'], [ 'A', 'C#', 'E', 'G#', 'B', 'D', 'F#', ]]], lambda x: chords.determine(x, True), 'chord name')
def play_smart_example(): progression = ["I", "vi", "ii", "iii7", "I7", "viidom7", "iii7", "V7"] key = 'C' chord_list = progressions.to_chords(progression, key) for i in range(len(chord_list)): chord_list[i] = chords.determine(chord_list[i], shorthand=True)[0] # print(chord_list[i]) while True: play_smart_solo_over_chords(chord_list)
def play_example(key): progression = ["I", "vi", "ii", "iii7", "I7", "viidom7", "iii7", "V7"] # key = 'C' chord_list = progressions.to_chords(progression, key) fluidsynth.set_instrument(13, 45) fluidsynth.set_instrument(10, 24) while True: for chord in chord_list: play_solo_bar_with_chord(chords.determine(chord, shorthand=True)[0])
def getChordFromNotes(notes): chords = {} for notelist in itertools.permutations(notes): notelist = list(notelist) chord = minguschords.determine(notelist, True) if len(chord) == 0: continue if chord[0] not in chords: chords[chord[0]] = 0 chords[chord[0]] += 1 sorted_d = sorted(chords.items(), key=operator.itemgetter(1)) try: c = sorted_d[0][0] if c == "perfect fourth" or c == "perfect fifth": c = notes[0] + c return c except: return "".join(notes)
def chord_practice(): minutes_to_practice = pyip.inputInt( prompt="How many minutes do you want to practice? ", min=1) seconds_between = pyip.inputFloat( prompt="How many rest seconds you want between chords? ", min=1) start_time = time() while (True): chosen_chord = choice(choice(scales_content['scales'])['chords']) determined_chord = chords.determine(chosen_chord, True) if determined_chord: print(f"\t{chosen_chord} - {determined_chord[0]}") else: print(f"\t{chosen_chord}") sleep(seconds_between) if (time() - start_time) >= minutes_to_practice * 60: break
def parse_chord(a_chord): """ PENDING: - compute semitones between notes of the chord - according to the semitones between the previous note and the previous note first name(ex C,D#) choose the current note (ex if C -> E, if B -> D# establish some priority: 1. first I,III,V,VII 2. then II,IV,VI """ #print(a_chord) root = a_chord[0][0] foundi = degrees.index(root[0]) ld = len(degrees) the_degrees = [ degrees[foundi], degrees[(foundi+2)%ld], degrees[(foundi+4)%ld], degrees[(foundi+6)%ld], ] #print(the_degrees) parsed_chord = [a_chord[0]] for i in range(1,len(a_chord)): #print("match",the_degrees[i]," in",a_chord[i]) for synonym in a_chord[i]: if synonym.lower()[0] == the_degrees[i].lower(): parsed_chord.append(synonym) break return chords.determine(parsed_chord), parsed_chord
Created on Jan 6, 2017 @author: stephenkoh ''' import mingus.core.chords as chords import mingus.core.keys as keys #all_triads = [] print('TRIADS') for i in range(len(keys.keys)): for elem in keys.keys[i]: print('\n%s' % elem) triads = chords.triads(elem) for triad in triads: typ = chords.determine(triad) for each in typ: print(each) ''' all_triads = list(set(all_triads)) all_triads.sort() print("\nTypes of triads naturally occurring:\n") for elem in all_triads: print(elem) ''' #all_sevenths = [] print('\nSEVENTHS:') for i in range(len(keys.keys)): for elem in keys.keys[i]: print('\n%s' % elem)
def determine(self, shorthand=False): """Determine the type of chord or interval currently in the container.""" return chords.determine(self.get_note_names(), shorthand)
''' Created on Jan 6, 2017 @author: stephenkoh ''' import mingus.core.chords as chords key = str(input('Please enter a key: ')) triads = chords.triads(key) print('\nTriads shorthand:') for elem in triads: print(chords.determine(elem, True)[0]) sevenths = chords.sevenths(key) print('\nSevenths shorthand:') for elem in sevenths: print(chords.determine(elem, True)[0])
def determine(chord, key, shorthand=False): """Determine the harmonic function of chord in key. This function can also deal with lists of chords. Examples: >>> determine(['C', 'E', 'G'], 'C') ['tonic'] >>> determine(['G', 'B', 'D'], 'C') ['dominant'] >>> determine(['G', 'B', 'D', 'F'], 'C', True) ['V7'] >>> determine([['C', 'E', 'G'], ['G', 'B', 'D']], 'C', True) [['I'], ['V']] """ result = [] # Handle lists of chords if type(chord[0]) == list: for c in chord: result.append(determine(c, key, shorthand)) return result func_dict = { 'I': 'tonic', 'ii': 'supertonic', 'iii': 'mediant', 'IV': 'subdominant', 'V': 'dominant', 'vi': 'submediant', 'vii': 'subtonic', } expected_chord = [ ['I', 'M', 'M7'], ['ii', 'm', 'm7'], ['iii', 'm', 'm7'], ['IV', 'M', 'M7'], ['V', 'M', '7'], ['vi', 'm', 'm7'], ['vii', 'dim', 'm7b5'], ] type_of_chord = chords.determine(chord, True, False, True) for chord in type_of_chord: name = chord[0] # Get accidentals a = 1 for n in chord[1:]: if n == 'b': name += 'b' elif n == '#': name += '#' else: break a += 1 chord_type = chord[a:] # Determine chord function (interval_type, interval) = intervals.determine(key, name).split(' ') if interval == 'unison': func = 'I' elif interval == 'second': func = 'ii' elif interval == 'third': func = 'iii' elif interval == 'fourth': func = 'IV' elif interval == 'fifth': func = 'V' elif interval == 'sixth': func = 'vi' elif interval == 'seventh': func = 'vii' # Check whether the chord is altered or not for x in expected_chord: if x[0] == func: # Triads if chord_type == x[1]: if not shorthand: func = func_dict[func] elif chord_type == x[2]: # Sevenths if shorthand: func += '7' else: func = func_dict[func] + ' seventh' else: # Other if shorthand: func += chord_type else: func = func_dict[func]\ + chords.chord_shorthand_meaning[chord_type] # Handle b's and #'s (for instance Dbm in key C is bII) if shorthand: if interval_type == 'minor': func = 'b' + func elif interval_type == 'augmented': func = '#' + func elif interval_type == 'diminished': func = 'bb' + func else: if interval_type == 'minor': func = 'minor ' + func elif interval_type == 'augmented': func = 'augmented ' + func elif interval_type == 'diminished': func = 'diminished ' + func # Add to results result.append(func) return result
''' Created on Jan 6, 2017 @author: stephenkoh ''' import mingus.core.chords as chords key = input('Please enter a key: ') song = [lambda x: chords.I(x), lambda x: chords.IV(x), lambda x: chords.V(x), lambda x: chords.I(x)] for i in range(len(song)): print(chords.determine(song[i](key), True)[0])
'iii7', 'V7', ] key = 'C' chords = progressions.to_chords(progression, key) if not fluidsynth.init(SF2): print("Couldn't load soundfont", SF2) sys.exit(1) while 1: i = 0 for chord in chords: c = NoteContainer(chords[i]) l = Note(c[0].name) p = c[1] l.octave_down() print(ch.determine(chords[i])[0]) # Play chord and lowered first note fluidsynth.play_NoteContainer(c) fluidsynth.play_Note(l) time.sleep(1.0) # Play highest note in chord fluidsynth.play_Note(c[-1]) # 50% chance on a bass note if random() > 0.50: p = Note(c[1].name)
if not fluidsynth.init(SF2): print "Couldn't load soundfont", SF2 sys.exit(1) chords = progressions.to_chords(progression, key) loop = 1 while loop < song_end: i = 0 if random_solo_channel: solo_channel = choice(range(5, 8) + [11]) for chord in chords: c = NoteContainer(chords[i]) l = Note(c[0].name) n = Note('C') l.octave_down() l.octave_down() print ch.determine(chords[i])[0] if not swing and play_chords and loop > chord_start and loop\ < chord_end: fluidsynth.play_NoteContainer(c, chord_channel, randrange(50, 75)) if play_chords and loop > chord_start and loop < chord_end: if orchestrate_second: if loop % 2 == 0: fluidsynth.play_NoteContainer(c, chord_channel2, randrange(50, 75)) else: fluidsynth.play_NoteContainer(c, chord_channel2, randrange(50, 75)) if double_time: beats = [random() > 0.5 for x in range((loop % 2 + 1) * 8)]
# 3.8 triad pairs (hexatonics) key = 'D' scale_choice = 'major' triad_pair = [1,2] # 1 = I chord, 2 = II chord, etc. triad_notes = [[1+i,3+i,5+i] for i in range(7)] # restrict to a 7 note scale by getting note patterns which extend to higher octaves, then mapping back to scale degrees # equivalently could calculate using [((n-1)%7)+1 for t in triad_notes for n in t] triad_notes_norm = [note_to_scale_degree(note, 'C', scale_choice) for note in get_scale_patterns(scale_choice, [n for t in triad_notes for n in t])['C'][0]] triad_notes_norm = [[t[0],t[1],t[2]] for t in [triad_notes_norm[3*i:3*i+3] for i in range(7)]] # unpack to same nested format from mingus.core.chords import determine triad1 = get_scale_patterns(scale_choice, p=triad_notes_norm[triad_pair[0]-1], keys=[key])[key][0] triad2 = get_scale_patterns(scale_choice, p=triad_notes_norm[triad_pair[1]-1], keys=[key])[key][0] triad1_name = determine([n.name for n in triad1])[0] triad2_name = determine([n.name for n in triad2])[0] # print(f'Choices are {triad1_name} and {triad2_name}') # TODO: generate some triad pair patterns # 3.9 chromatic cells scale_choice = 'chromatic' keys = ['C']#cycle_of_fifths() p = ['1', '7', 'b7', '7'] scale = get_scale(scale_choice, key='C') chrom_to_pattern = {note_to_scale_degree(note, 'C', 'chromatic'): i for i, note in enumerate(scale)} exercises[17] = get_scale_patterns(scale_choice, p=[chrom_to_pattern[note]+1 for note in p], keys=keys)
def ending(first_track, second_track, subject, key=r""): if not bool(key): key = 'C' canon_subject = shift(subject, 2) cadence = [chord.I(key), chord.IV(key), chord.V(key), chord.I(key)] notes = [] for note in canon_subject[-1]: if note[-1][0].name not in notes: notes.append(note[-1][0].name) bar = Bar(key=key) # Hitta om det finns ett ackord med de sista noterna i subjektet i, i så fall, komplettera det ackordet if len(notes) <= 2 or len(chord.determine(notes, True)) == 0: chord_notes = [intervals.fourth(notes[0], key)] else: subject_chord = chord.determine(notes, True)[0] chord_notes = chord.from_shorthand(subject_chord) if len(chord_notes) != len(notes): for note in notes: chord_notes.remove(note) else: chord_notes = chord_notes[0] bar.place_notes(chord_notes[random.randint(0, len(chord_notes) - 1)], 2) first_track.add_bar( bar) #Sätt något som passar med andra hälften av subjektet while second_track[ -1].current_beat < 1: #Placing fitting notes in second to last bar #print('test1') duration = 2**random.randint(1, 3) pitch = cadence[0][random.randint(1, len(cadence[0]) - 1)] # If the randomized duration doesn't fit in the bar, make it fit if 1 / duration > 1 - second_track[-1].current_beat: duration = 1 / (1 - second_track[-1].current_beat) # Place the new note in the bar second_track[-1].place_notes(pitch, duration) first_track[-1].place_notes(cadence[0][0], 2) bar = Bar(key=key) bar.place_notes(cadence[1][0], 2) bar.place_notes(cadence[2][0], 2) first_track.add_bar(bar) bar = Bar(key=key) bar.place_notes(cadence[3][0], 1) first_track.add_bar(bar) bar = Bar(key=key) while bar.current_beat < 0.5: #print('test2') # Randomize pitch and duration of each note. duration = 2**random.randint(1, 3) pitch = cadence[1][random.randint(1, len(cadence[1]) - 1)] # If the randomized duration doesn't fit in the bar, make it fit if 1 / duration > 1 - bar.current_beat: duration = 1 / (1 - bar.current_beat) # Place the new note in the bar bar.place_notes(pitch, duration) while bar.current_beat < 1: #print('test3') duration = 2**random.randint(1, 3) pitch = cadence[2][random.randint(1, len(cadence[2]) - 1)] # If the randomized duration doesn't fit in the bar, make it fit if 1 / duration > 1 - bar.current_beat: duration = 1 / (1 - bar.current_beat) # Place the new note in the bar bar.place_notes(pitch, duration) second_track.add_bar(bar) bar = Bar(key=key) bar.place_notes(cadence[3][2], 1) second_track.add_bar(bar)
split_points = [5, 9, 13, 17, 21, 25, 29, 33, 36.5, 40.5, 45, 49, 53] # bar numbers shared_tags = ['251', 'major', 'jiminpark'] individual_tags = [[] for i in range(9)] + 2 * [['pickup']] + [ [] for i in range(3) ] # i'th lick receives i'th element (tags) print(y_comp.tracks[1]) print(get_chords_from_track(y_comp.tracks[1])) licks = licks_from_track(y_comp.tracks[2], get_chords_from_track(y_comp.tracks[1]), split_points, shared_tags, individual_tags) print(licks[0].chords) # for _, lick in enumerate(licks): # lick.store(db) licks[0].store(db) if __name__ == '__main__': # main() from sidewinder.lick_library import Bars_from_list, Track_from_list tr = Track_from_list( Bars_from_list([[[0.0, 2.0, ['G-5', 'A#-5', 'D-6', 'F-6']], [0.5, 2.0, ['F-5', 'G-5', 'A-5', 'C-6']]]])) print(get_chords_from_track(tr)) import mingus.core.chords as chords print(chords.determine(['F', 'G', 'A', 'C']))
def generate_accompaniment(net_output_chords): generated_chords = [] chords = [] for chord in net_output_chords: root, key = (chord.split(":")) print(root, key) if key == 'maj': chords.append(ch.major_triad(root)) if key == 'min': chords.append(ch.minor_triad(root)) print(chords) key = chords[0][0] print('key', key) if not fluidsynth.init(SF2): print("Couldn't load soundfont", SF2) sys.exit(1) print(dir(fluidsynth.midi)) # fluidsynth.midi.start_audio_output() fluidsynth.midi.start_recording() phrase = 0 while phrase == 0: i = 0 for chord in chords: print("chord", chord) c = NoteContainer(chords[i]) generated_chords.append([{'note':cc.name.replace("B#","B").replace("E#","E").replace("##","#"), 'octave':cc.octave} for cc in c]) l = Note(c[0].name) p = c[1] l.octave_down() print(ch.determine(chords[i])[0]) # Play chord and lowered first note # fluidsynth.midi.MidiFileOut.write_NoteContainer("test.mid", c) print("NEW CHORD = ", c) if PLAY_ENABLED: fluidsynth.play_NoteContainer(c) fluidsynth.play_Note(l) time.sleep(1.0) # Play highest note in chord fluidsynth.play_Note(c[-1]) # 50% chance on a bass note if random() > 0.50: p = Note(c[1].name) p.octave_down() fluidsynth.play_Note(p) time.sleep(0.50) # 50% chance on a ninth if random() > 0.50: l = Note(intervals.second(c[0].name, key)) l.octave_up() fluidsynth.play_Note(l) time.sleep(0.25) # 50% chance on the second highest note if random() > 0.50: fluidsynth.play_Note(c[-2]) time.sleep(0.25) fluidsynth.stop_NoteContainer(c) fluidsynth.stop_Note(l) fluidsynth.stop_Note(p) i += 1 print("-" * 20) phrase = 1 return generated_chords
def chord_symbol(chord): return chords.determine(chord, shorthand=True)[0]
def determine(chord, key, shorthand=False): """Determine the harmonic function of chord in key. This function can also deal with lists of chords. Examples: >>> determine(['C', 'E', 'G'], 'C') ['tonic'] >>> determine(['G', 'B', 'D'], 'C') ['dominant'] >>> determine(['G', 'B', 'D', 'F'], 'C', True) ['V7'] >>> determine([['C', 'E', 'G'], ['G', 'B', 'D']], 'C', True) [['I'], ['V']] """ result = [] # Handle lists of chords if isinstance(chord[0], list): for c in chord: result.append(determine(c, key, shorthand)) return result func_dict = { "I": "tonic", "ii": "supertonic", "iii": "mediant", "IV": "subdominant", "V": "dominant", "vi": "submediant", "vii": "subtonic", } expected_chord = [ ["I", "M", "M7"], ["ii", "m", "m7"], ["iii", "m", "m7"], ["IV", "M", "M7"], ["V", "M", "7"], ["vi", "m", "m7"], ["vii", "dim", "m7b5"], ] type_of_chord = chords.determine(chord, True, False, True) for chord in type_of_chord: name = chord[0] # Get accidentals a = 1 for n in chord[1:]: if n == "b": name += "b" elif n == "#": name += "#" else: break a += 1 chord_type = chord[a:] # Determine chord function (interval_type, interval) = intervals.determine(key, name).split(" ") if interval == "unison": func = "I" elif interval == "second": func = "ii" elif interval == "third": func = "iii" elif interval == "fourth": func = "IV" elif interval == "fifth": func = "V" elif interval == "sixth": func = "vi" elif interval == "seventh": func = "vii" # Check whether the chord is altered or not for x in expected_chord: if x[0] == func: # Triads if chord_type == x[1]: if not shorthand: func = func_dict[func] elif chord_type == x[2]: # Sevenths if shorthand: func += "7" else: func = func_dict[func] + " seventh" else: # Other if shorthand: func += chord_type else: func = func_dict[ func] + chords.chord_shorthand_meaning[chord_type] # Handle b's and #'s (for instance Dbm in key C is bII) if shorthand: if interval_type == "minor": func = "b" + func elif interval_type == "augmented": func = "#" + func elif interval_type == "diminished": func = "bb" + func else: if interval_type == "minor": func = "minor " + func elif interval_type == "augmented": func = "augmented " + func elif interval_type == "diminished": func = "diminished " + func # Add to results result.append(func) return result
def generate_melody(with_chords, repetitions=1): use_custom_scale = pyip.inputYesNo( prompt="Do you want to use a custom scale? (y/n) ") possible_chords = [] if use_custom_scale == "yes": scale_input = input( """Insert the notes from the scale separated by a space, do not use flats, only sharps. \t\tExample: C D E F# A\n""") chosen_scale = scale_input.upper().split() for x in range(len(chosen_scale) + 1): combinations_object = combinations(chosen_scale, x) combinations_list = list(combinations_object) possible_chords += combinations_list for _ in range(len(chosen_scale) + 1): del possible_chords[0] get_random_scale = False use_custom_scale = True else: get_random_scale = True use_custom_scale = False try: determined_scale = scales.determine(chosen_scale)[0] except: determined_scale = "" amount_of_notes = pyip.inputInt( prompt="How many notes do you want for this melody? ", min=1) if with_chords: chords_each_x = pyip.inputInt( prompt="How many notes you want between chords? ", min=1) chord_in_note = [x for x in range(0, amount_of_notes, chords_each_x)] for _ in range(repetitions): melody_name = generate_random_name() melody_path = f"Melodies/{melody_name}" os.mkdir(melody_path) track = 0 channel = 0 time = 0 duration = 1 tempo = 120 volume = 100 midi_melody = MIDIFile(1) midi_melody.addTempo(track, time, tempo) if get_random_scale: chosen_scale = choice(scales_content["scales"]) possible_chords = chosen_scale["chords"] chosen_scale = chosen_scale["scale"] ly_string = r'''\version "2.20.0" \header{title = "PLACEHOLDER_NAME" subtitle = "PLACEHOLDER_SUBTITLE" tagline = ##f} \score { { ''' ly_string = ly_string.replace("PLACEHOLDER_NAME", melody_name) ly_string = ly_string.replace( "PLACEHOLDER_SUBTITLE", f"{str(chosen_scale)} - {determined_scale}") print( f"\nGenerating melody with scale: {chosen_scale} - {determined_scale}\n" ) print(f"\t****{melody_name}****") all_parts = [] for i in range(amount_of_notes): if with_chords: if i in chord_in_note: if i != 0: time += duration chosen_chord = choice(possible_chords) chosen_chord = chosen_chord[:3] try: determined_chord = chords.determine( list(chosen_chord))[0] except: determined_chord = "" ly_string += "\n< " for note in chosen_chord: ly_string += f"{note_to_ly(note)}' " note_midi_value = int(Note(note)) + 12 midi_melody.addNote(track, channel, note_midi_value, time, duration, volume) ly_string += ">\n\n" all_parts.append( f"\n\t{chosen_chord} - {determined_chord}\n") chosen_note = choice(chosen_scale) ly_string += f"{note_to_ly(chosen_note)}4' " note_midi_value = int(Note(chosen_note)) + 12 midi_melody.addNote(track, channel, note_midi_value, time + duration, duration, volume) time += duration all_parts.append(f"\t{chosen_note}") ly_string += """} \layout { } \midi { } }""" with open(f"{melody_path}/{melody_name}.txt", "w") as f: for part in all_parts: f.write(f"{part}\n") print(part) with open(f"{melody_path}/{melody_name}_pond.ly", "w") as f: f.write(ly_string) with open(f"{melody_path}/{melody_name}.mid", "wb") as f: midi_melody.writeFile(f)