def chordToMidiFile(inputM21): # this can be consolidated with noteToMidiFile c = inputM21 mt = midiModule.MidiTrack(1) mt.events += midiModule.getStartEvents(mt) mt.events += chordToMidiEvents(c) mt.events += midiModule.getEndEvents(mt) # set all events to have this track mt.updateEvents() mf = midiModule.MidiFile() mf.tracks = [mt] mf.ticksPerQuarterNote = defaults.ticksPerQuarter return mf
def noteToMidiFile(inputM21): ''' >>> from music21 import note >>> n1 = note.Note() >>> n1.quarterLength = 6 >>> mf = noteToMidiFile(n1) >>> mf.tracks[0].events [<MidiEvent DeltaTime, t=0, track=1, channel=None>, <MidiEvent SEQUENCE_TRACK_NAME, t=0, track=1, channel=None, data=''>, <MidiEvent DeltaTime, t=0, track=1, channel=None>, <MidiEvent NOTE_ON, t=None, track=1, channel=1, pitch=60, velocity=90>, <MidiEvent DeltaTime, t=6144, track=1, channel=None>, <MidiEvent NOTE_OFF, t=None, track=1, channel=1, pitch=60, velocity=0>, <MidiEvent DeltaTime, t=0, track=1, channel=None>, <MidiEvent END_OF_TRACK, t=None, track=1, channel=1, data=''>] ''' n = inputM21 mt = midiModule.MidiTrack(1) mt.events += midiModule.getStartEvents(mt) mt.events += noteToMidiEvents(n) mt.events += midiModule.getEndEvents(mt) # set all events to have this track mt.updateEvents() mf = midiModule.MidiFile() mf.tracks = [mt] mf.ticksPerQuarterNote = defaults.ticksPerQuarter return mf
def streamToMidiTrack(inputM21, instObj=None, translateTimeSignature=True): '''Returns a :class:`music21.midi.base.MidiTrack` object based on the content of this Stream. This assumes that this Stream has only one Part. For Streams that contain sub-streams, use streamToMidiTracks. >>> from music21 import * >>> s = stream.Stream() >>> n = note.Note('g#') >>> n.quarterLength = .5 >>> s.repeatAppend(n, 4) >>> mt = streamToMidiTrack(s) >>> len(mt.events) 20 ''' # NOTE: this procedure requires that there are no overlaps between # adjacent events. if instObj is None: # see if an instrument is defined in this or a parent stream instObj = inputM21.getInstrument() # each part will become midi track # each needs an id; can be adjusted later mt = midiModule.MidiTrack(1) mt.events += midiModule.getStartEvents(mt, instObj.partName) # initial time is start of this Stream #t = self.offset * defaults.ticksPerQuarter # should shift at tracks level t = 0 * defaults.ticksPerQuarter # have to be sorted, have to strip ties # retain containers to get all elements: time signatures, dynamics, etc s = inputM21.stripTies(inPlace=False, matchByPitch=False, retainContainers=True) s = s.flat # probably already flat and sorted for obj in s.sorted: tDurEvent = 0 # the found delta ticks in each event #environLocal.printDebug([str(obj).ljust(26), 't', str(t).ljust(10), 'tdif', tDif]) #if obj.isClass(note.GeneralNote): classes = obj.classes # test: match to 'GeneralNote' if 'Note' in classes or 'Rest' in classes or 'Chord' in classes: #if obj.isNote or obj.isRest or obj.isChord: # find difference since last event to this event # cannot use getOffsetBySite(self), as need flat offset # all values are in tpq; t stores abs time in tpq tDif = (obj.offset * defaults.ticksPerQuarter) - t # includ 'Unpitched' if 'Rest' in classes: # for a rest, do not do anything: difference in offset will # account for the gap continue # get a list of midi events # suing this property here is easier than using the above conversion # methods, as we do not need to know what the object is sub = obj.midiEvents # a note has 4 events: delta/note-on/delta/note-off if 'Note' in classes: sub[0].time = int(round(tDif)) # set first delta # get the duration in ticks; this is the delta to # to the note off message; already set when midi events are # obtained tDurEvent = int(round(sub[2].time)) # a chord has delta/note-on/delta/note-off for each memeber # of the chord. on the first delta is the offset, and only # the first delta preceding the first note-off is the duration if 'Chord' in classes: # divide events between note-on and note-off sub[0].time = int(round(tDif)) # set first delta # only the delta before the first note-off has the event dur # could also sum all durations before setting first # this is the second half of events tDurEvent = int(round(len(sub) / 2)) # to get new current time, need both the duration of the event # as well as any difference found between the last event t += tDif + tDurEvent # add events to the list mt.events += sub elif 'Dynamic' in classes: pass # configure dynamics elif 'TimeSignature' in classes: # find difference since last event to this event # cannot use getOffsetBySite(self), as need flat offset # all values are in tpq; t stores abs time in tpq tDif = (obj.offset * defaults.ticksPerQuarter) - t # return a pair of events sub = timeSignatureToMidiEvents(obj) # for a ts, this will usually be zero, but not always sub[0].time = int(round(tDif)) # set first delta t += tDif mt.events += sub elif 'KeySignature' in classes: tDif = (obj.offset * defaults.ticksPerQuarter) - t environLocal.printDebug([str(obj).ljust(26), 't', str(t).ljust(10), 'tdif', tDif]) sub = keySignatureToMidiEvents(obj) # for a ts, this will usually be zero, but not always sub[0].time = int(round(tDif)) # set first delta t += tDif mt.events += sub else: # other objects may have already been added pass # must update all events with a ref to this MidiTrack mt.updateEvents() mt.events += midiModule.getEndEvents(mt) return mt