Bmidilib (a Python midi library)
Overview
bmidilib.py, code for reading/creating midi files in Python
Ben Fisher, 2008. GPL.
Based originally on midi.py, placed into the public domain in December 2001 by Will Ware
To make a midi song, create a Builder object, and use its .note() method to add notes. By default, notes are added to the end of the song. However, the Builder object's current time can be moved backwards with the rewind() method. This is how to play many notes at once, as in a chord.
(This is an old project I wrote for fun in college.)
Bbuilder Examples
Bbuilder.py is a high-level interface for making Midi songs. Here are some demonstrations.making a simple melody from bmidilib import bbuilder b = bbuilder.BMidiBuilder() b.note('c', 1) #pitch 60, duration 1 qtr note b.note('d', 1) b.note('e', 1) b.note('f', 1) b.note('g', 4) b.save('out.mid')making a chord b = bbuilder.BMidiBuilder() b.note('c', 1) b.rewind() #automatically rewinds to start of last note b.note('e', 1) b.rewind() b.note('g', 1) b.save('out.mid') #doesn't "sort" the events until the end.
more options b = bbuilder.BMidiBuilder() b.tempo = 60 b.volume = 20 b.pan = 127 #out of right speaker b.setInstrument('flute') #looks up in list, until first match. b.setInstrument(73) also works b.note('c', 1, velocity=127) #velocity is the loudness of a particular note, 1-127
#ways to type same note: b.note(61, 1) b.note('c#', 1) #use sharps, not flats. b.note('c#4', 1) #octaves b.note('c#5', 1) b.note('c#6', 1) b.save('out.mid')
advanced (2 tracks) tr1 = bbuilder.BMidiBuilder() tr1.setInstrument('fretless bass') tr1.note('c3', 2) tr1.note('d3', 2) tr1.note('e3', 2) tr1.rest(2) tr1.note('f3',2)
tr2 = bbuilder.BMidiBuilder() tr2.setInstrument('ocarina') tr2.note('e4', 2) tr2.note('f4', 2) tr2.note('g4', 2) tr2.rest(2) tr2.note('a4',2) bbuilder.joinTracks( [tr1, tr2], 'out.mid')
advanced (inserting raw events) b = bbuilder.BMidiBuilder() b.tempo = 400 for i in range(127):
#insert a raw instrument change event evt = bmidilib.BMidiEvent() #event time will be set when inserted evt.type='PROGRAM_CHANGE' evt.channel=1 evt.data = i b.insertMidiEvent(evt) b.note('c3',0.4) b.save('song2.mid')
Example reading
First, place the bmidilib directory in the directory containing the script.from bmidilib import bmidilibm = bmidilib.BMidiFile() m.open('mymidi.mid') m.read() m.close() print m #lists all of the events in a human-readable way
#loop through only the note events in 2nd track, and print out pitches and durations for note in m.tracks[1].notelist: print note.pitch, note.duration
Example writing
from bmidilib import bbuilder b = bbuilder.BMidiBuilder() b.note('c', 1) b.note('d', 1) b.note('e', 1) b.note('f', 1) b.note('g', 4) b.save('out.mid')
Example writing (raw events)
# For creating midi files, bbuilder.py should be enough for everyday usage. # this is an example in case you are trying to do something beyond bbuilder.from bmidilib import bmidilib
file = bmidilib.BMidiFile() file.ticksPerQuarterNote = 120
tr = bmidilib.BMidiTrack() file.tracks.append(tr)
#note on event startevt = bmidilib.BMidiEvent() startevt.type = 'NOTE_ON' startevt.time = 0 startevt.channel = 1 startevt.pitch = 60 startevt.velocity = 80 tr.events.append(startevt)
#note off event (which is note_on with velocity 0) endevt = bmidilib.BMidiEvent() endevt.type = 'NOTE_ON' endevt.time = 120 endevt.channel = 1 endevt.pitch = 60 endevt.velocity = 0 tr.events.append(endevt)
evt = bmidilib.BMidiEvent() evt.type='END_OF_TRACK' evt.time = 500 evt.data = '' tr.events.append(evt)
file.open('out.mid', 'wb') file.write() file.close()
Class Hierarchy
BMidiFile BMidiTrack[] tracksBMidiTrack BMidiEvent[] events BNote[] notelist Notes in a mid file consist of two events, a "NoteOn" and a later "NoteOff" The "notelist" provides a simpler view, as a single BNote object that has duration. (If you are creating a BMidiTrack yourself, you do not need to add to the notelist)
BMidiEvent Raw information about the midi event. Includes raw NoteOn and NoteOff events. Does not include "delta times" which are created automatically.
BNote Information including note, duration
- Modifying these instances will not actually modify the midi - This is just an alternate view of information elsewhere So to change the pitch of a note, say, you have to have both note.startEvt.pitch = 60 note.endEvt.pitch = 60 note.pitch = 60
Bbuilder Documentation
Functions bbuilder.joinTracks(listTracks, outFilename)Public Settings b.tempo b.volume b.pan
Public Methods b.note(pitch, duration) b.rest(duration) b.rewind(duration) b.setInstrument(instrument) b.save(outFilename)