The MidiKeyboard class is available with the Pro version to read or write MIDI events from a MIDI keyboard connected to your computer.
If you only need to read MIDI messages from your device, you may prefer to use the ready-made MidiInReader (also based on the MidiKeyboard class).
Setup
To connect an external MIDI device, Unity needs a plugin to provide core functions such as list, select, open devices, write or read MIDI messages.
Download MidiKeyboard_V1.2.1_Plugins.unitypackage.zip here
- Unzip to get the Unity package file inside the downloaded file.
- Import this package into your Unity editor (see the Unity documentation). You will get something like this in your project window:
- Remove unused plugins. For example, if you have a newer Mac with a Silicon CPU, keep only the MacOSSilicon folder (optional).
Known limitations:
- Tested with:
- Windows 10 or higher, CPU 64 bits.
- MacOS 10.1 or higher, CPU Intel/AMD CPU or Apple Silicon (M1, M2, ..).
- Not available on Android and IOs.
- Cannot handle sysex messages (maybe in the future, if needed!).
Class MidiKeyboard
The class MidiKeyboard is static. Cool, there is no need to allocate 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 in the API Reference like:
- List connect devices (USB, MIDI port or internal).
- Open a device for writing MIDI events.
- Open all devices for reading.
- Read or write MIDI events to the device.
- Close the device.
- Full integration with Maestro MPTK (MPTKEvent, MIDI Synth, Effect, …)
API Reference for the class MidiKeyboard
Demos
As usual with Maestro MPTK, demonstrations are available.
Just Read MIDI event
A very simple script for reading MIDI events from a MIDI device.
For testing:
- Create a new scene in your Unity Editor (or use an existing one).
- Add an empty gameObject (or use an existing one).
- Copy / Paste this script in a C# file.
- Add this script to your gameObject.
- Connect your MIDI keyboard and run!
using UnityEngine;
using System;
using MidiPlayerTK;
namespace DemoMPTK
{
/// <summary>@brief
/// Example of MVP implementation for reading MIDI event from a keyboard.
/// See here for detailed API doc:
/// https://mptkapi.paxstellar.com/da/d70/class_midi_player_t_k_1_1_midi_keyboard.html
/// For testing:
/// - create a new scene
/// - add an empty gameObject
/// - add this script to the gameObject
/// - connect your MIDI keyboard and run!
/// </summary>
public class MidiKeyboardInput : MonoBehaviour
{
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 refresh all input MIDI devices able to send MIDI message
MidiKeyboard.MPTK_OpenAllInp();
}
private void OnApplicationQuit()
{
// Mandatory to avoid Unity crash!
MidiKeyboard.MPTK_CloseAllInp();
}
void Update()
{
int count = 0;
try
{
MidiKeyboard.PluginError status = MidiKeyboard.MPTK_LastStatus;
if (status != MidiKeyboard.PluginError.OK)
Debug.LogWarning($"MIDI Keyboard error, status: {status}");
// Read message available in the queue
// Limit the count of read messages to avoid locking Unity
while (count < 100)
{
count++;
// Read a MIDI event if available
MPTKEvent midievent = MidiKeyboard.MPTK_Read();
// No more Midi message
if (midievent == null)
break;
// ... and log
Debug.Log($"[{DateTime.UtcNow.Millisecond:00000}] {midievent}");
}
}
catch (System.Exception ex)
{
MidiPlayerGlobal.ErrorDetail(ex);
}
}
}
}
Read and Write with Unity User Interface
It’s a complete demonstration of the features you might need. Load the demonstration scene:
Thank to Giuseppe and his free asset ScreenLogger which was helpful to build this demo and test it on device.
Below is an excerpt from the demonstration script where the key methods of the MidiKeyboard class are emphasized.
Warning: Do not copy paste directly this code, it’s an extract of full C# file, it will not work!
This code is meant as a demonstration of how to implement the API and is tailored for the Unity scene “TestMidiKeyboard”. It could serves as an excellent foundation for your own project!
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}");
}
}
}
Have fun!