Start · Sprachen · JavaScript · Referenz · AudioParam.cancelAndHoldAtTime()

AudioParam.cancelAndHoldAtTime()

Methode

Entfernt alle geplanten Automationsereignisse ab <code>cancelTime</code> und hält den Parameter auf dem Wert, den er zu diesem Zeitpunkt gerade hat.

seit JavaScript Chrome 57+, Edge 79+, Safari 14.1+; Firefox: nicht Kategorie: webapi

Signatur

AudioParam.prototype.cancelAndHoldAtTime(cancelTime)

Beschreibung

cancelAndHoldAtTime() gehört zur Automations-API von AudioParam in der Web Audio API. Die Methode löscht alle Ereignisse, deren Startzeit bei oder nach cancelTime liegt. Anders als bei cancelScheduledValues() springt der Parameter dabei nicht auf einen früheren Wert zurück: Er behält den Wert, den er zu cancelTime hat, bis Sie neue Automationsereignisse planen.

Am meisten bringt die Methode, wenn eine Rampe gerade läuft, zum Beispiel linearRampToValueAtTime(), exponentialRampToValueAtTime(), setTargetAtTime() oder setValueCurveAtTime(). Die Rampe wird zu cancelTime abgeschnitten. Der dann erreichte Zwischenwert wird als fester Wert gehalten, und neue Rampen setzen genau dort an. So entstehen keine Knackser.

Typischer Einsatz sind Hüllkurven (ADSR) in Synthesizern. Lässt der Nutzer eine Taste los, während Attack oder Decay noch laufen, friert cancelAndHoldAtTime(ctx.currentTime) die Lautstärke auf dem aktuellen Stand ein. Danach kann die Release-Phase sauber von diesem Wert aus beginnen.

Parameter

Name Typ Default Beschreibung
$cancelTime Pflicht number Zeitpunkt in Sekunden auf der Zeitachse des AudioContext (vergleichbar mit ctx.currentTime). Ab diesem Zeitpunkt werden alle geplanten Ereignisse gelöscht, und der Wert zu diesem Zeitpunkt wird gehalten. Der Wert muss endlich und ≥ 0 sein.

Rückgabewert

Typ
AudioParam
Beschreibung
Eine Referenz auf dasselbe AudioParam-Objekt. Dadurch lassen sich Aufrufe verketten, z. B. param.cancelAndHoldAtTime(t).linearRampToValueAtTime(0, t + 0.5).

Beispiele

Release-Phase einer ADSR-Hüllkurve ohne Knacksen

const ctx = new AudioContext();
const osc = new OscillatorNode(ctx, { type: 'sawtooth', frequency: 220 });
const amp = new GainNode(ctx, { gain: 0 });
osc.connect(amp).connect(ctx.destination);
osc.start();

const noteOn = () => {
  const t = ctx.currentTime;
  amp.gain.cancelAndHoldAtTime(t);
  amp.gain.linearRampToValueAtTime(1, t + 0.8);   // Attack
  amp.gain.linearRampToValueAtTime(0.6, t + 1.5); // Decay → Sustain
};

const noteOff = () => {
  const t = ctx.currentTime;
  // Laufende Attack-/Decay-Rampe einfrieren und von dort ausblenden
  amp.gain.cancelAndHoldAtTime(t)
    .linearRampToValueAtTime(0, t + 0.4);        // Release
};

document.querySelector('#key').addEventListener('pointerdown', async () => {
  await ctx.resume();
  noteOn();
});
document.querySelector('#key').addEventListener('pointerup', noteOff);

Laufende Rampe mittendrin anhalten

const ctx = new AudioContext();
const osc = new OscillatorNode(ctx, { frequency: 200 });
osc.connect(ctx.destination);
osc.start();

const t0 = ctx.currentTime;
// Frequenz soll in 4 s von 200 auf 1000 Hz steigen
osc.frequency.setValueAtTime(200, t0);
osc.frequency.linearRampToValueAtTime(1000, t0 + 4);

// Nach 2 s abbrechen: Die Frequenz bleibt bei ca. 600 Hz stehen
osc.frequency.cancelAndHoldAtTime(t0 + 2);

setTimeout(() => {
  console.log(Math.round(osc.frequency.value));
  osc.stop();
}, 3000);
600

Feature-Erkennung mit Fallback (z. B. für Firefox)

const holdAt = (param, time) => {
  if (typeof param.cancelAndHoldAtTime === 'function') {
    return param.cancelAndHoldAtTime(time);
  }
  // Näherung: aktuellen Wert lesen und fest setzen
  const current = param.value;
  param.cancelScheduledValues(time);
  param.setValueAtTime(current, time);
  return param;
};

const ctx = new AudioContext();
const gain = new GainNode(ctx);
gain.gain.linearRampToValueAtTime(1, ctx.currentTime + 2);

holdAt(gain.gain, ctx.currentTime)
  .linearRampToValueAtTime(0, ctx.currentTime + 0.3);
console.log('Hüllkurve angepasst');
Hüllkurve angepasst

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Chromium-Browser (ab Chrome 57) und Safari (ab 14.1) unterstützen die Methode. Firefox unterstützt sie nicht. Prüfen Sie daher vor dem Aufruf mit typeof param.cancelAndHoldAtTime === 'function' und nutzen Sie sonst einen Fallback aus cancelScheduledValues() und setValueAtTime(param.value, t). Dieser Fallback ist nur eine Näherung, denn param.value kann der tatsächlichen Automation etwas hinterherhinken.
  • Ist cancelTime negativ oder nicht endlich (NaN, Infinity), wirft die Methode einen RangeError.
  • Die Zeit bezieht sich immer auf AudioContext.currentTime, nicht auf performance.now() oder Date.now(), und wird in Sekunden angegeben, nicht in Millisekunden.
  • Unterschied zu cancelScheduledValues(): Diese Methode entfernt die Ereignisse nur. Liegt der Abbruch mitten in einer Rampe, springt der Wert auf das letzte verbliebene Ereignis zurück, und es knackt hörbar. cancelAndHoldAtTime() vermeidet diesen Sprung.
  • Rampen, die Sie danach planen, starten beim gehaltenen Wert. Ein zusätzliches setValueAtTime() ist nicht nötig und würde bei einem falschen Wert sogar wieder einen Sprung verursachen.