Start · Sprachen · JavaScript · Referenz · MIDIOutput.send()

MIDIOutput.send()

Methode

Stellt eine oder mehrere MIDI-Nachrichten für den zugehörigen Ausgangsport in die Warteschlange, entweder sofort oder zu einem bestimmten Zeitpunkt.

seit JavaScript Web MIDI API – Chromium-Browser, Firefox 108+, nic Kategorie: webapi

Signatur

MIDIOutput.prototype.send(data, timestamp)

Beschreibung

Mit send() schickt man MIDI-Daten an einen Ausgangsport, zum Beispiel an einen Hardware-Synthesizer, eine DAW über einen virtuellen Port oder einen Controller mit LED-Rückmeldung. Die Daten werden als Folge von Bytes übergeben, etwa [0x90, 60, 127] für „Note On, Kanal 1, mittleres C, volle Anschlagstärke“.

Das Array muss aus vollständigen und gültigen MIDI-Nachrichten bestehen. Man kann mehrere Nachrichten hintereinander in ein Array packen. Running Status (also das Weglassen wiederholter Statusbytes) ist nicht erlaubt. System-Exclusive-Nachrichten (0xF0 … 0xF7) gehen nur, wenn der Zugriff mit navigator.requestMIDIAccess({ sysex: true }) angefordert wurde.

Mit dem optionalen Parameter timestamp legt man fest, wann die Nachricht gesendet wird. Der Wert ist ein DOMHighResTimeStamp auf derselben Zeitbasis wie performance.now(). So lassen sich Noten genau takten, ohne dass Timer im JavaScript-Hauptthread schwanken. Fehlt der Parameter oder liegt der Zeitpunkt in der Vergangenheit, wird die Nachricht sofort gesendet.

Ist der Port noch nicht offen, öffnet send() ihn automatisch. Wurde der Port geschlossen oder ist das Gerät getrennt, wird ein Fehler ausgelöst.

Parameter

Name Typ Default Beschreibung
$data Pflicht number[] | Uint8Array Folge von Datenbytes (0–255), die eine oder mehrere vollständige MIDI-Nachrichten bilden. Statusbytes ≥ 0x80, Datenbytes 0–127.
$timestamp DOMHighResTimeStamp (number) 0 (sofort) Zeitpunkt in Millisekunden relativ zu performance.timeOrigin, also auf derselben Zeitbasis wie performance.now(), zu dem gesendet werden soll. 0 oder ein Wert in der Vergangenheit bedeutet: sofort senden.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Bei ungültigen Daten wird ein TypeError ausgelöst, bei SysEx ohne Berechtigung ein InvalidAccessError, bei getrenntem Port ein InvalidStateError.

Beispiele

Note sofort an- und nach 500 ms per Zeitstempel ausschalten

const playNote = async () => {
  const access = await navigator.requestMIDIAccess();
  const output = [...access.outputs.values()][0];
  if (!output) {
    console.log('Kein MIDI-Ausgang gefunden');
    return;
  }
  // Note On: Kanal 1, mittleres C (60), Anschlagstärke 100
  output.send([0x90, 60, 100]);
  // Note Off genau 500 ms später, vom Browser getaktet
  output.send([0x80, 60, 0], performance.now() + 500);
  console.log(`Note gesendet an: ${output.name}`);
};

playNote();
Note gesendet an: USB MIDI Interface

Akkord und Programmwechsel mit einem einzigen Aufruf

const sendChord = (output, channel = 0) => {
  const noteOn = 0x90 | channel;
  // Mehrere vollständige Nachrichten in einem Array (kein Running Status!)
  output.send([
    0xC0 | channel, 5,        // Programmwechsel auf Klang 6
    noteOn, 60, 90,           // C
    noteOn, 64, 90,           // E
    noteOn, 67, 90            // G
  ]);
};

const access = await navigator.requestMIDIAccess();
const output = access.outputs.values().next().value;
if (output) sendChord(output);

Genau getaktete Tonfolge (Sequenzer)

const playSequence = (output, notes, bpm = 120) => {
  const beatMs = 60000 / bpm;
  const start = performance.now() + 100; // kleiner Vorlauf
  notes.forEach((note, i) => {
    const t = start + i * beatMs;
    output.send([0x90, note, 100], t);
    output.send([0x80, note, 0], t + beatMs * 0.9);
  });
};

const access = await navigator.requestMIDIAccess();
const output = access.outputs.values().next().value;
if (output) playSequence(output, [60, 62, 64, 65, 67]);

SysEx-Nachricht senden (Berechtigung nötig)

try {
  const access = await navigator.requestMIDIAccess({ sysex: true });
  const output = access.outputs.values().next().value;
  // Universal Identity Request
  output?.send(new Uint8Array([0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7]));
  console.log('Identity Request gesendet');
} catch (err) {
  console.error('SysEx nicht erlaubt:', err.name);
}
Identity Request gesendet

// Wichtig · Fallstricke

  • Browser-Unterstützung: Chrome, Edge und Opera unterstützen die Web MIDI API schon lange, Firefox ab Version 108 (mit Berechtigungsabfrage bzw. Site-Permission-Add-on). Safari unterstützt sie nicht. Vor der Nutzung prüfen: 'requestMIDIAccess' in navigator.
  • Nur in einem sicheren Kontext (HTTPS oder localhost) verfügbar. Der Browser fragt meist nach einer Berechtigung, bei sysex: true immer.
  • Kein Running Status: Jede Nachricht braucht ihr eigenes Statusbyte, sonst gibt es einen TypeError. Datenbytes über 127 sind ebenfalls ungültig.
  • Nachrichten mit Zeitstempel landen in einer internen Warteschlange. Mit MIDIOutput.clear() lässt sich diese leeren (noch nicht überall umgesetzt). Wer beim Stoppen hängende Noten vermeiden will, sendet zusätzlich „All Notes Off“ ([0xB0, 123, 0]).
  • Sehr große SysEx-Datenmengen oder eine sehr hohe Nachrichtenrate können einen Engpass verursachen, weil die MIDI-Übertragung auf 31,25 kbit/s begrenzt ist.
  • Der Zeitstempel muss auf der Zeitbasis von performance.now() liegen, nicht auf der von Date.now().