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
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
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
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. ''' 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
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
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