Signatur
Beschreibung
Mit stop() legst du fest, wann ein Quellknoten wie OscillatorNode, AudioBufferSourceNode oder ConstantSourceNode aufhört, Klang zu erzeugen. Der Zeitpunkt wird in Sekunden auf der Zeitachse des zugehörigen AudioContext angegeben, also relativ zu audioContext.currentTime. Ohne Argument oder mit einem Wert in der Vergangenheit stoppt die Wiedergabe sofort.
Die Methode ist nützlich für exakt getimte Klänge: Töne mit fester Dauer, Metronome, Sequencer oder Soundeffekte. Da die Planung im Audio-Thread passiert, ist das Timing sample-genau und hängt nicht von setTimeout oder der Auslastung des Haupt-Threads ab.
Wenn der Knoten wirklich stoppt, wird das Ereignis ended ausgelöst. Dort kannst du aufräumen, etwa Verbindungen per disconnect() trennen. Wichtig: Ein Quellknoten ist ein Einweg-Objekt. Nach dem Stoppen lässt er sich nicht neu starten. Für eine erneute Wiedergabe musst du einen neuen Knoten erzeugen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $when | number | 0 | Zeitpunkt in Sekunden auf der Zeitachse von AudioContext.currentTime, zu dem die Wiedergabe endet. Bei 0 oder einem Wert kleiner als currentTime stoppt die Wiedergabe sofort. Negative Werte lösen einen RangeError aus. |
Rückgabewert
undefined).Beispiele
Ton mit fester Dauer abspielen
const ctx = new AudioContext();
const playBeep = (frequency = 440, duration = 0.5) => {
const osc = new OscillatorNode(ctx, { type: 'sine', frequency });
osc.connect(ctx.destination);
const now = ctx.currentTime;
osc.start(now);
osc.stop(now + duration); // nach 0,5 s stoppen
osc.addEventListener('ended', () => {
osc.disconnect();
console.log('Ton beendet');
});
};
document.querySelector('#beep').addEventListener('click', playBeep);
Sample per Button starten und stoppen
const ctx = new AudioContext();
let source = null;
const loadBuffer = async (url) => {
const res = await fetch(url);
return ctx.decodeAudioData(await res.arrayBuffer());
};
const bufferPromise = loadBuffer('/sounds/loop.mp3');
document.querySelector('#play').onclick = async () => {
if (ctx.state === 'suspended') await ctx.resume();
source?.stop();
// Jeder Start braucht einen neuen Knoten
source = new AudioBufferSourceNode(ctx, { buffer: await bufferPromise, loop: true });
source.connect(ctx.destination);
source.start();
};
document.querySelector('#stop').onclick = () => {
source?.stop(); // sofort stoppen
source = null;
};
Knackfreies Ausblenden vor dem Stoppen
const ctx = new AudioContext();
const osc = new OscillatorNode(ctx, { frequency: 220 });
const gain = new GainNode(ctx, { gain: 1 });
osc.connect(gain).connect(ctx.destination);
const now = ctx.currentTime;
const fadeStart = now + 1;
const fadeEnd = fadeStart + 0.05;
osc.start(now);
gain.gain.setValueAtTime(1, fadeStart);
gain.gain.linearRampToValueAtTime(0, fadeEnd); // kurz ausblenden
osc.stop(fadeEnd); // erst danach stoppen
osc.onended = () => console.log('sauber beendet bei', ctx.currentTime.toFixed(2));
// Wichtig · Fallstricke
- Kein Neustart: Nach
stop()führt ein erneuter Aufruf vonstart()zu einemInvalidStateError. Erzeuge stattdessen einen neuen Quellknoten. Das ist günstig und so vorgesehen. - Reihenfolge: Wenn du
stop()vorstart()aufrufst, gibt es einenInvalidStateError. Mehrfachestop()-Aufrufe sind dagegen erlaubt. Jeder neue Aufruf ersetzt den zuvor geplanten Stoppzeitpunkt. - Negative Werte für
whenlösen einenRangeErroraus. - Knacksen: Wenn du mitten in der Wellenform hart stoppst, entstehen hörbare Klicks. Blende deshalb vorher über einen
GainNodekurz aus. - Autoplay-Richtlinien: Browser starten einen
AudioContextoft im Zustandsuspended. Vor der Wiedergabe musst du nach einer Nutzeraktionctx.resume()aufrufen. - Ältere WebKit-Versionen kannten zusätzlich
noteOff(). Das ist veraltet, verwende nurstop().