Python Midi Package
The python midi package is currently released in an experimental version. So there is little documentation, and the software might change as new needs arises.
It does work though. It can read and write any midi file that I have tested it on. If you find a Midi file it cannot read, please send me a copy, so that I can update the package.
Currently it cannot read and write to midi ports. So no real time event handling is possible.
Examples
This is an example of how to create the smallest possible type 0 midi file, where all the midi events are in the same track.:
from MidiOutFile import MidiOutFile
out_file = 'midiout/minimal_type0.mid'
midi = MidiOutFile(out_file)
# non optional midi framework
midi.header()
midi.start_of_track()
# musical events
midi.update_time(0)
midi.note_on(channel=0, note=0x40)
midi.update_time(192)
midi.note_off(channel=0, note=0x40)
# non optional midi framework
midi.update_time(0)
midi.end_of_track() # not optional!
midi.eof()
This prints all note_on events on midi channel 0. It's a short example of creating your own event handler by subclassing the MidiOutStream.:
from MidiOutStream import MidiOutStream
from MidiInFile import MidiInFile
class NoteOnPrinter(MidiOutStream):
"Prints all note_on events on channel 0"
def note_on(self, channel=0, note=0x40, velocity=0x40):
if channel == 0:
print channel, note, velocity, self.rel_time()
event_handler = NoteOnPrinter()
in_file = 'midiout/minimal_type0.mid'
midi_in = MidiInFile(event_handler, in_file)
midi_in.read()
Download
get it from the download section
License
GPL
Contact
pydrums
The pythonmidi module is really cool, i have no clue about midi, but it works. (THAT'S what i call the python way...).
So, thank you for it. Feedback is appreciated.
http://www.jesterea.com/pydrums.zip
Replies to this comment
mixing midi
i want to use this package to mix several midi files, i get a tempo and the midi files for each bar - like so: infiles=[['1.mid','5.mid','3.mid'],['1.mid','5.mid','3.mid'],['1.mid','5.mid','3.mid','5.mid','3.mid'],['3.mid','3.mid']]
then convert the mids into txt and write it out as midi again
is it possible to do that? i looped through the files but i only got concatenation, maybe relative vs absolute time?
any help would be appreciated,
best regards
wern
playing midi from within python
am I missing something?
Replies to this comment
Notes !
how do i know wich note is note=0x41 ....
which note represents ,,,, there is any manual ou something so see all notes in Hex
thnx
Replies to this comment
python midi with excel
Using this nifty little program and ableton, I'm having a whole lot of fun.
I'm making my modifications available here for whoever is interested:
http://www.geocities.com/alia_khouri/python-midi-xl.zip
Enjoy!
alia_khouri@yahoo.com
Replies to this comment
Great Module!
Blender and Midi
Johnny Matthews
Replies to this comment
typo
dispatch.sysex_event(sysex_data)
Playing midi
I'm a newer python user. I was working on a my own small program for the managing of the birthdays. I would like to make a pop up window that highlights a birthday with a midi sound in background.
Is Python Midi Package for me? which commands Do I have to use?
Thanks in advance Davideok
Replies to this comment
How to create more then 1 track.
start_of_track(0)
... (some note_on and note_off events)
end_of_track()
start_of_track(1)
... (some note_on and note_off events) ...
end_of_track()
Did not work.
Then I tried:
start_of_track(0)
start_of_track(1)
set_current_track(0)
... (some note_on and note_off events) ...
set_current_track(1)
... (some note_on and note_off events)
end_of_track()
Still does not work. In both cases only 1 track is created and all notes are on the same track.
Would greatly appreciate, if anybody could give me a short example, how to create multiple tracks.
Thanks so much.
Replies to this comment
Thanks for the Python MIDI Package
- Sami Kyostila
Midi out to another program
Problem with flats in Key Signature
I'm having a problem with your module: when I add a negative value as the first argument to midi.key_signature(), to indicate flats, it gives me this:
File "./xml2midi.py", line 131, in xml2midi
midi.key_signature(-3,0)
File "midi/MidiOutFile.py", line 381, in key_signature
self.meta_slice(KEY_SIGNATURE, fromBytes([sf, mi]))
File "midi/DataTypeConverters.py", line 143, in fromBytes
return pack('%sB' % len(value), *value)
File "/usr/lib/python2.5/struct.py", line 63, in pack
return o.pack(*args)
struct.error: ubyte format requires 0 <= number <= 255
Is this a bug, or am I doing something wrong?
Thanks, for any help and for the otherwise great module!
Replies to this comment
Absolute time
I'd like to know at which point in seconds a note is to be played.
Thanks
Replies to this comment
abs_time
There is no documentation that I am aware of.
Is it the absolute time in beats per minute relative to the start of the file?
Lola.mid
I tried to accomplish MidiFileParser.py. But there is no Lola.mid. Can sombody tell where ican find this?
error message:
Traceback (most recent call last):
File "MidiFileParser.py", line 189, in ?
midi_in = MidiFileParser(RawInstreamFile(test_file), MidiToText())
File "/home/mirakulix/Desktop/Dilomarbeit/Midi_Python_package/midi/RawInstreamFile.py", line 32, in __init__
infile = open(infile, 'rb')
IOError: [Errno 2] No such file or directory: 'test/midifiles/Lola.mid'
In hope for your help.
Jana
Replies to this comment
do somebody want wave??
"pure synthesis":
#----------------------------------imports def et autres------------------------------------------------------------------------------
from math import pi, sin, cos, floor
import wave,struct
kamp=32000.0
#-----------------------------------------------------------------------------------------------------------------------------------------
#-----------------------------fonctions de distorsion----------------------------------------------------------------------------
def hardclip(x,seuil):
if (x < seuil):
return x
else:
return seuil
def softclip(x):
fx= 35*x-35*x**3+21*x**5-5*x**7
dimfx= fx/25.
return dimfx
#hardclip: ecretage au dessus d'une valeur seuil
#softclip: ecretage progressif
def tcheby(x):
fx= 16*x**5-20*x**3+5*x
return fx
#-----------------------------------------------------------------------------------------------------------------------------------
#------------------------------partie synthese----------------------------------------------------------------------------------
freq=440.0
long=120000
fech=11025.0
tliste=[]
sinliste=[]
cosliste=[]
fnliste1=[]
fnliste2=[]
fnliste3=[]
for i in range(long):
t=(i/fech)
tliste.append(t)
for i in range(long):
t=tliste[i]
cosliste.append( cos(2*pi*freq*t) )
for i in range(long):
x=cosliste[i]
fx=tcheby((i/(long*1.0))*x)
fnliste3.append(fx)
wavfile = wave.open('tcheby.wav','w')
wavfile.setparams ((1, 2, 11025 , 32000, 'NONE', 'not compressed'))
for s in fnliste3:
wavfile.writeframes(struct.pack('h',((kamp/2)*s)))
wavfile.close()
"extraction:"
#----------------------------------imports def et autres------------------------------------------------------------------------------
from math import pi, sin, cos, floor
import wave,struct
#pour voir les messages d'erreur:
print 'messages d erreur:'
kamp=32000.0
#-----------------------------------------------------------------------------------------------------------------------------------------
#-----------------------------------------------utilitaires-------------------------------------------------------------------------------
def findmax(lst,range):
max=0
for i in range(range):
if (tab[i]>max):
max=tab[i]
return max
def findfreq(lst):
max1=0
max2=0
for i in range(1000):
if (lst[i+1]>lst[i]) and (lst[i+1]>lst[i+2]):
max1=i
while (max2<1):
if (lst[i+1]>lst[i+1]) and (lst[i+1]>lst[i+2]):
max2=i
freq=(max2-max1)/fech
return freq
#---------------------------------------------------------------------------------------------------------------------------------------
#-----------------------------fonctions de distorsion----------------------------------------------------------------------------
seuil=0.5
def hardclip(x,seuil):
if (x < seuil):
return x
else:
return seuil
def softclip(x):
fx= 35*x-35*x**3+21*x**5-5*x**7
dimfx= fx/25.
return dimfx
#hardclip: ecretage parfait
#softclip: ecretage progressif
def tcheby(x):
fx= 2*x**2-1
return fx
#-----------------------------------------------------------------------------------------------------------------------------------
#------------------------------partie synthese----------------------------------------------------------------------------------
freq=440.0
long=10000
fech=11025.0
kamp=32000
param1=(freq,10,(freq*2.),0,(freq/2.),0)
#freq: frequence du son produit
#long: longueur de la chaine
#fech: frequence d'echantillonage
#kamp: coefficient multiplicateur (a determiner)
def timbre(t,(fbase,volb,fh1,vol1,fh2,vol2)):
sinb = volb*sin (2*pi*fbase*t)
sin1 = vol1*sin (2*pi*fh1*t)
sin2 = vol2*sin (2*pi*fh2*t)
moy = (sinb+sin1+sin2) / (volb + vol1 +vol2 )
return (moy)
tliste=[]
sinliste=[]
cosliste=[]
fnliste1=[]
fnliste2=[]
fnliste3=[]
for i in range(long):
t=(i/fech)
tliste.append(t)
for i in range(long):
t=tliste[i]
sinliste.append( timbre(t,param1) )
for i in range(long):
t=tliste[i]
cosliste.append( cos(pi*freq*t) )
for i in range(long):
x=sinliste[i]
fx=hardclip(x,seuil)
fnliste1.append(fx)
for i in range(long):
x=sinliste[i]
fx=softclip(x)
fnliste2.append(fx)
for i in range(long):
x=cosliste[i]
fx=tcheby(x)
fnliste3.append(fx)
#------------------------------------------------------------------------------------------------------------------------
#-------------------------------partie distorsion d'echantillon--------------------------------------------------------
longueur=32000
dim=6000.0
#dim: pour avoir x inf a 1 pour utiliser les fn de disto
fwav = wave.open('guitare.wav')
wavparams=fwav.getparams()
echliste=[]
distoliste=[]
for i in range(longueur):
vhex=fwav.readframes(1)
vnum=struct.unpack('h',vhex)[0]
echliste.append(vnum)
for i in range(longueur):
x=echliste[i]/dim
fx=tcheby(x)
kfx=kamp*fx
distoliste.append(kfx)
#-------------------------------------------------------------------------------------------------------------------------
#-------------------------------generation des fichiers wav-----------------------------------------------------------
wavfile = wave.open('echgratte.wav','w')
wavfile.setparams (wavparams)
for s in echliste:
wavfile.writeframes(struct.pack('h',s))
wavfile.close()
wavfile = wave.open('distogratte.wav','w')
wavfile.setparams (wavparams)
for s in distoliste:
wavfile.writeframes(struct.pack('h',s))
wavfile.close()
#just replace the wavfile "guitare" by any wavefile you want
enjoy
License
Now supporting midi ports
But then when I look at the code I find this:
This makes it extremely easy to take input from one stream and
send it to another. Ie. if you want to read a Midi file, do some
processing, and send it to a midiport.
Which has me hoping that you added stuff to your module and haven't had time to update the site?
I'm trying to write something like guitar hero for keyboard.
alex
Replies to this comment
Bug in pitch bend output
@@ -107,8 +107,8 @@
value: 0-16383
"""
msb = (value>>7) & 0xFF
- lsb = value & 0xFF
- slc = fromBytes([PITCH_BEND + channel, msb, lsb])
+ lsb = value & 0x7F
+ slc = fromBytes([PITCH_BEND + channel, lsb, msb])
self.event_slice(slc)
@@ -445,4 +445,4 @@
midi.eof() # currently optional, should it do the write instead of write??
Replies to this comment
rests
Anyways, to my problem: I am writing a program which reads a text file of 0's and 1's, then converts them into 16th notes in a MIDI file (1 is a note, 0 is a rest). For some reason, the output file shows the correct number of notes, but they are placed next to each other with none of the rests between. Here is a sample of the code (the list is made of the first 16 characters of each line in the text file, eliminating newlines):
for line in text:
beat = list(line)
if int(beat[0]):
midi.update_time(0)
midi.note_on(channel=0, note=0x40)
midi.update_time(24)
midi.note_off(channel=0, note=0x40)
else:
midi.update_time(24)
if int(beat[1]):
midi.note_on(channel=0, note=0x40)
midi.update_time(24)
midi.note_off(channel=0, note=0x40)
else:
midi.update_time(24)
# ... continues to "if int(beat[15]):", then goes on to
midi.update_time(0)
midi.end_of_track()
midi.eof()
I am baffled as to why the rests don't appear, but perhaps I just don't have a good enough understanding of update_time(n).
Replies to this comment
Instrument
i'm unable to switch the instrument. I tried midi.instrument_name('Piano'), midi.instrument_name('Bass'), ... but nothing happened. What's wrong with my code?
Thanks!
Replies to this comment
Simple math operations with MIDI
I have some python classes to represent notes, scales, intervals. What I need is to istantiate such classes after reading a MIDI file. So, if the file contains a short melody (e.g. C - E - G), I have to istantiate the note class three times, then interval and so on.
Do you think I can use your module for this?
And if in a file there is a melody and a drum pattern, is it possible to identify the two instruments?
Thanks,
Carlo
I have question about create piano midi
I'm very stupid and stupid at python, it's the first time to use it and I want to create a program that generate piano MIDI, here is questions...
1. What's method update_time() and what's integer in () ?
2. What's methods note_on() and note_off and how to use ?
3. How can i set type of MIDI for 1 instead of 0
Hope anyone could help me, Thank you for Python Midi Package, it's very useful
** If anyone have example code of create piano midi please send it to me to
canurecognize@hotmail.com
thank you
Python Package Index
update for Python v3.0?
I was wondering if you're planning to update these MIDI packages to work with Python v3.0? There seems to be a few things that are broken now with some of the new Python v3 stuff.
Thank you for writing these MIDI packages.
-marc
I'm playing with your beatiful module. It is what I'm looking for.
I have a doubt: how I can write chords in a track?
I've tried to write three notes simultaneously:
m.start_of_track(1)
m.sequence_name('Piano')
m.instrument_name('Piano')
m.update_time(0)
m.note_on(channel=1, note=0x3C)
m.note_on(channel=1, note=0x3E)
m.note_on(channel=1, note=0x43)
m.update_time(96)
m.note_off(channel=1, note=0x3C)
m.note_off(channel=1, note=0x3E)
m.note_off(channel=1, note=0x43)
m.end_of_track()
but it generates some strange note durations in my sequencer: each note has a different duration.
(I've used different sequencers: AnvilStudio (win32), Jazz++, Muse and Rosegarden).
How can I solve it?
I thank your time and work.
Regards.
David
Replies to this comment