Skip to content

rushike/rmidipy

Repository files navigation

rmidipy

This python library is intended to open midi files as python objects. Midi file is binary files, list in form of tracks. Every track contains a sequence of events. Each event is associated delta time, which refers to time from perivous event, current event should occur.

In same structure rmidi has MIDI as base class, MIDI.Track for track representation and MIDI.Track.Event to represent each event.

Getting Started

rmidi is available on python pip. You can install library through below command.

    $ pip install rmidi

rmidi has two classes for handling the midi files MIDI and AbsoluteMidi, further documentation reveals out their differences. You can open **.mid** files with MIDI class only, which can transform to AbsoluteMidi class object

Opening and Creating the midi file

>>> from rmidi.midi import MIDI
>>> mid = MIDI.parse_midi(<midi-file-path>)
>>> # do any manupulation it
>>> mid.create_file(<midi-file-name>, <dir-path> = current-dir) # if dir is not specified file is store in current directory 

Create empty Midi File

>>> from rmidi.midi import MIDI
>>> mid = MIDI(empty = True) # creates file with, format_type = 0, track_count = 0, time_div = 0x1e0
>>> mid.create_file("empyty.mid")

Add note on/off event to track

Below shows how to add any note to midi object, thing to note specifically here is every note_on event, there should always be note_off event. You can also disable velocity, to have note_off event

>>> from rmidi.midi import MIDI
>>> mid = MIDI(empty = True, track_count = 0) # creates file with, format_type = 0,  time_div = 0x1e0
>>> mid.track(0).add_event(0, 'note_on', note_number = 60, velocity = 90, channel_no = 0) # add note with midi number 60 to track 0
>>> mid.track(0).add_event(4, 'note_off' note_number = 60, velocity = 90, channel_no = 0) # there should be coressponding note-off event assosiated with note-on

Here note_on and note_off event has same parameter structure, and everything in specified above. param structure (time, event, note_number, velocity, channel_no).

    time := delta time in traditional way of note presenting, as whole = 1, half = 2, quater = 4, and so on

MIDI

>>> from rmidi import MIDI
>>> y = MIDI.parse_midi(<midi_file_path>)
Output
_____________________________________________________________________________________________________________________________ . . .
| Absolute Time   |  Duration       |  Delta Time |  ETYPE     |   Event ID | META  | LENGTH     | DATA
|______________________________________________________________________________________________________________________________ . . .
| 0.000000        | 0.000000        | 0x0         | META       | 0xff       | 0x58  | 0x4        |  0x04  0x02 0x18  0x0
| 0.000000        | 0.000000        | 0x0         | META       | 0xff       | 0x59  | 0x2        |  0x00  0x0
| 0.000000        | 0.000000        | 0x0         | META       | 0xff       | 0x51  | 0x3        |  0x07  0xa1 0x2
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x79  0x0
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0xc0       | 0     | 0x1        |  0x0
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x07  0x6
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x0a  0x4
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x5b  0x0
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x5d  0x0
| 0.000000        | 0.000000        | 0x0         | META       | 0xff       | 0x21  | 0x1        |  0x0
| 0.000000        | 0.000000        | 0x0         | CHANNEL    | 0x90       | 0     | 0x2        |  0x48  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x48  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4a  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x4a  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4c  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x4c  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4d  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x4d  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4f  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x4f  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x51  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x51  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x53  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x53  0x0
| 0.000000        | 0.000000        | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x54  0x5
| 0.000000        | 0.000000        | 0x71f       | CHANNEL    | 0x90       | 0     | 0x2        |  0x54  0x0
| 0.000000        | 0.000000        | 0x1         | META       | 0xff       | 0x2f  | 0x0        |

Absolute midi

Absolute Midi is defined as its time from start, in seconds.

>>> from rmidi import MIDI, AbosluteMidi
>>> y = MIDI.parse_midi(<midi-file-path>)
>>> yabs = AbsoluteMidi.to_abs_midi(y)
>>> print(yabs)
Output
| Absolute Time   |  Duration       |  Note  Time         |  Delta Time |  ETYPE     |   Event ID | META  | LENGTH     | DATA
|______________________________________________________________________________________________________________________________ . . .
| 0.000000        | 0.000000        | 0                    | 0x0         | META       | 0xff       | 0x58  | 0x4        |  0x04  0x02 0x18  0x08
| 0.000000        | 0.000000        | 0                    | 0x0         | META       | 0xff       | 0x59  | 0x2        |  0x00  0x00
| 0.000000        | 0.000000        | 0                    | 0x0         | META       | 0xff       | 0x51  | 0x3        |  0x07  0xa1 0x20
| 0.000000        | 0.000000        | 0                    | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x79  0x00
| 0.000000        | 0.000000        | 0                    | 0x0         | CHANNEL    | 0xc0       | 0     | 0x1        |  0x00
| 0.000000        | 0.000000        | 0                    | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x07  0x64
| 0.000000        | 0.000000        | 0                    | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x0a  0x40
| 0.000000        | 0.000000        | 0                    | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x5b  0x00
| 0.000000        | 0.000000        | 0                    | 0x0         | CHANNEL    | 0xb0       | 0     | 0x2        |  0x5d  0x00
| 0.000000        | 0.000000        | 0                    | 0x0         | META       | 0xff       | 0x21  | 0x1        |  0x00
| 0.000000        | 31.649306       | 1.0666666666666667   | 0x0         | CHANNEL    | 0x90       | 0     | 0x2        |  0x48  0x50
| 33.333333       | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4a  0x50
| 66.666667       | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4c  0x50
| 100.000000      | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4d  0x50
| 133.333333      | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x4f  0x50
| 166.666667      | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x51  0x50
| 200.000000      | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x53  0x50
| 233.333333      | 31.649306       | 1.0666666666666667   | 0x61        | CHANNEL    | 0x90       | 0     | 0x2        |  0x54  0x50
| 0.000000        | 0.000000        | 0                    | 0x1         | META       | 0xff       | 0x2f  | 0x0        |
*******************************************************************************************************************

NoteSequence

rmidi.dataset.NoteSequence is similar object to that of Magenta.NoteSequence, It holds everthing in dict, whole midi file is express as python nested dictionary

>>> from rmidi.dataset import notesequence
>>> ns = NoteSequence(<midi-file-path>)
>>> print(ns)
Output
[
    {
        "track-0": [
            [
                "type : meta",
                "deltatime : 0",
                "time : 0",
                "duration : 0",
                "subtype : time_sig",
                "length : 4",
                "data : 0x04  0x02 0x18 0x08 \n"
            ],
            [
                "type : meta",
                "deltatime : 0",
                "time : 0",
                "duration : 0",
                "subtype : key_sig",
                "length : 2",
                "data : 0x00  0x00 \n"
            ],
            [
                "type : meta",
                "deltatime : 0",
                "time : 0",
                "duration : 0",
                "subtype : set_tempo",
                "length : 3",
                "data : 0x07  0xa1 0x20 \n"
            ],
            [
                "type : cntroller",
                "deltatime : 0",
                "event_id : 176",
                "time : 0",
                "duaration : 0",
                "pitch : None",
                "velocity : None",
                "is_drum : False",
                "subtype : mode_messages_0"
            ],
            [
                "type : program_change",
                "deltatime : 0",
                "event_id : 192",
                "time : 0",
                "duaration : 0",
                "pitch : None",
                "velocity : None",
                "is_drum : False"
            ],
            [
                "type : cntroller",
                "deltatime : 0",
                "event_id : 176",
                "time : 0",
                "duaration : 0",
                "pitch : None",
                "velocity : None",
                "is_drum : False",
                "subtype : main_volume"
            ],
            [
                "type : cntroller",
                "deltatime : 0",
                "event_id : 176",
                "time : 0",
                "duaration : 0",
                "pitch : None",
                "velocity : None",
                "is_drum : False",
                "subtype : pan"
            ],
            [
                "type : cntroller",
                "deltatime : 0",
                "event_id : 176",
                "time : 0",
                "duaration : 0",
                "pitch : None",
                "velocity : None",
                "is_drum : False",
                "subtype : effects_depth_0"
            ],
            [
                "type : cntroller",
                "deltatime : 0",
                "event_id : 176",
                "time : 0",
                "duaration : 0",
                "pitch : None",
                "velocity : None",
                "is_drum : False",
                "subtype : effects_depth_2"
            ],
            [
                "type : meta",
                "deltatime : 0",
                "time : 0",
                "duration : 0",
                "subtype : midi_port",
                "length : 1",
                "data : 0x00  \n"
            ],
            [
                "type : note_on",
                "deltatime : 0",
                "event_id : 144",
                "time : 0.0",
                "duaration : 31.649305555555554",
                "pitch : 72",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 33.33333333333333",
                "duaration : 31.649305555555557",
                "pitch : 74",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 66.66666666666666",
                "duaration : 31.649305555555557",
                "pitch : 76",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 99.99999999999999",
                "duaration : 31.649305555555557",
                "pitch : 77",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 133.33333333333331",
                "duaration : 31.649305555555543",
                "pitch : 79",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 166.66666666666663",
                "duaration : 31.649305555555543",
                "pitch : 81",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 199.99999999999994",
                "duaration : 31.649305555555543",
                "pitch : 83",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 233.33333333333326",
                "duaration : 31.649305555555543",
                "pitch : 84",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : meta",
                "deltatime : 1",
                "time : 0",
                "duration : 0",
                "subtype : end_of_track",
                "length : 0",
                "data : \n"
            ]
        ]
    }
]

NoteSequence object is subscriptable, you can access, any note from praticular track easily.

>>> event = ns[0][11] # this will give you the 11th event occured from 0th track
>>> event = ns[0, 11] # this to is valid in numpy style

NoteSequence@tostring

Converts the dict to pretty string

Input
from rmidi.dataset import NoteSequence
dict_ = {0: OrderedDict([(17, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 233.33333333333326, 'duaration': 31.649305555555543, 'pitch': 84, 'velocity': 80, 'is_drum': False}), (16, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 199.99999999999994, 'duaration': 31.649305555555543, 'pitch': 83, 'velocity': 80, 'is_drum': False}), (15, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 166.66666666666663, 'duaration': 31.649305555555543, 'pitch': 81, 'velocity': 80, 'is_drum': False}), (14, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 133.33333333333331, 'duaration': 31.649305555555543, 'pitch': 79, 'velocity': 80, 'is_drum': False}), (13, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 99.99999999999999, 'duaration': 31.649305555555557, 'pitch': 77, 'velocity': 80, 'is_drum': False}), (12, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 66.66666666666666, 'duaration': 31.649305555555557, 'pitch': 76, 'velocity': 80, 'is_drum': False}), (11, {'type': 'note_on', 'deltatime': 97, 'event_id': 144, 'time': 33.33333333333333, 'duaration': 31.649305555555557, 'pitch': 74, 'velocity': 80, 'is_drum': False}), (10, {'type': 'note_on', 'deltatime': 0, 'event_id': 144, 'time': 0.0, 'duaration': 31.649305555555554, 'pitch': 72, 'velocity': 80, 'is_drum': False})])}
print(NoteSequence.tostring(dict_))
Output
[
    {
        "track-0": [
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 233.33333333333326",
                "duaration : 31.649305555555543",
                "pitch : 84",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 199.99999999999994",
                "duaration : 31.649305555555543",
                "pitch : 83",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 166.66666666666663",
                "duaration : 31.649305555555543",
                "pitch : 81",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 133.33333333333331",
                "duaration : 31.649305555555543",
                "pitch : 79",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 99.99999999999999",
                "duaration : 31.649305555555557",
                "pitch : 77",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 66.66666666666666",
                "duaration : 31.649305555555557",
                "pitch : 76",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 33.33333333333333",
                "duaration : 31.649305555555557",
                "pitch : 74",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 0",
                "event_id : 144",
                "time : 0.0",
                "duaration : 31.649305555555554",
                "pitch : 72",
                "velocity : 80",
                "is_drum : False"
            ]
        ]
    }
]

NoteSequence@notes

To get just notes, i.e. just note_on and note_off event, you can call NoteSequence object as ns.notes

>>> from rmidi.dataset import NoteSequence
>>> ns = NoteSequence(<midi-file-path>)
>>> notes = ns.notes
>>> print(notes)
>>> print(ns.tostring(notes)) # to pretty print
Output
 [
    {
        "track-0": [
            [
                "type : note_on",
                "deltatime : 0",
                "event_id : 144",
                "time : 0.0",
                "duaration : 31.649305555555554",
                "pitch : 72",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 33.33333333333333",
                "duaration : 31.649305555555557",
                "pitch : 74",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 66.66666666666666",
                "duaration : 31.649305555555557",
                "pitch : 76",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 99.99999999999999",
                "duaration : 31.649305555555557",
                "pitch : 77",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 133.33333333333331",
                "duaration : 31.649305555555543",
                "pitch : 79",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 166.66666666666663",
                "duaration : 31.649305555555543",
                "pitch : 81",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 199.99999999999994",
                "duaration : 31.649305555555543",
                "pitch : 83",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 233.33333333333326",
                "duaration : 31.649305555555543",
                "pitch : 84",
                "velocity : 80",
                "is_drum : False"
            ]
        ]
    }
]

Notesequence@order_by

It orders the events within track base on event attribute, order by is intended to work for attributes 'time', 'duration', 'pitch', deltatime

>>> from rmidi.dataset import NoteSequence
>>> ns = NoteSequence(filepath)
>>> ordered = ns.order_by(<attribute_name>, reverse=True)
>>> print(ordered) # Output for pitch sorted in reverse
Output
[
    {
        "track-0": [
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 233.33333333333326",
                "duaration : 31.649305555555543",
                "pitch : 84",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 199.99999999999994",
                "duaration : 31.649305555555543",
                "pitch : 83",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 166.66666666666663",
                "duaration : 31.649305555555543",
                "pitch : 81",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 133.33333333333331",
                "duaration : 31.649305555555543",
                "pitch : 79",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 99.99999999999999",
                "duaration : 31.649305555555557",
                "pitch : 77",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 66.66666666666666",
                "duaration : 31.649305555555557",
                "pitch : 76",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 97",
                "event_id : 144",
                "time : 33.33333333333333",
                "duaration : 31.649305555555557",
                "pitch : 74",
                "velocity : 80",
                "is_drum : False"
            ],
            [
                "type : note_on",
                "deltatime : 0",
                "event_id : 144",
                "time : 0.0",
                "duaration : 31.649305555555554",
                "pitch : 72",
                "velocity : 80",
                "is_drum : False"
            ]
        ]
    }
]

Notesequence@to_abs_midi

Convert NoteSequece to AbsoluteMidi object.

>>> from rmidi.dataset import NoteSequence
>>> ns = NoteSequence(filepath)
>>> absmidi = ns.to_abs_midi()
>>> print(type(absmidi))

Output

<class 'rmidi.absolutemidi.AbsoluteMidi'>

Muse

Basic class able to generate midi from sequence, with fixed or random time associated with each event.

About

Math Sequence to midi,

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages