Ejemplo n.º 1
0
def capuaRuleFourB(srcStream):
    '''
    See capuaRuleOne for precise instructions.
    
    Applies more probable interpretation of Capua's fourth rule to the given
    srcStream, i.e. if a descending minor third is followed by a descending major
    second, the intervals will be changed to a major third followed by a minor
    second. Also copies any relevant accidental to note.editorial.misc under
    "saved-accidental" and changes note.editorial.color for rule 4 (orange
    green orange).
    
    returns the number of times a note was changed.
    '''
    numChanged = 0
    ssn = srcStream.flat.notesAndRests
    for i in range(0, len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or \
           n2.isRest or \
           n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if n1.accidental is not None or \
           n3.accidental is not None:
            continue

        ### never seems to improve things...
        if n2.step == "A" or n2.step == "D":
            continue

        # e.g., D F G => D F# G  or G Bb C => G B C
        if i1.directedName  == "m3" and \
           i2.directedName  == "M2":
            numChanged += 1
            if ("capua" in n2.editorial.misc):
                n2.editorial.misc['capua_rule_number'] += RULE_FOUR_B
            else:
                n2.editorial.misc['capua_rule_number'] = RULE_FOUR_B
            if (n2.accidental is not None and n2.accidental.name == "flat"):
                n2.editorial.misc["saved-accidental"] = n2.accidental
                n2.accidental = None
                n2.editorial.ficta = pitch.Accidental("natural")
                n2.editorial.misc["capua-ficta"] = pitch.Accidental("natural")
                n1.editorial.color = "orange"
                n2.editorial.color = "green"
                n3.editorial.color = "orange"
            else:
                n2.editorial.ficta = pitch.Accidental("sharp")
                n2.editorial.misc["capua-ficta"] = pitch.Accidental("sharp")
                n1.editorial.color = "orange"
                n2.editorial.color = "green"
                n3.editorial.color = "orange"

    return numChanged
Ejemplo n.º 2
0
def capuaRuleOne(srcStream):
    '''
    Applies Nicolaus de Capua's first rule to the given srcStream, i.e. if a line descends
    a major second then ascends back to the original note, the major second is
    made into a minor second. Also copies the relevant accidentals into
    `Note.editorial.misc["saved-accidental"]` and changes `Note.editorial.color`
    for rule 1 (blue green blue).
    
    The relevant Rule number is also stored in `Note.editorial.misc['capua_rule_number']` which
    can be got out by OR-ing this.
    
    Returns the number of notes that were changed (not counting notes whose colors were changed).    
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(0, len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if (n1.isRest or n2.isRest or n3.isRest):
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if (n1.pitch.accidental is not None
                or n3.pitch.accidental is not None):
            continue

        ### never seems to improve things...
        if n2.step == "A" or n2.step == "D":
            continue

        ## e.g. G, F, G => G, F#, G
        if i1.directedName == "M-2" and \
           i2.directedName == "M2":
            numChanged += 1
            if ("capua" in n2.editorial.misc):
                n2.editorial.misc['capua_rule_number'] += RULE_ONE
            else:
                n2.editorial.misc['capua_rule_number'] = RULE_ONE
            if (n2.pitch.accidental is not None
                    and n2.pitch.accidental.name == "flat"):
                n2.editorial.misc["saved-accidental"] = n2.pitch.accidental
                n2.pitch.accidental = None
                n2.editorial.ficta = pitch.Accidental("natural")
                n2.editorial.misc["capua-ficta"] = pitch.Accidental("natural")
                n1.editorial.color = "blue"
                n2.editorial.color = "forestGreen"
                n3.editorial.color = "blue"
            else:
                n2.editorial.ficta = pitch.Accidental("sharp")
                n2.editorial.misc["capua-ficta"] = pitch.Accidental("sharp")
                n1.editorial.color = "blue"
                n2.editorial.color = "ForestGreen"
                n3.editorial.color = "blue"

    return numChanged
Ejemplo n.º 3
0
def capuaRuleOne(srcStream):
    '''
    Applies Nicolaus de Capua's first rule to the given srcStream, i.e. if a line descends
    a major second then ascends back to the original note, the major second is
    made into a minor second. Also copies the relevant accidentals into
    `Note.editorial.savedAccidental` and changes `Note.style.color`
    for rule 1 (blue green blue).

    The relevant Rule number is also stored in `Note.editorial.capuaRuleNumber']` which
    can be got out by OR-ing this.

    Returns the number of notes that were changed (not counting notes whose colors were changed).
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or n2.isRest or n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if (n1.pitch.accidental is not None
                or n3.pitch.accidental is not None):
            continue

        # never seems to improve things...
        if n2.step == 'A' or n2.step == 'D':
            continue

        # e.g. G, F, G => G, F#, G
        if (i1.directedName == 'M-2' and i2.directedName == 'M2'):
            numChanged += 1
            if 'capuaRuleNumber' in n2.editorial:
                n2.editorial.capuaRuleNumber += RULE_ONE
            else:
                n2.editorial.capuaRuleNumber = RULE_ONE
            if n2.pitch.accidental is not None and n2.pitch.accidental.name == 'flat':
                n2.editorial.savedAccidental = n2.pitch.accidental
                n2.pitch.accidental = None
                n2.editorial.ficta = pitch.Accidental('natural')
                n2.editorial.capuaFicta = pitch.Accidental('natural')
                n1.style.color = 'blue'
                n2.style.color = 'forestGreen'
                n3.style.color = 'blue'
            else:
                n2.editorial.ficta = pitch.Accidental('sharp')
                n2.editorial.capuaFicta = pitch.Accidental('sharp')
                n1.style.color = 'blue'
                n2.style.color = 'ForestGreen'
                n3.style.color = 'blue'

    return numChanged
Ejemplo n.º 4
0
def capuaRuleFourB(srcStream):
    '''
    See capuaRuleOne for precise instructions.

    Applies more probable interpretation of Capua's fourth rule to the given
    srcStream, i.e. if a descending minor third is followed by a descending major
    second, the intervals will be changed to a major third followed by a minor
    second. Also copies any relevant accidental to note.editorial.savedAccidental
    and changes note.style.color for rule 4 (orange
    green orange).

    returns the number of times a note was changed.
    '''
    numChanged = 0
    ssn = srcStream.flat.notesAndRests
    for i in range(len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or n2.isRest or n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if (n1.pitch.accidental is not None
                or n3.pitch.accidental is not None):
            continue

        # never seems to improve things...
        if n2.step == 'A' or n2.step == 'D':
            continue

        # e.g., D F G => D F# G  or G Bb C => G B C
        if i1.directedName == 'm3' and i2.directedName == 'M2':
            numChanged += 1
            if 'capuaRuleNumber' in n2.editorial:
                n2.editorial.capuaRuleNumber += RULE_FOUR_B
            else:
                n2.editorial.capuaRuleNumber = RULE_FOUR_B
            if n2.pitch.accidental is not None and n2.pitch.accidental.name == 'flat':
                n2.editorial.savedAccidental = n2.pitch.accidental
                n2.pitch.accidental = None
                n2.editorial.ficta = pitch.Accidental('natural')
                n2.editorial.capuaFicta = pitch.Accidental('natural')
                n1.style.color = 'orange'
                n2.style.color = 'green'
                n3.style.color = 'orange'
            else:
                n2.editorial.ficta = pitch.Accidental('sharp')
                n2.editorial.capuaFicta = pitch.Accidental('sharp')
                n1.style.color = 'orange'
                n2.style.color = 'green'
                n3.style.color = 'orange'

    return numChanged
Ejemplo n.º 5
0
def capuaRuleFourA(srcStream):
    '''
    See capuaRuleOne for precise instructions.

    Applies one interpretation of Capua's fourth rule to the given srcStream,
    i.e. if a descending minor third is followed by a descending major second,
    the intervals will be changed to a major third followed by a minor second.
    Also changes note.editorial.color for rule 4 (orange green orange).
    
    returns the number of notes that were changed

    This rule is a less likely interpretation of the ambiguous rule 4, thus
    applyCapuaToStream uses capuaRuleFourB instead.
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(0, len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or \
           n2.isRest or \
           n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if n1.accidental is not None or \
           n2.accidental is not None or \
           n3.accidental is not None:
            continue

        ### never seems to improve things...
        if n2.step == "A" or n2.step == "D":
            continue

        # e.g., D B A => D Bb A
        if i1.directedName  == "m-3" and \
           i2.directedName  == "M-2":
            numChanged += 1
            if ("capua" in n2.editorial.misc):
                n2.editorial.misc['capua_rule_number'] += RULE_FOUR_A
            else:
                n2.editorial.misc['capua_rule_number'] = RULE_FOUR_A
            n2.editorial.ficta = pitch.Accidental("flat")
            n2.editorial.misc["capua-ficta"] = pitch.Accidental("flat")
            n1.editorial.color = "orange"
            n2.editorial.color = "ForestGreen"
            n3.editorial.color = "orange"

    return numChanged
Ejemplo n.º 6
0
def capuaRuleThree(srcStream):
    '''
    See capuaRuleOne for precise instructions.
    
    Applies Capua's third rule to the given srcStream, i.e. if there is a
    descending major third followed by an ascending major second, the second
    note will be made a half-step higher so that there is a descending minor
    third followed by an ascending minor second. Also changes
    note.editorial.color for rule 3 (pink green pink).
    
    returns the number of times a note was changed
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(0, len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or \
           n2.isRest or \
           n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if n1.accidental is not None or \
           n2.accidental is not None or \
           n3.accidental is not None:
            continue

        ### never seems to improve things...
        if n2.step == "A" or n2.step == "D":
            continue

        # e.g., E C D => E C# D
        if i1.directedName  == "M-3" and \
           i2.directedName  == "M2":
            numChanged += 1
            if ("capua" in n2.editorial.misc):
                n2.editorial.misc['capua_rule_number'] += RULE_THREE
            else:
                n2.editorial.misc['capua_rule_number'] = RULE_THREE
            n2.editorial.ficta = pitch.Accidental("sharp")
            n2.editorial.misc["capua-ficta"] = pitch.Accidental("sharp")
            n1.editorial.color = "DeepPink"
            n2.editorial.color = "ForestGreen"
            n3.editorial.color = "DeepPink"

    return numChanged
Ejemplo n.º 7
0
def capuaRuleFourA(srcStream):
    '''
    See capuaRuleOne for precise instructions.

    Applies one interpretation of Capua's fourth rule to the given srcStream,
    i.e. if a descending minor third is followed by a descending major second,
    the intervals will be changed to a major third followed by a minor second.
    Also changes note.style.color for rule 4 (orange green orange).

    returns the number of notes that were changed

    This rule is a less likely interpretation of the ambiguous rule 4, thus
    applyCapuaToStream uses capuaRuleFourB instead.
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or n2.isRest or n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if (n1.pitch.accidental is not None or n2.pitch.accidental is not None
                or n3.pitch.accidental is not None):
            continue

        # never seems to improve things...
        if n2.step == 'A' or n2.step == 'D':
            continue

        # e.g., D B A => D Bb A
        if i1.directedName == 'm-3' and i2.directedName == 'M-2':
            numChanged += 1
            if 'capuaRuleNumber' in n2.editorial:
                n2.editorial.capuaRuleNumber += RULE_FOUR_A
            else:
                n2.editorial.capuaRuleNumber = RULE_FOUR_A
            n2.editorial.ficta = pitch.Accidental('flat')
            n2.editorial.capuaFicta = pitch.Accidental('flat')
            n1.style.color = 'orange'
            n2.style.color = 'ForestGreen'
            n3.style.color = 'orange'

    return numChanged
Ejemplo n.º 8
0
def capuaRuleThree(srcStream):
    '''
    See capuaRuleOne for precise instructions.

    Applies Capua's third rule to the given srcStream, i.e. if there is a
    descending major third followed by an ascending major second, the second
    note will be made a half-step higher so that there is a descending minor
    third followed by an ascending minor second. Also changes
    note.style.color for rule 3 (pink green pink).

    returns the number of times a note was changed
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(len(ssn) - 2):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]

        if n1.isRest or n2.isRest or n3.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)

        if (n1.pitch.accidental is not None or n2.pitch.accidental is not None
                or n3.pitch.accidental is not None):
            continue

        # never seems to improve things...
        if n2.step == 'A' or n2.step == 'D':
            continue

        # e.g., E C D => E C# D
        if (i1.directedName == 'M-3' and i2.directedName == 'M2'):
            numChanged += 1
            if 'capuaRuleNumber' in n2.editorial:
                n2.editorial.capuaRuleNumber += RULE_THREE
            else:
                n2.editorial.capuaRuleNumber = RULE_THREE
            n2.editorial.ficta = pitch.Accidental('sharp')
            n2.editorial.capuaFicta = pitch.Accidental('sharp')
            n1.style.color = 'DeepPink'
            n2.style.color = 'ForestGreen'
            n3.style.color = 'DeepPink'

    return numChanged
Ejemplo n.º 9
0
    def _addAccidental(self, n, alter, pm, t):
        r'''
        helper function for all accidental types.

        >>> nToken = tinyNotation.NoteToken('BB--')
        >>> n = note.Note('B')
        >>> n.octave = 2
        >>> tPost = nToken._addAccidental(n, -2, r'(\-+)', 'BB--')
        >>> tPost
        'BB'
        >>> n.pitch.accidental
        <accidental double-flat>

        >>> nToken = tinyNotation.NoteToken('BB(--)')
        >>> nToken.isEditorial = True
        >>> n = note.Note('B')
        >>> n.octave = 2
        >>> tPost = nToken._addAccidental(n, -2, r'(\-+)', 'BB--')
        >>> tPost
        'BB'
        >>> n.editorial.ficta
        <accidental double-flat>
        '''
        acc = pitch.Accidental(alter)
        if self.isEditorial:
            n.editorial.ficta = acc
        else:
            n.pitch.accidental = acc
        t = re.sub(pm, '', t)
        return t
Ejemplo n.º 10
0
    def testMeasureCopyingB(self):
        from music21 import converter
        from music21 import pitch

        src = """m1 G: IV || b3 d: III b4 ii
m2 v b2 III6 b3 iv6 b4 ii/o6/5
m3 i6/4 b3 V
m4-5 = m2-3
m6-7 = m4-5
"""
        s = converter.parse(src, format='romantext')
        rnStream = s.flat.getElementsByClass('RomanNumeral')

        for elementNumber in [0, 6, 12]:
            self.assertEqual(rnStream[elementNumber + 4].figure, 'III6')
            self.assertEqual(
                str([str(p) for p in rnStream[elementNumber + 4].pitches]),
                "['A4', 'C5', 'F5']")

            x = rnStream[elementNumber + 4].pitches[2].accidental
            if x == None:
                x = pitch.Accidental('natural')
            self.assertEqual(x.alter, 0)

            self.assertEqual(rnStream[elementNumber + 5].figure, 'iv6')
            self.assertEqual(
                str([str(p) for p in rnStream[elementNumber + 5].pitches]),
                "['B-4', 'D5', 'G5']")

            self.assertEqual(
                rnStream[elementNumber +
                         5].pitches[0].accidental.displayStatus, True)
Ejemplo n.º 11
0
    def accidentalFromAlter(self, alterElement):
        '''
        return a :class:`~music21.pitch.Accidental` object from an <alter> tag.
        
        
        >>> ci = capella.fromCapellaXML.CapellaImporter()
        >>> alter = ci.domElementFromText('<alter step="-1"/>')
        >>> ci.accidentalFromAlter(alter)
        <accidental flat>

        The only known display type is "suppress"

        >>> alter = ci.domElementFromText('<alter step="2" display="suppress"/>')
        >>> acc = ci.accidentalFromAlter(alter)
        >>> acc
        <accidental double-sharp>
        >>> acc.displayType
        'never'
        '''
        if 'step' in alterElement._attrs:
            alteration = int(alterElement._attrs['step'].value)
        acc = pitch.Accidental(alteration)

        if 'display' in alterElement._attrs and alterElement._attrs[
                'display'].value == 'suppress':
            acc.displayType = 'never'
        return acc
Ejemplo n.º 12
0
    def _toAccidental(self):
        '''

        >>> from music21.figuredBass import notation as n
        >>> m1 = n.Modifier('#')
        >>> m2 = n.Modifier('-')
        >>> m3 = n.Modifier('n')
        >>> m4 = n.Modifier('+') #Raises pitch by semitone
        >>> m5 = n.Modifier('b') #acceptable for flat since note names not allowed
        >>> m1.accidental
        <accidental sharp>
        >>> m2.accidental
        <accidental flat>
        >>> m3.accidental
        <accidental natural>
        >>> m4.accidental
        <accidental sharp>
        >>> m5.accidental
        <accidental flat>
        '''
        if not self.modifierString:
            return None

        a = pitch.Accidental()
        try:
            a.set(self.modifierString)
        except pitch.AccidentalException:
            try:
                newModifierString = specialModifiers[self.modifierString]
            except KeyError:
                raise ModifierException(
                    "Figure modifier unsupported in music21: %s." % self.modifierString)
            a.set(newModifierString)

        return a
Ejemplo n.º 13
0
    def getOnePitchFromPosition(self, pos):
        '''
        get one pitch from a position...

        
        >>> nwt = noteworthy.translate.NoteworthyTranslator()
        >>> nwt.currentClef = 'BASS'
        >>> p = nwt.getOnePitchFromPosition('b3')
        >>> p
        <music21.pitch.Pitch G-3>
        >>> p.ps
        54.0
        '''
        accidental = ""
        if pos[0] in ['n', 'b', '#', 'x', 'v']:
            accidental = pos[0]
            pos = pos[1:]
            if accidental == 'b': 
                accidental  = '-'
            elif accidental  == 'x': 
                accidental = '##'
            elif accidental  == 'v':
                accidental = "--"
        positionNote = int(pos)
        (noteStep, octave) = self.getStepAndOctaveFromPosition(positionNote)
    
        p = pitch.Pitch()
        p.step = noteStep
        p.octave = octave
        pname = p.nameWithOctave

        if accidental != "":
            p.accidental = pitch.Accidental(accidental)
            self.activeAccidentals[pname] = accidental
        ## previous accidental in same bar that is still active
        elif pname in self.activeAccidentals:
            p.accidental = pitch.Accidental(self.activeAccidentals[pname])
        else:
            stepAccidental = self.currentKey.accidentalByStep(noteStep)
            if stepAccidental is not None:
                p.accidental = stepAccidental
        return p
Ejemplo n.º 14
0
 def _addAccidental(self, n, alter, pm, t):
     '''
     helper function for all accidental types.
     '''
     acc = pitch.Accidental(alter)
     if self.isEditorial:
         n.editorial.ficta = acc
     else:
         n.pitch.accidental = acc
     t = re.sub(pm, '', t)
     return t
Ejemplo n.º 15
0
    def testGetAccidentalCountIntermediate(self):
        s = stream.Stream()
        s.append(note.Note("C4"))   # no accidental
        s.append(note.Note("C#4"))  # sharp
        s.append(note.Note("D-4"))  # flat
        self.assertEqual(getAccidentalCount(s), {'flat': 1, 'sharp': 1})
        self.assertEqual(getAccidentalCount(s, True), {'flat': 1, 'sharp': 1, 'natural': 1})

        note4 = note.Note("C4")
        self.assertIsNone(note4.pitch.accidental)
        note4.pitch.accidental = pitch.Accidental('natural')  # add a natural accidental
        s.append(note4)
        self.assertEqual(getAccidentalCount(s), {'flat': 1, 'sharp': 1, 'natural': 1})
Ejemplo n.º 16
0
    def modifyPitch(self, pitchToAlter, inPlace=False):
        '''
        Given a :class:`~music21.pitch.Pitch`, modify its :attr:`~music21.pitch.Pitch.accidental`
        given the Modifier's :attr:`~music21.figuredBass.notation.Modifier.accidental`.
        
        >>> from music21 import pitch
        >>> from music21.figuredBass import notation
        >>> m1 = notation.Modifier('#')
        >>> m2 = notation.Modifier('-')
        >>> m3 = notation.Modifier('n')
        >>> p1a = pitch.Pitch('D5')
        >>> m1.modifyPitch(p1a) # Sharp
        <music21.pitch.Pitch D#5>
        >>> m2.modifyPitch(p1a) # Flat
        <music21.pitch.Pitch D-5>
        >>> p1b = pitch.Pitch('D#5')
        >>> m3.modifyPitch(p1b)
        <music21.pitch.Pitch D5>
         
        OMIT_FROM_DOCS
        >>> m4 = notation.Modifier('##')
        >>> m5 = notation.Modifier('--')
        >>> p2 = pitch.Pitch('F5')
        >>> m4.modifyPitch(p2) # Double Sharp
        <music21.pitch.Pitch F##5>
        >>> m5.modifyPitch(p2) # Double Flat
        <music21.pitch.Pitch F--5>
        '''
        if not inPlace:
            pitchToAlter = copy.deepcopy(pitchToAlter)
        if self.accidental == None:
            return pitchToAlter
        if self.accidental.alter == 0.0:
            pitchToAlter.accidental = self.accidental
        else:
            if pitchToAlter.accidental == None:
                pitchToAlter.accidental = self.accidental
            else:
                newAccidental = pitch.Accidental()
                newAlter = pitchToAlter.accidental.alter + self.accidental.alter
                try:
                    newAccidental.set(newAlter)
                    pitchToAlter.accidental = newAccidental
                except pitch.AccidentalException:
                    raise ModifierException(
                        "Resulting pitch accidental unsupported in music21.")

        return pitchToAlter
Ejemplo n.º 17
0
    def testStreamLilySemiComplex(self):
        from copy import deepcopy
        from music21 import meter, note, stream, pitch, duration

        a = stream.Stream()
        ts = meter.TimeSignature("3/8")

        b = stream.Stream()
        q = note.EighthNote()

        dur1 = duration.Duration()
        dur1.type = "eighth"

        tup1 = duration.Tuplet()
        tup1.tupletActual = [5, dur1]
        tup1.tupletNormal = [3, dur1]

        q.octave = 2
        q.duration.appendTuplet(tup1)

        for i in range(0, 5):
            b.append(deepcopy(q))
            b.elements[i].accidental = pitch.Accidental(i - 2)

        b.elements[0].duration.tuplets[0].type = "start"
        b.elements[-1].duration.tuplets[0].type = "stop"
        b2temp = b.elements[2]
        c = b2temp.editorial
        c.comment.text = "a real C"

        bestC = b.bestClef(allowTreble8vb=True)
        a.insert(bestC)
        a.insert(ts)
        a.insert(b)

        conv = LilypondConverter()
        outStr = conv.fromObject(a)
        testStr = u'\n  { \\clef "bass"  \\time 3/8  \n  { \\times 3/5 {ceses,8 ces,8 c,8_"a real C" cis,8 cisis,8}   } }'
        #        for i in range(len(outStr)):
        #            self.assertEqual(outStr[i], testStr[i])
        #        print outStr
        #        print testStr

        self.assertEqual(outStr, testStr)
Ejemplo n.º 18
0
    def toAccidental(self, value, accidentalObject=None):
        '''
        Converts a string to an accidental (or adds it to the current
        accidentalObject).  If accidentalObject passed in is None
        returns the new accidental
        
        >>> from music21 import *
        >>> importer = lily.translate.LilypondImporter()
        >>> acc = importer.toAccidental('eses')
        >>> acc
        <accidental double-flat>
        >>> acc2 = importer.toAccidental('eh!?')
        >>> acc2
        <accidental half-flat>
        >>> acc2.displayType
        'always'
        >>> acc2.displayStyle
        'parentheses'

        '''

        if accidentalObject is None:
            returnAccidental = True
            from music21 import pitch
            accidentalObject = pitch.Accidental()
        else:
            returnAccidental = False

        if value.endswith('?'):
            value = value[0:len(value) - 1]
            accidentalObject.displayStyle = "parentheses"
        if value.endswith('!'):
            value = value[0:len(value) - 1]
            accidentalObject.displayType = "always"

        if value in self.accidentalConvert:
            accidentalObject.name = self.accidentalConvert[value]
        else:
            raise LilyTranslateException(
                'Cannot convert this value to an accidental %s.' % value)

        if returnAccidental is True:
            return accidentalObject
Ejemplo n.º 19
0
    def visit_body(self, node, children):
        ch = chant.Chant()
        curSection = chant.Section()
        curClef = chant.Clef()
        curGABCClef = None

        # First pass: add measurs
        for word in children:
            if not isinstance(word, chant.Word): raise Exception('Quoi?')
            curSection.append(word)

            # Scope of accidentals ends with word boundaries
            curClefHasFlat = curGABCClef in ['cb1', 'cb2', 'cb3', 'cb4']
            bIsFlat = False or curClefHasFlat
            bIsNatural = False
            eIsFlat = False
            eIsNatural = False

            # Update the pitches of all notes based on the the clef
            # and accidentals
            for el in word.flat:
                if isinstance(el, note.Note):
                    if curGABCClef is None: 
                        raise MissingClef('Missing clef! Cannot process notes without a clef.')
                    position = el.editorial.gabcPosition
                    stepWithOctave = gabcPositionToStep(position, curGABCClef)
                    el.nameWithOctave = stepWithOctave
                    
                    if bIsNatural and el.step == 'B':
                        el.pitch.accidental = pitch.Accidental('natural')
                    elif eIsNatural and el.step == 'E':
                        el.pitch.accidental = pitch.Accidental('natural')
                    elif bIsFlat and el.step == 'B':
                        el.pitch.accidental = pitch.Accidental('flat')
                    elif eIsFlat and el.step == 'E':
                        el.pitch.accidental = pitch.Accidental('flat')

                elif isinstance(el, chant.Alteration):
                    if curGABCClef is None: 
                        raise MissingClef('Cannot process notes without a clef.')
                    position = el.editorial.gabcPosition
                    step = gabcPositionToStep(position, curGABCClef)
                    el.pitch = pitch.Pitch(step)

                    # Reset alterations
                    bIsFlat = False or curClefHasFlat
                    bIsNatural = False
                    eIsFlat = False
                    eIsNatural = False

                    # Update
                    if isinstance(el, chant.Flat) and el.pitch.step == 'E':
                        eIsFlat = True
                    elif isinstance(el, chant.Flat) and el.pitch.step == 'B':
                        bIsFlat = True
                    elif isinstance(el, chant.Natural) and el.pitch.step == 'B':
                        bIsNatural = True
                    elif isinstance(el, chant.Natural) and el.pitch.step == 'E':
                        eIsNatural = True
                    
                # Scope of accidentals ends at breathmarks
                elif isinstance(el, chant.Pausa):
                    bIsFlat = False or curClefHasFlat
                    bIsNatural = False
                    eIsFlat = False
                    eIsNatural = False  
                    
                    # Intermediate sections start (!) at pausa finalis (double barlines)
                    # because annotations below them always refer to the next sections.
                    # The very last pausa finalis is part of the last section though
                    if isinstance(el, chant.PausaFinalis):
                        if not word == children[-1]:
                            curSection.remove(word)
                            ch.append(curSection)
                            curSection = chant.Section()
                            curSection.append(word)
                        else:
                            ch.append(curSection)
                            curSection = chant.Section()
                        
                elif isinstance(el, chant.Clef):
                    curClef = el
                    curGABCClef = curClef.editorial.gabc
                elif isinstance(el, chant.Annotation):
                    pass
                else:
                    raise Exception('Unknown element')
        
        if len(curSection.flat) > 0:
            ch.append(curSection)

        # ch.joinTextAcrossPausas()
        return ch
Ejemplo n.º 20
0
    def _getNote(self):
        if self._note is not None:
            return self._note
        noteObj = None
        storedtie = None

        stringRep = self.stringRep
        storedDict = self.storedDict

        if stringRep is None:
            raise TinyNotationException(
                'Cannot return a note without some parameters')

        if self.PRECTIE.match(stringRep):
            environLocal.printDebug('Found Front Tie')
            stringRep = self.PRECTIE.sub("", stringRep)
            storedtie = tie.Tie("stop")
            storedDict['lastNoteTied'] = False

        elif 'lastNoteTied' in storedDict and storedDict[
                'lastNoteTied'] is True:
            storedtie = tie.Tie("stop")
            storedDict['lastNoteTied'] = False

        x = self.customPitchMatch(stringRep, storedDict)

        if x is not None:
            noteObj = x
        elif (self.REST.match(stringRep) is not None):  # rest
            noteObj = note.Rest()
        elif (self.OCTAVE2.match(stringRep)):  # BB etc.
            nn = self.OCTAVE2.match(stringRep)
            noteObj = self._getPitch(nn, 3 - len(nn.group(1)))
        elif (self.OCTAVE3.match(stringRep)):
            noteObj = self._getPitch(self.OCTAVE3.match(stringRep), 3)
        elif (self.OCTAVE5.match(stringRep)):  # must match octave 5 then 4!
            nn = self.OCTAVE5.match(stringRep)
            noteObj = self._getPitch(nn, 4 + len(nn.group(2)))
        elif (self.OCTAVE4.match(stringRep)):
            noteObj = self._getPitch(self.OCTAVE4.match(stringRep), 4)
        else:
            raise TinyNotationException(
                "could not get pitch information from " + str(stringRep))

        if storedtie:
            noteObj.tie = storedtie

        ## get duration
        usedLastDuration = False

        if (self.TYPE.search(stringRep)):
            typeNum = self.TYPE.search(stringRep).group(1)
            if (typeNum == "0"):  ## special case = full measure + fermata
                if 'barDuration' in storedDict:
                    noteObj.duration = storedDict['barDuration']
                newFerm = expressions.Fermata()
                noteObj.expressions.append(newFerm)
            else:
                noteObj.duration.type = duration.typeFromNumDict[int(typeNum)]
        else:
            if 'lastDuration' in storedDict:
                noteObj.duration = copy.deepcopy(storedDict['lastDuration'])
                usedLastDuration = True
            if (noteObj.duration.tuplets):
                noteObj.duration.tuplets[0].type = ""
                # if it continues a tuplet it cannot be start; maybe end

        ## get dots; called out because subclassable
        self.getDots(stringRep, noteObj)

        ## get ties
        if self.TIE.search(stringRep):
            environLocal.printDebug('Found Tie Tie')
            storedDict['lastNoteTied'] = True
            if noteObj.tie is None:
                noteObj.tie = tie.Tie("start")
            else:
                noteObj.tie.type = 'continue'

        ## use dict to set tuplets
        if ((('inTrip' in storedDict and storedDict['inTrip'] == True) or
             ('inQuad' in storedDict and storedDict['inQuad'] == True))
                and usedLastDuration == False):
            newTup = duration.Tuplet()
            newTup.durationActual.type = noteObj.duration.type
            newTup.durationNormal.type = noteObj.duration.type
            if 'inQuad' in storedDict and storedDict['inQuad'] == True:
                newTup.numNotesActual = 4.0
                newTup.numNotesNormal = 3.0
            if 'beginTuplet' in storedDict and storedDict[
                    'beginTuplet'] == True:
                newTup.type = "start"
            noteObj.duration.appendTuplet(newTup)

        if ((('inTrip' in storedDict and storedDict['inTrip'] == True) or
             ('inQuad' in storedDict and storedDict['inQuad'] == True)) and
            ('endTuplet' in storedDict and storedDict['endTuplet'] == True)):
            noteObj.duration.tuplets[0].type = "stop"

        storedDict['lastDuration'] = noteObj.duration

        ## get accidentals
        if (isinstance(noteObj, note.Note)):
            if (self.EDSHARP.search(stringRep)):  # must come before sharp
                alter = len(self.EDSHARP.search(stringRep).group(1))
                acc1 = pitch.Accidental(alter)
                noteObj.editorial.ficta = acc1
                noteObj.editorial.misc['pmfc-ficta'] = acc1
            elif (self.EDFLAT.search(stringRep)):  # must come before flat
                alter = -1 * len(self.EDFLAT.search(stringRep).group(1))
                acc1 = pitch.Accidental(alter)
                noteObj.editorial.ficta = acc1
                noteObj.editorial.misc['pmfc-ficta'] = acc1
            elif (self.EDNAT.search(stringRep)):
                acc1 = pitch.Accidental("natural")
                noteObj.editorial.ficta = acc1
                noteObj.editorial.misc['pmfc-ficta'] = acc1
                noteObj.accidental = acc1
            elif (self.SHARP.search(stringRep)):
                alter = len(self.SHARP.search(stringRep).group(1))
                noteObj.accidental = pitch.Accidental(alter)
            elif (self.FLAT.search(stringRep)):
                alter = -1 * len(self.FLAT.search(stringRep).group(1))
                noteObj.accidental = pitch.Accidental(alter)

        self.customNotationMatch(noteObj, stringRep, storedDict)

        if self.ID_EL.search(stringRep):
            noteObj.id = self.ID_EL.search(stringRep).group(1)

        if self.LYRIC.search(stringRep):
            noteObj.lyric = self.LYRIC.search(stringRep).group(1)

        self._note = noteObj
        return self._note
Ejemplo n.º 21
0
def partPari(show = True):
    '''
    generate the score of Arvo Pärt's "Pari Intervallo" algorithmically
    using music21.scale.ConcreteScale() to simulate Tintinabulation.
    '''
    s = stream.Score()
    cminor = key.Key('c')
    #real Paert
    main = converter.parse("tinynotation: 4/4 E-1 C D E- F G F E- D C D E- G A- F G E- F G F E- D F G c B- c G A- B- c B- A- B- G c e- d c d c B- A- G F E- F G c E- F G E- D E- F E- D C E- G F E- C F E- D C E- D C D C~ C")
    
    # fake Paert
    #main = converter.parse("E-1 F G A- G F c d e- G A- F E- D d e- c B- A- c d A- G F G F A- B- A- c d A- B- c B- A- G F G F E-~ E-", '4/4')
    main.__class__ = stream.Part
    main.transpose('P8', inPlace=True)
    main.insert(0, cminor)
    main.insert(0, instrument.Recorder())
    bass = copy.deepcopy(main.flat)
    for n in bass.notes:
        n.pitch.diatonicNoteNum = n.pitch.diatonicNoteNum - 9
        if (n.pitch.step == 'A' or n.pitch.step == 'B') and n.pitch.octave == 2:
            n.accidental = pitch.Accidental('natural')
        else:
            n.accidental = cminor.accidentalByStep(n.step)
        if n.offset == (2-1) * 4 or n.offset == (74-1) * 4:
            n.pitch = pitch.Pitch("C3") # exceptions to rule
        elif n.offset == (73 - 1) * 4:
            n.tie = None
            n.pitch = pitch.Pitch("C3") 
    top = copy.deepcopy(main.flat)
    main.insert(0, clef.Treble8vbClef())
    middle = copy.deepcopy(main.flat)
    
    
    cMinorArpeg = scale.ConcreteScale(pitches = ["C2","E-2","G2"])
    # dummy test on other data
    #myA = pitch.Pitch("A2")
    #myA.microtone = -15
    #cMinorArpeg = scale.ConcreteScale(pitches = ["C2", "E`2", "F~2", myA])
    
    lastNote = top.notes[-1]
    top.remove(lastNote)
    for n in top:
        if 'Note' in n.classes:
            n.pitch = cMinorArpeg.next(n.pitch, stepSize=2)
            if n.offset != (73-1)*4.0:  # m. 73 is different
                n.duration.quarterLength = 3.0
                top.insert(n.offset + 3, note.Rest())
            else:
                n.duration.quarterLength = 6.0
                n.tie = None
    r1 = note.Rest(type = 'half')
    top.insertAndShift(0, r1)
    top.getElementsByClass(key.Key)[0].setOffsetBySite(top, 0)
    lastNote = middle.notes[-1]
    middle.remove(lastNote)
   
    for n in middle:
        if 'Note' in n.classes:
            n.pitch = cMinorArpeg.next(n.pitch, direction=scale.DIRECTION_DESCENDING, stepSize=2)
            if n.offset != (73-1)*4.0:  # m. 73 is different
                n.duration.quarterLength = 3.0
                middle.insert(n.offset + 3, note.Rest())
            else:
                n.duration.quarterLength = 5.0
                n.tie = None
    r2 = note.Rest(quarterLength = 3.0)
    middle.insertAndShift(0, r2)    
    middle.getElementsByClass(key.Key)[0].setOffsetBySite(middle, 0)

    ttied = top.makeMeasures().makeTies(inPlace=False)
    mtied = middle.makeMeasures().makeTies(inPlace=False)
    bass.makeMeasures(inPlace = True)
    main.makeMeasures(inPlace = True)
    
    s.insert(0, ttied)
    s.insert(0, main)
    s.insert(0, mtied)
    s.insert(0, bass)
    
    for p in s.parts:
        p.getElementsByClass(stream.Measure)[-1].rightBarline = bar.Barline('final')

    if show == True:
        s.show()
Ejemplo n.º 22
0
def toPart(volpianoText, *, breaksToLayout=False):
    # noinspection PyShadowingNames
    '''
    Returns a music21 Part from volpiano text.

    >>> veniSancti = volpiano.toPart('1---c--d---f--d---ed--c--d---f'
    ...                              + '---g--h--j---hgf--g--h---')
    >>> veniSancti.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.note.Note C>
        {1.0} <music21.note.Note D>
        {2.0} <music21.note.Note F>
        {3.0} <music21.note.Note D>
        {4.0} <music21.note.Note E>
        {5.0} <music21.note.Note D>
        {6.0} <music21.volpiano.Neume <music21.note.Note E><music21.note.Note D>>
        {6.0} <music21.note.Note C>
        {7.0} <music21.note.Note D>
        {8.0} <music21.note.Note F>
        {9.0} <music21.note.Note G>
        {10.0} <music21.note.Note A>
        {11.0} <music21.note.Note B>
        {12.0} <music21.note.Note A>
        {13.0} <music21.note.Note G>
        {14.0} <music21.note.Note F>
        {15.0} <music21.volpiano.Neume <music21.note.Note A><music21.note.Note G>>
        {15.0} <music21.note.Note G>
        {16.0} <music21.note.Note A>

    Clefs!

    >>> clefTest = volpiano.toPart('1---c--2---c')
    >>> clefTest.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.note.Note C>
        {1.0} <music21.clef.BassClef>
        {1.0} <music21.note.Note E>
    >>> for n in clefTest.recurse().notes:
    ...     n.nameWithOctave
    'C4'
    'E2'

    Flats and Naturals:

    >>> accTest = volpiano.toPart('1---e--we--e--We--e')
    >>> [n.name for n in accTest.recurse().notes]
    ['E', 'E-', 'E-', 'E', 'E']

    Breaks and barlines

    >>> breakTest = volpiano.toPart('1---e-7-e-77-e-777-e-3-e-4')
    >>> breakTest.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.note.Note E>
        {1.0} <music21.volpiano.LineBreak object at 0x105250fd0>
        {1.0} <music21.note.Note E>
        {2.0} <music21.volpiano.PageBreak object at 0x105262128>
        {2.0} <music21.note.Note E>
        {3.0} <music21.volpiano.ColumnBreak object at 0x105262240>
        {3.0} <music21.note.Note E>
        {4.0} <music21.bar.Barline type=regular>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note E>
        {1.0} <music21.bar.Barline type=double>


    As layout objects using breaksToLayout=True

    >>> breakTest = volpiano.toPart('1---e-7-e-77-e-777-e-3-e-4', breaksToLayout=True)
    >>> breakTest.show('text')
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.note.Note E>
        {1.0} <music21.layout.SystemLayout>
        {1.0} <music21.note.Note E>
        {2.0} <music21.layout.PageLayout>
        {2.0} <music21.note.Note E>
        {3.0} <music21.volpiano.ColumnBreak object at 0x105262240>
        {3.0} <music21.note.Note E>
        {4.0} <music21.bar.Barline type=regular>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note E>
        {1.0} <music21.bar.Barline type=double>


    Liquescence test:

    >>> breakTest = volpiano.toPart('1---e-E-')
    >>> breakTest.recurse().notes[0].editorial.liquescence
    False
    >>> breakTest.recurse().notes[0].notehead
    'normal'
    >>> breakTest.recurse().notes[1].editorial.liquescence
    True
    >>> breakTest.recurse().notes[1].notehead
    'x'

    Changed in v5.7 -- corrected spelling of liquescence.
    '''
    p = stream.Part()
    m = stream.Measure()

    currentMeasure = m
    currentNeumeSpanner = None
    noteThatWouldGoInSpanner = None
    lastClef = clef.TrebleClef()
    continuousNumberOfBreakTokens = 0

    bIsFlat = False
    eIsFlat = False

    for token in volpianoText:
        if token == '7':
            continuousNumberOfBreakTokens += 1
            continue
        elif continuousNumberOfBreakTokens > 0:
            if not breaksToLayout:  # default
                breakClass = classByNumBreakTokens[
                    continuousNumberOfBreakTokens]
                breakToken = breakClass()  # pylint: disable=not-callable
            else:
                breakClass = classByNumBreakTokensLayout[
                    continuousNumberOfBreakTokens]
                if continuousNumberOfBreakTokens < 3:
                    breakToken = breakClass(isNew=True)  # pylint: disable=not-callable
                else:
                    breakToken = breakClass()  # pylint: disable=not-callable

            currentMeasure.append(breakToken)

        continuousNumberOfBreakTokens = 0

        if token == '-':
            noteThatWouldGoInSpanner = None
            if currentNeumeSpanner:
                currentMeasure.append(currentNeumeSpanner)
                currentNeumeSpanner = None
            continue

        if token in '1234':
            noteThatWouldGoInSpanner = None
            currentNeumeSpanner = None

        if token in '12':
            if token == '1':
                c = clef.TrebleClef()
            else:
                c = clef.BassClef()

            lastClef = c
            m.append(c)

        elif token in '34':
            bl = bar.Barline()
            if token == '4':
                bl.type = 'double'
            m.rightBarline = bl
            p.append(m)
            m = stream.Measure()

        elif token in normalPitches or token in liquescentPitches:
            n = note.Note()
            n.stemDirection = 'noStem'

            if token in normalPitches:
                distanceFromLowestLine = normalPitches.index(token) - 5
                n.editorial.liquescence = False
            else:
                distanceFromLowestLine = liquescentPitches.index(token) - 5
                n.notehead = 'x'
                n.editorial.liquescence = True

            clefLowestLine = lastClef.lowestLine
            diatonicNoteNum = clefLowestLine + distanceFromLowestLine

            n.pitch.diatonicNoteNum = diatonicNoteNum
            if n.pitch.step == 'B' and bIsFlat:
                n.pitch.accidental = pitch.Accidental('flat')
            elif n.pitch.step == 'E' and eIsFlat:
                n.pitch.accidental = pitch.Accidental('flat')

            m.append(n)

            if noteThatWouldGoInSpanner is not None:
                currentNeumeSpanner = Neume([noteThatWouldGoInSpanner, n])
                noteThatWouldGoInSpanner = None
            else:
                noteThatWouldGoInSpanner = n

        elif token in accidentalTokens:
            if token.lower() in eflatTokens and token in naturalTokens:
                eIsFlat = False
            elif token.lower() in bflatTokens and token in naturalTokens:
                bIsFlat = False
            elif token.lower() in eflatTokens and token in flatTokens:
                eIsFlat = True
            elif token.lower() in bflatTokens and token in flatTokens:
                bIsFlat = True
            else:  # pragma: no cover
                raise VolpianoException('Unknown accidental: ' + token +
                                        ': Should not happen')

    if continuousNumberOfBreakTokens > 0:
        breakClass = classByNumBreakTokens[continuousNumberOfBreakTokens]
        breakToken = breakClass()  # pylint: disable=not-callable
        currentMeasure.append(breakToken)

    if m:
        p.append(m)

    return p
Ejemplo n.º 23
0
def capuaRuleTwo(srcStream):
    '''
    See capuaRuleOne for precise instructions.
    
    Applies Capua's second rule to the given srcStream, i.e. if four notes are
    ascending with the pattern M2 m2 M2, the intervals shall be made M2 M2 m2.
    Also changes note.editorial.color for rule 2 (purple purple green purple).
    
    returns the number of times any note was changed
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(0, len(ssn) - 3):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]
        n4 = ssn[i + 3]

        if n1.isRest or \
           n2.isRest or \
           n3.isRest or \
           n4.isRest:
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)
        i3 = interval.notesToInterval(n3, n4)

        if n1.accidental is not None or \
           n2.accidental is not None or \
           n4.accidental is not None:
            continue

        ### never seems to improve things...
        if n3.step == "A" or n3.step == "D":
            continue

        # e.g., D E F G => D E F# G
        #    or F A Bb C => F A B C
        if i1.directedName == "M2" and \
           i2.directedName == "m2" and \
           i3.directedName == "M2":
            numChanged += 1
            if ("capua" in n3.editorial.misc):
                n3.editorial.misc['capua_rule_number'] += RULE_TWO
            else:
                n3.editorial.misc['capua_rule_number'] = RULE_TWO

            if (n3.accidental is not None and n3.accidental.name == "flat"):
                n3.editorial.misc["saved-accidental"] = n3.accidental
                n3.accidental = None
                n3.editorial.ficta = pitch.Accidental("natural")
                n3.editorial.misc["capua-ficta"] = pitch.Accidental("natural")
                n1.editorial.color = "purple"
                n2.editorial.color = "purple"
                n3.editorial.color = "ForestGreen"
                n4.editorial.color = "purple"
            else:
                n3.editorial.ficta = pitch.Accidental("sharp")
                n3.editorial.misc["capua-ficta"] = pitch.Accidental("sharp")
                n1.editorial.color = "purple"
                n2.editorial.color = "purple"
                n3.editorial.color = "ForestGreen"
                n4.editorial.color = "purple"

    return numChanged
Ejemplo n.º 24
0
    def fix(self):
        for (midiRef, omrRef, op) in self.changes:
            omrRef.color = "black"
            # if they're not notes, don't bother with rest
            if self.checkIfNoteInstance(midiRef, omrRef) is False:
                continue
            # if the are the same, don't bother to try changing it
            # 3 is the number of noChange Ops
            if isinstance(op, aligner.ChangeOps) and op == aligner.ChangeOps.NoChange:
                continue

            # don't bother with notes with too big of an interval between them
            if self.intervalTooBig(midiRef, omrRef, setint=5):
                continue
            # case 1: omr has extraneous natural sign in front of it, get rid of it
            if self.hasNatAcc(omrRef):
                if self.isEnharmonic(midiRef, omrRef):
                    omrRef.pitch.accidental = None
                else:
                    # case 2-1: midi note is sharp, omr note is one step higher and natural,
                    # should be a flat instead. e.g midi = g#, gt = a-, omr = an
                    # omr note has higher ps than midi-- on a higher
                    # line or space than midi note
                    if omrRef.pitch > midiRef.pitch:
                        if omrRef.pitch.transpose(interval.Interval(-1)
                                                  ).isEnharmonic(midiRef.pitch):
                            omrRef.pitch.accidental = pitch.Accidental('flat')
                    # case 2-2: midi note is flat, omr note is one step lower and natural,
                    # should be a flat instead. e.g midi = g-, gt = f#, omr = fn
                    # omr note has lower ps than midi-- on a higher line
                    # or space than midi note
                    elif omrRef.pitch < midiRef.pitch:
                        if omrRef.pitch.transpose(interval.Interval(1)
                                                  ).isEnharmonic(midiRef.pitch):
                            omrRef.pitch.accidental = pitch.Accidental('sharp')
            # case 3: notes are on same step, but omr got read wrong.
            # e.g. midi = g#, gt = g#, omr = gn or omr = g-
            elif self.hasSharpFlatAcc(omrRef) and self.stepEq(midiRef, omrRef):
                if self.hasAcc(omrRef):
                    omrRef.pitch.accidental = midiRef.pitch.accidental
                else:
                    omrRef.pitch.accidental = None

            elif self.hasSharpFlatAcc(omrRef) and self.stepNotEq(midiRef, omrRef):
                # case 4-1: notes are on different step, off by an interval of 2,
                # omr note is higher and sharp
                # e.g. midi = g#, gt = a-, omr = a#
                if omrRef.pitch > midiRef.pitch:
                    if omrRef.pitch.accidental == pitch.Accidental('sharp'):
                        if omrRef.pitch.transpose(interval.Interval(-2)
                                                  ).isEnharmonic(midiRef.pitch):
                            omrRef.pitch.accidental = pitch.Accidental('flat')
                # case 4-2: notes are on different step, off by an interval of 2,
                # omr note is lower and flat
                # e.g. midi = a-, gt = g#, omr = g-
                elif omrRef.pitch < midiRef.pitch:
                    if omrRef.pitch.accidental == pitch.Accidental('flat'):
                        if omrRef.pitch.transpose(interval.Interval(2)
                                                  ).isEnharmonic(midiRef.pitch):
                            omrRef.pitch.accidental = pitch.Accidental('sharp')
            # case 5: same step, MIDI has accidental,
            # omr was read wrong (e.g. key signature not parsed)
            # e.g. midi = b-, gt = b-, omr=
            elif (omrRef.pitch != midiRef.pitch
                    and self.hasSharpFlatAcc(midiRef)
                    and self.stepEq(midiRef, omrRef)):
                omrRef.pitch = midiRef.pitch
Ejemplo n.º 25
0
def capuaRuleTwo(srcStream):
    '''
    See capuaRuleOne for precise instructions.

    Applies Capua's second rule to the given srcStream, i.e. if four notes are
    ascending with the pattern M2 m2 M2, the intervals shall be made M2 M2 m2.
    Also changes note.style.color for rule 2 (purple purple green purple).

    returns the number of times any note was changed
    '''
    numChanged = 0

    ssn = srcStream.flat.notesAndRests
    for i in range(len(ssn) - 3):
        n1 = ssn[i]
        n2 = ssn[i + 1]
        n3 = ssn[i + 2]
        n4 = ssn[i + 3]

        if (n1.isRest or n2.isRest or n3.isRest or n4.isRest):
            continue

        i1 = interval.notesToInterval(n1, n2)
        i2 = interval.notesToInterval(n2, n3)
        i3 = interval.notesToInterval(n3, n4)

        if (n1.pitch.accidental is not None or n2.pitch.accidental is not None
                or n4.pitch.accidental is not None):
            continue

        # never seems to improve things...
        if n3.step == 'A' or n3.step == 'D':
            continue

        # e.g., D E F G => D E F# G
        #    or F A Bb C => F A B C
        if (i1.directedName == 'M2' and i2.directedName == 'm2'
                and i3.directedName == 'M2'):
            numChanged += 1
            if 'capuaRuleNumber' in n3.editorial:
                n3.editorial.capuaRuleNumber += RULE_TWO
            else:
                n3.editorial.capuaRuleNumber = RULE_TWO

            if n3.pitch.accidental is not None and n3.pitch.accidental.name == 'flat':
                n3.editorial.savedAccidental = n3.pitch.accidental
                n3.pitch.accidental = None
                n3.editorial.ficta = pitch.Accidental('natural')
                n3.editorial.capuaFicta = pitch.Accidental('natural')
                n1.style.color = 'purple'
                n2.style.color = 'purple'
                n3.style.color = 'ForestGreen'
                n4.style.color = 'purple'
            else:
                n3.editorial.ficta = pitch.Accidental('sharp')
                n3.editorial.capuaFicta = pitch.Accidental('sharp')
                n1.style.color = 'purple'
                n2.style.color = 'purple'
                n3.style.color = 'ForestGreen'
                n4.style.color = 'purple'

    return numChanged