Previous topic

music21.midi.realtime

Next topic

music21.musedata

Table Of Contents

Table Of Contents

This Page

music21.midi.translate

Module to translate MIDI data to music21 Streams and voice versa. Note that quantization of notes takes place in the quantize() method not here.

Functions

music21.midi.translate.streamToMidiFile(inputM21)

Converts a Stream hierarchy into a MidiFile object.

>>> s = stream.Stream()
>>> n = note.Note('g#')
>>> n.quarterLength = .5
>>> s.repeatAppend(n, 4)
>>> mf = midi.translate.streamToMidiFile(s)
>>> len(mf.tracks)
1
>>> len(mf.tracks[0].events)
22

From here, you can call mf.writestr() to get the actual file info.

>>> sc = scale.PhrygianScale('g')
>>> s = stream.Stream()
>>> x=[s.append(note.Note(sc.pitchFromDegree(i % 11), quarterLength=.25)) for i in range(60)]
>>> mf = midi.translate.streamToMidiFile(s)
>>> mf.open('/Volumes/xdisc/_scratch/midi.mid', 'wb')
>>> mf.write()
>>> mf.close()  
music21.midi.translate.midiFileToStream(mf, inputM21=None, quantizePost=True)

Convert a MidiFile object to a Stream object.

The inputM21 object can specify an existing Stream (or Stream subclass) to fill.

>>> import os
>>> fp = os.path.join(common.getSourceFilePath(), 'midi', 'testPrimitive',  'test05.mid')
>>> mf = midi.MidiFile()
>>> mf.open(fp)
>>> mf.read()
>>> mf.close()
>>> len(mf.tracks)
1
>>> s = midi.translate.midiFileToStream(mf)
>>> s
<music21.stream.Score ...>
>>> len(s.flat.notesAndRests)
11
music21.midi.translate.chordToMidiEvents(inputM21, includeDeltaTime=True)

Translates a Chord object to a list of base.DeltaTime and base.MidiEvents objects.

See noteToMidiEvents above for more details.

>>> c = chord.Chord(['c3','g#4', 'b5'])
>>> c.volume = volume.Volume(velocity=90)
>>> c.volume.velocityIsRelative = False
>>> eventList = midi.translate.chordToMidiEvents(c)
>>> eventList
[<MidiEvent DeltaTime, t=0, track=None, channel=None>, <MidiEvent NOTE_ON, t=None, track=None, channel=1, pitch=48, velocity=90>, <MidiEvent DeltaTime, t=0, track=None, channel=None>, <MidiEvent NOTE_ON, t=None, track=None, channel=1, pitch=68, velocity=90>, <MidiEvent DeltaTime, t=0, track=None, channel=None>, <MidiEvent NOTE_ON, t=None, track=None, channel=1, pitch=83, velocity=90>, <MidiEvent DeltaTime, t=1024, track=None, channel=None>, <MidiEvent NOTE_OFF, t=None, track=None, channel=1, pitch=48, velocity=0>, <MidiEvent DeltaTime, t=0, track=None, channel=None>, <MidiEvent NOTE_OFF, t=None, track=None, channel=1, pitch=68, velocity=0>, <MidiEvent DeltaTime, t=0, track=None, channel=None>, <MidiEvent NOTE_OFF, t=None, track=None, channel=1, pitch=83, velocity=0>]
music21.midi.translate.chordToMidiFile(inputM21)

Similar to noteToMidiFile, translates a Chord to a fully-formed MidiFile object.

music21.midi.translate.durationToMidi(d)

Converts a Duration object to midi ticks.

Depends on defaults.ticksPerQuarter, Returns an int.

>>> n = note.Note()
>>> n.duration.type = 'half'
>>> midi.translate.durationToMidi(n.duration)
2048
>>> d = duration.Duration()
>>> dReference = midi.translate.midiToDuration(1024, inputM21DurationObject = d)
>>> dReference is d
True
>>> d.type
'quarter'
>>> d.type = '16th'
>>> d.quarterLength
0.25
>>> midi.translate.durationToMidi(d)
256
music21.midi.translate.getEndEvents(mt=None, channel=1)

Returns a list of midi.MidiEvent objects found at the end of a track.

music21.midi.translate.instrumentToMidiEvents(inputM21, includeDeltaTime=True, midiTrack=None, channel=1)

Converts a Instrument object to a list of MidiEvents

TODO: DOCS and TESTS

music21.midi.translate.keySignatureToMidiEvents(ks, includeDeltaTime=True)

Convert a single KeySignature object to a two-element list of midi events, where the first is an empty DeltaTime (unless includeDeltaTime is False) and the second is a KEY_SIGNATURE MidiEvent

>>> ks = key.KeySignature(2)
>>> ks
<music21.key.KeySignature of 2 sharps>
>>> eventList = midi.translate.keySignatureToMidiEvents(ks)
>>> eventList[1]
<MidiEvent KEY_SIGNATURE, t=None, track=None, channel=1, data='\x02\x00'>
>>> ks = key.KeySignature(-5)
>>> ks.mode = 'minor'
>>> ks
<music21.key.KeySignature of 5 flats, mode minor>
>>> eventList = midi.translate.keySignatureToMidiEvents(ks, includeDeltaTime = False)
>>> eventList[0]
<MidiEvent KEY_SIGNATURE, t=None, track=None, channel=1, data='\xfb\x01'>
music21.midi.translate.midiAsciiStringToBinaryString(midiFormat=1, ticksPerQuarterNote=960, tracksEventsList=None)

Convert Ascii midi data to a binary midi string.

tracksEventsList contains a list of tracks which contain also a list of events.
asciiMidiEventList = [‘0 90 27 66’, ‘0 90 3e 60’, ‘3840 80 27 00’, ‘0 80 3e 00’]
The format of one event is : ‘aa bb cc dd’
aa = delta time to last event (integer) bb = Midi event type cc = Note number (hex) dd = Velocity (integer)

Example:

>>> asciiMidiEventList = []
>>> asciiMidiEventList.append('0 90 31 15')
>>> midiTrack = []
>>> midiTrack.append(asciiMidiEventList)
>>> midiBinStr = midi.translate.midiAsciiStringToBinaryString(tracksEventsList = midiTrack)
>>> midiBinStr
b'MThd\x00\x00\x00\x06\x00\x01\x00\x01\x03\xc0MTrk\x00\x00\x00\x04\x00\x901\x0f'
music21.midi.translate.midiEventsToChord(eventList, ticksPerQuarter=None, inputM21=None)

Creates a Chord from a list of DeltaTime and MidiEvent objects. See midiEventsToNote for details.

All DeltaTime objects except the first are ignored.

>>> mt = midi.MidiTrack(1)
>>> dt1 = midi.DeltaTime(mt)
>>> dt1.time = 0
>>> me1 = midi.MidiEvent(mt)
>>> me1.type = "NOTE_ON"
>>> me1.pitch = 45
>>> me1.velocity = 94
>>> dt2 = midi.DeltaTime(mt)
>>> dt2.time = 0
>>> me2 = midi.MidiEvent(mt)
>>> me2.type = "NOTE_ON"
>>> me2.pitch = 46
>>> me2.velocity = 94
>>> dt3 = midi.DeltaTime(mt)
>>> dt3.time = 2048
>>> me3 = midi.MidiEvent(mt)
>>> me3.type = "NOTE_OFF"
>>> me3.pitch = 45
>>> me3.velocity = 0
>>> dt4 = midi.DeltaTime(mt)
>>> dt4.time = 0
>>> me4 = midi.MidiEvent(mt)
>>> me4.type = "NOTE_OFF"
>>> me4.pitch = 46
>>> me4.velocity = 0
>>> c = midi.translate.midiEventsToChord([dt1, me1, dt2, me2, dt3, me3, dt4, me4])
>>> c
<music21.chord.Chord A2 B-2>
>>> c.duration.quarterLength
2.0
music21.midi.translate.midiEventsToInstrument(eventList)

Convert a single MIDI event into a music21 Instrument object.

music21.midi.translate.midiEventsToKeySignature(eventList)

Convert a single MIDI event into a KeySignature object.

>>> mt = midi.MidiTrack(1)
>>> me1 = midi.MidiEvent(mt)
>>> me1.type = "KEY_SIGNATURE"
>>> me1.data = midi.putNumbersAsList([2, 0]) # d major
>>> ks = midi.translate.midiEventsToKeySignature(me1)
>>> ks
<music21.key.KeySignature of 2 sharps, mode major>
>>> ks.mode
'major'
>>> me2 = midi.MidiEvent(mt)
>>> me2.type = "KEY_SIGNATURE"
>>> me2.data = midi.putNumbersAsList([-2, 1]) # g minor
>>> me2.data
'\xfe\x01'
>>> midi.getNumbersAsList(me2.data)
[254, 1]
>>> ks = midi.translate.midiEventsToKeySignature(me2)
>>> ks
<music21.key.KeySignature of 2 flats, mode minor>
>>> ks.mode
'minor'
music21.midi.translate.midiEventsToNote(eventList, ticksPerQuarter=None, inputM21=None)

Convert from a list of midi.DeltaTime and midi.MidiEvent objects to a music21 Note.

The list can be presented in one of two forms:

[deltaTime1, midiEvent1, deltaTime2, midiEvent2]

or

[(deltaTime1, midiEvent1), (deltaTime2, midiEvent2)]

It is assumed, but not checked, that midiEvent2 is an appropriate Note_Off command. Thus, only three elements are really needed.

The inputM21 parameter can be a Note or None; in the case of None, a Note object is created. In either case it returns a Note (N.B.: this will change soon so that None will be returned if inputM21 is given. This will match the behavior of other translate objects).

N.B. this takes in a list of music21 MidiEvent objects so see [...] on how to convert raw MIDI data to MidiEvent objects

In this example, we start a NOTE_ON event at offset 1.0 that lasts for 2.0 quarter notes until we send a zero-velocity NOTE_ON (=NOTE_OFF) event for the same pitch.

>>> mt = midi.MidiTrack(1)
>>> dt1 = midi.DeltaTime(mt)
>>> dt1.time = 1024
>>> me1 = midi.MidiEvent(mt)
>>> me1.type = "NOTE_ON"
>>> me1.pitch = 45
>>> me1.velocity = 94
>>> dt2 = midi.DeltaTime(mt)
>>> dt2.time = 2048
>>> me2 = midi.MidiEvent(mt)
>>> me2.type = "NOTE_ON"
>>> me2.pitch = 45
>>> me2.velocity = 0
>>> n = midi.translate.midiEventsToNote([dt1, me1, dt2, me2])
>>> n.pitch
<music21.pitch.Pitch A2>
>>> n.duration.quarterLength
1.0
>>> n.volume.velocity
94

An inputM21 object can be given in which case it’s set.

>>> m = note.Note()
>>> dummy = midi.translate.midiEventsToNote([dt1, me1, dt2, me2], inputM21=m)
>>> m.pitch
<music21.pitch.Pitch A2>
>>> m.duration.quarterLength
1.0
>>> m.volume.velocity
94
music21.midi.translate.midiEventsToTempo(eventList)

Convert a single MIDI event into a music21 Tempo object.

TODO: Need Tests

music21.midi.translate.midiEventsToTimeSignature(eventList)

Convert a single MIDI event into a music21 TimeSignature object.

>>> mt = midi.MidiTrack(1)
>>> me1 = midi.MidiEvent(mt)
>>> me1.type = "TIME_SIGNATURE"
>>> me1.data = midi.putNumbersAsList([3, 1, 24, 8]) # 3/2 time
>>> ts = midi.translate.midiEventsToTimeSignature(me1)
>>> ts
<music21.meter.TimeSignature 3/2>
>>> me2 = midi.MidiEvent(mt)
>>> me2.type = "TIME_SIGNATURE"
>>> me2.data = midi.putNumbersAsList([3, 4]) # 3/16 time
>>> ts = midi.translate.midiEventsToTimeSignature(me2)
>>> ts
<music21.meter.TimeSignature 3/16>
music21.midi.translate.midiFilePathToStream(filePath, inputM21=None)

Used by music21.converter:

Take in a file path (name of a file on disk) and using midiFileToStream,

return a Score object (or if inputM21 is passed in, use that object instead).

>>> fp = '/Users/test/music21/midi/testPrimitive/test05.mid'
>>> streamScore = midi.translate.midiFilePathToStream(fp)
>>> streamScore
<music21.stream.Score ...>
music21.midi.translate.midiStringToStream(strData)

Convert a string of binary midi data to a Music21 stream.Score object.

TODO: NOT WORKING AS IT SHOULD

# >>> midiBinStr = ‘MThdx00x00x00x06x00x01x00x01x03xc0MTrkx00x00x00x04x00x901x0f’ # # >>> s = midi.translate.midiStringToStream(midiBinStr) # >>> s.show(‘text’) # {0.0} <music21.stream.Part ...> # {0.0} <music21.note.Note G> #

music21.midi.translate.midiToDuration(ticks, ticksPerQuarter=None, inputM21DurationObject=None)

Converts a number of MIDI Ticks to a music21 duration.Duration() object.

Optional parameters include ticksPerQuarter – in case something other than the default.ticksPerQuarter (1024) is used in this file. And it can take a Duration object to modify, specified as inputM21DurationObject

>>> d = midi.translate.midiToDuration(1024)
>>> d
<music21.duration.Duration 1.0>
>>> d.type
'quarter'
>>> n = note.Note()
>>> midi.translate.midiToDuration(3072, inputM21DurationObject=n.duration)
<music21.duration.Duration 3.0>
>>> n.duration.type
'half'
>>> n.duration.dots
1

More complex rhythms can also be set automatically:

>>> d2 = duration.Duration()
>>> d2reference = midi.translate.midiToDuration(1200, inputM21DurationObject=d2)
>>> d2 is d2reference
True
>>> d2.type
'complex'
>>> d2.quarterLength
1.171875
>>> d2.components
[<music21.duration.DurationUnit 1.0>, <music21.duration.DurationUnit 0.125>, <music21.duration.DurationUnit 0.046875>]
>>> d2.components[2].type
'128th'
>>> d2.components[2].dots
1
music21.midi.translate.midiTrackToStream(mt, ticksPerQuarter=None, quantizePost=True, inputM21=None)

Note that quantization takes place in stream.py since it’s useful not just for MIDI.

>>> import os
>>> fp = os.path.join(common.getSourceFilePath(), 'midi', 'testPrimitive',  'test05.mid')
>>> mf = midi.MidiFile()
>>> mf.open(fp)
>>> mf.read()
>>> mf.close()
>>> len(mf.tracks)
1
>>> mt = mf.tracks[0] 
>>> s = midi.translate.midiTrackToStream(mt)
>>> s
<music21.stream.Stream ...>
>>> len(s.notesAndRests)
11
music21.midi.translate.midiTracksToStreams(midiTracks, ticksPerQuarter=None, quantizePost=True, inputM21=None)

Given a list of midiTracks, populate this Stream with a Part for each track.

music21.midi.translate.music21ObjectToMidiFile(music21Object)
music21.midi.translate.noteToMidiEvents(inputM21, includeDeltaTime=True, channel=1)

Translate a music21 Note to a list of four MIDI events – the DeltaTime for the start of the note (0), the NOTE_ON event, the DeltaTime to the end of the note, and the NOTE_OFF event.

If includeDeltaTime is not True then the DeltaTime events aren’t returned, thus only two events are returned.

The initial deltaTime object is always 0. It will be changed when processing Notes from a Stream.

The channel can be specified, otherwise channel 1 is assumed.

>>> n1 = note.Note('C#4')
>>> eventList = midi.translate.noteToMidiEvents(n1)
>>> eventList
[<MidiEvent DeltaTime, t=0, track=None, channel=1>, <MidiEvent NOTE_ON, t=None, track=None, channel=1, pitch=61, velocity=90>, <MidiEvent DeltaTime, t=1024, track=None, channel=1>, <MidiEvent NOTE_OFF, t=None, track=None, channel=1, pitch=61, velocity=0>]
>>> n1.duration.quarterLength = 2.5
>>> eventList = midi.translate.noteToMidiEvents(n1)
>>> eventList
[<MidiEvent DeltaTime, t=0, track=None, channel=1>, <MidiEvent NOTE_ON, t=None, track=None, channel=1, pitch=61, velocity=90>, <MidiEvent DeltaTime, t=2560, track=None, channel=1>, <MidiEvent NOTE_OFF, t=None, track=None, channel=1, pitch=61, velocity=0>]

Omitting DeltaTimes:

>>> eventList2 = midi.translate.noteToMidiEvents(n1, includeDeltaTime=False, channel=9)
>>> eventList2
[<MidiEvent NOTE_ON, t=None, track=None, channel=9, pitch=61, velocity=90>, <MidiEvent NOTE_OFF, t=None, track=None, channel=9, pitch=61, velocity=0>]
music21.midi.translate.noteToMidiFile(inputM21)

Converts a single Music21 Note to an entire MidiFile object with one track, on channel 1.

>>> n1 = note.Note('C4')
>>> n1.quarterLength = 6
>>> mf = midi.translate.noteToMidiFile(n1)
>>> mf
<MidiFile 1 tracks
  <MidiTrack 1 -- 8 events
    <MidiEvent DeltaTime, t=0, track=1, channel=1>
    <MidiEvent SEQUENCE_TRACK_NAME, t=0, track=1, channel=1, data=''>
    <MidiEvent DeltaTime, t=0, track=1, channel=1>
    <MidiEvent NOTE_ON, t=None, track=1, channel=1, pitch=60, velocity=90>
    <MidiEvent DeltaTime, t=6144, track=1, channel=1>
    <MidiEvent NOTE_OFF, t=None, track=1, channel=1, pitch=60, velocity=0>
    <MidiEvent DeltaTime, t=0, track=1, channel=1>
    <MidiEvent END_OF_TRACK, t=None, track=1, channel=1, data=''>
  >
>
>>> mf.tracks[0].events
[<MidiEvent DeltaTime, t=0, track=1, channel=1>, <MidiEvent SEQUENCE_TRACK_NAME, t=0, track=1, channel=1, data=''>, <MidiEvent DeltaTime, t=0, track=1, channel=1>, <MidiEvent NOTE_ON, t=None, track=1, channel=1, pitch=60, velocity=90>, <MidiEvent DeltaTime, t=6144, track=1, channel=1>, <MidiEvent NOTE_OFF, t=None, track=1, channel=1, pitch=60, velocity=0>, <MidiEvent DeltaTime, t=0, track=1, channel=1>, <MidiEvent END_OF_TRACK, t=None, track=1, channel=1, data=''>]
music21.midi.translate.offsetToMidi(o)

Helper function to convert a music21 offset value to MIDI ticks, depends on defaults.ticksPerQuarter

Returns an int.

>>> defaults.ticksPerQuarter
1024
>>> midi.translate.offsetToMidi(20.5)
20992
music21.midi.translate.packetsToMidiTrack(packets, trackId=1, channels=None)

Given packets already allocated with channel and/or instrument assignments, place these in a MidiTrack.

Note that all packets can be sent; only those with matching trackIds will be collected into the resulting track

The channels defines a collection of channels available for this Track

Use _streamToPackets to convert the Stream to the packets

music21.midi.translate.streamHierarchyToMidiTracks(inputM21, acceptableChannelList=None)

Given a Stream, Score, Part, etc., that may have substreams (i.e., a hierarchy), return a list of MidiTrack objects.

acceptableChannelList is a list of MIDI Channel numbers that can be used. If None, then 1-9, 11-16 are used (10 being reserved for percussion).

Called by streamToMidiFile()

The process:

  1. makes a deepcopy of the Stream (Developer TODO: could this be done with a shallow copy?)
  2. we make a list of all instruments that are being used in the piece.
music21.midi.translate.tempoToMidiEvents(tempoIndication, includeDeltaTime=True)

Given any TempoIndication, convert it to a MIDI tempo indication.

>>> mm = tempo.MetronomeMark(number=90)
>>> events = midi.translate.tempoToMidiEvents(mm)
>>> events[0]
<MidiEvent DeltaTime, t=0, track=None, channel=None>

Data is not displayed directly below since it’s a bytes object in PY3 and str in PY2

>>> events[1]
<MidiEvent SET_TEMPO, t=None, track=None, channel=1, data=...>
>>> events[1].data    
b'\n,+'
>>> microSecondsPerQuarterNote = midi.getNumber(events[1].data, len(events[1].data))[0]
>>> microSecondsPerQuarterNote
666667
>>> round(60 * 1000000.0 / microSecondsPerQuarterNote, 1)
90.0

Test roundtrip. Note that for pure tempo numbers, by default we create a text name if there’s an appropriate one:

>>> midi.translate.midiEventsToTempo(events)
<music21.tempo.MetronomeMark maestoso Quarter=90.0>
music21.midi.translate.timeSignatureToMidiEvents(ts, includeDeltaTime=True)

Translate a TimeSignature to a pair of events: a DeltaTime and a MidiEvent TIME_SIGNATURE.

Returns a two-element list

>>> ts = meter.TimeSignature('5/4')
>>> eventList = midi.translate.timeSignatureToMidiEvents(ts)
>>> eventList[0]
<MidiEvent DeltaTime, t=0, track=None, channel=None>
>>> eventList[1]
<MidiEvent TIME_SIGNATURE, t=None, track=None, channel=1, data='\x05\x02\x18\x08'>