Start · Sprachen · JavaScript · Referenz · MIDIInput

MIDIInput

Schnittstelle

Die <code>MIDIInput</code>-Schnittstelle der Web MIDI API steht für einen MIDI-Eingangsport und empfängt dessen Nachrichten über das Ereignis <code>midimessage</code>.

seit JavaScript Web MIDI API — Chrome/Edge 43+, Opera 30+, Firefox Kategorie: webapi

Signatur

interface MIDIInput extends MIDIPort

Beschreibung

MIDIInput steht für einen einzelnen MIDI-Eingangsport, etwa ein USB-Keyboard, einen Controller mit Drehreglern oder einen virtuellen MIDI-Bus. Die Schnittstelle erbt von MIDIPort und damit auch von EventTarget. Eigenschaften wie id, name, manufacturer, state und connection sowie die Methoden open() und close() sind also verfügbar.

Eine eigene Methode oder einen Konstruktor hat MIDIInput nicht. Instanzen bekommt man ausschließlich über navigator.requestMIDIAccess(). Das zurückgelieferte MIDIAccess-Objekt enthält in inputs eine MIDIInputMap (eine Map-ähnliche Struktur, die von der ID auf den MIDIInput verweist).

Das Wichtigste an der Schnittstelle ist das Ereignis midimessage. Es wird für jede eingehende MIDI-Nachricht ausgelöst und liefert ein MIDIMessageEvent. Dessen Eigenschaft data ist ein Uint8Array mit den Rohbytes: Statusbyte (Nachrichtentyp und Kanal) und Datenbytes (z. B. Notennummer und Anschlagstärke). Man registriert den Handler über addEventListener("midimessage", …) oder die Eigenschaft onmidimessage.

Typische Einsatzfälle sind Web-Synthesizer (zusammen mit der Web Audio API), Lern-Apps für Musikinstrumente, das Steuern von Visualisierungen mit Hardware-Controllern und Diagnose-Werkzeuge, die MIDI-Nachrichten mitschneiden.

Parameter

Name Typ Default Beschreibung
$onmidimessage ((event: MIDIMessageEvent) => void) | null null Handler-Eigenschaft für das Ereignis midimessage. Wird sie gesetzt, öffnet der Browser den Port automatisch (implizites open()).
$event.data Uint8Array Rohbytes der MIDI-Nachricht im MIDIMessageEvent. data[0] ist das Statusbyte, danach folgen die Datenbytes.
$event.timeStamp DOMHighResTimeStamp Empfangszeitpunkt in Millisekunden, vergleichbar mit performance.now().

Rückgabewert

Typ
MIDIInput
Beschreibung
Wird nicht direkt erzeugt, sondern über MIDIAccess.inputs bereitgestellt. Geerbt von MIDIPort sind unter anderem type (immer "input"), state ("connected" oder "disconnected") und connection ("open", "closed" oder "pending").

Beispiele

Alle MIDI-Eingänge auflisten

const listInputs = async () => {
  if (!navigator.requestMIDIAccess) {
    console.warn('Web MIDI wird nicht unterstützt');
    return;
  }
  const access = await navigator.requestMIDIAccess();
  for (const input of access.inputs.values()) {
    console.log(`${input.name} (${input.manufacturer}) – ${input.state}`);
  }
};

listInputs();
Digital Piano (Roland) – connected

Note-On/Note-Off mit addEventListener auswerten

const noteName = (n) =>
  ['C','C#','D','D#','E','F','F#','G','G#','A','A#','H'][n % 12] + (Math.floor(n / 12) - 1);

const handleMessage = (event) => {
  const [status, note, velocity] = event.data;
  const command = status & 0xf0;
  const channel = (status & 0x0f) + 1;

  // Note-On mit Anschlagstärke 0 gilt laut MIDI-Standard als Note-Off
  if (command === 0x90 && velocity > 0) {
    console.log(`Kanal ${channel}: ${noteName(note)} an (Anschlagstärke ${velocity})`);
  } else if (command === 0x80 || (command === 0x90 && velocity === 0)) {
    console.log(`Kanal ${channel}: ${noteName(note)} aus`);
  }
};

const access = await navigator.requestMIDIAccess();
access.inputs.forEach((input) => {
  input.addEventListener('midimessage', handleMessage);
});
Kanal 1: C4 an (Anschlagstärke 96) Kanal 1: C4 aus

Handler per onmidimessage setzen und wieder entfernen

const access = await navigator.requestMIDIAccess();
const [input] = access.inputs.values();

if (input) {
  // Controller-Änderungen (CC) mitschneiden, z. B. für Drehregler
  input.onmidimessage = ({ data }) => {
    if ((data[0] & 0xf0) === 0xb0) {
      console.log(`CC ${data[1]} = ${data[2]}`);
    }
  };

  // Nach 10 Sekunden Mitschnitt beenden und Port freigeben
  setTimeout(async () => {
    input.onmidimessage = null;
    await input.close();
    console.log('Port geschlossen:', input.connection);
  }, 10_000);
}
CC 7 = 100 Port geschlossen: closed

Anschließen und Trennen von Geräten erkennen

const access = await navigator.requestMIDIAccess();

access.addEventListener('statechange', ({ port }) => {
  if (port.type !== 'input') return;
  console.log(`${port.name}: ${port.state}`);
  if (port.state === 'connected') {
    port.onmidimessage = (e) => console.log('Daten:', [...e.data]);
  }
});
Launchpad Mini: connected Daten: [144, 36, 127]

// Wichtig · Fallstricke

  • Browser-Unterstützung: Chromium-Browser unterstützen die Web MIDI API seit Langem, Firefox seit Version 108 (mit Berechtigungsabfrage und Site-Permission-Add-on). Safari unterstützt sie nicht. Vor der Nutzung sollte man immer mit 'requestMIDIAccess' in navigator prüfen, ob die API vorhanden ist.
  • Sicherer Kontext und Berechtigung: Die API funktioniert nur über HTTPS (oder localhost) und fragt den Nutzer um Erlaubnis. In iframes muss die Permissions Policy midi erlaubt sein.
  • SysEx: System-Exclusive-Nachrichten (Statusbyte 0xF0) kommen nur an, wenn der Zugriff mit requestMIDIAccess({ sysex: true }) angefordert wurde. Das löst eine eigene, strengere Berechtigungsabfrage aus, weil SysEx die Firmware eines Geräts verändern kann.
  • Implizites Öffnen: Wer onmidimessage setzt, öffnet den Port automatisch. Bei addEventListener passiert das in manchen Implementierungen nicht zuverlässig. Im Zweifel vorher await input.open() aufrufen.
  • Note-Off-Falle: Viele Geräte senden statt Note-Off (0x80) ein Note-On (0x90) mit Anschlagstärke 0. Beide Fälle sollten ausgewertet werden.
  • Laufzeit-Status und Active Sensing: MIDIMessageEvent.data enthält immer vollständige Nachrichten mit Statusbyte. Echtzeit-Nachrichten wie Clock (0xF8) oder Active Sensing (0xFE) können sehr häufig kommen und sollten früh herausgefiltert werden, damit die Leistung nicht leidet.
  • Die MIDIInputMap ist eine Momentaufnahme. Geräte, die später angeschlossen werden, erkennt man über das Ereignis statechange an MIDIAccess.