Signatur
Beschreibung
Ein MIDIMessageEvent wird immer dann ausgelöst, wenn ein angeschlossenes MIDI-Eingabegerät (Keyboard, Controller, Drum-Pad, DAW-Software über einen virtuellen Port) eine Nachricht sendet. Das Ereignis wird am jeweiligen MIDIInput-Objekt als midimessage ausgelöst und lässt sich per addEventListener("midimessage", …) oder über die Eigenschaft onmidimessage abfangen.
Die wichtigste Eigenschaft ist data, ein Uint8Array mit den Rohbytes einer vollständigen MIDI-Nachricht. Das erste Byte ist das Statusbyte: Die oberen 4 Bit geben den Nachrichtentyp an (z. B. 0x90 = Note On, 0x80 = Note Off, 0xB0 = Control Change, 0xE0 = Pitch Bend), die unteren 4 Bit den MIDI-Kanal (0–15). Die folgenden Datenbytes (0–127) enthalten z. B. Notennummer und Anschlagstärke. Zusätzlich erbt das Ereignis timeStamp von Event, das den Empfangszeitpunkt als DOMHighResTimeStamp (vergleichbar mit performance.now()) angibt.
Typische Anwendungsfälle sind Web-Synthesizer mit der Web Audio API, Lernanwendungen für Klavier, Lichtsteuerungen oder das Mappen von Hardware-Reglern auf UI-Elemente. Den Zugriff auf die Geräte erhält man zuvor über navigator.requestMIDIAccess(). Für Tests lässt sich ein Ereignis auch selbst mit dem Konstruktor new MIDIMessageEvent(type, { data }) erzeugen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses, in der Praxis immer "midimessage" (nur beim Konstruktor relevant). |
|
| $options | object | {} | Konstruktor-Optionen: data (Uint8Array, die MIDI-Bytes) sowie die üblichen EventInit-Felder bubbles, cancelable, composed. |
| $data | Uint8Array | Schreibgeschützte Instanz-Eigenschaft: Rohbytes der MIDI-Nachricht (Statusbyte + Datenbytes). |
Rückgabewert
MIDIMessageEvent; im Handler erhält man das vom Browser erzeugte Ereignisobjekt mit data und timeStamp.Beispiele
Alle Eingänge abhören und Note-On/Off auswerten
const noteName = (n) => ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'][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;
if (command === 0x90 && velocity > 0) {
console.log(`Note On ${noteName(note)} Kanal ${channel} Velocity ${velocity}`);
} else if (command === 0x80 || (command === 0x90 && velocity === 0)) {
console.log(`Note Off ${noteName(note)} Kanal ${channel}`);
}
};
const init = async () => {
try {
const access = await navigator.requestMIDIAccess();
for (const input of access.inputs.values()) {
input.addEventListener('midimessage', handleMessage);
}
} catch (err) {
console.error('MIDI-Zugriff verweigert:', err);
}
};
init();
Drehregler (Control Change) per onmidimessage auf einen Slider mappen
const slider = document.querySelector('#volume');
const access = await navigator.requestMIDIAccess();
const [input] = access.inputs.values();
if (input) {
input.onmidimessage = ({ data, timeStamp }) => {
const [status, controller, value] = data;
// Control Change, Controller 7 = Kanal-Lautstärke
if ((status & 0xf0) === 0xb0 && controller === 7) {
slider.value = Math.round((value / 127) * 100);
console.log(`Lautstärke ${slider.value} % @ ${timeStamp.toFixed(1)} ms`);
}
};
}
// Später wieder abmelden:
// input.onmidimessage = null;
Ereignis für Tests manuell erzeugen und wieder entfernen
const target = new EventTarget();
const logger = (e) => console.log(e instanceof MIDIMessageEvent, Array.from(e.data));
target.addEventListener('midimessage', logger);
const fake = new MIDIMessageEvent('midimessage', {
data: new Uint8Array([0x90, 60, 127])
});
target.dispatchEvent(fake);
target.removeEventListener('midimessage', logger);
target.dispatchEvent(fake); // keine Ausgabe mehr
// Wichtig · Fallstricke
- Browser-Kompatibilität: Unterstützt in Chrome, Edge, Opera und Firefox (ab 108); Safari unterstützt die Web MIDI API nicht. Vorher mit
'requestMIDIAccess' in navigatorprüfen. - Sicherer Kontext & Berechtigung: Nur über HTTPS (oder
localhost) verfügbar; der Nutzer muss den Zugriff bestätigen. In iframes ist die Permissions-Policymidinötig. - Note On mit Velocity 0: Viele Geräte senden statt Note Off (
0x80) ein Note On (0x90) mit Velocity 0 – beide Fälle behandeln. - Nachrichtenlänge variiert:
datakann 1 Byte (z. B. Timing Clock0xF8, bis zu 24× pro Viertelnote!), 2, 3 oder bei SysEx beliebig viele Bytes enthalten. Clock-/Active-Sensing-Nachrichten (0xF8,0xFE) früh herausfiltern, um den Handler nicht zu überlasten. - SysEx: System-Exclusive-Nachrichten (
0xF0) kommen nur an, wenn mitrequestMIDIAccess({ sysex: true })angefragt wurde – das löst eine gesonderte Berechtigungsabfrage aus. - Die veraltete Eigenschaft
receivedTimeexistiert nicht mehr; stattdessenevent.timeStampverwenden. - Ein Listener per
addEventListeneröffnet den Port implizit;onmidimessageebenso.