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 set_opt(self, scale: str = 'B2 major', duration: float = 0.08, show_notes: bool = False, randomize: bool = False, time_between_notes: float = None, show_notes_template: str = '{name} ({freq})'): "Populate config based on given args" if scale in {None, 'all', 'ALL'}: # use all available notes scale = musthe.Note.all(min_octave=2, max_octave=6) # not too high, it hurts else: # valid input: use given scale scale_root, scale_type = scale.split(' ') if ' ' in scale else ( scale, 'major') scale = musthe.Scale(scale_root.upper(), scale_type.lower()) if randomize: scale = list(scale) random.shuffle(scale) else: # sort by making very different notes succeeding each others scale = list(scale) scale = tuple(scale[idx] for idx in right_left_walk(len(scale))) scale = tuple(scale) return { 'scale': scale, 'notes': iter(scale), 'duration': float(duration), 'show_notes': bool(show_notes), 'time_between_notes': time_between_notes, 'show_notes_template': str(show_notes_template), }
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 chord_translate(chord_str: str, scale: int, base_oct: int = 3) -> List[str]: chord_str = chord_str.replace("(", "").replace(")", "") try: chord = pychord.Chord(chord_str) addomit = dict() except ValueError as e: # add omit だけ抜き取りたい chord_without_quality = re.sub(f"^{note}", "", chord_str) valid_qualities = list(pychord.quality.QUALITY_DICT.keys()) valid_qualities.remove("") valid_qualities.sort(key=len, reverse=True) found = False addomit_str = "" for quality in valid_qualities: if chord_without_quality.find(quality) == 0: # 先頭のコードqualityを削除する found = True addomit_str = re.sub(f"^{re.escape(quality)}", "", chord_without_quality) chord = pychord.Chord( re.sub(f"{re.escape(addomit_str)}$", "", chord_str)) break if not found: raise e # TODO: Fix this # Should raise error if removed addomit_str is not empty addomit = { "adds": [r.groups()[-2:] for r in re.finditer(add_regex, addomit_str)], "omits": [r.groups()[-1] for r in re.finditer(omit_regex, addomit_str)], } if len(addomit) > 0: s = musthe.Scale(f"{chord.root}3", "major") adds = addomit.get("adds") omits = addomit.get("omits") for add in adds: align = (add[0].count("#") + add[0].count("+") - add[0].count("b") - add[0].count("-")) adder_note_dict = parse_note_str( transpose(s[int(add[1]) - 1].scientific_notation(), align)) chord.quality.append_note(adder_note_dict["note"], chord._root, int(adder_note_dict["oct"]) - 3) for omit in omits: for o in range(int(omit) - 2, int(omit) + 1): if o in chord.quality.components: chord.quality.components.remove(o) chord.transpose(scale) notes = chord.components_with_pitch(base_oct) return notes
def build_chord(num, key): # print "\n\nBUILDING CHORD: ", num, " chord in ", key scale = theory.Scale(key[0], key[1]) letter = scale[num - 1] if key[1] == 'major': ending = major_chords[num - 1] if key[1] == 'harmonic_minor': ending = minor_chords[num - 1] # print "\nChord is ", letter, ending, '\n\n' return str(letter) + ending
def get_chord_in_scale(idx, key): scale = theory.Scale(key[0], key[1]) root = scale[(idx - 1) % 7] if key[1] == 'major': #return theory.Chord(root, major_chords[idx-1]) return idx if key[1] == 'harmonic_minor': #return theory.Chord(root, minor_chords[idx-1]) return idx
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 get_notes(path, key): tree = ET.parse(path) root = tree.getroot() scale = theory.Scale(key[0], key[1]) P1 = root.find('part') all_notes = [] for measure in P1: for note in measure.findall('note'): if note.find('accidental') is not None: raise ValueError( '\n\nWARNING: sorry mate, no notes outside the key signature for now. check back soon...\n\n' ) elif note.find('pitch') is not None: for i in range(7): if scale[i].letter == note.find('pitch').find('step').text: all_notes.append( str(scale[i].letter) + str(scale[i].accidental)) return all_notes
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