2 min read

Web MIDI API

The Web MIDI API allows web applications to interact with Musical Instrument Digital Interface (MIDI) devices, such as synthesizers, digital pianos, and drum machines. It enables the browser to send and receive MIDI messages.

1. Requesting Access

To use MIDI devices, you must first request access using navigator.requestMIDIAccess(). This returns a Promise that resolves to a MIDIAccess object.

let midiAccess = null;

navigator.requestMIDIAccess()
  .then(onMIDISuccess, onMIDIFailure);

function onMIDISuccess(access) {
  console.log('MIDI Access Granted!');
  midiAccess = access;
  listInputsAndOutputs(midiAccess);
}

function onMIDIFailure() {
  console.log('Could not access your MIDI devices.');
}

2. Listing Inputs and Outputs

The MIDIAccess object provides maps for inputs and outputs.

function listInputsAndOutputs(midiAccess) {
  for (const entry of midiAccess.inputs) {
    const input = entry[1];
    console.log(`Input port [type:'${input.type}'] id:'${input.id}' manufacturer:'${input.manufacturer}' name:'${input.name}' version:'${input.version}'`);
  }

  for (const entry of midiAccess.outputs) {
    const output = entry[1];
    console.log(`Output port [type:'${output.type}'] id:'${output.id}' manufacturer:'${output.manufacturer}' name:'${output.name}' version:'${output.version}'`);
  }
}

3. Receiving MIDI Messages

To receive data from a MIDI device (like pressing a key on a keyboard), you attach an onmidimessage event handler to an input port.

function startLoggingMIDIInput(midiAccess) {
  midiAccess.inputs.forEach((entry) => {
    entry.onmidimessage = onMIDIMessage;
  });
}

function onMIDIMessage(event) {
  const [command, note, velocity] = event.data;
  console.log(`Command: ${command}, Note: ${note}, Velocity: ${velocity}`);
}

4. Sending MIDI Messages

To send data to a device (like playing a sound on a synthesizer), you use the send() method on an output port.

function playNote(midiAccess, note = 60, velocity = 127) {
  const output = midiAccess.outputs.values().next().value; // Get first output

  if (output) {
    const noteOnMessage = [0x90, note, velocity]; // 0x90 = Note On, Channel 1
    const noteOffMessage = [0x80, note, velocity]; // 0x80 = Note Off, Channel 1

    output.send(noteOnMessage);  // Play note
    output.send(noteOffMessage, window.performance.now() + 1000); // Stop after 1s
  }
}

programming/javascript/vanilla/javascript programming/javascript/vanilla/events programming/javascript/vanilla/promises-async-await