コード例 #1
0
ファイル: translate.py プロジェクト: chyeh727/music21
def romanTextToStreamOpus(rtHandler, inputM21=None):
    '''The main processing routine for RomanText objects that may or may not
    be multi movement.
    
    Takes in a romanText.rtObjects.RTFile() object, or a string as rtHandler.
    
    Runs `romanTextToStreamScore()` as its main work.
    
    If inputM21 is None then it will create a Score or Opus object.
    
    Return either a Score object, or, if a multi-movement work is defined, an
    Opus object.
    '''
    from music21 import stream
    if common.isStr(rtHandler):
        rtf = rtObjects.RTFile()
        rtHandler = rtf.readstr(rtHandler)  # return handler, processes tokens

    if rtHandler.definesMovements():  # create an opus
        if inputM21 == None:
            s = stream.Opus()
        else:
            s = inputM21
        # copy the common header to each of the sub-handlers
        handlerBundles = rtHandler.splitByMovement(duplicateHeader=True)
        # see if we have header information
        for h in handlerBundles:
            #print h, len(h)
            # append to opus
            s.append(romanTextToStreamScore(h))
        return s  # an opus
    else:  # create a Score
        return romanTextToStreamScore(rtHandler, inputM21=inputM21)
コード例 #2
0
ファイル: translate.py プロジェクト: chyeh727/music21
    def testExternalA(self):
        from music21.romanText import testFiles

        for tf in testFiles.ALL:
            rtf = rtObjects.RTFile()
            rth = rtf.readstr(tf)  # return handler, processes tokens
            s = romanTextToStreamScore(rth)
            s.show()
コード例 #3
0
ファイル: subConverters.py プロジェクト: rmattes/music21
 def parseFile(self, fp, number=None):
     from music21.romanText import rtObjects
     from music21.romanText import translate as romanTextTranslate
     rtf = rtObjects.RTFile()  # not sure why -- @UndefinedVariable
     rtf.open(fp)
     # returns a handler instance of parse tokens
     rtHandler = rtf.read()
     rtf.close()
     romanTextTranslate.romanTextToStreamScore(rtHandler, self.stream)
コード例 #4
0
ファイル: subConverters.py プロジェクト: rmattes/music21
 def parseData(self, strData, number=None):
     from music21.romanText import rtObjects
     from music21.romanText import translate as romanTextTranslate
     rtf = rtObjects.RTFile()  # not sure why -- @UndefinedVariable
     rtHandler = rtf.readstr(strData)
     if rtHandler.definesMovements():
         # this re-defines Score as an Opus
         self.stream = romanTextTranslate.romanTextToStreamOpus(rtHandler)
     else:
         romanTextTranslate.romanTextToStreamScore(rtHandler, self.stream)
コード例 #5
0
    def testBasicA(self):
        from music21.romanText import testFiles

        for tf in testFiles.ALL:
            rtf = rtObjects.RTFile()
            rth = rtf.readstr(tf) # return handler, processes tokens
            unused_s = romanTextToStreamOpus(rth) # will run romanTextToStreamScore on all but k273
            #s.show()
        
        s = romanTextToStreamScore(testFiles.swv23)
        self.assertEqual(s.metadata.composer, 'Heinrich Schutz')
        # this is defined as a Piece tag, but shows up here as a title, after
        # being set as an alternate title
        self.assertEqual(s.metadata.title, 'Warum toben die Heiden, Psalmen Davids no. 2, SWV 23')
        
        s = romanTextToStreamScore(testFiles.riemenschneider001)
        self.assertEqual(s.metadata.composer, 'J. S. Bach')
        self.assertEqual(s.metadata.title, 'Aus meines Herzens Grunde')

        s = romanTextToStreamScore(testFiles.monteverdi_3_13)
        self.assertEqual(s.metadata.composer, 'Claudio Monteverdi')
コード例 #6
0
ファイル: translate.py プロジェクト: chyeh727/music21
def romanTextToStreamScore(rtHandler, inputM21=None):
    '''The main processing module for single-movement RomanText works.

    Given a romanText handler or string, return or fill a Score Stream.
    '''
    # accept a string directly; mostly for testing
    if common.isStr(rtHandler):
        rtf = rtObjects.RTFile()
        rtHandler = rtf.readstr(rtHandler)  # return handler, processes tokens

    # this could be just a Stream, but b/c we are creating metadata, perhaps better to match presentation of other scores.

    from music21 import metadata
    from music21 import stream
    from music21 import note
    from music21 import meter
    from music21 import key
    from music21 import roman
    from music21 import tie

    if inputM21 == None:
        s = stream.Score()
    else:
        s = inputM21

    # metadata can be first
    md = metadata.Metadata()
    s.insert(0, md)

    p = stream.Part()
    # ts indication are found in header, and also found elsewhere
    tsCurrent = meter.TimeSignature('4/4')  # create default 4/4
    tsSet = False  # store if set to a measure
    lastMeasureToken = None
    lastMeasureNumber = 0
    previousRn = None
    keySigCurrent = None
    keySigSet = True  # set a keySignature
    foundAKeySignatureSoFar = False
    kCurrent, unused_prefixLyric = _getKeyAndPrefix(
        'C')  # default if none defined
    prefixLyric = ''

    repeatEndings = {}
    rnKeyCache = {}

    for t in rtHandler.tokens:
        try:

            # environLocal.printDebug(['token', t])
            if t.isTitle():
                md.title = t.data

            elif t.isWork():
                md.alternativeTitle = t.data

            elif t.isPiece():
                md.alternativeTitle = t.data

            elif t.isComposer():
                md.composer = t.data

            elif t.isMovement():
                md.movementNumber = t.data

            elif t.isTimeSignature():
                tsCurrent = meter.TimeSignature(t.data)
                tsSet = False
                # environLocal.printDebug(['tsCurrent:', tsCurrent])

            elif t.isKeySignature():
                if t.data == "":
                    keySigCurrent = key.KeySignature(0)
                elif t.data == "Bb":
                    keySigCurrent = key.KeySignature(-1)
                else:
                    pass
                    # better to print a message
                    # environLocal.printDebug(['still need to write a generic RomanText KeySignature routine.  this is just temporary'])
                    # raise RomanTextTranslateException("still need to write a generic RomanText KeySignature routine.  this is just temporary")
                keySigSet = False
                # environLocal.printDebug(['keySigCurrent:', keySigCurrent])
                foundAKeySignatureSoFar = True

            elif t.isMeasure():
                # environLocal.printDebug(['handling measure token:', t])
                #if t.number[0] % 10 == 0:
                #    print "at number " + str(t.number[0])
                if t.variantNumber is not None:
                    # environLocal.printDebug(['skipping variant: %s' % t])
                    continue
                if t.variantLetter is not None:
                    # environLocal.printDebug(['skipping variant: %s' % t])
                    continue

                # if this measure number is more than 1 greater than the last
                # defined measure number, and the previous chord is not None,
                # then fill with copies of the last-defined measure
                if ((t.number[0] > lastMeasureNumber + 1)
                        and (previousRn is not None)):
                    for i in range(lastMeasureNumber + 1, t.number[0]):
                        mFill = stream.Measure()
                        mFill.number = i
                        newRn = copy.deepcopy(previousRn)
                        newRn.lyric = ""
                        # set to entire bar duration and tie
                        newRn.duration = copy.deepcopy(tsCurrent.barDuration)
                        if previousRn.tie is None:
                            previousRn.tie = tie.Tie('start')
                        else:
                            previousRn.tie.type = 'continue'
                        # set to stop for now; may extend on next iteration
                        newRn.tie = tie.Tie('stop')
                        previousRn = newRn
                        mFill.append(newRn)
                        appendMeasureToRepeatEndingsDict(
                            lastMeasureToken, mFill, repeatEndings, i)
                        p._appendCore(mFill)
                    lastMeasureNumber = t.number[0] - 1
                    lastMeasureToken = t

                # create a new measure or copy a past measure
                if len(t.number) == 1 and t.isCopyDefinition:  # if not a range
                    p.elementsChanged()
                    m, kCurrent = _copySingleMeasure(t, p, kCurrent)
                    p._appendCore(m)
                    lastMeasureNumber = m.number
                    lastMeasureToken = t
                    romans = m.getElementsByClass(roman.RomanNumeral,
                                                  returnStreamSubClass='list')
                    if len(romans) > 0:
                        previousRn = romans[-1]

                elif len(t.number) > 1:
                    p.elementsChanged()
                    measures, kCurrent = _copyMultipleMeasures(t, p, kCurrent)
                    p.append(measures)  # appendCore does not work with list
                    lastMeasureNumber = measures[-1].number
                    lastMeasureToken = t
                    romans = measures[-1].getElementsByClass(
                        roman.RomanNumeral, returnStreamSubClass='list')
                    if len(romans) > 0:
                        previousRn = romans[-1]

                else:
                    m = stream.Measure()
                    m.number = t.number[0]
                    appendMeasureToRepeatEndingsDict(t, m, repeatEndings)
                    lastMeasureNumber = t.number[0]
                    lastMeasureToken = t

                    if not tsSet:
                        m.timeSignature = tsCurrent
                        tsSet = True  # only set when changed
                    if not keySigSet and keySigCurrent is not None:
                        m.insert(0, keySigCurrent)
                        keySigSet = True  # only set when changed

                    o = 0.0  # start offsets at zero
                    previousChordInMeasure = None
                    pivotChordPossible = False
                    numberOfAtoms = len(t.atoms)
                    setKeyChangeToken = False  # first RomanNumeral object after a key change should have this set to True

                    for i, a in enumerate(t.atoms):
                        if isinstance(a, rtObjects.RTKey) or \
                           ((foundAKeySignatureSoFar == False) and \
                            (isinstance(a, rtObjects.RTAnalyticKey))):
                            # found a change of Key+KeySignature or
                            # just found a change of analysis but no keysignature so far

                            # environLocal.printDebug(['handling key token:', a])
                            try:  # this sets the key and the keysignature
                                kCurrent, pl = _getKeyAndPrefix(a)
                                prefixLyric += pl
                            except:
                                raise RomanTextTranslateException(
                                    'cannot get key from %s in line %s' %
                                    (a.src, t.src))
                            # insert at beginning of measure if at beginning -- for things like pickups.
                            if m.number < 2:
                                m._insertCore(0, kCurrent)
                            else:
                                m._insertCore(o, kCurrent)
                            foundAKeySignatureSoFar = True
                            setKeyChangeToken = True

                        elif isinstance(a, rtObjects.RTKeySignature):
                            try:  # this sets the keysignature but not the prefix text
                                thisSig = a.getKeySignature()
                            except:
                                raise RomanTextTranslateException(
                                    'cannot get key from %s in line %s' %
                                    (a.src, t.src))
                            #insert at beginning of measure if at beginning -- for things like pickups.
                            if m.number < 2:
                                m._insertCore(0, thisSig)
                            else:
                                m._insertCore(o, thisSig)
                            foundAKeySignatureSoFar = True

                        elif isinstance(a, rtObjects.RTAnalyticKey):
                            # just a change in analyzed key, not a change in anything else
                            #try: # this sets the key, not the keysignature
                            kCurrent, pl = _getKeyAndPrefix(a)
                            prefixLyric += pl
                            setKeyChangeToken = True

                            #except:
                            #    raise RomanTextTranslateException('cannot get key from %s in line %s' % (a.src, t.src))

                        elif isinstance(a, rtObjects.RTBeat):
                            # set new offset based on beat
                            try:
                                o = a.getOffset(tsCurrent)
                            except ValueError:
                                raise RomanTextTranslateException(
                                    "cannot properly get an offset from beat data %s under timeSignature %s in line %s"
                                    % (a.src, tsCurrent, t.src))
                            if (previousChordInMeasure is None
                                    and previousRn is not None and o > 0):
                                # setting a new beat before giving any chords
                                firstChord = copy.deepcopy(previousRn)
                                firstChord.quarterLength = o
                                firstChord.lyric = ""
                                if previousRn.tie == None:
                                    previousRn.tie = tie.Tie('start')
                                else:
                                    previousRn.tie.type = 'continue'
                                firstChord.tie = tie.Tie('stop')
                                previousRn = firstChord
                                previousChordInMeasure = firstChord
                                m._insertCore(0, firstChord)
                            pivotChordPossible = False

                        elif isinstance(a, rtObjects.RTNoChord):
                            # use source to evaluation roman
                            rn = note.Rest()
                            if pivotChordPossible == False:
                                # probably best to find duration
                                if previousChordInMeasure is None:
                                    pass  # use default duration
                                else:  # update duration of previous chord in Measure
                                    oPrevious = previousChordInMeasure.getOffsetBySite(
                                        m)
                                    newQL = o - oPrevious
                                    if newQL <= 0:
                                        raise RomanTextTranslateException(
                                            'too many notes in this measure: %s'
                                            % t.src)
                                    previousChordInMeasure.quarterLength = newQL
                                prefixLyric = ""
                                m._insertCore(o, rn)
                                previousChordInMeasure = rn
                                previousRn = rn
                                pivotChordPossible = False

                        elif isinstance(a, rtObjects.RTChord):
                            # use source to evaluation roman
                            try:
                                asrc = a.src
                                #                            if kCurrent.mode == 'minor':
                                #                                if asrc.lower().startswith('vi'): #vi or vii w/ or w/o o
                                #                                    if asrc.upper() == a.src: # VI or VII to bVI or bVII
                                #                                        asrc = 'b' + asrc
                                cacheTuple = (asrc,
                                              kCurrent.tonicPitchNameWithCase)
                                if USE_RN_CACHE and cacheTuple in rnKeyCache:
                                    #print "Got a match: " + str(cacheTuple)
                                    # Problems with Caches not picking up pivot chords... Not faster, see below.
                                    rn = copy.deepcopy(rnKeyCache[cacheTuple])
                                else:
                                    #print "No match for: " + str(cacheTuple)
                                    rn = roman.RomanNumeral(
                                        asrc, copy.deepcopy(kCurrent))
                                    rnKeyCache[cacheTuple] = rn
                                # surprisingly, not faster... and more dangerous
                                #rn = roman.RomanNumeral(asrc, kCurrent)
                                ## SLOWEST!!!
                                #rn = roman.RomanNumeral(asrc, kCurrent.tonicPitchNameWithCase)

                                #>>> from timeit import timeit as t
                                #>>> t('roman.RomanNumeral("IV", "c#")', 'from music21 import roman', number=1000)
                                #45.75
                                #>>> t('roman.RomanNumeral("IV", k)', 'from music21 import roman, key; k = key.Key("c#")', number=1000)
                                #16.09
                                #>>> t('roman.RomanNumeral("IV", copy.deepcopy(k))', 'from music21 import roman, key; import copy; k = key.Key("c#")', number=1000)
                                #22.49
                                ## key cache, does not help much...
                                #>>> t('copy.deepcopy(r)', 'from music21 import roman; import copy; r = roman.RomanNumeral("IV", "c#")', number=1000)
                                #19.01

                                if setKeyChangeToken is True:
                                    rn.followsKeyChange = True
                                    setKeyChangeToken = False
                                else:
                                    rn.followsKeyChange = False
                            except (roman.RomanNumeralException,
                                    common.Music21CommonException):
                                #environLocal.printDebug('cannot create RN from: %s' % a.src)
                                rn = note.Note()  # create placeholder

                            if pivotChordPossible == False:
                                # probably best to find duration
                                if previousChordInMeasure is None:
                                    pass  # use default duration
                                else:  # update duration of previous chord in Measure
                                    oPrevious = previousChordInMeasure.getOffsetBySite(
                                        m)
                                    newQL = o - oPrevious
                                    if newQL <= 0:
                                        raise RomanTextTranslateException(
                                            'too many notes in this measure: %s'
                                            % t.src)
                                    previousChordInMeasure.quarterLength = newQL

                                rn.addLyric(prefixLyric + a.src)
                                prefixLyric = ""
                                m._insertCore(o, rn)
                                previousChordInMeasure = rn
                                previousRn = rn
                                pivotChordPossible = True
                            else:
                                previousChordInMeasure.lyric += "//" + prefixLyric + a.src
                                previousChordInMeasure.pivotChord = rn
                                prefixLyric = ""
                                pivotChordPossible = False

                        elif isinstance(a, rtObjects.RTRepeat):
                            if o == 0:
                                if isinstance(a, rtObjects.RTRepeatStart):
                                    m.leftBarline = bar.Repeat(
                                        direction='start')
                                else:
                                    rtt = RomanTextUnprocessedToken(a)
                                    m._insertCore(o, rtt)
                            elif tsCurrent is not None and (
                                    tsCurrent.barDuration.quarterLength == o
                                    or i == numberOfAtoms - 1):
                                if isinstance(a, rtObjects.RTRepeatStop):
                                    m.rightBarline = bar.Repeat(
                                        direction='end')
                                else:
                                    rtt = RomanTextUnprocessedToken(a)
                                    m._insertCore(o, rtt)
                            else:  # mid measure repeat signs
                                rtt = RomanTextUnprocessedToken(a)
                                m._insertCore(o, rtt)

                        else:
                            rtt = RomanTextUnprocessedToken(a)
                            m._insertCore(o, rtt)
                            #environLocal.warn("Got an unknown token: %r" % a)

                    # may need to adjust duration of last chord added
                    if tsCurrent is not None:
                        previousRn.quarterLength = tsCurrent.barDuration.quarterLength - o
                    m.elementsChanged()
                    p._appendCore(m)

        except Exception:
            import traceback
            tracebackMessage = traceback.format_exc()
            raise RomanTextTranslateException(
                "At line %d for token %r, an exception was raised: \n%s" %
                (t.lineNumber, t, tracebackMessage))

    p.elementsChanged()
    fixPickupMeasure(p)
    p.makeBeams(inPlace=True)
    p.makeAccidentals(inPlace=True)
    _addRepeatsFromRepeatEndings(p, repeatEndings)  # 1st and second endings...
    s.insert(0, p)

    return s