Class MidiKeyboard

The class MidiKeyboard is available with the Pro version from the version 2.85 in order to  read or write Midi events from a Midi keyboard connected to your computer.

If you need only to read Midi message from your device, perhaps you could prefer to use the prefab MidiInReader.


For connecting external Midi device, Unity needs a plugin in order to propose core functions as list, select, open devices, write or read Midi messages.

Plugin MidiKeyboard after importing asset.

Known limitations:

  • Available for Windows 10 64 bits and MacOs 10.1 and after.
  • Not available on Android and IOs.
  • Not able to process Sysex messages (perhaps in the future if there is a need!)


As usual, a demonstration is available. In fact, it’s a very simple demonstration but which contains the main functions that you could have the need.

load the scene TestMidiKeyboard

Thank to Giuseppe and his free asset ScreenLogger which was helpful to build this demo.

The class MidiKeyboard is static. Cool, there is no need to allocate an object. We like simple thing! This page could also help you for writing script for MPTK.

On top of that, the schema is classical and you will find all the details of the class MidiKeyboard here in the documentation or from the asset in Unity.

  • List devices
  • Open the selected device
  • Read or write to the device
  • Close the device

See below an extract of the demonstration script. The most important methods from the class MidiKeyboard are highlighted.

private void Start(){ // Midi Keyboard need to be initialized at start MidiKeyboard.MPTK_Init(); // Log version of the Midi plugins Debug.Log(MidiKeyboard.MPTK_Version()); // Open or close all Midi Input Devices ToggleRead.onValueChanged.AddListener((bool state) => { if (state) MidiKeyboard.MPTK_OpenAllInp(); else MidiKeyboard.MPTK_CloseAllInp(); CheckStatus($"Open/close all input"); }); // Read or not system message (not sysex) ToggleMsgSystem.onValueChanged.AddListener((bool state) => { MidiKeyboard.MPTK_ExcludeSystemMessage(state); }); // Read preset value and send a midi message to change preset on the device 'index" InputPreset.OnEventValue.AddListener((int val) => { int index = InputIndexDevice.Value; // send a patch change MPTKEvent midiEvent = new MPTKEvent() { Command = MPTKCommand.PatchChange, Value = InputPreset.Value, Channel = InputChannel.Value, Delay = 0, }; MidiKeyboard.MPTK_PlayEvent(midiEvent, index); CheckStatus($"Play PatchChange {index}"); }); } // Open a device for output. public void OpenDevice() { index = InputIndexDevice.Value; MidiKeyboard.MPTK_OpenOut(index); CheckStatus($"Open Device {index}"); } // Play ore note public void PlayOneNote(int random) { MPTKEvent midiEvent; int index = InputIndexDevice.Value; // playing a NoteOn midiEvent = new MPTKEvent() { Command = MPTKCommand.NoteOn, Value = InputNote.Value + random, Channel = InputChannel.Value, Velocity = 0x64, // Sound can vary depending on the velocity Delay = 0, }; MidiKeyboard.MPTK_PlayEvent(midiEvent, index); CheckStatus($"Play NoteOn {index}"); // Send Notoff with a delay of 2 seconds midiEvent = new MPTKEvent() { Command = MPTKCommand.NoteOff, Value = InputNote.Value + random, Channel = InputChannel.Value, Velocity = 0, Delay = 2000, }; MidiKeyboard.MPTK_PlayEvent(midiEvent, index); // When event is delayed, last status is sent when event is send, so after the delay! } // Read message from the keyboard private void Update() { if (ToggleRead.isOn) { // Process the message queue by max 100 to avoid locking Unity while (count++ < 100) { // Parse the message. MPTKEvent midievent = MidiKeyboard.MPTK_Read(); // No more Midi message if (midievent == null) break; Debug.Log($"[{DateTime.Now.Millisecond:00000}] {midievent}"); } } }