Signatur
Beschreibung
start() startet die Wiedergabe eines AudioBuffer, der einer AudioBufferSourceNode zugewiesen ist. Der Startzeitpunkt wird auf der Zeitachse des AudioContext (context.currentTime, in Sekunden) angegeben. Dadurch lassen sich Klänge sample-genau planen, zum Beispiel für Drum-Sequencer, Metronome oder Spiele-Soundeffekte.
Mit offset legst du fest, ab welcher Stelle im Puffer (in Sekunden) die Wiedergabe beginnt. duration begrenzt, wie lange abgespielt wird. Ist loop aktiv, läuft die Wiedergabe ohne duration endlos zwischen loopStart und loopEnd, bis stop() aufgerufen wird.
Wichtig: Eine AudioBufferSourceNode ist ein Einweg-Objekt. start() darf pro Knoten nur einmal aufgerufen werden. Für jede weitere Wiedergabe erzeugst du einen neuen Knoten. Das kostet wenig, weil sich mehrere Knoten denselben AudioBuffer teilen können.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $when | number | 0 | Startzeitpunkt in Sekunden auf der Zeitachse von context.currentTime. Liegt der Wert in der Vergangenheit oder ist er 0, beginnt die Wiedergabe sofort. Negative Werte lösen einen RangeError aus. |
| $offset | number | 0 | Stelle im Puffer in Sekunden, an der die Wiedergabe beginnt. Werte hinter dem Pufferende führen dazu, dass nichts zu hören ist. Bei aktivem loop wird der Wert in den Loop-Bereich umgerechnet. Negative Werte lösen einen RangeError aus. |
| $duration | number | Restlänge des Puffers | Wiedergabedauer in Sekunden (Pufferzeit, nicht Echtzeit). Fehlt der Wert, wird bis zum Pufferende gespielt, bei loop endlos. Negative Werte lösen einen RangeError aus. |
Rückgabewert
undefined). Wenn die Wiedergabe endet, wird das Event ended ausgelöst.Beispiele
Sound laden und sofort abspielen
const ctx = new AudioContext();
const loadBuffer = async (url) => {
const res = await fetch(url);
const data = await res.arrayBuffer();
return ctx.decodeAudioData(data);
};
const playSound = (buffer) => {
// Für jede Wiedergabe einen neuen Knoten erzeugen
const source = new AudioBufferSourceNode(ctx, { buffer });
source.connect(ctx.destination);
source.start(); // sofort
source.addEventListener('ended', () => console.log('Wiedergabe beendet'));
};
document.querySelector('#play').addEventListener('click', async () => {
await ctx.resume(); // Autoplay-Richtlinie
const buffer = await loadBuffer('/sounds/klick.mp3');
playSound(buffer);
});
Metronom: vier Schläge exakt planen
const ctx = new AudioContext();
// Kurzen Klick synthetisch erzeugen (50 ms Rauschen, abklingend)
const length = Math.floor(ctx.sampleRate * 0.05);
const click = ctx.createBuffer(1, length, ctx.sampleRate);
const ch = click.getChannelData(0);
for (let i = 0; i < length; i++) {
ch[i] = (Math.random() * 2 - 1) * (1 - i / length);
}
const bpm = 120;
const interval = 60 / bpm;
const startAt = ctx.currentTime + 0.1; // kleiner Vorlauf
for (let beat = 0; beat < 4; beat++) {
const src = ctx.createBufferSource();
src.buffer = click;
src.connect(ctx.destination);
src.start(startAt + beat * interval);
}
console.log(`4 Schläge im Abstand von ${interval} s geplant`);
Ausschnitt abspielen mit offset und duration
const ctx = new AudioContext();
const playSnippet = async (url) => {
const buffer = await ctx.decodeAudioData(await (await fetch(url)).arrayBuffer());
const src = ctx.createBufferSource();
src.buffer = buffer;
src.connect(ctx.destination);
// In 1 s starten, ab Sekunde 12 der Datei, genau 5 s lang
src.start(ctx.currentTime + 1, 12, 5);
console.log(`Puffer-Länge: ${buffer.duration.toFixed(1)} s`);
};
playSnippet('/audio/podcast.mp3');
Endlosschleife starten und später stoppen
const ctx = new AudioContext();
const startLoop = (buffer) => {
const src = ctx.createBufferSource();
src.buffer = buffer;
src.loop = true;
src.loopStart = 0.5;
src.loopEnd = 2.5;
src.connect(ctx.destination);
src.start(0, 0.5); // ohne duration läuft sie endlos
return src;
};
// const loop = startLoop(buffer);
// setTimeout(() => loop.stop(), 10_000);
// Wichtig · Fallstricke
- Nur ein Aufruf pro Knoten: Ein zweiter Aufruf von
start()auf demselben Knoten löst einenInvalidStateErroraus. Auch nachstop()lässt sich der Knoten nicht erneut starten. Erzeuge stattdessen einen neuen Knoten, den Puffer kannst du wiederverwenden. - Zeitbasis:
whenist eine absolute Zeit auf der Uhr des Kontexts und keine Verzögerung. Für „in 2 Sekunden“ schreibst ductx.currentTime + 2. - Autoplay-Richtlinien: Browser starten einen
AudioContextoft im Zustandsuspended. Rufectx.resume()in einem Handler für eine Nutzeraktion (z. B.click) auf, sonst ist nichts zu hören. - Negative Parameter lösen einen
RangeErroraus. Einoffsethinter dem Pufferende bleibt stumm, es gibt aber keinen Fehler. - playbackRate:
offsetunddurationbeziehen sich auf die Pufferzeit. BeiplaybackRate = 2dauertduration: 4in Echtzeit nur etwa 2 Sekunden. - Ist beim Start kein
buffergesetzt, gibt der Knoten Stille aus. Einen später zugewiesenen Puffer spielt er noch ab, der Puffer lässt sich aber nur einmal setzen. - Die ältere Methode
noteOn()ist veraltet und wurde durchstart()ersetzt. Moderne Browser unterstützenstart()vollständig.