Signatur
Beschreibung
start() ist auf allen Knoten verfügbar, die von AudioScheduledSourceNode erben. Dazu gehören OscillatorNode, AudioBufferSourceNode und ConstantSourceNode. Die Methode spielt nicht unbedingt sofort ab. Sie plant den Start zu einem Zeitpunkt auf der Uhr des Audio-Kontexts (AudioContext.currentTime, in Sekunden). Dadurch lassen sich Klänge auf das Sample genau timen, zum Beispiel für Metronome, Sequenzer oder Spiel-Soundeffekte. setTimeout ist dafür zu ungenau.
Übergibt man keinen Zeitpunkt oder einen Wert, der kleiner oder gleich currentTime ist, startet die Wiedergabe sofort. Wie lange die Quelle spielt, steuert man mit stop(). Das Ende der Wiedergabe meldet das Ereignis ended.
Wichtig: Jeder Quellknoten lässt sich nur einmal starten. Quellknoten sind als billige Wegwerf-Objekte gedacht: Für jeden neuen Ton erzeugt man einen neuen Knoten. Teure Daten wie ein AudioBuffer lassen sich dabei wiederverwenden.
AudioBufferSourceNode überschreibt die Methode mit der erweiterten Signatur start(when, offset, duration). Damit kann man ab einer bestimmten Stelle im Puffer abspielen und die Spieldauer begrenzen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $when | number | 0 | Zeitpunkt in Sekunden auf der Uhr des Kontexts (AudioContext.currentTime), zu dem die Wiedergabe beginnt. Bei 0 oder einem Wert kleiner als currentTime startet die Wiedergabe sofort. Negative Werte lösen einen RangeError aus. |
| $offset | number | 0 | Nur bei AudioBufferSourceNode: Stelle im Puffer in Sekunden, ab der abgespielt wird. |
| $duration | number | Nur bei AudioBufferSourceNode: Wie lange abgespielt wird, in Sekunden. Ohne Angabe läuft die Wiedergabe bis zum Ende des Puffers bzw. bis stop() aufgerufen wird. |
Rückgabewert
undefined).Beispiele
Einen Ton sofort starten und nach einer Sekunde stoppen
const ctx = new AudioContext();
const playBeep = () => {
const osc = new OscillatorNode(ctx, { type: 'sine', frequency: 440 });
osc.connect(ctx.destination);
osc.start(); // sofort
osc.stop(ctx.currentTime + 1); // nach 1 Sekunde
osc.addEventListener('ended', () => console.log('Ton beendet'));
};
// Wegen der Autoplay-Regeln nur nach einer Nutzeraktion
document.querySelector('#play').addEventListener('click', async () => {
if (ctx.state === 'suspended') await ctx.resume();
playBeep();
});
Metronom: Klicks exakt im Voraus planen
const ctx = new AudioContext();
const scheduleClicks = (bpm = 120, count = 8) => {
const interval = 60 / bpm;
const startAt = ctx.currentTime + 0.1; // kleiner Puffer
for (let i = 0; i < count; i++) {
const t = startAt + i * interval;
const osc = new OscillatorNode(ctx, { frequency: i % 4 === 0 ? 1000 : 800 });
const gain = new GainNode(ctx, { gain: 0.5 });
osc.connect(gain).connect(ctx.destination);
osc.start(t); // exakt geplanter Startzeitpunkt
osc.stop(t + 0.05); // kurzer Klick
}
console.log(`${count} Klicks geplant ab ${startAt.toFixed(2)} s`);
};
document.querySelector('#metronome').addEventListener('click', async () => {
await ctx.resume();
scheduleClicks();
});
Ausschnitt aus einer Audiodatei abspielen (AudioBufferSourceNode)
const ctx = new AudioContext();
const loadBuffer = async (url) => {
const res = await fetch(url);
const data = await res.arrayBuffer();
return ctx.decodeAudioData(data);
};
const playSnippet = (buffer, offset, duration) => {
// Für jede Wiedergabe einen NEUEN Quellknoten erzeugen
const src = new AudioBufferSourceNode(ctx, { buffer });
src.connect(ctx.destination);
src.start(ctx.currentTime, offset, duration);
};
document.querySelector('#snippet').addEventListener('click', async () => {
await ctx.resume();
const buffer = await loadBuffer('/audio/song.mp3');
playSnippet(buffer, 30, 5); // ab Sekunde 30, für 5 Sekunden
});
Fehler beim zweiten start()-Aufruf
const ctx = new AudioContext();
const osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start();
try {
osc.start(); // nicht erlaubt
} catch (err) {
console.log(err.name);
}
osc.stop();
// Wichtig · Fallstricke
- Nur einmal pro Knoten: Ein zweiter Aufruf von
start()auf demselben Knoten löst eineInvalidStateError-DOMExceptionaus. Das gilt auch nachstop(). Für jede neue Wiedergabe erzeugt man einen neuen Knoten. - Negative Werte für
when,offsetoderdurationlösen einenRangeErroraus. - Autoplay-Regeln: Wird ein
AudioContextohne Nutzeraktion erzeugt, ist er in vielen Browsern zunächst im Zustand"suspended".start()wirft dann keinen Fehler, aber es ist nichts zu hören. Deshalb nach einem Klick oder Tastendruckawait ctx.resume()aufrufen. - Zeitbasis:
whenbezieht sich aufAudioContext.currentTime. Die Werte vonDate.now()oderperformance.now()passen nicht dazu. Relative Zeitpunkte daher immer alsctx.currentTime + xangeben. - Ältere WebKit-Versionen kannten stattdessen
noteOn(). Diese Methode ist veraltet. Alle aktuellen Browser unterstützenstart(). - Bei
AudioBufferSourceNodemitloop = trueund ohnedurationendet die Wiedergabe erst mitstop().