Example #1
0
def check_unresolved_leaps(voice):
    """Raises an error if a voice does not resolve its leap.

    >>> from music21 import note, stream
    >>> soprano = stream.Part(map(note.Note, ['C5', 'F5', 'E5']))
    >>> alto = stream.Part(map(note.Note, ['G4', 'D4', 'C4']))
    >>> check_unresolved_leaps(soprano)
    >>> check_unresolved_leaps(alto)
    Traceback (most recent call last):
    ...
    errors.UnresolvedLeapError: Found unresolved leap at index 2
    """
    previous_note, must_resolve = None, 0
    for i, current_note in enumerate(voice):
        if previous_note == current_note:
            pass
        elif must_resolve:
            test_interval = interval.notesToGeneric(previous_note, current_note)
            if test_interval.directed != must_resolve:
                raise UnresolvedLeapError(i)
            must_resolve = 0
        elif i > 0:
            test_interval = interval.notesToGeneric(previous_note, current_note)
            if test_interval.undirected >= 4:
                must_resolve = -2*test_interval.directed//test_interval.undirected
        previous_note = current_note
Example #2
0
def check_direct_octaves(bass, soprano):
    """Raises an error if two voices contain direct octaves.

    >>> from music21 import note, stream
    >>> soprano = stream.Part(map(note.Note, ['C5', 'D5', 'E5']))
    >>> bass = stream.Part(map(note.Note, ['E3', 'D3', 'A3']))
    >>> check_direct_octaves(bass, soprano)
    >>> soprano = stream.Part(map(note.Note, ['E5', 'E5', 'A5']))
    >>> check_direct_octaves(bass, soprano)
    Traceback (most recent call last):
    ...
    errors.DirectOctavesError: Found direct octave at index 2
    """
    if len(bass) <= 1:
        return
    for i, (bass_note, soprano_note) in enumerate(zip(bass, soprano)):
        is_p8 = helpers.is_perfect_octave(bass_note, soprano_note)
        if is_p8 and i > 0:
            bass_interval = interval.notesToGeneric(bass[i-1], bass_note).directed
            soprano_interval = interval.notesToGeneric(soprano[i-1], soprano_note).directed
            if soprano_interval * bass_interval > 0 and abs(soprano_interval) > 2:
                raise DirectOctavesError(i)
Example #3
0
def check_spacing(lower_voice, upper_voice):
    """Raises an error if the interval between two voices exceeds an octave.

    >>> from music21 import note, stream
    >>> soprano = stream.Part(map(note.Note, ['C5', 'D5', 'E5']))
    >>> alto = stream.Part(map(note.Note, ['A4', 'B4', 'A4']))
    >>> tenor = stream.Part(map(note.Note, ['A3', 'G3', 'A3']))
    >>> check_spacing(alto, soprano)
    >>> check_spacing(tenor, alto)
    Traceback (most recent call last):
    ...
    errors.SpacingError: Found spacing error at index 1
    """
    for i, (lower_note, upper_note) in enumerate(zip(lower_voice, upper_voice)):
            if interval.notesToGeneric(lower_note, upper_note).undirected > 8:
                raise SpacingError(i)
Example #4
0
def is_fourth(lower_note, upper_note):
    """Returns whether the interval between two given notes reduced to an octave is a is_fourth.

    >>> from music21 import note
    >>> c4 = note.Note('C4')
    >>> f4 = note.Note('F4')
    >>> g4 = note.Note('G4')
    >>> is_fourth(c4, f4)
    True
    >>> is_fourth(c4, g4)
    False
    """
    test_interval = interval.notesToGeneric(lower_note, upper_note)
    if test_interval.simpleUndirected == 4:
        return True
    return False
def part_to_codestring(part):
    s = stream.Stream()
    notes = list(part.notes)
    codestring = ''
    for i in range(len(notes) - 2):
        n_0 = notes[i]
        n_1 = notes[i + 1]
        if isinstance(n_0, chord.Chord):
            n_0 = n_0[0]
        if isinstance(n_1, chord.Chord):
            n_1 = n_1[0]

        interval_obj = interval.notesToGeneric(n_0, n_1)
        interval_num = interval_obj.directed
        # print(interval_num)
        codestring += interval_to_codestring(interval_num)
    return codestring
def addChords(score,
              quarterLength=1):
    """
    Inputs provisional chords based on leaps in the melodic line.
    """

    # Raise exception for illegal beatStrengths
    validQuarterLengths = {4, 3, 2, 1.5, 1, 0.5, 0.25}
    if quarterLength not in validQuarterLengths:
        raise ValueError(f'Invalid quarter length: must be one of {validQuarterLengths}.')

    # Prepare dict of offsets and corresponding lists of pitches
    chordDict = {}
    vpr = score.parts[0].recurse()
    for i in range(1, len(vpr.notesAndRests)): # starting pair index = [1] and [0]
        note2 = vpr.notesAndRests[i]
        adjustedBeatPosition = floor(note2.offset / quarterLength) * quarterLength
        # i.e. floor(x * accuracy) / accuracy # signs reversed as < 1
        if adjustedBeatPosition != note2.offset:  # metrically weak enough
            if 'NotRest' in note2.classes:
                note1 = vpr.notesAndRests[i-1]
                if 'NotRest' in note1.classes:
                    if abs(interval.notesToGeneric(note1, note2).directed) > 2: # a leap
                        measureOffset = note2.activeSite.offset
                        offset = measureOffset + adjustedBeatPosition # combined unique value
                        if offset in chordDict.keys():  # Add to existing
                            tempList = [x for x in chordDict[offset][0]]
                            tempList.append(note1.pitch)
                            tempList.append(note2.pitch)
                            chordDict[offset][0] = tempList
                        else:  # Create new entry
                            chordDict[offset] = [[note1.pitch, note2.pitch],
                                                 measureOffset,
                                                 adjustedBeatPosition
                                                 ]

    # Prepare and insert chords
    for x in chordDict.keys():
        noDuplicatesChord = chord.Chord(list(set([y for y in chordDict[x][0]])))
        noDuplicatesChord.quarterLength = quarterLength
        measureOffset = round(chordDict[x][1], 2)  # NB not int
        adjustedBeatPosition = chordDict[x][2]
        finalStep = score.parts[1].getElementsByClass('Measure').getElementsByOffset(measureOffset)[0]
        finalStep.insert(adjustedBeatPosition, noDuplicatesChord)

    return score
Example #7
0
def same_distance(note1, note2):
    if interval.notesToGeneric(note1, note2) == 'P1':
        return 0.2
    else:
        return 1
Example #8
0
def three_steps(note1, note2):
    if interval.notesToGeneric(note1, note2) == 'P4' or 'A4':
        return 0.8
    else:
        return 0
Example #9
0
def two_steps(note1, note2):
    if interval.notesToGeneric(note1, note2) == 'M3' or 'm3':
        return 1
    else:
        return 0
Example #10
0
def one_step(note1, note2):
    if interval.notesToGeneric(note1, note2) == 'M2' or 'm2':
        return 0.7
    else:
        return 0