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
Beispiel #2
0
 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),
     }
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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)
Beispiel #8
0
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
Beispiel #9
0
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