Search code examples
pythonmidimusic21

Music21 plays all notes at once when saving to midi file


I've noticed and issue when trying to assemble sequential and parallel chords in music21 toolkit.

ch = stream.Part([
  stream.Measure([note.Rest(duration=duration.Duration(type='eighth'))]),
  stream.Measure([note.Note('C4'), note.Note('F4')]),
  stream.Measure([note.Rest(duration=duration.Duration(type='half'))]),
  stream.Measure([chord.Chord([note.Note('C4'), note.Note('F4')], duration=duration.Duration(type='half'))])
])

Code from above gives me correct scores when ch.write('musicxml.png) enter image description here

But when saving as MIDI: ch.write('midi') all the notes are played at once. (I cant attach MIDI, so hexdump)

00000000  4d 54 68 64 00 00 00 06  00 01 00 01 04 00 4d 54  |MThd..........MT|
00000010  72 6b 00 00 00 3f 00 ff  03 00 00 e0 00 40 00 90  |rk...?.......@..|
00000020  45 5a 00 90 42 5a 00 90  46 5a 00 90 45 5a 00 90  |EZ..BZ..FZ..EZ..|
00000030  42 5a 00 90 46 5a 88 00  80 45 00 00 80 42 00 00  |BZ..FZ...E...B..|
00000040  80 46 00 88 00 80 45 00  00 80 42 00 00 80 46 00  |.F....E...B...F.|
00000050  88 00 ff 2f 00                                    |.../.|
00000055

Is this a bug in music21? Or I messed up something?


Solution

  • Each measure you create is at offset 0, so when you pass them to Part(), they all get inserted at offset 0, meaning at the same time. It happens that the xml writer tries to fix up notation (calling makeNotation etc) but the midi writer is more literal.

    Try appending each Measure to stream.Part() instead of passing them to the constructor. Or try calling .makeNotation() on your Part before writing it to midi.