def barlineListFromBarline(self, barlineElement): ''' Indication that the barline at this point should be something other than normal. Capella does not indicate measure breaks or barline breaks normally, so the only barlines that are indicated are unusual ones. Returns a LIST of :class:`~music21.bar.Barline` or :class:`~music21.bar.Repeat` objects because the `repEndBegin` type requires two `bar.Repeat` objects to encode in `music21`. >>> ci = capella.fromCapellaXML.CapellaImporter() >>> barlineTag = ci.domElementFromText('<barline type="end"/>') >>> ci.barlineListFromBarline(barlineTag) [<music21.bar.Barline style=final>] >>> repeatTag = ci.domElementFromText('<barline type="repEndBegin"/>') >>> ci.barlineListFromBarline(repeatTag) [<music21.bar.Repeat direction=end>, <music21.bar.Repeat direction=start>] ''' barlineList = [] hasRepeatEnd = False if 'type' in barlineElement._attrs: barlineType = barlineElement._attrs['type'].value if barlineType.startswith('rep'): # begins with rep if barlineType in self.barlineMap: repeatType = self.barlineMap[barlineType] if repeatType.find('end') > -1: barlineList.append(bar.Repeat('end')) hasRepeatEnd = True if repeatType.find('start') > -1: startRep = bar.Repeat('start') if hasRepeatEnd is True: startRep.priority = 1 barlineList.append(startRep) else: if barlineType in self.barlineMap: barlineList.append( bar.Barline(self.barlineMap[barlineType])) return barlineList
def _addRepeatsFromRepeatEndings(s, repeatEndings): ''' given a Stream and the repeatEndings dict, add repeats to the stream... ''' from music21 import spanner consolidatedRepeats = _consolidateRepeatEndings(repeatEndings) for repeatEndingTuple in consolidatedRepeats: measureList, endingNumber = repeatEndingTuple[0], repeatEndingTuple[1] rb = spanner.RepeatBracket(measureList, number=endingNumber) rbOffset = measureList[0].getOffsetBySite(s) #Adding repeat bracket to stream at beginning of repeated section. #Maybe better at end? s.insert(rbOffset, rb) if endingNumber == 1: # should be "if not max(endingNumbers), but we can't tell that for each repeat... if measureList[-1].rightBarline is None: measureList[-1].rightBarline = bar.Repeat(direction='end')
def testSortorder(self): from music21 import stream, bar, clef, note, metadata m = stream.Measure() b = bar.Repeat() m.leftBarline = b c = clef.BassClef() m.append(c) n = note.Note() m.append(n) # check sort order self.assertEqual(m[0], b) self.assertEqual(m[1], c) self.assertEqual(m[2], n) # if we add metadata, it sorts ahead of bar md = metadata.Metadata() m.insert(0, md) self.assertEqual(m[0], md) self.assertEqual(m[1], b)
def createBarlines(self, attributes): r''' Translates bar lines into music21. >>> nwt = noteworthy.translate.NoteworthyTranslator() >>> nwt.currentPart = stream.Part() >>> nwt.currentMeasure = stream.Measure() >>> nwt.createBarlines({"Style":"MasterRepeatOpen"}) >>> nwt.currentMeasure <music21.stream.Measure 0 offset=0.0> >>> nwt.currentMeasure.leftBarline <music21.bar.Repeat direction=start> ''' self.activeAccidentals = {} if 'Style' not in attributes: # pure barline self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() return style = attributes['Style'] if style == "MasterRepeatOpen": self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() self.currentMeasure.leftBarline = bar.Repeat(direction='start') elif style == "MasterRepeatClose": self.currentMeasure.rightBarline = bar.Repeat(direction='end') self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() elif style == "LocalRepeatOpen": self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() self.currentMeasure.leftBarline = bar.Repeat(direction='start') elif style == "LocalRepeatClose": self.currentMeasure.rightBarline = bar.Repeat(direction='end') self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() elif style == "Double": self.currentMeasure.rightBarline = bar.Barline('double') self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() elif style == "SectionOpen": self.currentMeasure.rightBarline = bar.Barline('heavy-light') self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() elif style == "SectionClose": self.currentMeasure.rightBarline = bar.Barline('final') self.currentPart.append(self.currentMeasure) self.currentMeasure = stream.Measure() else: raise NoteworthyTranslateException('cannot find a style %s in our list' % style)
def romanTextToStreamScore(rtHandler, inputM21=None): '''The main processing module for single-movement RomanText works. Given a romanText handler or string, return or fill a Score Stream. ''' # accept a string directly; mostly for testing if common.isStr(rtHandler): rtf = rtObjects.RTFile() rtHandler = rtf.readstr(rtHandler) # return handler, processes tokens # this could be just a Stream, but b/c we are creating metadata, perhaps better to match presentation of other scores. from music21 import metadata from music21 import stream from music21 import note from music21 import meter from music21 import key from music21 import roman from music21 import tie if inputM21 == None: s = stream.Score() else: s = inputM21 # metadata can be first md = metadata.Metadata() s.insert(0, md) p = stream.Part() # ts indication are found in header, and also found elsewhere tsCurrent = meter.TimeSignature('4/4') # create default 4/4 tsSet = False # store if set to a measure lastMeasureToken = None lastMeasureNumber = 0 previousRn = None keySigCurrent = None keySigSet = True # set a keySignature foundAKeySignatureSoFar = False kCurrent, unused_prefixLyric = _getKeyAndPrefix( 'C') # default if none defined prefixLyric = '' repeatEndings = {} rnKeyCache = {} for t in rtHandler.tokens: try: # environLocal.printDebug(['token', t]) if t.isTitle(): md.title = t.data elif t.isWork(): md.alternativeTitle = t.data elif t.isPiece(): md.alternativeTitle = t.data elif t.isComposer(): md.composer = t.data elif t.isMovement(): md.movementNumber = t.data elif t.isTimeSignature(): tsCurrent = meter.TimeSignature(t.data) tsSet = False # environLocal.printDebug(['tsCurrent:', tsCurrent]) elif t.isKeySignature(): if t.data == "": keySigCurrent = key.KeySignature(0) elif t.data == "Bb": keySigCurrent = key.KeySignature(-1) else: pass # better to print a message # environLocal.printDebug(['still need to write a generic RomanText KeySignature routine. this is just temporary']) # raise RomanTextTranslateException("still need to write a generic RomanText KeySignature routine. this is just temporary") keySigSet = False # environLocal.printDebug(['keySigCurrent:', keySigCurrent]) foundAKeySignatureSoFar = True elif t.isMeasure(): # environLocal.printDebug(['handling measure token:', t]) #if t.number[0] % 10 == 0: # print "at number " + str(t.number[0]) if t.variantNumber is not None: # environLocal.printDebug(['skipping variant: %s' % t]) continue if t.variantLetter is not None: # environLocal.printDebug(['skipping variant: %s' % t]) continue # if this measure number is more than 1 greater than the last # defined measure number, and the previous chord is not None, # then fill with copies of the last-defined measure if ((t.number[0] > lastMeasureNumber + 1) and (previousRn is not None)): for i in range(lastMeasureNumber + 1, t.number[0]): mFill = stream.Measure() mFill.number = i newRn = copy.deepcopy(previousRn) newRn.lyric = "" # set to entire bar duration and tie newRn.duration = copy.deepcopy(tsCurrent.barDuration) if previousRn.tie is None: previousRn.tie = tie.Tie('start') else: previousRn.tie.type = 'continue' # set to stop for now; may extend on next iteration newRn.tie = tie.Tie('stop') previousRn = newRn mFill.append(newRn) appendMeasureToRepeatEndingsDict( lastMeasureToken, mFill, repeatEndings, i) p._appendCore(mFill) lastMeasureNumber = t.number[0] - 1 lastMeasureToken = t # create a new measure or copy a past measure if len(t.number) == 1 and t.isCopyDefinition: # if not a range p.elementsChanged() m, kCurrent = _copySingleMeasure(t, p, kCurrent) p._appendCore(m) lastMeasureNumber = m.number lastMeasureToken = t romans = m.getElementsByClass(roman.RomanNumeral, returnStreamSubClass='list') if len(romans) > 0: previousRn = romans[-1] elif len(t.number) > 1: p.elementsChanged() measures, kCurrent = _copyMultipleMeasures(t, p, kCurrent) p.append(measures) # appendCore does not work with list lastMeasureNumber = measures[-1].number lastMeasureToken = t romans = measures[-1].getElementsByClass( roman.RomanNumeral, returnStreamSubClass='list') if len(romans) > 0: previousRn = romans[-1] else: m = stream.Measure() m.number = t.number[0] appendMeasureToRepeatEndingsDict(t, m, repeatEndings) lastMeasureNumber = t.number[0] lastMeasureToken = t if not tsSet: m.timeSignature = tsCurrent tsSet = True # only set when changed if not keySigSet and keySigCurrent is not None: m.insert(0, keySigCurrent) keySigSet = True # only set when changed o = 0.0 # start offsets at zero previousChordInMeasure = None pivotChordPossible = False numberOfAtoms = len(t.atoms) setKeyChangeToken = False # first RomanNumeral object after a key change should have this set to True for i, a in enumerate(t.atoms): if isinstance(a, rtObjects.RTKey) or \ ((foundAKeySignatureSoFar == False) and \ (isinstance(a, rtObjects.RTAnalyticKey))): # found a change of Key+KeySignature or # just found a change of analysis but no keysignature so far # environLocal.printDebug(['handling key token:', a]) try: # this sets the key and the keysignature kCurrent, pl = _getKeyAndPrefix(a) prefixLyric += pl except: raise RomanTextTranslateException( 'cannot get key from %s in line %s' % (a.src, t.src)) # insert at beginning of measure if at beginning -- for things like pickups. if m.number < 2: m._insertCore(0, kCurrent) else: m._insertCore(o, kCurrent) foundAKeySignatureSoFar = True setKeyChangeToken = True elif isinstance(a, rtObjects.RTKeySignature): try: # this sets the keysignature but not the prefix text thisSig = a.getKeySignature() except: raise RomanTextTranslateException( 'cannot get key from %s in line %s' % (a.src, t.src)) #insert at beginning of measure if at beginning -- for things like pickups. if m.number < 2: m._insertCore(0, thisSig) else: m._insertCore(o, thisSig) foundAKeySignatureSoFar = True elif isinstance(a, rtObjects.RTAnalyticKey): # just a change in analyzed key, not a change in anything else #try: # this sets the key, not the keysignature kCurrent, pl = _getKeyAndPrefix(a) prefixLyric += pl setKeyChangeToken = True #except: # raise RomanTextTranslateException('cannot get key from %s in line %s' % (a.src, t.src)) elif isinstance(a, rtObjects.RTBeat): # set new offset based on beat try: o = a.getOffset(tsCurrent) except ValueError: raise RomanTextTranslateException( "cannot properly get an offset from beat data %s under timeSignature %s in line %s" % (a.src, tsCurrent, t.src)) if (previousChordInMeasure is None and previousRn is not None and o > 0): # setting a new beat before giving any chords firstChord = copy.deepcopy(previousRn) firstChord.quarterLength = o firstChord.lyric = "" if previousRn.tie == None: previousRn.tie = tie.Tie('start') else: previousRn.tie.type = 'continue' firstChord.tie = tie.Tie('stop') previousRn = firstChord previousChordInMeasure = firstChord m._insertCore(0, firstChord) pivotChordPossible = False elif isinstance(a, rtObjects.RTNoChord): # use source to evaluation roman rn = note.Rest() if pivotChordPossible == False: # probably best to find duration if previousChordInMeasure is None: pass # use default duration else: # update duration of previous chord in Measure oPrevious = previousChordInMeasure.getOffsetBySite( m) newQL = o - oPrevious if newQL <= 0: raise RomanTextTranslateException( 'too many notes in this measure: %s' % t.src) previousChordInMeasure.quarterLength = newQL prefixLyric = "" m._insertCore(o, rn) previousChordInMeasure = rn previousRn = rn pivotChordPossible = False elif isinstance(a, rtObjects.RTChord): # use source to evaluation roman try: asrc = a.src # if kCurrent.mode == 'minor': # if asrc.lower().startswith('vi'): #vi or vii w/ or w/o o # if asrc.upper() == a.src: # VI or VII to bVI or bVII # asrc = 'b' + asrc cacheTuple = (asrc, kCurrent.tonicPitchNameWithCase) if USE_RN_CACHE and cacheTuple in rnKeyCache: #print "Got a match: " + str(cacheTuple) # Problems with Caches not picking up pivot chords... Not faster, see below. rn = copy.deepcopy(rnKeyCache[cacheTuple]) else: #print "No match for: " + str(cacheTuple) rn = roman.RomanNumeral( asrc, copy.deepcopy(kCurrent)) rnKeyCache[cacheTuple] = rn # surprisingly, not faster... and more dangerous #rn = roman.RomanNumeral(asrc, kCurrent) ## SLOWEST!!! #rn = roman.RomanNumeral(asrc, kCurrent.tonicPitchNameWithCase) #>>> from timeit import timeit as t #>>> t('roman.RomanNumeral("IV", "c#")', 'from music21 import roman', number=1000) #45.75 #>>> t('roman.RomanNumeral("IV", k)', 'from music21 import roman, key; k = key.Key("c#")', number=1000) #16.09 #>>> t('roman.RomanNumeral("IV", copy.deepcopy(k))', 'from music21 import roman, key; import copy; k = key.Key("c#")', number=1000) #22.49 ## key cache, does not help much... #>>> t('copy.deepcopy(r)', 'from music21 import roman; import copy; r = roman.RomanNumeral("IV", "c#")', number=1000) #19.01 if setKeyChangeToken is True: rn.followsKeyChange = True setKeyChangeToken = False else: rn.followsKeyChange = False except (roman.RomanNumeralException, common.Music21CommonException): #environLocal.printDebug('cannot create RN from: %s' % a.src) rn = note.Note() # create placeholder if pivotChordPossible == False: # probably best to find duration if previousChordInMeasure is None: pass # use default duration else: # update duration of previous chord in Measure oPrevious = previousChordInMeasure.getOffsetBySite( m) newQL = o - oPrevious if newQL <= 0: raise RomanTextTranslateException( 'too many notes in this measure: %s' % t.src) previousChordInMeasure.quarterLength = newQL rn.addLyric(prefixLyric + a.src) prefixLyric = "" m._insertCore(o, rn) previousChordInMeasure = rn previousRn = rn pivotChordPossible = True else: previousChordInMeasure.lyric += "//" + prefixLyric + a.src previousChordInMeasure.pivotChord = rn prefixLyric = "" pivotChordPossible = False elif isinstance(a, rtObjects.RTRepeat): if o == 0: if isinstance(a, rtObjects.RTRepeatStart): m.leftBarline = bar.Repeat( direction='start') else: rtt = RomanTextUnprocessedToken(a) m._insertCore(o, rtt) elif tsCurrent is not None and ( tsCurrent.barDuration.quarterLength == o or i == numberOfAtoms - 1): if isinstance(a, rtObjects.RTRepeatStop): m.rightBarline = bar.Repeat( direction='end') else: rtt = RomanTextUnprocessedToken(a) m._insertCore(o, rtt) else: # mid measure repeat signs rtt = RomanTextUnprocessedToken(a) m._insertCore(o, rtt) else: rtt = RomanTextUnprocessedToken(a) m._insertCore(o, rtt) #environLocal.warn("Got an unknown token: %r" % a) # may need to adjust duration of last chord added if tsCurrent is not None: previousRn.quarterLength = tsCurrent.barDuration.quarterLength - o m.elementsChanged() p._appendCore(m) except Exception: import traceback tracebackMessage = traceback.format_exc() raise RomanTextTranslateException( "At line %d for token %r, an exception was raised: \n%s" % (t.lineNumber, t, tracebackMessage)) p.elementsChanged() fixPickupMeasure(p) p.makeBeams(inPlace=True) p.makeAccidentals(inPlace=True) _addRepeatsFromRepeatEndings(p, repeatEndings) # 1st and second endings... s.insert(0, p) return s
def convertM21(self, outVote, arrError, ground): errorColor = "#ff0000" missingColor = "#00ff00" # sOut=stream.Stream() sOut = stream.Score() sPart = stream.Part() measureIndex = 1 measure = stream.Measure() measure.number = measureIndex indexS = 0 for symbol in outVote: mytie = "" realDuration = None s = symbol isError = False isMissing = False if (len(ground) > indexS): sGround = ground[indexS] if (indexS in arrError): isError = True if s == "*": s = sGround isMissing = True if isinstance(s, list): s = s[0] if s.find('TS:') != -1: ts = meter.TimeSignature(s[3:]) if isError: ts.color = errorColor if isMissing: ts.color = missingColor measure.append(ts) if s.find('KS:') != -1: k = key.KeySignature(int(s[3:])) if isError: k.color = errorColor if isMissing: k.color = missingColor measure.append(k) if s.find('CL:') != -1: c = clef.clefFromString(str(s[3:])) if isError: c.color = errorColor if isMissing: c.color = missingColor measure.append(c) if s.find('N:') != -1: try: if isinstance(symbol, list): realDuration = symbol[1] mytie = symbol[2] sep = s.index("_") duration = s[sep + 1:] # if realDuration!=None: # duration=realDuration if (float(duration) > 0): n = note.Note(s[2:sep], quarterLength=float(duration)) if isError: n.color = errorColor if isMissing: n.color = missingColor if mytie != "": n.tie = tie.Tie(mytie) measure.append(n) except: print "error" + s if s.find('R:') != -1: try: if isinstance(symbol, list): realDuration = symbol[1] mytie = symbol[2] duration = s[2:] # if realDuration!=None: # duration=realDuration n = note.Rest(quarterLength=float(duration)) if isError: n.color = errorColor if isMissing: n.color = missingColor measure.append(n) except: print "error" + s if s.find('C:') != -1: notes = s.split("[:") cPitch = [] for n in notes: if n != 'C:': sep = n.index("_") duration = n[sep + 1:] pitch = n[0:sep] cPitch.append(pitch) c = chord.Chord(cPitch) c.duration.quarterLength = float(duration) if isError: c.color = errorColor if isMissing: c.color = missingColor measure.append(c) if s.find('!') != -1: if isinstance(symbol, list): barType = symbol[1] barRepeat = symbol[2] if barType != "": mybartype = bar.styleToMusicXMLBarStyle(barType) myBar = bar.Barline(style=mybartype) measure.rightBarline = myBar if barRepeat != "": myBar = bar.Repeat(direction=barRepeat) if barRepeat == "start": measure.leftBarline = myBar if barRepeat == "end": measure.rightBarline = myBar sPart.append(measure) measureIndex += 1 measure = stream.Measure() measure.number = measureIndex indexS += 1 sOut.append(sPart) return sOut