Ejemplo n.º 1
0
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 = romanTextModule.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 = {}

    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.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.append(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
                    m, kCurrent = _copySingleMeasure(t, p, kCurrent)
                    p.append(m)
                    lastMeasureNumber = m.number
                    lastMeasureToken = t
                    romans = m.getElementsByClass(roman.RomanNumeral)
                    if len(romans) > 0:
                        previousRn = romans[-1] 

                elif len(t.number) > 1:
                    measures, kCurrent = _copyMultipleMeasures(t, p, kCurrent)
                    p.append(measures)
                    lastMeasureNumber = measures[-1].number
                    lastMeasureToken = t
                    romans = measures[-1].getElementsByClass(roman.RomanNumeral)
                    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, romanTextModule.RTKey) or \
                           ((foundAKeySignatureSoFar == False) and \
                            (isinstance(a, romanTextModule.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.insert(0, kCurrent)
                            else:
                                m.insert(o, kCurrent)
                            foundAKeySignatureSoFar = True
                            setKeyChangeToken = True
    
                        elif isinstance(a, romanTextModule.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.insert(0, thisSig)
                            else:
                                m.insert(o, thisSig)
                            foundAKeySignatureSoFar = True
    
                        elif isinstance(a, romanTextModule.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, romanTextModule.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.insert(0, firstChord)
                            pivotChordPossible = False

                        elif isinstance(a, romanTextModule.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.insert(o, rn)
                                previousChordInMeasure = rn
                                previousRn = rn
                                pivotChordPossible = False

                        elif isinstance(a, romanTextModule.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
                                rn = roman.RomanNumeral(asrc, copy.deepcopy(kCurrent))
                                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.insert(o, rn)
                                previousChordInMeasure = rn
                                previousRn = rn
                                pivotChordPossible = True
                            else:
                                previousChordInMeasure.lyric += "//" + prefixLyric + a.src
                                previousChordInMeasure.pivotChord = rn
                                prefixLyric = ""
                                pivotChordPossible = False

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

                        else:
                            rtt = RomanTextUnprocessedToken(a)
                            m.insert(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
                    p.append(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))

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

    return s
Ejemplo n.º 2
0
def parseTokens(mh, dst, p, useMeasures):
    '''
    parses all the tokens in a measure or part.
    '''
    # in case need to transpose due to clef indication
    from music21 import abcFormat

    postTransposition = 0
    clefSet = False
    for t in mh.tokens:
        if isinstance(t, abcFormat.ABCMetadata):
            if t.isMeter():
                ts = t.getTimeSignatureObject()
                if ts is not None:  # can be None
                    # should append at the right position
                    if useMeasures:  # assume at start of measures
                        dst.timeSignature = ts
                    else:
                        dst.coreAppend(ts)
            elif t.isKey():
                ks = t.getKeySignatureObject()
                if useMeasures:  # assume at start of measures
                    dst.keySignature = ks
                else:
                    dst.coreAppend(ks)
                # check for clef information sometimes stored in key
                clefObj, transposition = t.getClefObject()
                if clefObj is not None:
                    clefSet = False
                    # environLocal.printDebug(['found clef in key token:', t,
                    #     clefObj, transposition])
                    if useMeasures:  # assume at start of measures
                        dst.clef = clefObj
                    else:
                        dst.coreAppend(clefObj)
                    postTransposition = transposition
            elif t.isTempo():
                mmObj = t.getMetronomeMarkObject()
                dst.coreAppend(mmObj)

        # as ABCChord is subclass of ABCNote, handle first
        elif isinstance(t, abcFormat.ABCChord):
            # may have more than notes?
            pitchNameList = []
            accStatusList = []  # accidental display status list
            for tSub in t.subTokens:
                # notes are contained as subtokens are already parsed
                if isinstance(tSub, abcFormat.ABCNote):
                    pitchNameList.append(tSub.pitchName)
                    accStatusList.append(tSub.accidentalDisplayStatus)
            c = chord.Chord(pitchNameList)
            c.duration.quarterLength = t.quarterLength
            if t.activeTuplet:
                thisTuplet = copy.deepcopy(t.activeTuplet)
                if thisTuplet.durationNormal is None:
                    thisTuplet.setDurationType(c.duration.type,
                                               c.duration.dots)
                c.duration.appendTuplet(thisTuplet)
            # adjust accidental display for each contained pitch
            for pIndex in range(len(c.pitches)):
                if c.pitches[pIndex].accidental is None:
                    continue
                c.pitches[pIndex].accidental.displayStatus = accStatusList[
                    pIndex]
            dst.coreAppend(c)

            # ql += t.quarterLength

        elif isinstance(t, abcFormat.ABCNote):
            # add the attached chord symbol
            if t.chordSymbols:
                cs_name = t.chordSymbols[0]
                cs_name = re.sub('["]', '', cs_name).lstrip().rstrip()
                cs_name = re.sub('[()]', '', cs_name)
                cs_name = common.cleanedFlatNotation(cs_name)
                try:
                    if cs_name in ('NC', 'N.C.', 'No Chord', 'None'):
                        cs = harmony.NoChord(cs_name)
                    else:
                        cs = harmony.ChordSymbol(cs_name)
                    dst.coreAppend(cs, setActiveSite=False)
                    dst.coreElementsChanged()
                except ValueError:
                    pass  # Exclude malformed chord
            if t.isRest:
                n = note.Rest()
            else:
                n = note.Note(t.pitchName)
                if n.pitch.accidental is not None:
                    n.pitch.accidental.displayStatus = t.accidentalDisplayStatus

            n.duration.quarterLength = t.quarterLength
            if t.activeTuplet:
                thisTuplet = copy.deepcopy(t.activeTuplet)
                if thisTuplet.durationNormal is None:
                    thisTuplet.setDurationType(n.duration.type,
                                               n.duration.dots)
                n.duration.appendTuplet(thisTuplet)

            # start or end a tie at note n
            if t.tie is not None:
                if t.tie in ('start', 'continue'):
                    n.tie = tie.Tie(t.tie)
                    n.tie.style = 'normal'
                elif t.tie == 'stop':
                    n.tie = tie.Tie(t.tie)
            # Was: Extremely Slow for large Opus files... why?
            # Answer: some pieces didn't close all their spanners, so
            # everything was in a Slur/Diminuendo, etc.
            for span in t.applicableSpanners:
                span.addSpannedElements(n)

            if t.inGrace:
                n = n.getGrace()

            n.articulations = []
            while any(t.articulations):
                tokenArticulationStr = t.articulations.pop()
                if tokenArticulationStr not in _abcArticulationsToM21:
                    continue
                m21ArticulationClass = _abcArticulationsToM21[
                    tokenArticulationStr]
                m21ArticulationObj = m21ArticulationClass()
                n.articulations.append(m21ArticulationObj)

            dst.coreAppend(n, setActiveSite=False)

        elif isinstance(t, abcFormat.ABCSlurStart):
            p.coreAppend(t.slurObj)
        elif isinstance(t, abcFormat.ABCCrescStart):
            p.coreAppend(t.crescObj)
        elif isinstance(t, abcFormat.ABCDimStart):
            p.coreAppend(t.dimObj)
    dst.coreElementsChanged()
    return postTransposition, clefSet
Ejemplo n.º 3
0
def _musedataRecordListToNoteOrChord(records, previousElement=None):
    '''Given a list of MuseDataRecord objects, return a configured
    :class:`~music21.note.Note` or :class:`~music21.chord.Chord`.

    Optionally pass a previous element, which may be music21 Note, Chord, or Rest; 
    this is used to determine tie status
    '''
    from music21 import note
    from music21 import chord
    from music21 import tie

    if len(records) == 1:
        post = note.Note()
        # directly assign pitch object; will already have accidental
        post.pitch = records[0].getPitchObject()
    else:
        #environLocal.printDebug(['attempting chord creation: records', len(records)])
        # can supply a lost of Pitch objects at creation
        post = chord.Chord([r.getPitchObject() for r in records])

    # if a chord, we are assume that all durations are the same
    post.quarterLength = records[0].getQuarterLength()

    # see if there are nay lyrics; not sure what to do if lyrics are defined
    # for multiple chord tones
    lyricList = records[0].getLyrics()
    if lyricList is not None:
        # cyclicalling addLyric will auto increment lyric number assinged
        for lyric in lyricList:
            post.addLyric(lyric)

    # see if there are any beams; again, get from first record only
    beamsChars = records[0].getBeams()
    if beamsChars is not None:
        post.beams = _musedataBeamToBeams(beamsChars)

    # get accents and expressions; assumes all on first
    # returns an empty list of None
    dynamicObjs = []  # stored in stream, not Note

    for a in records[0].getArticulationObjects():
        post.articulations.append(a)
    for e in records[0].getExpressionObjects():
        post.expressions.append(e)

    for d in records[0].getDynamicObjects():
        dynamicObjs.append(d)

    # presently this sets a single tie for a chord; may be different cases
    if records[0].isTied():
        post.tie = tie.Tie('start')  # can be start or continue;
        if previousElement != None and previousElement.tie != None:
            # if previous is a start or a continue; this has to be a continue
            # as musedata does not mark the end of a tie
            if previousElement.tie.type in ['start', 'continue']:
                post.tie = tie.Tie('continue')
    else:  # if no tie indication in the musedata record
        if previousElement != None and previousElement.tie != None:
            if previousElement.tie.type in ['start', 'continue']:
                post.tie = tie.Tie('stop')  # can be start, end, continue
    return post, dynamicObjs
Ejemplo n.º 4
0
def parseTokens(mh, dst, p, useMeasures):
    # in case need to transpose due to clef indication
    from music21 import abcFormat

    postTransposition = 0
    clefSet = False
    for t in mh.tokens:
        if isinstance(t, abcFormat.ABCMetadata):
            if t.isMeter():
                ts = t.getTimeSignatureObject()
                if ts != None:  # can be None
                    # should append at the right position
                    if useMeasures:  # assume at start of measures
                        dst.timeSignature = ts
                    else:
                        dst._appendCore(ts)
            elif t.isKey():
                ks = t.getKeySignatureObject()
                if useMeasures:  # assume at start of measures
                    dst.keySignature = ks
                else:
                    dst._appendCore(ks)
                # check for clef information sometimes stored in key
                clefObj, transposition = t.getClefObject()
                if clefObj != None:
                    clefSet = False
                    #environLocal.printDebug(['found clef in key token:', t,
                    #     clefObj, transposition])
                    if useMeasures:  # assume at start of measures
                        dst.clef = clefObj
                    else:
                        dst._appendCore(clefObj)
                    postTransposition = transposition
            elif t.isTempo():
                mmObj = t.getMetronomeMarkObject()
                dst._appendCore(mmObj)

        # as ABCChord is subclass of ABCNote, handle first
        elif isinstance(t, abcFormat.ABCChord):
            # may have more than notes?
            pitchNameList = []
            accStatusList = []  # accidental display status list
            for tSub in t.subTokens:
                # notes are contained as subtokens are already parsed
                if isinstance(tSub, abcFormat.ABCNote):
                    pitchNameList.append(tSub.pitchName)
                    accStatusList.append(tSub.accidentalDisplayStatus)
            c = chord.Chord(pitchNameList)
            c.quarterLength = t.quarterLength
            # adjust accidental display for each contained pitch
            for pIndex in range(len(c.pitches)):
                if c.pitches[pIndex].accidental == None:
                    continue
                c.pitches[pIndex].accidental.displayStatus = accStatusList[
                    pIndex]
            dst._appendCore(c)

            #ql += t.quarterLength

        elif isinstance(t, abcFormat.ABCNote):
            if t.isRest:
                n = note.Rest()
            else:
                n = note.Note(t.pitchName)
                if n.pitch.accidental != None:
                    n.pitch.accidental.displayStatus = t.accidentalDisplayStatus

            n.quarterLength = t.quarterLength

            # start or end a tie at note n
            if t.tie is not None:
                if t.tie == "start":
                    n.tie = tie.Tie(t.tie)
                    n.tie.style = "normal"
                elif t.tie == "stop":
                    n.tie = tie.Tie(t.tie)
            ### Was: Extremely Slow for large Opus files... why?
            ### Answer: some pieces didn't close all their spanners, so
            ###         everything was in a Slur/Diminuendo, etc.
            for span in t.applicableSpanners:
                span.addSpannedElements(n)

            if t.inGrace:
                n = n.getGrace()

            n.articulations = []
            while any(t.artic):
                tmp = t.artic.pop()
                if tmp == "staccato":
                    n.articulations.append(articulations.Staccato())
                elif tmp == "upbow":
                    n.articulations.append(articulations.UpBow())
                elif tmp == "downbow":
                    n.articulations.append(articulations.DownBow())
                elif tmp == "accent":
                    n.articulations.append(articulations.Accent())
                elif tmp == "strongaccent":
                    n.articulations.append(articulations.StrongAccent())
                elif tmp == "tenuto":
                    n.articulations.append(articulations.Tenuto())

            dst._appendCore(n)
        elif isinstance(t, abcFormat.ABCSlurStart):
            p._appendCore(t.slurObj)
        elif isinstance(t, abcFormat.ABCCrescStart):
            p._appendCore(t.crescObj)
        elif isinstance(t, abcFormat.ABCDimStart):
            p._appendCore(t.dimObj)
    dst.elementsChanged()
    return postTransposition, clefSet
Ejemplo n.º 5
0
def abcToStreamPart(abcHandler, inputM21=None, spannerBundle=None):
    '''
    Handler conversion of a single Part of a multi-part score.
    Results are added into the provided inputM21 object
    or a newly created Part object

    The part object is then returned.
    '''
    from music21 import abcFormat

    if inputM21 is None:
        p = stream.Part()
    else:
        p = inputM21

    if spannerBundle is None:
        #environLocal.printDebug(['mxToMeasure()', 'creating SpannerBundle'])
        spannerBundle = spanner.SpannerBundle()

    # need to call on entire handlers, as looks for special criterial,
    # like that at least 2 regular bars are used, not just double bars
    if abcHandler.definesMeasures():
        # first, split into a list of Measures; if there is only metadata and
        # one measure, that means that no measures are defined
        barHandlers = abcHandler.splitByMeasure()
        #environLocal.printDebug(['barHandlers', len(barHandlers)])
        # merge loading meta data with each bar that preceedes it
        mergedHandlers = abcFormat.mergeLeadingMetaData(barHandlers)
        #environLocal.printDebug(['mergedHandlers', len(mergedHandlers)])
    else:  # simply stick in a single list
        mergedHandlers = [abcHandler]

    # if only one merged handler, do not create measures
    if len(mergedHandlers) <= 1:
        useMeasures = False
    else:
        useMeasures = True

    # each unit in merged handlers defines possible a Measure (w/ or w/o metadata), trailing meta data, or a single collection of metadata and note data

    barCount = 0
    measureNumber = 1
    # merged handler are ABCHandlerBar objects, defining attributes for barlines

    for mh in mergedHandlers:
        # if use measures and the handler has notes; otherwise add to part
        #environLocal.printDebug(['abcToStreamPart', 'handler', 'left:', mh.leftBarToken, 'right:', mh.rightBarToken, 'len(mh)', len(mh)])

        if useMeasures and mh.hasNotes():
            #environLocal.printDebug(['abcToStreamPart', 'useMeasures', useMeasures, 'mh.hasNotes()', mh.hasNotes()])
            dst = stream.Measure()
            # bar tokens are already extracted form token list and are available
            # as attributes on the handler object
            # may return None for a regular barline

            if mh.leftBarToken is not None:
                # this may be Repeat Bar subclass
                bLeft = mh.leftBarToken.getBarObject()
                if bLeft != None:
                    dst.leftBarline = bLeft
                if mh.leftBarToken.isRepeatBracket():
                    # get any open spanners of RepeatBracket type
                    rbSpanners = spannerBundle.getByClassComplete(
                        'RepeatBracket', False)
                    # this indication is most likely an opening, as ABC does
                    # not encode second ending ending boundaries
                    # we can still check thought:
                    if len(rbSpanners) == 0:
                        # add this measure as a componnt
                        rb = spanner.RepeatBracket(dst)
                        # set number, returned here
                        rb.number = mh.leftBarToken.isRepeatBracket()
                        # only append if created; otherwise, already stored
                        spannerBundle.append(rb)
                    else:  # close it here
                        rb = rbSpanners[0]  # get RepeatBracket
                        rb.addSpannedElements(dst)
                        rb.completeStatus = True
                        # this returns 1 or 2 depending on the repeat
                    # in ABC, second repeats close immediately; that is
                    # they never span more than one measure
                    if mh.leftBarToken.isRepeatBracket() == 2:
                        rb.completeStatus = True

            if mh.rightBarToken is not None:
                bRight = mh.rightBarToken.getBarObject()
                if bRight != None:
                    dst.rightBarline = bRight
                # above returns bars and repeats; we need to look if we just
                # have repeats
                if mh.rightBarToken.isRepeat():
                    # if we have a right bar repeat, and a spanner repeat
                    # bracket is open (even if just assigned above) we need
                    # to close it now.
                    # presently, now r bar conditions start a repeat bracket
                    rbSpanners = spannerBundle.getByClassComplete(
                        'RepeatBracket', False)
                    if len(rbSpanners) > 0:
                        rb = rbSpanners[0]  # get RepeatBracket
                        rb.addSpannedElements(dst)
                        rb.completeStatus = True
                        # this returns 1 or 2 depending on the repeat
                        # do not need to append; already in bundle
            barCount += 1
        else:
            dst = p  # store directly in a part instance

        #environLocal.printDebug([mh, 'dst', dst])
        #ql = 0 # might not be zero if there is a pickup
        # in case need to transpose due to clef indication
        postTransposition = 0
        clefSet = False
        for t in mh.tokens:
            if isinstance(t, abcFormat.ABCMetadata):
                if t.isMeter():
                    ts = t.getTimeSignatureObject()
                    if ts != None:  # can be None
                        # should append at the right position
                        if useMeasures:  # assume at start of measures
                            dst.timeSignature = ts
                        else:
                            dst._appendCore(ts)
                elif t.isKey():
                    ks = t.getKeySignatureObject()
                    if useMeasures:  # assume at start of measures
                        dst.keySignature = ks
                    else:
                        dst._appendCore(ks)
                    # check for clef information sometimes stored in key
                    clefObj, transposition = t.getClefObject()
                    if clefObj != None:
                        clefSet = False
                        #environLocal.printDebug(['found clef in key token:', t, clefObj, transposition])
                        if useMeasures:  # assume at start of measures
                            dst.clef = clefObj
                        else:
                            dst._appendCore(clefObj)
                        postTransposition = transposition
                elif t.isTempo():
                    mmObj = t.getMetronomeMarkObject()
                    dst._appendCore(mmObj)

            # as ABCChord is subclass of ABCNote, handle first
            elif isinstance(t, abcFormat.ABCChord):
                # may have more than notes?
                pitchNameList = []
                accStatusList = []  # accidental display status list
                for tSub in t.subTokens:
                    # notes are contained as subtokens are already parsed
                    if isinstance(tSub, abcFormat.ABCNote):
                        pitchNameList.append(tSub.pitchName)
                        accStatusList.append(tSub.accidentalDisplayStatus)
                c = chord.Chord(pitchNameList)
                c.quarterLength = t.quarterLength
                # adjust accidental display for each contained pitch
                for pIndex in range(len(c.pitches)):
                    if c.pitches[pIndex].accidental == None:
                        continue
                    c.pitches[pIndex].accidental.displayStatus = accStatusList[
                        pIndex]
                dst._appendCore(c)

                #ql += t.quarterLength

            elif isinstance(t, abcFormat.ABCNote):
                if t.isRest:
                    n = note.Rest()
                else:
                    n = note.Note(t.pitchName)
                    if n.accidental != None:
                        n.accidental.displayStatus = t.accidentalDisplayStatus

                n.quarterLength = t.quarterLength

                # start or end a tie at note n
                if t.tie is not None:
                    if t.tie == "start":
                        n.tie = tie.Tie(t.tie)
                        n.tie.style = "normal"
                    elif t.tie == "stop":
                        n.tie = tie.Tie(t.tie)
                ### Was: Extremely Slow for large Opus files... why?
                ### Answer: some pieces didn't close all their spanners, so
                ###         everything was in a Slur/Diminuendo, etc.
                for span in t.applicableSpanners:
                    span.addSpannedElements(n)

                if t.inGrace:
                    n = n.getGrace()

                n.articulations = []
                while len(t.artic) > 0:
                    tmp = t.artic.pop()
                    if tmp == "staccato":
                        n.articulations.append(articulations.Staccato())
                    if tmp == "upbow":
                        n.articulations.append(articulations.UpBow())
                    if tmp == "downbow":
                        n.articulations.append(articulations.DownBow())
                    if tmp == "accent":
                        n.articulations.append(articulations.Accent())
                    if tmp == "strongaccent":
                        n.articulations.append(articulations.StrongAccent())
                    if tmp == "tenuto":
                        n.articulations.append(articulations.Tenuto())

                dst._appendCore(n)
            elif isinstance(t, abcFormat.ABCSlurStart):
                p._appendCore(t.slurObj)
            elif isinstance(t, abcFormat.ABCCrescStart):
                p._appendCore(t.crescObj)
            elif isinstance(t, abcFormat.ABCDimStart):
                p._appendCore(t.dimObj)
        dst._elementsChanged()

        # append measure to part; in the case of trailing meta data
        # dst may be part, even though useMeasures is True
        if useMeasures and 'Measure' in dst.classes:
            # check for incomplete bars
            # must have a time signature in this bar, or defined recently
            # could use getTimeSignatures() on Stream

            if barCount == 1 and dst.timeSignature != None:  # easy case
                # can only do this b/c ts is defined
                if dst.barDurationProportion() < 1.0:
                    dst.padAsAnacrusis()
                    dst.number = 0
                    #environLocal.printDebug(['incompletely filled Measure found on abc import; interpreting as a anacrusis:', 'padingLeft:', dst.paddingLeft])
            else:
                dst.number = measureNumber
                measureNumber += 1
            p._appendCore(dst)

    try:
        reBar(p, inPlace=True)
    except (ABCTranslateException, meter.MeterException, ZeroDivisionError):
        pass
    # clefs are not typically defined, but if so, are set to the first measure
    # following the meta data, or in the open stream
    if not clefSet:
        if useMeasures:  # assume at start of measures
            p.getElementsByClass('Measure')[0].clef = p.flat.bestClef()
        else:
            p._insertCore(0, p.bestClef())

    if postTransposition != 0:
        p.transpose(postTransposition, inPlace=True)

    if useMeasures and len(
            p.flat.getTimeSignatures(searchContext=False,
                                     returnDefault=False)) > 0:
        # call make beams for now; later, import beams
        #environLocal.printDebug(['abcToStreamPart: calling makeBeams'])
        try:
            p.makeBeams(inPlace=True)
        except meter.MeterException as e:
            environLocal.warn("Error in beaming...ignoring: %s" % str(e))

    # copy spanners into topmost container; here, a part
    rm = []
    for sp in spannerBundle.getByCompleteStatus(True):
        p._insertCore(0, sp)
        rm.append(sp)
    # remove from original spanner bundle
    for sp in rm:
        spannerBundle.remove(sp)
    p._elementsChanged()
    return p
Ejemplo n.º 6
0
    def reduceThisMeasure(self, mI, measureIndex, maxChords, closedPosition,
                          forceOctave):
        m = stream.Measure()
        m.number = measureIndex

        mIchord = mI.chordify()
        newPart = self.reduceMeasureToNChords(
            mIchord,
            maxChords,
            weightAlgorithm=self.qlbsmpConsonance,
            trimBelow=0.3)
        #newPart.show('text')
        cLast = None
        cLastEnd = 0.0
        for cEl in newPart:
            cElCopy = copy.deepcopy(cEl)
            if 'Chord' in cEl.classes and closedPosition is not False:
                if forceOctave is not False:
                    cElCopy.closedPosition(forceOctave=forceOctave,
                                           inPlace=True)
                else:
                    cElCopy.closedPosition(inPlace=True)
                cElCopy.removeRedundantPitches(inPlace=True)
            newOffset = cEl.getOffsetBySite(newPart)

            # extend over gaps
            if cLast is not None:
                if round(newOffset - cLastEnd, 6) != 0.0:
                    cLast.quarterLength += newOffset - cLastEnd
            cLast = cElCopy
            cLastEnd = newOffset + cElCopy.quarterLength
            m._insertCore(newOffset, cElCopy)

        tsContext = mI.parts[0].getContextByClass('TimeSignature')
        if tsContext is not None:
            if round(tsContext.barDuration.quarterLength - cLastEnd, 6) != 0.0:
                cLast.quarterLength += tsContext.barDuration.quarterLength - cLastEnd

        m.elementsChanged()

        # add ties
        if self._lastPitchedObject is not None:
            firstPitched = m[0]
            if self._lastPitchedObject.isNote and firstPitched.isNote:
                if self._lastPitchedObject.pitch == firstPitched.pitch:
                    self._lastPitchedObject.tie = tie.Tie("start")
            elif self._lastPitchedObject.isChord and firstPitched.isChord:
                if len(self._lastPitchedObject) == len(firstPitched):
                    allSame = True
                    for pitchI in range(len(self._lastPitchedObject)):
                        if (self._lastPitchedObject.pitches[pitchI] !=
                                firstPitched.pitches[pitchI]):
                            allSame = False
                    if allSame is True:
                        self._lastPitchedObject.tie = tie.Tie('start')
        self._lastPitchedObject = m[-1]

        sourceMeasureTs = mI.parts[0].getElementsByClass(
            'Measure')[0].timeSignature
        if sourceMeasureTs != self._lastTs:
            m.timeSignature = copy.deepcopy(sourceMeasureTs)
            self._lastTs = sourceMeasureTs

        return m
Ejemplo n.º 7
0
    def multiPartReduction(self, inStream, maxChords = 2, closedPosition = False, forceOctave = False):
        '''
        Return a multipart reduction of a stream.
        '''
        i = 0
        p = stream.Part()
        lastPitchedObject = None
        gobcM = inStream.parts[0].getElementsByClass('Measure')
        lenMeasures = len(gobcM)
        lastTs = None
        while i <= lenMeasures:
            mI = inStream.measure(i, ignoreNumbers=True)
            if len(mI.flat.notesAndRests) == 0:
                if i == 0:
                    pass
                else:
                    break
            else:
                m = stream.Measure()
                m.number = i

                mIchord = mI.chordify()
                newPart = self.reduceMeasureToNChords(mIchord, maxChords, weightAlgorithm=self.qlbsmpConsonance, trimBelow = 0.3)
                #newPart.show('text')
                cLast = None
                cLastEnd = 0.0
                for cEl in newPart:
                    cElCopy = copy.deepcopy(cEl)
                    if 'Chord' in cEl.classes:
                        if closedPosition is not False:
                            if forceOctave is not False:
                                cElCopy.closedPosition(forceOctave = forceOctave, inPlace = True)
                            else:
                                cElCopy.closedPosition(inPlace=True)
                            cElCopy.removeRedundantPitches(inPlace=True)
                    newOffset = cEl.getOffsetBySite(newPart)
                    
                    # extend over gaps
                    if cLast is not None:
                        if round(newOffset - cLastEnd, 6) != 0.0:
                            cLast.quarterLength += newOffset - cLastEnd
                    cLast = cElCopy
                    cLastEnd = newOffset + cElCopy.quarterLength
                    m._insertCore(newOffset, cElCopy)
                
                tsContext = mI.parts[0].getContextByClass('TimeSignature')
                if tsContext is not None:
                    if round(tsContext.barDuration.quarterLength - cLastEnd, 6) != 0.0:
                        cLast.quarterLength += tsContext.barDuration.quarterLength - cLastEnd
                
                
                m.elementsChanged()

                # add ties
                if lastPitchedObject is not None:
                    firstPitched = m[0]
                    if lastPitchedObject.isNote and firstPitched.isNote:
                        if lastPitchedObject.pitch == firstPitched.pitch:
                            lastPitchedObject.tie = tie.Tie("start")
                    elif lastPitchedObject.isChord and firstPitched.isChord:
                        if len(lastPitchedObject) == len(firstPitched):
                            allSame = True
                            for pitchI in range(len(lastPitchedObject)):
                                if lastPitchedObject.pitches[pitchI] != firstPitched.pitches[pitchI]:
                                    allSame = False
                            if allSame is True:
                                lastPitchedObject.tie = tie.Tie('start')
                lastPitchedObject = m[-1]

                sourceMeasureTs = mI.parts[0].getElementsByClass('Measure')[0].timeSignature
                if sourceMeasureTs != lastTs:
                    m.timeSignature = copy.deepcopy(sourceMeasureTs)
                    lastTs = sourceMeasureTs

                p._appendCore(m)
            if self.printDebug == True:
                print(i, " ", end="")
                if i % 20 == 0 and i != 0:
                    print("")
            i += 1
        p.elementsChanged()
        p.getElementsByClass('Measure')[0].insert(0, p.bestClef(allowTreble8vb=True))
        p.makeNotation(inPlace=True)
        return p