Start · Sprachen · JavaScript · Referenz · AudioProcessingEvent.playbackTime

AudioProcessingEvent.playbackTime

Eigenschaft

Schreibgeschützte Eigenschaft, die angibt, zu welchem Zeitpunkt (in Sekunden, bezogen auf <code>AudioContext.currentTime</code>) der verarbeitete Audioblock abgespielt wird.

seit JavaScript Baseline: alle Browser (veraltet) deprecated seit ja Kategorie: webapi

Signatur

AudioProcessingEvent.playbackTime

Beschreibung

Die Eigenschaft playbackTime eines AudioProcessingEvent enthält einen double-Wert in Sekunden. Er gibt an, wann der Audioblock, den du gerade im audioprocess-Handler eines ScriptProcessorNode in outputBuffer schreibst, tatsächlich hörbar wird. Die Zeitachse ist dieselbe wie bei AudioContext.currentTime.

Weil ein ScriptProcessorNode Daten blockweise und mit Pufferlatenz verarbeitet, liegt playbackTime in der Regel etwas nach dem aktuellen currentTime. Den Wert kannst du nutzen, um eigene Klangerzeugung zeitlich genau zu steuern, etwa bei einem Metronom, einem Sequenzer oder einer Hüllkurve, die an geplante Ereignisse gekoppelt ist.

Die Eigenschaft ist schreibgeschützt und gilt nur für das jeweilige Ereignisobjekt. Zusammen mit inputBuffer.length und sampleRate kannst du für jedes einzelne Sample die genaue Abspielzeit berechnen: playbackTime + i / sampleRate.

Rückgabewert

Typ
number
Beschreibung
Ein double in Sekunden auf der Zeitachse des zugehörigen AudioContext. Er gibt an, wann das erste Sample des aktuellen Blocks abgespielt wird.

Beispiele

Abspielzeit und Latenz protokollieren

const ctx = new AudioContext();
const processor = ctx.createScriptProcessor(4096, 1, 1);

processor.addEventListener('audioprocess', (event) => {
  const latency = event.playbackTime - ctx.currentTime;
  console.log(`Block spielt bei ${event.playbackTime.toFixed(3)} s (Latenz ≈ ${(latency * 1000).toFixed(1)} ms)`);
  // Eingang unverändert durchreichen
  event.outputBuffer.getChannelData(0).set(event.inputBuffer.getChannelData(0));
});

processor.connect(ctx.destination);
Block spielt bei 0.186 s (Latenz ≈ 92.9 ms)

Sinuston zeitgenau (phasenkontinuierlich) erzeugen

const ctx = new AudioContext();
const processor = ctx.createScriptProcessor(2048, 0, 1);
const freq = 440;

processor.onaudioprocess = (event) => {
  const out = event.outputBuffer.getChannelData(0);
  const sr = ctx.sampleRate;
  for (let i = 0; i < out.length; i++) {
    // Absolute Zeit jedes Samples
    const t = event.playbackTime + i / sr;
    out[i] = 0.2 * Math.sin(2 * Math.PI * freq * t);
  }
};

processor.connect(ctx.destination);

Metronom-Klick zu geplanten Zeitpunkten

const ctx = new AudioContext();
const processor = ctx.createScriptProcessor(1024, 0, 1);
const interval = 0.5; // 120 BPM
const clickLen = 0.01;

processor.onaudioprocess = ({ playbackTime, outputBuffer }) => {
  const out = outputBuffer.getChannelData(0);
  const sr = ctx.sampleRate;
  for (let i = 0; i < out.length; i++) {
    const t = playbackTime + i / sr;
    const phase = t % interval;
    out[i] = phase < clickLen ? (Math.random() * 2 - 1) * 0.5 : 0;
  }
};

processor.connect(ctx.destination);

// Wichtig · Fallstricke

  • Veraltet: AudioProcessingEvent und ScriptProcessorNode sind in der Web-Audio-Spezifikation als veraltet markiert. Nutze für neue Projekte AudioWorkletNode bzw. AudioWorkletProcessor. Dort liefern die globalen Werte currentTime und currentFrame im AudioWorkletGlobalScope die entsprechenden Zeitinformationen.
  • Der Handler läuft im Haupt-Thread. Wenn die Seite ausgelastet ist, kommt es zu Aussetzern, und playbackTime kann zwischen zwei Aufrufen um mehr als eine Blocklänge springen.
  • Leite die Phase von Oszillatoren aus playbackTime ab statt aus einem eigenen Zähler. So bleibt die Synchronisation mit anderen Knoten erhalten, die über start(when) geplant sind.
  • Die Browser setzen den Wert unterschiedlich genau um. In älteren Safari-Versionen (nur webkitAudioContext) ist playbackTime teilweise ungenau oder nicht vorhanden. Prüfe daher mit typeof event.playbackTime === 'number'.
  • Auf playbackTime kommt es erst an, wenn der Kontext läuft. Wegen der Autoplay-Richtlinien musst du ctx.resume() meist nach einer Nutzeraktion aufrufen.