Signatur
Beschreibung
resume() setzt die Zeit in einem OfflineAudioContext fort, der zuvor mit suspend(suspendTime) angehalten wurde. Ein Offline-Kontext berechnet Audio so schnell wie möglich in einen Puffer, nicht in Echtzeit. Mit suspend() und resume() kannst du diese Berechnung an genau festgelegten Zeitpunkten anhalten. Dann kannst du den Audio-Graphen umbauen und das Rendering danach fortsetzen.
Typische Einsätze sind:
- Graph ändern: an festen Stellen Knoten verbinden oder trennen und Parameter setzen, zum Beispiel Effekte umschalten oder Quellen hinzufügen.
- Fortschritt anzeigen: in regelmäßigen Abständen anhalten, den Fortschritt melden und weiterrendern.
- Dinge vorbereiten: teure Aufgaben wie das Dekodieren weiterer Dateien erledigen, bevor das Rendering weiterläuft.
Anders als bei AudioContext.resume() kann ein Offline-Kontext nur fortgesetzt werden, wenn das Rendering schon mit startRendering() gestartet wurde. Das Promise von resume() wird erfüllt, sobald der Kontext wieder rendert. Das eigentliche Ergebnis, also der fertige AudioBuffer, kommt weiterhin aus dem Promise von startRendering().
Rückgabewert
undefined erfüllt wird, sobald das Rendering weiterläuft. Es wird mit einem InvalidStateError (DOMException) abgelehnt, wenn das Rendering noch nicht gestartet wurde oder der Kontext bereits geschlossen ist bzw. fertig gerendert hat.Beispiele
Frequenz an einem festen Zeitpunkt ändern
const ctx = new OfflineAudioContext({ numberOfChannels: 1, length: 44100 * 2, sampleRate: 44100 });
const osc = new OscillatorNode(ctx, { frequency: 440 });
osc.connect(ctx.destination);
osc.start();
// Anhalten bei 1 Sekunde vormerken – vor startRendering()!
ctx.suspend(1).then(async () => {
console.log('Angehalten bei', ctx.currentTime.toFixed(3), 's');
osc.frequency.value = 880; // Graph während der Pause ändern
await ctx.resume();
console.log('Rendering läuft weiter');
});
const buffer = await ctx.startRendering();
console.log('Fertig:', buffer.duration, 's');
Fortschrittsanzeige beim Offline-Export
const renderWithProgress = async (ctx, step = 0.5, onProgress) => {
const total = ctx.length / ctx.sampleRate;
for (let t = step; t < total; t += step) {
ctx.suspend(t).then(() => {
onProgress(Math.round((ctx.currentTime / total) * 100));
return ctx.resume();
});
}
return ctx.startRendering();
};
const ctx = new OfflineAudioContext(2, 44100 * 2, 44100);
const osc = new OscillatorNode(ctx);
osc.connect(ctx.destination);
osc.start();
const result = await renderWithProgress(ctx, 0.5, (p) => console.log(`${p} %`));
console.log('Samples:', result.length);
Fehler: resume() vor startRendering()
const ctx = new OfflineAudioContext(1, 44100, 44100);
try {
await ctx.resume();
} catch (err) {
console.log(err.name); // Rendering wurde noch nicht gestartet
}
// Wichtig · Fallstricke
- Erst rendern, dann fortsetzen: Wenn du
resume()vorstartRendering()aufrufst, wird das Promise mitInvalidStateErrorabgelehnt. Nach dem Ende des Renderings passiert dasselbe. suspend()vorher vormerken: Rufesuspend(time)in der Regel vorstartRendering()auf. Weil das Offline-Rendering sehr schnell läuft, ist ein späterer Zeitpunkt sonst womöglich schon vorbei. Zeitpunkte, die kleiner alscurrentTimeoder mindestens so groß wie die Gesamtdauer sind, werden abgelehnt.- Zeitpunkte werden gerundet: Die Pausenzeit wird auf ein Vielfaches des Render-Blocks gerundet (128 Frames).
currentTimekann deshalb leicht vom angefragten Wert abweichen. Wenn zweisuspend()-Aufrufe auf denselben Block fallen, wird der zweite abgelehnt. - Vergessenes
resume(): Ohneresume()bleibt der Kontext dauerhaft angehalten. Das Promise vonstartRendering()wird dann nie erfüllt. - Kompatibilität: Alte Safari-Versionen mit
webkitOfflineAudioContextunterstützensuspend()undresume()nicht. Prüfe die Unterstützung bei Bedarf mittypeof ctx.resume === 'function'.