如何使用music21从.mxl文件提取音符的音高与时长数据?
Hey there! I totally get where you're coming from—diving into music analysis with Python and music21 can feel a bit overwhelming at first, especially when you're hunting for specific data like note pitches and durations from .mxl files. Let me walk you through a straightforward way to do this, step by step.
Step 1: Make sure music21 is installed
First things first, if you haven’t already, install the library using pip:
pip install music21
Step 2: Load your .mxl file and extract notes
music21’s converter module handles .mxl files seamlessly. We’ll load the file, then traverse its structure to pull out every note (including individual notes within chords, since chords are just groups of notes played together).
Here’s a complete working example you can copy-paste and test:
from music21 import converter, note, chord # Load the .mxl file (replace "your_file.mxl" with your actual file path) score = converter.parse("your_file.mxl") # Initialize a list to store our note data note_data = [] # Traverse all elements in the flattened score structure for element in score.flat: # Handle single notes if isinstance(element, note.Note): pitch_name = element.pitch.nameWithOctave # e.g., "C4" midi_pitch = element.pitch.midi # e.g., 60 duration = element.duration.quarterLength # relative to a quarter note (1.0) note_data.append({ "pitch_name": pitch_name, "midi_pitch": midi_pitch, "duration": duration }) # Handle chords (split into individual notes) elif isinstance(element, chord.Chord): for pitch in element.pitches: pitch_name = pitch.nameWithOctave midi_pitch = pitch.midi duration = element.duration.quarterLength # all notes in a chord share the same duration note_data.append({ "pitch_name": pitch_name, "midi_pitch": midi_pitch, "duration": duration }) # Print the extracted data for idx, entry in enumerate(note_data, 1): print(f"Note {idx}: Pitch = {entry['pitch_name']} (MIDI {entry['midi_pitch']}), Duration = {entry['duration']} quarter notes")
Key details to keep in mind:
score.flat: This flattens the score’s nested structure (like parts, measures, voices) into a single list of elements, so you don’t have to write nested loops to dig through each section.duration.quarterLength: This measures duration relative to a quarter note (valued at 1.0). For example:- Eighth note = 0.5
- Half note = 2.0
- Whole note = 4.0
- Chords are broken down into individual notes because each pitch in a chord has the same duration as the chord itself—this way you get a complete list of every sounding pitch.
Optional: Target specific parts
If you only want notes from a particular part (e.g., piano left hand), you can access parts directly instead of flattening the entire score:
# Get the second part (index 1, adjust based on your score's structure) piano_left_hand = score.parts[1] for element in piano_left_hand.flat: # Same note/chord handling logic as above pass
That should cover exactly what you need to pull out basic note data from your .mxl files. If you run into weird edge cases (like grace notes or rests), let me know and we can tweak the code to handle those!
内容的提问来源于stack exchange,提问作者Luca Pontiggia




