I'm trying to read a MIDI file and then convert each note (midi number) to a simulated keypress on the keyboard (A,f,h,J,t...).
I'm able to read any MIDI file with the python-midi library like this:
pattern = midi.read_midifile("example.mid")
and I can also simulate keypresses with pywin32 like this:
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys(key)
But I have no idea on how to actually convert midi numbers (that are in midi files) to keypresses.
To be more precise I'm trying to convert MIDI numbers to notes and then notes to keypresses according to virtualpiano.net (61-key) so that the program would play that piano by pressing the corresponding button on the keyboard (you can press key assist in settings of the piano to see which key is what button)
Of course I would also have to wait between keypresses but that's easy enough.
Any help is appreciated. (Windows 10 64-bit (32-bit Python 2.7))
Check this question first. This is general idea on how to simulate keypresses, it may look a lot but it's just a big list of keys. Then to convert midi to keyboard buttons you would create a dictionary mapping between notes and Keyboard buttons.
I understand that what you really need is a way to convert a midi note number to a note in standard notation.
Here are some elements from Wikipedia:
(from MIDI - General MIDI
(from MIDI Tuning Standard - Frequency values)
And finally from C (musical note) - Designation by octave
So C4 is midi note 69, and midi notes are separated with a semitone(*). As you have 12 semitones in one octave, you will get C5 at midi note 81, and the famous A440 (midi note 69) is A4 in scientific notation.
As an example for the table
And you would get F♯4 at midi 66...
(*) it is musically what is called equal temperament. Midi allows for finer pitch definition but it would be far beyond this answer.
If you take a look at the
midi
module that you are using, you will see that there are some constants that can be used to convert notes to their MIDI number and vice versa.Opening a MIDI file with
read_midifile()
returns aPattern
object which looks like this (taken from the examples):The
NoteOnEvent
contains timing, MIDI number/pitch and velocity which you can retrieve:Now all of that is interesting, but you don't really need to convert the MIDI number to a note, you just need to convert it to the keyboard key for that note as used by http://virtualpiano.net/.
Middle C is equal to MIDI 60 and this note corresponds to the 25th key on the virtualpiano keyboard which is activated by pressing the letter
t
. The next note, Cs_5, is MIDI 61 which is uppercaseT
(<shift>-t)
. From there you can work out the mapping for the MIDI numbers to the supported virtualpiano keys; it's this:The next problem that you will face is sending the key events. Note that in MIDI multiple notes can be played simultaneously, or can overlap in time. This means that you might need to be able to send more than one key press event at the same time.
I don't think that you can handle the velocity using a computer keyboard. There is also the issue of timing, but you said that that's not a problem for you.