# 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.

```javascript
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.

```javascript
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.

```javascript
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.

```javascript
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]]