Skip to content
Utility functions for handling MIDI data in a nice/intuitive way.
Jupyter Notebook Python
Branch: master
Clone or download
cflamant and craffel Fix integrated piano roll division by zero (#169)
* Fix integrated piano roll division by zero

When supplying a time array to piano roll, if the time array
exceeds the length of the "native" piano roll generated based
on when the last note finishes, the mean of empty arrays is
computed, resulting in warnings and populating the outputted
piano roll with nan. Similarly, if the time array has a greater
sampling rate than the "native" piano roll, more empty arrays
are generated, resulting in nan when numpy.mean is computed.

- Fixed the above issues as long as time array is increasing
  and greater than or equal to 0.
- Added unit test for the fix
- Made casting to integer explicit in instrument.py to stop
  the numpy deprecation warning

* Remove print statements
Latest commit 78e33ab Jun 2, 2019

README.md

pretty_midi contains utility function/classes for handling MIDI data, so that it's in a format which is easy to modify and extract information from.

Documentation is available here. You can also find a Jupyter notebook tutorial here.

pretty_midi is available via pip or via the setup.py script. In order to synthesize MIDI data using fluidsynth, you need the fluidsynth program and pyfluidsynth.

If you end up using pretty_midi in a published research project, please cite the following report:

Colin Raffel and Daniel P. W. Ellis. Intuitive Analysis, Creation and Manipulation of MIDI Data with pretty_midi. In Proceedings of the 15th International Conference on Music Information Retrieval Late Breaking and Demo Papers, 2014.

Example usage for analyzing, manipulating and synthesizing a MIDI file:

import pretty_midi
# Load MIDI file into PrettyMIDI object
midi_data = pretty_midi.PrettyMIDI('example.mid')
# Print an empirical estimate of its global tempo
print(midi_data.estimate_tempo())
# Compute the relative amount of each semitone across the entire song, a proxy for key
total_velocity = sum(sum(midi_data.get_chroma()))
print([sum(semitone)/total_velocity for semitone in midi_data.get_chroma()])
# Shift all notes up by 5 semitones
for instrument in midi_data.instruments:
    # Don't want to shift drum notes
    if not instrument.is_drum:
        for note in instrument.notes:
            note.pitch += 5
# Synthesize the resulting MIDI data using sine waves
audio_data = midi_data.synthesize()

Example usage for creating a simple MIDI file:

import pretty_midi
# Create a PrettyMIDI object
cello_c_chord = pretty_midi.PrettyMIDI()
# Create an Instrument instance for a cello instrument
cello_program = pretty_midi.instrument_name_to_program('Cello')
cello = pretty_midi.Instrument(program=cello_program)
# Iterate over note names, which will be converted to note number later
for note_name in ['C5', 'E5', 'G5']:
    # Retrieve the MIDI note number for this note name
    note_number = pretty_midi.note_name_to_number(note_name)
    # Create a Note instance for this note, starting at 0s and ending at .5s
    note = pretty_midi.Note(velocity=100, pitch=note_number, start=0, end=.5)
    # Add it to our cello instrument
    cello.notes.append(note)
# Add the cello instrument to the PrettyMIDI object
cello_c_chord.instruments.append(cello)
# Write out the MIDI data
cello_c_chord.write('cello-C-chord.mid')
You can’t perform that action at this time.