def add_new_root_notes(notes: List[str], on: str, base_oct: int = 3): if musthe.Note(notes[0]).number > musthe.Note(f"{on}{base_oct}").number: adjust = 0 else: adjust = -1 notes.insert(0, f"{on}{base_oct + adjust}") return notes
def my_chorus(chord_progression, length, num=1, velocity=80, channel=0): """ :param chord_progression: the chord progression, chould be a list or str :param length: the beat :param num: the times of repetition :param velocity: 0~127,the velocity of chord :param channel:0~12 :return: """ d = {'C': 1, 'D': 2, 'E': 3, 'F': 4, 'G': 5, 'A': 6, 'B': 7} all_note = [] if type(chord_progression) == list: # 如果来的是一个列表,就是几个和弦 for chord in chord_progression: note = [] if chord[1:len(chord)]: temp = musthe.Chord(musthe.Note(chord[0]), chord[1:len(chord)]).notes else: temp = musthe.Chord(musthe.Note(chord[0])).notes for i in range(len(temp)): note.append(d[str(temp[i])]) all_note.append(note) else: # 如果来的只有一个和弦 note = [] if chord_progression[1:len(chord_progression)]: temp = musthe.Chord(musthe.Note(chord_progression[0]), chord_progression[1:len(chord_progression)]).notes else: temp = musthe.Chord(musthe.Note(chord_progression[0])).notes for i in range(len(temp)): note.append(d[str(temp[i])]) all_note.append(note) major_notes = [0, 2, 2, 1, 2, 2, 2, 1] base_note = 60 base_num = 0 delay = 0 bpm = 100 meta_time = 60000 / bpm for chord_note in all_note: for j in range(num): count = 0 for note in chord_note: track.append(Message('note_on', note=base_note + base_num * 12 + sum(major_notes[0:note]), velocity=velocity if count else velocity + 10, time=round(delay * meta_time), channel=channel)) for note in chord_note: track.append(Message('note_off', note=base_note + base_num * 12 + sum(major_notes[0:note]), velocity=velocity if count else velocity + 10, time=0 if count else round(0.96 * meta_time * length), channel=channel)) count = count + 1
def change(num, key, mode, count=3): """ change the chord from number to str. example: in C major, 1 change to ['C', 'E', 'G'] :param num: the progression number, should be int from 1~7. :param key: char, the first note of scale,could be C D E F G A B. :param mode: see doc of class Impromptu. :param count: default 3, could be 3, 4 or 5, corresponding triad, seventh chord and hord of the ninthc. :return: """ d = {'C': 1, 'D': 2, 'E': 3, 'F': 4, 'G': 5, 'A': 6, 'B': 7} result = [] try: if type(num) == int and 0 < num < 8: s = musthe.Scale(musthe.Note(key), mode) scale = [] for i in range(len(s)): scale.append(str(s[i])) for i in range(count): result.append(d[scale[(num - 1 + 2 * i) % 7]]) else: raise TypeError('num should be int from 1~7.') except NameError: return change(num, key, mode='aeolian', count=count) return result
def get_scale_idx(note, key): scale = theory.Scale(key[0], key[1]) for i in range(7): # print scale.__getitem__(i) if scale.__getitem__(i).letter.__eq__(theory.Note(note).letter): return i + 1 raise ValueError("note ", note, " not in scale ", key)
def get_chord_options(note, key): scale = theory.Scale(theory.Note(key[0]), key[1]) scale_idx_1 = get_scale_idx(note, key) scale_idx_2 = scale_idx_1 - 2 scale_idx_3 = scale_idx_1 - 4 options = [scale_idx_1, scale_idx_2, scale_idx_3] for i in range(len(options)): if options[i] <= 0: options[i] += 7 # print "chord options are ", sorted(options) return sorted(options)
def up_octave(note) -> str: return (musthe.Note(note) + musthe.Interval("P8")).scientific_notation()
def harmonic_random(reffile): chords = [] lf = open(reffile) nf = open(reffile) for line in lf: label, value, time = line.split() if random.randint(1,10) <= 3: continue time = datetime.strptime(time, '%H:%M:%S.%f') chord = gen_rand_chord() chords.append((pychord.Chord(chord), time)) chord_groups = [[] for c in chords] for line in nf: label, value, time = line.split() if label != 'NOTE': continue time = datetime.strptime(time, '%H:%M:%S.%f') if time < chords[0][1]: continue for i in range(len(chords)-1): if chords[i][1] <= time < chords[i+1][1]: chord_groups[i].append(value[:-1]) break else: assert chords[-1][1] <= time chord_groups[-1].append(value[:-1]) bad_notes = 0 total_notes = 0 for i in range(len(chords)): chord = chords[i][0] notes = chord_groups[i] quality = chord.quality.quality if quality in major_quals: quality = 'major' elif quality in minor_quals: quality = 'natural_minor' else: quality = None if quality: scale = musthe.Scale(musthe.Note(chord.root), quality) scale_notes = [str(scale[i]) for i in range(len(scale))] else: scale = [] for i in range(len(notes)): lower = max(0, i-HARMONIC_WINDOW) upper = min(len(notes)-1, i+HARMONIC_WINDOW) relevant_notes = [notes[j] for j in range(lower, upper+1)] for note in relevant_notes: if note in chord.components():# or musthe.Note(note) in scale: break else: bad_notes += 1 total_notes += len(notes) # print('{:>8}'.format(f'{bad_notes}/{total_notes}\t'), end='') # print(f'{bad_notes/total_notes*100:.0f}% error') return bad_notes / total_notes