pythonmidimusic21

music21 getElementsByClass not showing any output for class stream.Voice


I am struggling to understand why the below code is throwing an error when it ran seamlessly about a year back. The code snippet is from a popular Coursera course. Does the Music21 package has some recent changes around stream.Voice?

data_fn = 'data/original_metheny.mid'
midi_data = converter.parse(data_fn)
melody_stream = midi_data[5] # For Metheny piece, Melody is Part #5.
melody1, melody2 = melody_stream.getElementsByClass(stream.Voice)

The error thrown is ValueError: not enough values to unpack (expected 2, got 0), which means there is no output for stream.Voice class when previously there were outputs for the same data (midi file). melody_stream.getElementsByClass('Measure') does show outputs.

Can you guide how to debug this?


Solution

  • Yes, one of the improvements in music21 v.7 is that files imported from MIDI now have a similar representation to files imported from MusicXML and other formats. Specifically, Parts now have Measures, which may or may not have Voices, rather than Parts directly containing Voices. Code should not depend on finding Voices directly contained in Parts, which is what this example was doing.

    Instead, use this code to find all the measure-voices:

    melody_stream.recurse().getElementsByClass(stream.Voice)
    

    Or, equivalently, use the shortcut syntax in v.7:

    melody_stream[stream.Voice]
    

    Or, if you don't want the measures at all, call flatten() or chordify() depending on your use case.