def to_musicxml(sc_enc): "Converts Chord tuples (see chorales.prepare_poly) to musicXML" timestep = Duration(1. / FRAMES_PER_CROTCHET) musicxml_score = Stream() prev_chord = dict( ) # midi->(note instance from previous chord), used to determine tie type (start, continue, stop) for has_fermata, chord_notes in sc_enc: notes = [] if len(chord_notes) == 0: # no notes => rest for this frame r = Rest() r.duration = timestep musicxml_score.append(r) else: for note_tuple in chord_notes: note = Note() if has_fermata: note.expressions.append(expressions.Fermata()) note.midi = note_tuple[0] if note_tuple[1]: # current note is tied note.tie = Tie('stop') if prev_chord and note.pitch.midi in prev_chord: prev_note = prev_chord[note.pitch.midi] if prev_note.tie is None: prev_note.tie = Tie('start') else: prev_note.tie = Tie('continue') notes.append(note) prev_chord = {note.pitch.midi: note for note in notes} chord = Chord(notes=notes, duration=timestep) if has_fermata: chord.expressions.append(expressions.Fermata()) musicxml_score.append(chord) return musicxml_score
def durationType(self, n, search, pm, t, parent): ''' The result of a successful search for a duration type: puts a Duration in the right place. ''' self.durationFound = True typeNum = int(search.group(1)) if typeNum == 0: if parent.stateDict['currentTimeSignature'] is not None: n.duration = copy.deepcopy(parent.stateDict['currentTimeSignature'].barDuration) n.expressions.append(expressions.Fermata()) else: n.duration.type = duration.typeFromNumDict[typeNum] t = re.sub(pm, '', t) return t
def ch1_writing_II_A(show=True, *arguments, **keywords): '''p. 7 Compose a melody using whole and half steps in any musical style. This technique uses a random walk of whole or half steps with direction choices determined by whether the present note is above or below the target end. ''' import random from music21 import stream, expressions, pitch dirWeight = [-1, 1] # start with an even distribution s = stream.Stream() nStart = note.Note('g4') n = copy.deepcopy(nStart) while True: # n.quarterLength = random.choice([.25, .5, 1]) n.duration.type = random.choice(['16th', 'eighth', 'quarter']) s.append(n) # if we have written more than fifteen notes # and the last notes matches the first pitch class, then end. if len(s) > 4 and n.pitch.pitchClass == nStart.pitch.pitchClass: n.expressions.append(expressions.Fermata()) break if len(s) > 30: # emergency break in case the piece is too long break direction = random.choice(dirWeight) if direction == 1: i = random.choice(['w', 'h']) else: i = random.choice(['w-', 'h-']) try: n = n.transpose(i) except pitch.AccidentalException: break # end b/c our transposition have exceeded accidental range iSpread = interval.notesToInterval(nStart, n) if iSpread.direction == -1: # we are below our target, favor upward dirWeight = [-1, 1, 1] if iSpread.direction == 1: # we are above our target, favor down dirWeight = [-1, -1, 1] if show: s.show() else: unused_post = musicxml.m21ToString.fromMusic21Object(s)
def testOne(self): c = Converter(self.parseTest) c.parse() s = c.stream sfn = s.flat.notes self.assertEqual(sfn[0].tie.type, 'start') self.assertEqual(sfn[1].tie.type, 'continue') self.assertEqual(sfn[2].tie.type, 'stop') self.assertEqual(sfn[0].step, 'C') self.assertEqual(sfn[0].octave, 3) self.assertEqual(sfn[1].lyric, "hello") self.assertEqual(sfn[2].id, "mine") self.assertEqual(sfn[6].pitch.accidental.alter, 1) self.assertEqual(sfn[7].pitch.accidental.alter, -2) self.assertEqual(sfn[9].editorial.ficta.alter, 0) self.assertEqual(sfn[12].duration.quarterLength, 1.0) self.assertEqual(sfn[12].expressions[0].classes, expressions.Fermata().classes)
def durationType(self, element, search, pm, t, parent): ''' The result of a successful search for a duration type: puts a Duration in the right place. ''' self.durationFound = True typeNum = int(search.group(1)) if typeNum == 0: if parent.stateDict['currentTimeSignature'] is not None: element.duration = copy.deepcopy( parent.stateDict['currentTimeSignature'].barDuration) element.expressions.append(expressions.Fermata()) else: try: element.duration.type = duration.typeFromNumDict[typeNum] except KeyError as ke: raise TinyNotationException( f'Cannot parse token with duration {typeNum}') from ke t = re.sub(pm, '', t) return t
def _getNote(self): if self._note is not None: return self._note noteObj = None storedtie = None stringRep = self.stringRep storedDict = self.storedDict if stringRep is None: raise TinyNotationException( 'Cannot return a note without some parameters') if self.PRECTIE.match(stringRep): environLocal.printDebug('Found Front Tie') stringRep = self.PRECTIE.sub("", stringRep) storedtie = tie.Tie("stop") storedDict['lastNoteTied'] = False elif 'lastNoteTied' in storedDict and storedDict[ 'lastNoteTied'] is True: storedtie = tie.Tie("stop") storedDict['lastNoteTied'] = False x = self.customPitchMatch(stringRep, storedDict) if x is not None: noteObj = x elif (self.REST.match(stringRep) is not None): # rest noteObj = note.Rest() elif (self.OCTAVE2.match(stringRep)): # BB etc. nn = self.OCTAVE2.match(stringRep) noteObj = self._getPitch(nn, 3 - len(nn.group(1))) elif (self.OCTAVE3.match(stringRep)): noteObj = self._getPitch(self.OCTAVE3.match(stringRep), 3) elif (self.OCTAVE5.match(stringRep)): # must match octave 5 then 4! nn = self.OCTAVE5.match(stringRep) noteObj = self._getPitch(nn, 4 + len(nn.group(2))) elif (self.OCTAVE4.match(stringRep)): noteObj = self._getPitch(self.OCTAVE4.match(stringRep), 4) else: raise TinyNotationException( "could not get pitch information from " + str(stringRep)) if storedtie: noteObj.tie = storedtie ## get duration usedLastDuration = False if (self.TYPE.search(stringRep)): typeNum = self.TYPE.search(stringRep).group(1) if (typeNum == "0"): ## special case = full measure + fermata if 'barDuration' in storedDict: noteObj.duration = storedDict['barDuration'] newFerm = expressions.Fermata() noteObj.expressions.append(newFerm) else: noteObj.duration.type = duration.typeFromNumDict[int(typeNum)] else: if 'lastDuration' in storedDict: noteObj.duration = copy.deepcopy(storedDict['lastDuration']) usedLastDuration = True if (noteObj.duration.tuplets): noteObj.duration.tuplets[0].type = "" # if it continues a tuplet it cannot be start; maybe end ## get dots; called out because subclassable self.getDots(stringRep, noteObj) ## get ties if self.TIE.search(stringRep): environLocal.printDebug('Found Tie Tie') storedDict['lastNoteTied'] = True if noteObj.tie is None: noteObj.tie = tie.Tie("start") else: noteObj.tie.type = 'continue' ## use dict to set tuplets if ((('inTrip' in storedDict and storedDict['inTrip'] == True) or ('inQuad' in storedDict and storedDict['inQuad'] == True)) and usedLastDuration == False): newTup = duration.Tuplet() newTup.durationActual.type = noteObj.duration.type newTup.durationNormal.type = noteObj.duration.type if 'inQuad' in storedDict and storedDict['inQuad'] == True: newTup.numNotesActual = 4.0 newTup.numNotesNormal = 3.0 if 'beginTuplet' in storedDict and storedDict[ 'beginTuplet'] == True: newTup.type = "start" noteObj.duration.appendTuplet(newTup) if ((('inTrip' in storedDict and storedDict['inTrip'] == True) or ('inQuad' in storedDict and storedDict['inQuad'] == True)) and ('endTuplet' in storedDict and storedDict['endTuplet'] == True)): noteObj.duration.tuplets[0].type = "stop" storedDict['lastDuration'] = noteObj.duration ## get accidentals if (isinstance(noteObj, note.Note)): if (self.EDSHARP.search(stringRep)): # must come before sharp alter = len(self.EDSHARP.search(stringRep).group(1)) acc1 = pitch.Accidental(alter) noteObj.editorial.ficta = acc1 noteObj.editorial.misc['pmfc-ficta'] = acc1 elif (self.EDFLAT.search(stringRep)): # must come before flat alter = -1 * len(self.EDFLAT.search(stringRep).group(1)) acc1 = pitch.Accidental(alter) noteObj.editorial.ficta = acc1 noteObj.editorial.misc['pmfc-ficta'] = acc1 elif (self.EDNAT.search(stringRep)): acc1 = pitch.Accidental("natural") noteObj.editorial.ficta = acc1 noteObj.editorial.misc['pmfc-ficta'] = acc1 noteObj.accidental = acc1 elif (self.SHARP.search(stringRep)): alter = len(self.SHARP.search(stringRep).group(1)) noteObj.accidental = pitch.Accidental(alter) elif (self.FLAT.search(stringRep)): alter = -1 * len(self.FLAT.search(stringRep).group(1)) noteObj.accidental = pitch.Accidental(alter) self.customNotationMatch(noteObj, stringRep, storedDict) if self.ID_EL.search(stringRep): noteObj.id = self.ID_EL.search(stringRep).group(1) if self.LYRIC.search(stringRep): noteObj.lyric = self.LYRIC.search(stringRep).group(1) self._note = noteObj return self._note