Signatur
Beschreibung
currentTime ist eine globale, schreibgeschützte Eigenschaft im Scope eines AudioWorklets. Sie gibt einen number-Wert (Double) in Sekunden zurück. Dieser Wert entspricht der Kontextzeit des Audioblocks, den die Engine gerade verarbeitet. Er entspricht BaseAudioContext.currentTime im Hauptthread, wird aber direkt im Audio-Rendering-Thread gelesen und ist deshalb für diesen Block exakt.
Weil der Code eines AudioWorkletProcessor im globalen Scope des Worklets läuft, greifst du einfach über den Bezeichner currentTime darauf zu. Ein Präfix wie globalThis ist nicht nötig. Die Zeit springt pro Aufruf von process() um genau 128 / sampleRate Sekunden weiter, also um eine Blocklänge (render quantum). Innerhalb eines Blocks bleibt sie gleich.
Typische Anwendungen:
- sample-genaues Planen von Ereignissen, z. B. Hüllkurven, Metronom-Klicks oder das Ein- und Ausschalten eines Oszillators zu einem bestimmten Zeitpunkt,
- Abgleich mit Zeitstempeln, die der Hauptthread per
port.postMessage()schickt, - Messungen und Diagnose im Rendering-Thread.
Wenn du die Zeit eines einzelnen Samples innerhalb des Blocks brauchst, rechne sie selbst aus: currentTime + i / sampleRate. Alternativ kannst du mit currentFrame arbeiten.
Rückgabewert
Beispiele
Kontextzeit im Prozessor auslesen
// time-logger.js (wird per audioWorklet.addModule geladen)
class TimeLogger extends AudioWorkletProcessor {
constructor() {
super();
this.lastLog = 0;
}
process() {
// Etwa einmal pro Sekunde die Zeit an den Hauptthread melden
if (currentTime - this.lastLog >= 1) {
this.lastLog = currentTime;
this.port.postMessage({ time: currentTime, frame: currentFrame });
}
return true;
}
}
registerProcessor('time-logger', TimeLogger);
// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('time-logger.js');
const node = new AudioWorkletNode(ctx, 'time-logger');
node.port.onmessage = ({ data }) => console.log(data);
node.connect(ctx.destination);
Sample-genaues Ein- und Ausschalten eines Tons
// gated-sine.js
class GatedSine extends AudioWorkletProcessor {
constructor() {
super();
this.phase = 0;
this.start = Infinity;
this.stop = Infinity;
// Hauptthread schickt Start- und Stoppzeit in Kontextzeit
this.port.onmessage = ({ data }) => {
this.start = data.start;
this.stop = data.stop;
};
}
process(inputs, outputs) {
const out = outputs[0][0];
for (let i = 0; i < out.length; i++) {
const t = currentTime + i / sampleRate; // Zeit dieses Samples
const active = t >= this.start && t < this.stop;
out[i] = active ? Math.sin(this.phase) * 0.2 : 0;
this.phase += (2 * Math.PI * 440) / sampleRate;
}
return true;
}
}
registerProcessor('gated-sine', GatedSine);
// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('gated-sine.js');
const sine = new AudioWorkletNode(ctx, 'gated-sine');
sine.connect(ctx.destination);
const now = ctx.currentTime;
sine.port.postMessage({ start: now + 0.5, stop: now + 1.5 });
Blockdauer aus currentTime ableiten
// block-check.js
class BlockCheck extends AudioWorkletProcessor {
constructor() {
super();
this.prev = null;
}
process() {
if (this.prev !== null) {
const delta = currentTime - this.prev;
// Entspricht 128 / sampleRate
this.port.postMessage({ delta, expected: 128 / sampleRate });
return false; // Prozessor danach beenden
}
this.prev = currentTime;
return true;
}
}
registerProcessor('block-check', BlockCheck);
// Wichtig · Fallstricke
- Nur im Worklet verfügbar:
currentTimegibt es ausschließlich imAudioWorkletGlobalScope. Im Hauptthread verwendest du stattdessenaudioContext.currentTime. - Schreibgeschützt: Eine Zuweisung hat keine Wirkung. Im Strict Mode, der in ES-Modulen immer gilt, löst sie einen
TypeErroraus. Lege außerdem keine eigene Variable mit dem NamencurrentTimean, denn sie würde die globale Eigenschaft verdecken. - Auflösung pro Block: Der Wert ändert sich nur einmal pro Render-Quantum, normalerweise alle 128 Frames. Für eine Genauigkeit auf Sample-Ebene rechnest du
currentTime + i / sampleRate. - Keine Wanduhr: Die Kontextzeit bleibt stehen, solange der
AudioContextangehalten ist (suspend()). Sie hängt nicht mitperformance.now()oderDate.now()zusammen. Zum Umrechnen dientAudioContext.getOutputTimestamp()im Hauptthread. - Latenz bei Nachrichten: Zeitwerte, die per
postMessageankommen, können schon in der Vergangenheit liegen. Plane deshalb mit etwas Vorlauf, z. B.ctx.currentTime + 0.1. - Kompatibilität: AudioWorklet setzt einen sicheren Kontext (HTTPS) voraus. Unterstützt wird es in Chrome/Edge 66+, Firefox 76+ und Safari 14.1+.