2

I parsed a MIDI file in music21 by using converter.parse function in music21. And for extracting notes and chords with duration, I have used the code as follows:

    score = converter.parse('midiexample.mid')
    flat = score.flat
    for el in flat.notes:
        if isinstance(el, music21.note.Note):
            pitch = el.pitch
            note_name = pitch.nameWithOctave
            new_note_c = note.Note(note_name)
            new_note_c.duration = el.duration
            dur = round(float(el.duration.quarterLength), 1)
            all_elements.append((str(note_name), dur))
        elif isinstance(el, music21.chord.Chord):
            chord_pitches = []
            for p in el.pitches:
                #note_name = p.pitch
                #note_name_oct = note_name.nameWithOctave
                new_note_c = note.Note(p.nameWithOctave)
                #new_note_c.duration = el.duration
                dur = round(float(el.duration.quarterLength), 1)
                chord_pitches.append((str(new_note_c.nameWithOctave)))
            chord_pitches = ".".join([i for i in chord_pitches])
            all_elements.append((chord_pitches, dur))


def get_music_midi_filename_from_chords(input_chords):
    midi_stream = stream.Stream()

    for note_pattern, duration_pattern in input_chords:
        if('.' in note_pattern):
            notes_in_chord = note_pattern.split('.')
            chord_notes = []
            for current_note in notes_in_chord:
                new_note = note.Note(current_note)
                new_note.duration = duration.Duration(duration_pattern)
                new_note.storedInstrument = instrument.Piano()
                chord_notes.append(new_note)
            new_chord = chord.Chord(chord_notes)
            print(f'New_chord appended as {new_chord}')
        else:
            note_single = note.Note(note_pattern)
            note_single.duration = duration.Duration(duration_pattern)
            note_single.storedInstrument = instrument.Piano()
            new_chord = note_single
            print(f'Appended note {new_chord}')
        midi_stream.append(new_chord)

        #new_tempo = tempo.MetronomeMark(number=50)
            
        #midi_stream.append(new_tempo)

    midi_stream = midi_stream.chordify()
    timestr = time.strftime("%Y%m%d-%H%M%S")
    new_file = 'output-' + timestr + '.mid'
    return midi_stream.write('midi', fp=new_file
)

When I call the function to get music, the MIDI file I produced has 2:51 time duration whereas the song I passed only has 1:16 of time duration. What am I doing wrong in this case? I need to make sure I am able to get the notes and chords along with their duration as correct as I can get. But an addition of a minute seems fishy. Is the duration rounding the cause? I am not able to debug this error.

Also, while comparing, I got the MIDI comparison of original MIDI and my produced MIDI and I found them as follows:

enter image description here

Original MIDI is dark blue, my produced one is longer. The notes are somewhat similar but the duration is prolonged in my code:

4
  • 1
    Don't any notes overlap?
    – Jos
    Feb 10 at 14:11
  • How do you mean by overlap? I get the sequence like [('A5', 0.5), ('A3', 0.5), ('E6', 2.0), ('E4', 2.0), ('E6', 1.25), ('E4', 1.25), ('D6.E6', 0.25)] with duration and pitch/sequence of pitches in that format. There can be same pitches a number of times.
    – ROOT31415
    Feb 10 at 14:23
  • 1
    Perhaps what I'm asking is not correct, but are you reading the tempo of the original file at all? I would think it could be done with web.mit.edu/music21/doc/moduleReference/… Feb 10 at 17:05
  • 1
    Could you separate the original MIDI and the produced MIDI in two different graphs and change the X-axis to beats or bars?
    – empty
    Feb 10 at 18:25

1 Answer 1

4
  • MIDI files almost always use time units based on quarter notes, not time units based on seconds.
  • MIDI file software uses the tempo events in a MIDI file to convert the quarter-note-based time units into seconds-based time.
  • If there are no tempo events in a MIDI file, a default tempo of 120 quarter notes per minute is assumed.

It looks like your code is copying notes from your input MIDI file to your output MIDI file, but not copying any tempo information.

If your input MIDI file is 342 quarter notes long and has a tempo of 270 quarter notes per minute it would be 1 minute 16 seconds long.

If the output MIDI file is 342 quarter notes long but has a default tempo of 120 quarter notes per minute it ends up as 2 minutes 51 seconds long.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.