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.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.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
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
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. ''' if inputM21 == 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 = abcModule.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, abcModule.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, abcModule.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, abcModule.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, abcModule.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, abcModule.ABCSlurStart): p._appendCore(t.slurObj) elif isinstance(t, abcModule.ABCCrescStart): p._appendCore(t.crescObj) elif isinstance(t, abcModule.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