Signatur
Beschreibung
MIDIOutput gehört zur Web MIDI API und steht für einen einzelnen MIDI-Ausgang, etwa einen Hardware-Synthesizer, ein USB-MIDI-Interface oder einen virtuellen MIDI-Port des Betriebssystems. Selbst erzeugen kann man solche Objekte nicht. Man bekommt sie über die Map MIDIAccess.outputs, nachdem navigator.requestMIDIAccess() erfolgreich war.
Das Interface erbt von MIDIPort und damit auch von EventTarget. Deshalb gibt es alle Port-Eigenschaften wie id, name, manufacturer, state und connection, außerdem die Methoden open() und close() und das Event statechange. Dazu kommen zwei eigene Methoden:
send(data, timestamp)stellt eine MIDI-Nachricht (ein Byte-Array) in die Warteschlange. Sie wird sofort gesendet oder zu einem bestimmten Zeitpunkt auf der Zeitachse vonperformance.now().clear()verwirft alle Nachrichten, die in der Warteschlange stehen und noch nicht gesendet wurden. Diese Methode ist nicht in allen Browsern umgesetzt.
Typische Einsatzfälle sind Web-Sequencer, Editoren für Synthesizer-Patches, Lichtsteuerung per MIDI, Lernanwendungen und das Senden von SysEx-Nachrichten (System Exclusive) an Hardware. Weil man Nachrichten mit einem Zeitstempel einplanen kann, lassen sich Noten sehr genau timen, ohne dass setTimeout ungenau wird.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $data Pflicht | Array<number> | Uint8Array | Parameter von send(): eine vollständige MIDI-Nachricht als Folge von Bytes (0–255), z. B. [0x90, 60, 127] für Note-On. Ist die Nachricht ungültig, wird ein TypeError geworfen. |
|
| $timestamp | DOMHighResTimeStamp (number) | 0 (sofort senden) | Parameter von send(): Zeitpunkt in Millisekunden auf der Zeitachse von performance.now(), zu dem die Nachricht gesendet werden soll. Liegt der Wert in der Vergangenheit oder ist er 0, wird sofort gesendet. |
Rückgabewert
send() und clear() geben undefined zurück. Ein Fehler wird als Ausnahme geworfen: InvalidStateError, wenn der Port getrennt ist, InvalidAccessError bei SysEx ohne Berechtigung und TypeError bei ungültigen Daten.Beispiele
Ausgänge auflisten und einen Ton spielen
const spieleTon = async () => {
const midi = await navigator.requestMIDIAccess();
for (const output of midi.outputs.values()) {
console.log(`${output.name} (${output.manufacturer}) – ${output.state}`);
}
const [output] = midi.outputs.values();
if (!output) {
console.warn('Kein MIDI-Ausgang gefunden');
return;
}
// Note-On: Kanal 1, mittleres C (60), Anschlagstärke 100
output.send([0x90, 60, 100]);
// Note-Off 500 ms später, zeitgenau geplant
output.send([0x80, 60, 0], performance.now() + 500);
};
document.querySelector('#play').addEventListener('click', spieleTon);
Akkordfolge zeitgenau planen und abbrechen
const planeAkkorde = (output, bpm = 120) => {
const schlag = 60000 / bpm;
const akkorde = [[60, 64, 67], [57, 60, 64], [65, 69, 72], [67, 71, 74]];
const start = performance.now() + 100;
akkorde.forEach((akkord, i) => {
const an = start + i * schlag;
for (const note of akkord) {
output.send([0x90, note, 90], an);
output.send([0x80, note, 0], an + schlag * 0.9);
}
});
};
const stopp = (output) => {
// Geplante Nachrichten verwerfen (sofern unterstützt)
if (typeof output.clear === 'function') output.clear();
// All Notes Off (CC 123) auf allen 16 Kanälen
for (let ch = 0; ch < 16; ch++) {
output.send([0xB0 | ch, 123, 0]);
}
};
SysEx-Nachricht senden (mit Berechtigung)
const sendeSysEx = async () => {
try {
const midi = await navigator.requestMIDIAccess({ sysex: true });
const output = [...midi.outputs.values()].find((o) => o.name.includes('Synth'));
if (!output) throw new Error('Gerät nicht gefunden');
await output.open();
// Universal Identity Request
output.send(new Uint8Array([0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7]));
console.log('Identity Request gesendet an', output.name);
} catch (err) {
console.error('MIDI-Fehler:', err.name, err.message);
}
};
sendeSysEx();
// Wichtig · Fallstricke
- Browser-Unterstützung: Chrome, Edge und Opera unterstützen die API, Firefox erst ab Version 108 und dort mit einer Abfrage bzw. per Website-Berechtigungs-Add-on. Safari unterstützt die Web MIDI API nicht. Vor der Nutzung sollte man prüfen, ob sie vorhanden ist:
'requestMIDIAccess' in navigator. - Sicherer Kontext und Berechtigung: Die API funktioniert nur über HTTPS bzw.
localhost. Der Browser fragt den Nutzer um Erlaubnis. SysEx braucht{ sysex: true }, weil man damit die Firmware eines Geräts verändern kann. Ohne diese Freigabe wirftsend()bei SysEx einenInvalidAccessError. Außerdem kann eine Permissions-Policy (midi) den Zugriff in iframes sperren. - clear(): Die Methode ist in Chromium lange Zeit nicht umgesetzt worden. Vor dem Aufruf sollte man daher prüfen, ob es sie gibt. Hängende Noten lassen sich zuverlässig mit „All Notes Off“ (CC 123) oder mit einzelnen Note-Off-Nachrichten beenden.
- Zeitstempel: Der Zeitstempel bezieht sich auf
performance.now()und nicht aufDate.now()und auch nicht aufAudioContext.currentTime(Sekunden). Wer MIDI und Web Audio synchronisieren will, muss die Zeitwerte umrechnen. - Laufender Status (Running Status) ist nicht erlaubt: Jede Nachricht muss ein vollständiges Statusbyte haben. Die Bytes einer SysEx-Nachricht müssen mit
0xF0beginnen und mit0xF7enden. - Ist der Port noch geschlossen, öffnet
send()ihn automatisch. Ist das Gerät getrennt (state === 'disconnected'), wird einInvalidStateErrorgeworfen.